int _LibMain( int hdll, int reason, void *reserved ) { thread_data *tdata; int rc = 0; switch( reason ) { case DLL_THREAD_ATTACH: tdata = ( thread_data * )RdosAllocateMem( __ThreadDataSize ); if( tdata ) { memset( tdata, 0, __ThreadDataSize ); tdata->__data_size = __ThreadDataSize; __RdosAddThread( tdata ); } break; case DLL_PROCESS_ATTACH: __InitRtns( INIT_PRIORITY_THREAD ); tdata = ( thread_data * )RdosAllocateMem( __ThreadDataSize ); memset( tdata, 0, __ThreadDataSize ); tdata->__data_size = __ThreadDataSize; __InitThreadData( tdata ); __RdosInit( 1, tdata, hdll ); __InitRtns( 255 ); __CommonInit(); __sig_init_rtn(); if( !__RdosThreadInit() ) return( -1 ); __InitMultipleThread(); rc = LibMain( hdll, reason, reserved ); if( !rc ) { __FiniRtns( 0, 255 ); } break; case DLL_THREAD_DETACH: __RdosRemoveThread(); break; case DLL_PROCESS_DETACH: __FiniRtns( 0, FINI_PRIORITY_EXIT - 1 ); __RdosRemoveThread(); RdosFreeMem( __FirstThreadData ); __FirstThreadData = NULL; break; } return( rc ); }
int __CBeginThread( thread_fn *start_addr, int prio, const char *thread_name, unsigned stack_size, void *arglist ) /************************************************************/ { thread_args *td; int th; __InitMultipleThread(); td = malloc( sizeof( *td ) ); if( td == NULL ) { return( -1L ); } td->rtn = start_addr; td->argument = arglist; td->signal = RdosGetThreadHandle(); RdosClearSignal(); RdosCreateKernelThread( prio, stack_size, begin_thread_helper, thread_name, td ); RdosWaitForSignal(); th = td->tid; free( td ); return( th ); }
int __CBeginThread( thread_fn *start_addr, void *stack_bottom, unsigned stack_size, void *arglist ) /******************************************************/ { TID tid; APIRET rc; thread_args td; if( __ThreadData == NULL ) { if( __InitThreadProcessing() == NULL ) return( -1 ); __InitMultipleThread(); } stack_bottom = stack_bottom; td.rtn = start_addr; td.argument = arglist; rc = DosCreateEventSem( NULL, &td.event, 0, 0 ); if( rc != 0 ) return( -1 ); rc = DosCreateThread( &tid, (PFNTHREAD)begin_thread_helper, (ULONG)&td, 0, stack_size + __threadstksize ); if( rc != 0 ) { tid = -1; } else { /* suspend parent thread so that it can't call _beginthread() again before new thread extracts data from "td" (no problem if new thread calls _beginthread() since it has its own stack) */ DosWaitEventSem( td.event, SEM_INDEFINITE_WAIT ); } DosCloseEventSem( td.event ); return( tid ); }
unsigned long __CBeginThreadEx( void *security, unsigned stack_size, thread_fnex *start_addr, void *arglist, unsigned initflag, unsigned *thrdaddr ) { thread_args *td; HANDLE th; if( __TlsIndex == NO_INDEX ) { if( !__NTThreadInit() ) return( 0 ); __InitMultipleThread(); } td = malloc( sizeof( *td ) ); if( td == NULL ) { _RWD_errno = ENOMEM; return( 0 ); } stack_size = __ROUND_UP_SIZE_4K( stack_size ); td->rtn = start_addr; td->argument = arglist; th = CreateThread( (LPSECURITY_ATTRIBUTES)security, (DWORD)stack_size, (LPTHREAD_START_ROUTINE)&begin_thread_helper, (LPVOID) td, (DWORD)initflag, (LPDWORD)thrdaddr ); if( th == NULL ) free( td ); return( (unsigned long)th ); }
static void __imthread_fn( void ) { #if defined(__NT__) if( !__NTThreadInit() ) return; #elif defined(_NETWARE_LIB) if( !__LibCThreadInit() ) return; #elif defined(__QNX__) #elif defined(__LINUX__) #elif defined(__WARP__) if( __InitThreadProcessing() == 0 ) return; #elif defined(__RDOS__) if( !__RdosThreadInit() ) return; #endif #if !defined(__LINUX__) __InitMultipleThread(); #endif }
int __CBeginThread( thread_fn *start_addr, int prio, const char *thread_name, unsigned stack_size, void *arglist ) /************************************************************/ { thread_args *td; int th; int wait_handle; if( __TlsIndex == NO_INDEX ) { if( !__RdosThreadInit() ) return( -1L ); __InitMultipleThread(); } td = malloc( sizeof( *td ) ); if( td == NULL ) { _RWD_errno = ENOMEM; return( -1L ); } stack_size = __ROUND_UP_SIZE_4K( stack_size ); wait_handle = RdosCreateWait(); td->rtn = start_addr; td->argument = arglist; td->signal = RdosCreateSignal(); RdosResetSignal( td->signal ); RdosAddWaitForSignal( wait_handle, td->signal, 0 ); __create_thread(begin_thread_helper, prio, thread_name, td, stack_size); RdosWaitForever( wait_handle ); RdosFreeSignal( td->signal ); RdosCloseWait( wait_handle ); th = td->tid; free( td ); return( th ); }
int __CBeginThread( thread_fn *start_addr, void *stack_bottom, unsigned stack_size, void *arglist ) /************************************************************/ { DWORD tid; thread_args *td; HANDLE th; stack_bottom = stack_bottom; /* parameter not used for NT version */ if( __TlsIndex == NO_INDEX ) { if( !__NTThreadInit() ) return( -1L ); __InitMultipleThread(); } td = malloc( sizeof( *td ) ); if( td == NULL ) { _RWD_errno = ENOMEM; return( -1L ); } stack_size = __ROUND_UP_SIZE_4K( stack_size ); td->rtn = start_addr; td->argument = arglist; th = CreateThread( NULL, stack_size, (LPTHREAD_START_ROUTINE)&begin_thread_helper, (LPVOID) td, CREATE_SUSPENDED, &tid ); if( th ) { td->thread_handle = th; ResumeThread( th ); } else { // we didn't create the thread so it isn't going to free this free( td ); th = (HANDLE)-1L; } return( (int)th ); }
extern int __CBeginThread( thread_fn * start_addr, void * stack_bottom, unsigned stack_size, void * arglist ) { begin_thread_data data; int error; if( __NXSlotID == NO_INDEX ) { __InitMultipleThread(); } data.start_addr = start_addr; data.stack_bottom = stack_bottom; data.arglist = arglist; if( NULL == (data.semaphore = NXSemaAlloc( 0, NULL )) ) return( -1 ); /* // We create the thread as detached (non-joinable) and // to automatically clear context */ if( data.cx = NXContextAlloc( (void (*)(void *))&begin_thread_helper, &data,NX_PRIO_MED, __SYS_ALLOCD_STACK, NX_CTX_NORMAL, &error ) ) { error = NXThreadCreate( data.cx, NX_THR_DETACHED |NX_THR_BIND_CONTEXT, &data.nxtid ); } if( 0 == error ) { NXSemaWait( data.semaphore ); } else { /* should we set errno here? */ data.tid = -1; } NXSemaFree( data.semaphore ); return( data.tid ); }
/***************************************************************************** // Initialise runtime environemnt. Equivalent of old prelude *****************************************************************************/ int __init_environment( void * reserved ) { int rc = -1; if(NULL == (NLMHandle = getnlmhandle())) return -1; if(NULL == (AllocRTag = AllocateResourceTag( NLMHandle, "OpenWatcom CLIB Memory", AllocSignature ))) return -1; _saved_DS = __DS(); /* // Call initialisation routines where priority is <= 1 and set the // initialisation finish level to 1 */ __InitRtns( INIT_PRIORITY_THREAD ); InitFiniLevel = INIT_PRIORITY_THREAD; /* // Initialise multiple thread support */ if(__CreateFirstThreadData()) { __InitMultipleThread(); /* // Call initiliation routines at priority 255 (all) and the set the // initialisation finish level to 255 */ __InitRtns( 255 ); InitFiniLevel = 255; /* // Environment initialised. */ rc = 0; } return( rc ); }
int __CBeginThread( thread_fn *start_addr, void *stack_bottom, unsigned stack_size, void *arglist ) /******************************************************/ { pid_t pid; thread_args td; int rc; if( stack_bottom == NULL ) { if( stack_size == 0 ) { stack_size = 1024*4; } stack_bottom = lib_calloc( stack_size, 1 ); if( stack_bottom == NULL ) { _RWD_errno = ENOMEM; return( -1 ); } } __InitMultipleThread(); td.rtn = start_addr; td.argument = arglist; td.stack_bottom = stack_bottom; rc = __posix_sem_init( &td.event, 1, 0 ); if( rc == -1 ) return( -1 ); pid = tfork( stack_bottom, stack_size, begin_thread_helper, &td, 0 ); if( pid != -1 ) { /* suspend parent thread so that it can't call _beginthread() again before new thread extracts data from "td" (no problem if new thread calls _beginthread() since it has its own stack) */ __posix_sem_wait( &td.event ); } __posix_sem_destroy( &td.event ); return( pid ); }
unsigned _LibMain( unsigned hmod, unsigned termination ) /******************************************************/ { static int processes; unsigned rc; if( termination != 0 ) { // If we're running with single DGROUP and tried to load // twice, do not run any termination code! Also reset the // process counter so that the already loaded DLL can // terminate properly if( processes > 1 ) { --processes; return( 0 ); } rc = LibMain( hmod, termination ); --processes; #ifdef __SW_BR __FiniRtns( 0, 255 ); #else if( _LpwCmdLine ) { lib_free( _LpwCmdLine ); _LpwCmdLine = NULL; } if( _LpwPgmName ) { lib_free( _LpwPgmName ); _LpwPgmName = NULL; } __FiniRtns( FINI_PRIORITY_EXIT, 255 ); // calls to free memory have to be done before semaphores closed __FreeInitThreadData( __FirstThreadData ); __OS2Fini(); // must be done before following finalizers get called __FiniRtns( 0, FINI_PRIORITY_EXIT - 1 ); __shutdown_stack_checking(); #endif return( rc ); } ++processes; if( processes > 1 ) { if( __disallow_single_dgroup(hmod) ) { return( 0 ); } } __hmodule = hmod; #ifdef __SW_BR { static char fname[_MAX_PATH]; static wchar_t wfname[_MAX_PATH]; __Is_DLL = 1; __InitRtns( 255 ); DosQueryModuleName( hmod, sizeof( fname ), fname ); _LpDllName = fname; _LpwDllName = wfname; _atouni( _LpwDllName, _LpDllName ); } #else { PTIB pptib; PPIB pppib; unsigned i; DosGetInfoBlocks( &pptib, &pppib ); _RWD_Envptr = pppib->pib_pchenv; _LpCmdLine = pppib->pib_pchcmd; while( *_LpCmdLine ) { // skip over program name _LpCmdLine++; } _LpCmdLine++; _LpwCmdLine = lib_malloc( (strlen( _LpCmdLine ) + 1) * sizeof( wchar_t ) ); _atouni( _LpwCmdLine, _LpCmdLine ); { // ugly stuff to deal with two copies of .exe name in the // environment space. apparently the OS fullpath name is // just before this one in the environment space char *cmd_path; cmd_path = pppib->pib_pchcmd; for( cmd_path -= 2; *cmd_path != '\0'; --cmd_path ); ++cmd_path; _LpPgmName = cmd_path; _LpwPgmName = lib_malloc( (strlen( _LpPgmName ) + 1) * sizeof( wchar_t ) ); _atouni( _LpwPgmName, _LpPgmName ); } __InitRtns( INIT_PRIORITY_THREAD ); if( __InitThreadProcessing() == NULL ) return( 0 ); __OS2Init( TRUE, __AllocInitThreadData( NULL ) ); for( i = 2; i <= __MaxThreads; i++ ) { if( !__OS2AddThread( i, NULL ) ) { return( 0 ); } } __InitRtns( INIT_PRIORITY_EXIT - 1 ); __InitMultipleThread(); { static char fname[_MAX_PATH]; static wchar_t wfname[_MAX_PATH]; DosQueryModuleName( hmod, sizeof( fname ), fname ); _LpDllName = fname; _LpwDllName = wfname; _atouni( _LpwDllName, _LpDllName ); } __InitRtns( 255 ); } #endif __CommonInit(); #ifndef __SW_BR /* allocate alternate stack for F77 */ __ASTACKPTR = (char *)_STACKLOW + __ASTACKSIZ; #endif return( LibMain( hmod, termination ) ); }
int APIENTRY _LibMain( HANDLE hdll, DWORD reason, LPVOID reserved ) { int rc; static int processes; switch( reason ) { case DLL_THREAD_ATTACH: #ifndef __SW_BR if( !__NTAddThread( NULL ) ) { return( FALSE ); } #endif rc = LibMain( hdll, reason, reserved ); break; case DLL_PROCESS_ATTACH: ++processes; if( processes > 1 ) { if( __disallow_single_dgroup( hdll ) ) { rc = FALSE; break; } } #ifdef __SW_BR __Is_DLL = 1; __InitRtns( INIT_PRIORITY_EXIT - 1 ); #else // The following initializers are called: (in the CLIB run-time DLL): // nothing is called __InitRtns( INIT_PRIORITY_THREAD ); // allocate some thread data storage and initialize run-time variables { thread_data *tdata = __AllocInitThreadData( NULL ); if( !tdata || !__NTInit( TRUE, tdata, hdll ) ) { rc = FALSE; break; } } // set up TLSIndex thingee if( !__NTThreadInit() ) { // safe to call multiple times rc = FALSE; break; } // The following initializers are called: (in the CLIB run-time DLL): // __chk8087 // __verify_pentium_fdiv_bug // __Init_Argv // __imthread_fn (which calls _NTThreadInit and __InitMultipleThread) __InitRtns( INIT_PRIORITY_EXIT - 1 ); // sets up semaphores and starts linked list of thread data storage __InitMultipleThread(); // now safe to call multiple times #endif if( _pRawDllMain != NULL ) { if( !_pRawDllMain( hdll, reason, reserved ) ) { __FiniRtns( 0, FINI_PRIORITY_EXIT - 1 ); rc = FALSE; break; } } // The following initializers are called: (in the CLIB run-time DLL): // profilog_init // __InitWinLinesSem // dbgdata@do_it // __setenvp // __mbInitOnStartup // __sig_init // (??) in STK // __InitFiles // __clock_init __InitRtns( 255 ); #ifdef __SW_BR { static char fn[_MAX_PATH]; __lib_GetModuleFileNameA( hdll, fn, sizeof( fn ) ); _LpDllName = fn; } { static wchar_t wfn[_MAX_PATH]; __lib_GetModuleFileNameW( hdll, wfn, sizeof( wfn ) ); _LpwDllName = wfn; } #endif __CommonInit(); __sig_init_rtn(); rc = LibMain( hdll, reason, reserved ); if( !rc ) { __FiniRtns( 0, 255 ); } break; case DLL_THREAD_DETACH: rc = LibMain( hdll, reason, reserved ); #ifndef __SW_BR __NTRemoveThread( TRUE ); #endif break; case DLL_PROCESS_DETACH: rc = LibMain( hdll, reason, reserved ); __FiniRtns( FINI_PRIORITY_EXIT, 255 ); if( _pRawDllMain != NULL ) { _pRawDllMain( hdll, reason, reserved ); } #ifndef __SW_BR __NTFini(); // must be done before following finalizers get called #endif __FiniRtns( 0, FINI_PRIORITY_EXIT - 1 ); #ifndef __SW_BR __NTRemoveThread( TRUE ); __FreeInitThreadData( __FirstThreadData ); __FirstThreadData = NULL; #endif --processes; } return( rc ); }