extern int *__threadid( void ) { void *netid; int id; netid = GetThreadID(); id = gettid( netid ); if( netid != NULL && id == 0 ) { // handle stray threads id = gettid( NULL ); if( id != 0 ) { void *ptr; __ThreadIDs[ id ] = netid; ptr = lib_calloc( 1, __ThreadDataSize ); if( ptr == NULL ) { __fatal_runtime_error( "Unable to allocate thread-specific data", 1 ); } __ThreadData[ id ].data = ptr; __ThreadData[ id ].allocated_entry = 1; __ThreadData[ id ].data->__allocated = 1; __ThreadData[ id ].data->__randnext = 1; __ThreadData[ id ].data->__data_size = __ThreadDataSize; if( __initthread( ptr ) ) { lib_free( ptr ); __fatal_runtime_error( "Unable to initialize thread-specific data", 1 ); } } } CurrThrdID = id; return( &CurrThrdID ); }
static CRITICAL_SECTION *__NTGetCriticalSection( void ) { CRITICAL_SECTION *ptr; if( critsect_next < MAX_CRITICAL_SECTION ) { ptr = &(critsect_cache[critsect_next]); critsect_next++; } else { ptr = lib_calloc( 1, sizeof( *ptr ) ); if( ptr == NULL ) { __fatal_runtime_error( "Unable to allocate semaphore data", 1 ); } critsect_vector = lib_realloc( critsect_vector, (critsect_vectornext+1)*sizeof(CRITICAL_SECTION*)); if( critsect_vector == NULL ) { __fatal_runtime_error( "Unable to allocate semaphore data", 1 ); } critsect_vector[critsect_vectornext] = ptr; critsect_vectornext++; } InitializeCriticalSection( ptr ); return( ptr ); }
void __InitFiles( void ) { __stream_link *link; FILE *fp; fp = _RWD_iob; stderr->_flag &= ~(_IONBF | _IOLBF | _IOFBF); stderr->_flag |= _IONBF; for( fp = _RWD_iob; fp->_flag != 0; ++fp ) { link = lib_malloc( sizeof( __stream_link ) ); if( link == NULL ) { __fatal_runtime_error( "Not enough memory to allocate file structures\r\n", 1 ); } link->stream = fp; link->next = _RWD_ostream; _RWD_ostream = link; fp->_link = link; fp->_link->_base = NULL; fp->_link->_tmpfchar = 0; fp->_link->_orientation = _NOT_ORIENTED; } _RWD_cstream = NULL; }
void _WCI86FAR __default_sigfpe_handler( int fpe_sig ) { char msg[] = "Floating point exception (00)"; msg[sizeof( msg ) - 4] += _bin_to_ascii_offs( fpe_sig >> 4 ); msg[sizeof( msg ) - 3] += _bin_to_ascii_offs( fpe_sig ); __fatal_runtime_error( msg, EXIT_FAILURE ); }
_WCRTLINK void _WCFAR *__chkstack( void _WCFAR *ptr ) /***************************************************/ { if( FP_SEG( ptr ) != FP_SEG( &Routine ) ) { __fatal_runtime_error( "thread stack not in DGROUP", 1 ); // never return } return( ptr ); }
static void init( void ) /**********************/ { __lfn_rm_tb_selector = __alloc_dos_tb( TOTAL_RM_TB_SIZE_PARA, (unsigned short *)&__lfn_rm_tb_segment ); if( __lfn_rm_tb_selector == 0 ) { __fatal_runtime_error( "Unable to allocate LFN real mode transfer buffer", -1 ); } *(long *)&__lfn_rm_tb_linear = TinyDPMIBase( __lfn_rm_tb_selector ); }
void __InitFiles( void ) { #ifdef _M_I86 __stream_link _WCI86NEAR *ptr; #endif __stream_link *link; FILE *fp; fp = _RWD_iob; #if defined( __RDOS__ ) || defined( __RDOSDEV__ ) stdout->_flag &= ~(_IONBF | _IOLBF | _IOFBF); stderr->_flag &= ~(_IONBF | _IOLBF | _IOFBF); #else #if defined( __NETWARE__ ) stdout->_flag &= ~(_IONBF | _IOLBF | _IOFBF); stdout->_flag |= _IONBF; #endif stderr->_flag &= ~(_IONBF | _IOLBF | _IOFBF); stderr->_flag |= _IONBF; #endif for( fp = _RWD_iob; fp->_flag != 0; ++fp ) { #ifdef _M_I86 ptr = lib_nmalloc( sizeof( __stream_link ) ); if( ptr != NULL ) { link = ptr; } else { #endif link = lib_malloc( sizeof( __stream_link ) ); if( link == NULL ) { __fatal_runtime_error( "Not enough memory to allocate file structures", 1 ); // never return } #ifdef _M_I86 } #endif link->stream = fp; link->next = _RWD_ostream; _RWD_ostream = link; fp->_link = link; fp->_link->_base = NULL; fp->_link->_tmpfchar = 0; fp->_link->_orientation = _NOT_ORIENTED; } _RWD_cstream = NULL; }
_WCRTLINK void __CloseSemaphore( semaphore_object *obj ) { #if defined( __RUNTIME_CHECKS__ ) && defined( _M_IX86 ) // 0 is ok // 1 is ok // JBS I don't think so. I would mean a critical section is active. // JBS For every lock, there should be an unlock. // if( obj->count >= 2 ) { // __fatal_runtime_error( "Semaphore locked too many times", 1 ); // } if( obj->count >= 1 ) { __fatal_runtime_error( "Semaphore not unlocked", 1 ); } #endif #if !defined( __NT__ ) #if defined( _M_I86 ) if( obj->count > 0 ) { DosSemClear( &obj->semaphore ); } #else if( obj->initialized != 0 ) { #if defined( __NETWARE__ ) obj->semaphore = 0; #elif defined( __QNX__ ) __qsem_destroy( &obj->semaphore ); #elif defined( __LINUX__ ) // TODO: Close the semaphore for Linux! #elif defined( __RDOS__ ) RdosDeleteSection( obj->semaphore ); obj->semaphore = 0; #elif defined( __RDOSDEV__ ) #else DosCloseMutexSem( obj->semaphore ); #endif } #endif obj->initialized = 0; obj->owner = 0; obj->count = 0; #endif }
_WCRTLINK void __ReleaseSemaphore( semaphore_object *obj ) { TID tid; tid = GetCurrentThreadId(); #if defined( _NETWARE_CLIB ) if( tid == 0 ) return; #endif if( obj->count > 0 ) { if( obj->owner != tid ) { __fatal_runtime_error( "Semaphore unlocked by wrong owner", 1 ); } if( --obj->count == 0 ) { obj->owner = 0; #if defined( _M_I86 ) DosSemClear( &obj->semaphore ); #else #if defined( __NETWARE__ ) obj->semaphore = 0; #elif defined( __NT__ ) LeaveCriticalSection( obj->semaphore ); #elif defined( __QNX__ ) __qsem_post( &obj->semaphore ); #elif defined( __LINUX__ ) // TODO: Relase semaphore under Linux! #elif defined( __RDOS__ ) RdosLeaveSection( obj->semaphore ); #elif defined( __RDOSDEV__ ) RdosLeaveKernelSection( &obj->semaphore ); #else DosReleaseMutexSem( obj->semaphore ); #endif #endif } } }
// realloc thread data thread_data *__ReallocThreadData( void ) { TID tid; thread_data *tdata; _AccessTDList(); tid = GetCurrentThreadId(); #ifdef __OS2__ if( tid <= __MaxThreads ) { thread_data_vector *tdv; tdv = &(__ThreadData[tid]); if( tdv->allocated_entry ) { #if defined (_NETWARE_LIBC) /* // we don't want to lose __FirstThreadData as our global // destructors will try and access it as they are called // from a different thread. */ if(__IsFirstThreadData(tdv->data)) { tdata = lib_realloc( tdv->data, __ThreadDataSize ); __RegisterFirstThreadData(tdata); } else #endif tdata = lib_realloc( tdv->data, __ThreadDataSize ); if( tdata == NULL ) { __fatal_runtime_error( "Unable to resize thread-specific data", 1 ); } tdv->data = tdata; } else { tdata = lib_calloc( 1, __ThreadDataSize ); if( tdata == NULL ) { __fatal_runtime_error( "Unable to resize thread-specific data", 1 ); } memcpy( tdata, tdv->data, tdv->data->__data_size ); tdv->allocated_entry = 1; tdv->data = tdata; } } else #endif { thread_data_list *tdl; for( tdl = __thread_data_list ; tdl != NULL ; tdl = tdl->next ) { if( tdl->tid == tid ) { break; } } if( tdl == NULL ) { __fatal_runtime_error( "Thread has no thread-specific data", 1 ); } if( tdl->allocated_entry ) { #if defined(_NETWARE_LIBC) if(tdata = lib_malloc( __ThreadDataSize )) { memcpy(tdata, tdl->data, min(__ThreadDataSize, tdl->data->__data_size)); lib_free(tdl->data); } #else tdata = lib_realloc( tdl->data, __ThreadDataSize ); #endif if( tdata == NULL ) { __fatal_runtime_error( "Unable to resize thread-specific data", 1 ); } tdl->data = tdata; } else { tdata = lib_calloc( 1, __ThreadDataSize ); if( tdata == NULL ) { __fatal_runtime_error( "Unable to resize thread-specific data", 1 ); } memcpy( tdata, tdl->data, tdl->data->__data_size ); tdl->allocated_entry = 1; tdl->data = tdata; } } tdata->__allocated = 1; tdata->__data_size = __ThreadDataSize; tdata->__resize = 0; #if defined(__NT__) TlsSetValue( __TlsIndex, tdata ); #endif #if defined(_NETWARE_LIBC) if(0 != NXKeySetValue(__NXSlotID, tdata)) { lib_free(tdata); tdata = NULL; } #endif _ReleaseTDList(); return( tdata ); }
// lookup thread data thread_data *__GetThreadData( void ) { thread_data *tdata = NULL; #ifdef __OS2__ TID tid; tid = GetCurrentThreadId(); if( tid <= __MaxThreads ) { tdata = __AllocInitThreadData( tdata ); if( tdata != NULL ) { if( __initthread( tdata ) ) { __FreeInitThreadData( tdata ); tdata = NULL; } else { __ThreadData[tid].data = tdata; __ThreadData[tid].allocated_entry = tdata->__allocated; } } } else { thread_data_list *tdl; thread_data_list **pprev; _AccessTDList(); tdata = NULL; pprev = &__thread_data_list; for( tdl = *pprev; tdl != NULL ; tdl = tdl->next ) { if( tdl->tid == tid ) { tdata = tdl->data; break; } pprev = &(tdl->next); } if( tdata == NULL ) { tdata = __AllocInitThreadData( tdata ); if( tdata != NULL ) { if( !__AddThreadData( tid, tdata ) ) { __FreeInitThreadData( tdata ); tdata = NULL; } } } else if( *pprev ) { // promote to front *pprev = tdl->next; tdl->next = __thread_data_list; __thread_data_list = tdl; // check for need to resize thread data if( tdata->__resize ) { tdata = __ReallocThreadData(); } } _ReleaseTDList(); } #elif defined(__NT__) if( __NTAddThread( tdata ) ) { tdata = (thread_data *)TlsGetValue( __TlsIndex ); } #elif defined(_NETWARE_LIBC) if( __LibCAddThread( tdata ) ) { if(0 != NXKeyGetValue(__NXSlotID, (void **) &tdata)) tdata = NULL; } #elif defined(__RDOS__) if( __RdosAddThread( tdata ) ) { tdata = (thread_data *)__tls_get_value( __TlsIndex ); } #endif if( tdata == NULL ) { __fatal_runtime_error( "Thread has no thread-specific data", 1 ); } return( tdata ); }
static void _no_support_loaded( void ) { __fatal_runtime_error( "Floating-point support not loaded", 1 ); }
int _OS2Main( char far *stklow, char far * stktop, unsigned envseg, unsigned cmdoff ) /*************************************************/ { cmdoff = cmdoff; /* supress warnings */ envseg = envseg; stktop = stktop; /* set up global variables */ #if defined(__SW_BD) _STACKTOP = 0; _curbrk = _dynend = (unsigned)&end; stklow = NULL; #else _STACKTOP = FP_OFF( stktop ); _curbrk = _dynend = _STACKTOP; #endif DosGetHugeShift( (PUSHORT)&_HShift ); DosGetMachineMode( (PBYTE)&_osmode ); { unsigned short version; DosGetVersion( (PUSHORT)&version ); _osmajor = version >> 8; _osminor = version & 0xff; } #if defined(__SW_BD) _LpPgmName = ""; _LpCmdLine = ""; #else /* copy progname and arguments to bottom of stack */ { char far *src; char far *pgmp; src = MK_FP( envseg, cmdoff ); _LpPgmName = stklow; /* back up from the ao: pointer to the eo: pointer (see OS/2 2.0 docs)*/ for( pgmp = src - 1; *--pgmp != '\0'; ); ++pgmp; while( *stklow++ = *pgmp++ ); while( *src ) ++src; ++src; _LpCmdLine = stklow; while( *stklow++ = *src++ ); } #endif #if defined(__SW_BM) { SEL globalseg; SEL localseg; DosGetInfoSeg( &globalseg, &localseg ); _threadid = MK_FP( localseg, offsetof( LINFOSEG, tidCurrent ) ); if( __InitThreadProcessing() == NULL ) __fatal_runtime_error( "Not enough memory", 1 ); #if defined(__SW_BD) { unsigned i; unsigned j; j = __MaxThreads; for( i = 1; i <= j; i++ ) { __SetupThreadProcessing( i ); } } #else __SetupThreadProcessing( 1 ); #endif _STACKLOW = (unsigned)stklow; } #else _nothread = getpid(); _threadid = &_nothread; _STACKLOW = (unsigned)stklow; /* set bottom of stack */ #endif // { /* removed JBS 99/11/10 */ // // make sure the iomode array is of the proper length // // this needs to be done before the InitRtns // extern void __grow_iomode(int); // if( _osmode == OS2_MODE ) { // __grow_iomode( 100 ); // } // } __InitRtns( 255 ); #ifdef __SW_BD { int status; status = setjmp( JmpBuff ); if( status == 0 ) return( _CMain() ); return( RetCode ); } #else return( _CMain() ); #endif }
static void _no_support_loaded() { __fatal_runtime_error( "C++ floating-point support not loaded\r\n", 1 ); }
void _Not_Enough_Memory() { __fatal_runtime_error( "Not enough memory", 1 ); }
static void _no_support_loaded( void ) { __fatal_runtime_error( "C++ floating-point support not loaded", 1 ); // never return }
void __InitMultipleThread( void ) /*******************************/ { if( __GetThreadPtr != __MultipleThread ) { #if defined( _NETWARE_CLIB ) { /* __ThreadData[ 0 ] is used whenever GetThreadID() returns a pointer not in our __ThreadIDs list - ie. whenever it returns NULL, a pointer to a thread we didn't create, or an invalid pointer */ void *ptr; ptr = lib_calloc( 1, __ThreadDataSize ); if( ptr == NULL ) { __fatal_runtime_error( "Unable to allocate thread-specific data", 1 ); } __ThreadData[ 0 ].data = ptr; __ThreadData[ 0 ].allocated_entry = 1; __ThreadData[ 0 ].data->__allocated = 1; __ThreadData[ 0 ].data->__randnext = 1; __ThreadData[ 0 ].data->__data_size = __ThreadDataSize; if( __initthread( ptr ) ) { lib_free( ptr ); __fatal_runtime_error( "Unable to initialize thread-specific data", 1 ); } ptr = lib_calloc( 1, __ThreadDataSize ); if( ptr == NULL ) { __fatal_runtime_error( "Unable to allocate thread-specific data", 1 ); } __FirstThreadData = ptr; __FirstThreadData->__allocated = 1; __FirstThreadData->__randnext = 1; __FirstThreadData->__data_size = __ThreadDataSize; __ThreadData[ 1 ].data = __FirstThreadData; __ThreadData[ 1 ].allocated_entry = __FirstThreadData->__allocated; __ThreadIDs[ 1 ] = GetThreadID(); if( __initthread( ptr ) ) { lib_free( ptr ); __fatal_runtime_error( "Unable to initialize thread-specific data", 1 ); } } #elif defined( _NETWARE_LIBC ) InitSemaphore.semaphore = 0; /* sema4 is mutex in this case */ InitSemaphore.initialized = 1; //_ThreadExitRtn = &__ThreadExit; - might need this at some point?? // Note: __AddThreadData uses the InitSemaphore, _AccessTDList & _ReleaseTDList __FirstThreadData->thread_id = GetCurrentThreadId(); __AddThreadData( __FirstThreadData->thread_id, __FirstThreadData ); if(0 != NXKeySetValue(__NXSlotID, __FirstThreadData)) { __fatal_runtime_error( "Unable to initialize thread-specific data", 1 ); } #elif defined( __NT__ ) InitSemaphore.semaphore = __NTGetCriticalSection(); InitSemaphore.initialized = 1; _ThreadExitRtn = &__ThreadExit; // Note: __AddThreadData uses the InitSemaphore, _AccessTDList & _ReleaseTDList __AddThreadData( __FirstThreadData->thread_id, __FirstThreadData ); TlsSetValue( __TlsIndex, __FirstThreadData ); #elif defined( __QNX__ ) __qsem_init( &InitSemaphore.semaphore, 1, 1 ); InitSemaphore.initialized = 1; // first thread data already in magic memory #elif defined( __LINUX__ ) // TODO: Init semaphores for Linux #elif defined( __RDOS__ ) InitSemaphore.semaphore = RdosCreateSection(); InitSemaphore.initialized = 1; __AddThreadData( __FirstThreadData->thread_id, __FirstThreadData ); __tls_set_value( __TlsIndex, __FirstThreadData ); #elif defined( __RDOSDEV__ ) RdosInitKernelSection( &InitSemaphore.semaphore ); InitSemaphore.initialized = 1; #elif defined( __OS2__ ) DosCreateMutexSem( NULL, &InitSemaphore.semaphore, 0, FALSE ); InitSemaphore.initialized = 1; __ThreadData[1].data = __FirstThreadData; __ThreadData[1].allocated_entry = __FirstThreadData->__allocated; #else #error Multiple thread support is not defined for this platform #endif #if !defined( _M_I86 ) // Set these up after we have created the InitSemaphore #if !defined (_THIN_LIB) _AccessFileH = &__AccessFileH; _ReleaseFileH = &__ReleaseFileH; _AccessIOB = &__AccessIOB; _ReleaseIOB = &__ReleaseIOB; #endif _AccessTDList = &__AccessTDList; _ReleaseTDList = &__ReleaseTDList; __AccessSema4 = &__AccessSemaphore; __ReleaseSema4 = &__ReleaseSemaphore; __CloseSema4 = &__CloseSemaphore; #if !defined( __NETWARE__ ) _AccessNHeap = &__AccessNHeap; _AccessFHeap = &__AccessFHeap; _ReleaseNHeap = &__ReleaseNHeap; _ReleaseFHeap = &__ReleaseFHeap; #endif #if defined( __NT__ ) _AccessFList = &__AccessFList; _ReleaseFList = &__ReleaseFList; #endif #endif __GetThreadPtr = __MultipleThread; } }
_WCRTLINK void __AccessSemaphore( semaphore_object *obj ) { TID tid; tid = GetCurrentThreadId(); #if defined( _NETWARE_CLIB ) if( tid == 0 ) return; #endif if( obj->owner != tid ) { #if defined( _M_I86 ) DosSemRequest( &obj->semaphore, -1L ); #else #if !defined( __NETWARE__ ) if( obj->initialized == 0 ) { #if defined( __RUNTIME_CHECKS__ ) && defined( _M_IX86 ) if( obj == &InitSemaphore ) { __fatal_runtime_error( "Bad semaphore lock", 1 ); } #endif __AccessSemaphore( &InitSemaphore ); if( obj->initialized == 0 ) { #if defined( __NT__ ) obj->semaphore = __NTGetCriticalSection(); #elif defined( __QNX__ ) __qsem_init( &obj->semaphore, 1, 1 ); #elif defined( __LINUX__ ) // TODO: Access semaphore under Linux! #elif defined( __RDOS__ ) obj->semaphore = RdosCreateSection(); #elif defined( __RDOSDEV__ ) RdosInitKernelSection(&obj->semaphore); #else DosCreateMutexSem( NULL, &obj->semaphore, 0, FALSE ); #endif obj->initialized = 1; } __ReleaseSemaphore( &InitSemaphore ); } #endif #if defined( __NETWARE__ ) while( obj->semaphore != 0 ) { #if defined (_NETWARE_CLIB) ThreadSwitch(); #else NXThreadYield(); #endif } obj->semaphore = 1; obj->initialized = 1; #elif defined( __NT__ ) EnterCriticalSection( obj->semaphore ); #elif defined( __QNX__ ) __qsem_wait( &obj->semaphore ); #elif defined( __LINUX__ ) // TODO: Wait for semaphore under Linux! #elif defined( __RDOS__ ) RdosEnterSection( obj->semaphore ); #elif defined( __RDOSDEV__ ) RdosEnterKernelSection( &obj->semaphore ); #else DosRequestMutexSem( obj->semaphore, SEM_INDEFINITE_WAIT ); #endif #endif obj->owner = tid; } obj->count++; }