mthread.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 810 行 · 第 1/2 页
C
810 行
if(0 != (ccode = NXKeyGetValue(__NXSlotID, (void **) &tdata)))
tdata = NULL;
if( tdata == NULL )
{
tdata = __GetThreadData();
}
else if( tdata->__resize )
{
tdata = __ReallocThreadData();
}
SetLastError(old);
return( tdata );
#elif defined( __WARP__ )
// 32 bit OS/2
TID tid;
thread_data *tdata = NULL;
tid = GetCurrentThreadId();
if( tid <= __MaxThreads ) {
tdata = __ThreadData[tid].data;
}
if( tdata == NULL ) {
tdata = __GetThreadData();
} else if( tdata->__resize ) {
tdata = __ReallocThreadData();
}
return( tdata );
#elif defined( __OS2_286__ )
// 16 bit OS/2
return( __ThreadData[GetCurrentThreadId()] );
#elif defined( __QNX__ )
void *tdata;
__getmagicvar( &tdata, _m_thread_data );
if( tdata == NULL ) {
tdata = __QNXAddThread( tdata );
}
return( tdata );
#elif defined( __LINUX__ )
// TODO: Init multiple threads for Linux!
return( NULL );
#else
return( __ThreadData[GetCurrentThreadId()].data );
#endif
}
#if defined( __386__ ) || defined( __AXP__ ) || defined( __PPC__ ) || defined( __MIPS__ )
thread_data *__AllocInitThreadData( thread_data *tdata )
/******************************************************/
{
if( tdata == NULL ) {
tdata = lib_calloc( 1, __ThreadDataSize );
if( tdata != NULL ) {
tdata->__allocated = 1;
tdata->__data_size = __ThreadDataSize;
}
}
__InitThreadData( tdata );
return( tdata );
}
void __FreeInitThreadData( thread_data *tdata )
/******************************************************/
{
if( tdata != NULL ) {
if( tdata->__allocated == 1 )
lib_free( tdata );
}
}
#if defined( __NT__ )
BOOL __NTThreadInit( void )
/*************************/
{
if( __TlsIndex == NO_INDEX ) {
__TlsIndex = TlsAlloc();
// avoid Win32s bug (0-2 are assumed to be reserved by Win32s)
if( WIN32_IS_WIN32S ) {
while( (__TlsIndex != NO_INDEX) && (__TlsIndex <= 2) ) {
__TlsIndex = TlsAlloc();
}
}
}
if( __TlsIndex == NO_INDEX ) {
return( FALSE );
}
return( TRUE );
}
static void __NTThreadFini( void )
/********************************/
{
if( __TlsIndex != NO_INDEX ) {
TlsFree( __TlsIndex );
__TlsIndex = NO_INDEX;
}
}
BOOL __NTAddThread( thread_data *tdata )
/**************************************/
{
if( __TlsIndex == NO_INDEX ) {
return( FALSE );
}
tdata = __AllocInitThreadData( tdata );
if( tdata == NULL ) {
return( FALSE );
}
if( !__AddThreadData( tdata->thread_id, tdata ) ) {
lib_free( tdata );
return( FALSE );
}
TlsSetValue( __TlsIndex, tdata );
return( TRUE );
}
void __NTRemoveThread( int close_handle )
/***************************************/
{
thread_data *tdata;
HANDLE thread_handle;
if( __TlsIndex != NO_INDEX ) {
tdata = TlsGetValue( __TlsIndex );
#if defined( __RUNTIME_CHECKS__ ) && defined( _M_IX86 )
if( tdata == (thread_data *)2 ) return;
#else
if( tdata == NULL ) return;
#endif
thread_handle = tdata->thread_handle;
__RemoveThreadData( tdata->thread_id );
#if defined( __RUNTIME_CHECKS__ ) && defined( _M_IX86 )
TlsSetValue( __TlsIndex, (void*)2 );
#else
TlsSetValue( __TlsIndex, NULL );
#endif
if( thread_handle != 0 && close_handle ) {
CloseHandle( thread_handle );
}
}
}
static void __ThreadExit( void )
/******************************/
{
__NTRemoveThread( TRUE );
__NTThreadFini();
}
#elif defined( __OS2__ )
int __OS2AddThread( TID tid, thread_data *tdata )
/***********************************************/
{
tdata = __AllocInitThreadData( tdata );
if( tdata == NULL ) return( 0 );
if( tid <= __MaxThreads ) {
if( __initthread( tdata ) ) {
lib_free( tdata );
return( 0 );
} else {
__ThreadData[tid].data = tdata;
__ThreadData[tid].allocated_entry = tdata->__allocated;
}
} else {
if( !__AddThreadData( tid, tdata ) ) {
// unable to setup storage
lib_free( tdata );
return( 0 );
}
}
return( 1 );
}
void __OS2RemoveThread( void )
/****************************/
{
TID tid;
tid = *_threadid;
if( tid <= __MaxThreads ) {
if( __ThreadData[tid].allocated_entry ) {
lib_free( __ThreadData[tid].data );
}
__ThreadData[tid].data = NULL;
} else {
__RemoveThreadData( tid );
}
}
#elif defined( __QNX__ )
thread_data *__QNXAddThread( thread_data *tdata )
/***********************************************/
{
void *tmp;
tdata = __AllocInitThreadData( tdata );
// if tdata is NULL it doesn't matter what we do with it
tmp = (void *)tdata;
__setmagicvar( &tmp, _m_thread_data );
return( tdata );
}
void __QNXRemoveThread( void )
/****************************/
{
void *tmp;
thread_data *tdata;
__getmagicvar( &tmp, _m_thread_data );
if( tmp != NULL ) {
tdata = tmp;
if( tdata->__allocated ) {
lib_free( tdata );
}
tmp = 0;
__setmagicvar( &tmp, _m_thread_data );
}
}
#elif defined( __LINUX__ )
thread_data *__LinuxAddThread( thread_data *tdata )
/***********************************************/
{
// TODO: Implement this for Linux!
return( NULL );
}
void __LinuxRemoveThread( void )
/****************************/
{
// TODO: Implement this for Linux!
}
#endif
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\r\n", 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\r\n", 1 );
}
ptr = lib_calloc( 1, __ThreadDataSize );
if( ptr == NULL ) {
__fatal_runtime_error(
"Unable to allocate thread-specific data\r\n", 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\r\n", 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\r\n", 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
#else
DosCreateMutexSem( NULL, &InitSemaphore.semaphore, 0, FALSE );
InitSemaphore.initialized = 1;
__ThreadData[1].data = __FirstThreadData;
__ThreadData[1].allocated_entry = __FirstThreadData->__allocated;
#endif
// 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
__GetThreadPtr = &__MultipleThread;
}
}
#endif
static void __FiniSema4s( void ) // called from finalizer
/******************************/
{
int i;
_CloseSemaphore( &IOBSemaphore );
for( i = 0; i < MAX_SEMAPHORE; i++ )
{ /* 17-feb-93 */
_CloseSemaphore( &FileSemaphores[ i ] );
}
#if defined( __NT__ )
_CloseSemaphore( &FListSemaphore );
__NTFreeCriticalSection();
#endif
#if !defined( __QNX__ )
__FiniThreadProcessing();
#if !defined( __OS2_286__ )
// All thread data areas freed, including main process thread data
// so mark first thread data pointer null. Note that OS/2 1.x does
// not have __FirstThreadData at all.
__FirstThreadData = NULL;
#endif
#endif
#if !defined( __NETWARE__ )
_heapshrink();
_CloseSemaphore( &NHeapSemaphore );
_CloseSemaphore( &FHeapSemaphore );
#endif
#if defined( __386__ ) || defined( __AXP__ ) || defined( __PPC__ ) || defined( __MIPS__ )
_CloseSemaphore( &TDListSemaphore );
_CloseSemaphore( &InitSemaphore );
// After closing InitSemaphore, we need to reset the sem access routines to
// the dummy ones; someone may still want semaphore protection during shutdown
// processing but since threading is gone now, there should be no reentrancy
// problems
__AccessSema4 = &nullSema4Rtn;
__ReleaseSema4 = &nullSema4Rtn;
__CloseSema4 = &nullSema4Rtn;
#if !defined( __NETWARE__ )
_AccessNHeap = &__NullAccHeapRtn;
_AccessFHeap = &__NullAccHeapRtn;
_ReleaseNHeap = &__NullAccHeapRtn;
_ReleaseFHeap = &__NullAccHeapRtn;
#endif
#if defined( __NT__ )
__NTDeleteCriticalSection();
__NTThreadFini();
#endif
#if defined (_NETWARE_LIBC)
__LibCThreadFini();
#endif
#endif
}
AYI( __FiniSema4s, INIT_PRIORITY_RUNTIME )
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?