diff -urp src.old/winsup/cygwin/init.cc src/winsup/cygwin/init.cc --- src.old/winsup/cygwin/init.cc Fri Aug 16 13:44:03 2002 +++ src/winsup/cygwin/init.cc Fri Aug 16 13:54:03 2002 @@ -25,12 +25,8 @@ WINAPI dll_entry (HANDLE h, DWORD reason dynamically_loaded = (static_load == NULL); break; case DLL_THREAD_ATTACH: - if (user_data->threadinterface) - { - if (!TlsSetValue(user_data->threadinterface->reent_index, - &user_data->threadinterface->reents)) - api_fatal("Sig proc MT init failed\n"); - } + if (MT_INTERFACE->reent_key.set (&MT_INTERFACE->reents)) + api_fatal("Sig proc MT init failed\n"); break; case DLL_PROCESS_DETACH: case DLL_THREAD_DETACH: diff -urp src.old/winsup/cygwin/thread.cc src/winsup/cygwin/thread.cc --- src.old/winsup/cygwin/thread.cc Fri Aug 16 13:44:04 2002 +++ src/winsup/cygwin/thread.cc Fri Aug 16 14:15:56 2002 @@ -49,30 +49,24 @@ extern int threadsafe; struct _reent * _reent_clib () { - int tmp = GetLastError (); struct __reent_t *_r = - (struct __reent_t *) TlsGetValue (MT_INTERFACE->reent_index); - + (struct __reent_t *) MT_INTERFACE->reent_key.get (); #ifdef _CYG_THREAD_FAILSAFE if (_r == 0) system_printf ("local thread storage not inited"); #endif - - SetLastError (tmp); return _r->_clib; } struct _winsup_t * _reent_winsup () { - int tmp = GetLastError (); - struct __reent_t *_r; - _r = (struct __reent_t *) TlsGetValue (MT_INTERFACE->reent_index); + struct __reent_t *_r = + (struct __reent_t *) MT_INTERFACE->reent_key.get (); #ifdef _CYG_THREAD_FAILSAFE if (_r == 0) system_printf ("local thread storage not inited"); #endif - SetLastError (tmp); return _r->_winsup; } @@ -177,7 +171,6 @@ MTinterface::Init (int forked) semalist.index = 0; #endif - reent_index = TlsAlloc (); reents._clib = _impure_ptr; reents._winsup = &winsup_reent; @@ -189,34 +182,14 @@ MTinterface::Init (int forked) winsup_reent._process_facility = 0; #endif - TlsSetValue (reent_index, &reents); - // the static reent_data will be used in the main thread - - - if (!indexallocated) + if (!forked) { - indexallocated = (-1); - thread_self_dwTlsIndex = TlsAlloc (); - if (thread_self_dwTlsIndex == TLS_OUT_OF_INDEXES) - system_printf - ("local storage for thread couldn't be set\nThis means that we are not thread safe!"); + mainthread.init_pthread (); + /*store the main thread's reents and self pointer */ + reent_key.set (&reents); + thread_self_key.set (&mainthread); } - - concurrency = 0; - threadcount = 1; /*1 current thread when Init occurs.*/ - - mainthread.win32_obj_id = myself->hProcess; - mainthread.setThreadIdtoCurrent (); - /*store the main thread's self pointer */ - TlsSetValue (thread_self_dwTlsIndex, &mainthread); - - if (forked) - return; - - keys = NULL; - mutexs = NULL; - conds = NULL; - semaphores = NULL; + /* else: pthread initialization is done in fixup_after_fork */ /*possible the atfork lists should be inited here as well */ @@ -245,6 +218,8 @@ MTinterface::fixup_before_fork (void) void MTinterface::fixup_after_fork (void) { + threadcount = 1; + pthread_key *key = keys; debug_printf ("keys is %x",keys); while (key) @@ -273,6 +248,17 @@ MTinterface::fixup_after_fork (void) sem->fixup_after_fork (); sem = sem->next; } + + pthread *thread = pthread::self(false); + if (!thread) + { + mainthread.init_pthread (); + /*store the main thread's reents and self pointer */ + reent_key.set (&reents); + thread_self_key.set (&mainthread); + } + else + thread->init_pthread (); } /* It is assumed that a key will not be deleted while it's destructors @@ -294,9 +280,40 @@ MTinterface::on_thread_detach (void) /* static methods */ pthread * -pthread::self () +pthread::self (const bool auto_init) +{ + pthread *thread = (pthread *) MT_INTERFACE->thread_self_key.get (); + if (!thread && auto_init) + { + /* thread was not created by pthread_create nor it is the mainthread + Try to allocate a structure for it. + This thread will be marked detached */ + thread = new pthread (); + if (thread) + { + if (verifyable_object_isvalid (&thread, PTHREAD_MAGIC) != VALID_OBJECT) + { + delete thread; + return NULL; + } + + thread->init_pthread (); + thread->attr.joinable = PTHREAD_CREATE_DETACHED; + thread->joiner = thread; + MT_INTERFACE->thread_self_key.set (thread); + } + } + + return thread; +} + +void +pthread::destructor (void *value) { - return (pthread *) TlsGetValue (MT_INTERFACE->thread_self_dwTlsIndex); + pthread *thread = (pthread *) value; + /* cleanup thread if thread is detached and not joined */ + if (thread && __pthread_equal(&thread->joiner, &thread)) + delete thread; } /* member methods */ @@ -346,7 +363,7 @@ pthread::create (void *(*func) (void *), cancel_event = ::CreateEvent (NULL,TRUE,FALSE,NULL); if (!cancel_event) { - system_printf ("couldn't create cancel event, this %p LastError %d", this, GetLastError () ); + system_printf ("couldn't create cancel event, this %p LastError %E", this ); /*we need the event for correct behaviour */ magic = 0; return; @@ -383,14 +400,12 @@ pthread::exit (void *value_ptr) pop_all_cleanup_handlers (); mutex.Lock (); - // cleanup if thread is in detached state and not joined - if( __pthread_equal(&joiner, &thread ) ) - delete this; - else + if (!__pthread_equal(&joiner, &thread)) { return_ptr = value_ptr; mutex.UnLock (); } + // else: cleanup is now done in key destructor function if (InterlockedDecrement (&MT_INTERFACE->threadcount) == 0) ::exit (0); @@ -708,6 +723,27 @@ pthread::pop_all_cleanup_handlers () pop_cleanup_handler (1); } +void +pthread::init_pthread (void) +{ + if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (), + GetCurrentProcess (), &win32_obj_id, + 0, FALSE, DUPLICATE_SAME_ACCESS)) + + { + system_printf ("Failed to duplicate handle for current thread: %E"); + win32_obj_id = NULL; + } + setThreadIdtoCurrent (); + cancel_event = ::CreateEvent (NULL,TRUE,FALSE,NULL); + if (!cancel_event) + { + system_printf ("couldn't create cancel event for mainthread, LastError %E"); + } + attr.joinable = PTHREAD_CREATE_JOINABLE; + joiner = NULL; +} + pthread_attr::pthread_attr ():verifyable_object (PTHREAD_ATTR_MAGIC), joinable (PTHREAD_CREATE_JOINABLE), contentionscope (PTHREAD_SCOPE_PROCESS), inheritsched (PTHREAD_INHERIT_SCHED), stacksize (0) @@ -1268,17 +1304,15 @@ pthread::thread_init_wrapper (void *_arg local_winsup._process_logmask = LOG_UPTO (LOG_DEBUG); - /*This is not checked by the OS !! */ - if (!TlsSetValue (MT_INTERFACE->reent_index, &local_reent)) + if (MT_INTERFACE->reent_key.set (&local_reent)) system_printf ("local storage for thread couldn't be set"); - - /*the OS doesn't check this for <= 64 Tls entries (pre win2k) */ - TlsSetValue (MT_INTERFACE->thread_self_dwTlsIndex, thread); + if (MT_INTERFACE->thread_self_key.set (thread)) + system_printf ("thread self pointer for thread couldn't be set"); thread->mutex.Lock (); // if thread is detached force cleanup on exit if (thread->attr.joinable == PTHREAD_CREATE_DETACHED && thread->joiner == NULL) - thread->joiner = pthread::self (); + thread->joiner = thread; thread->mutex.UnLock (); #ifdef _CYG_THREAD_FAILSAFE diff -urp src.old/winsup/cygwin/thread.h src/winsup/cygwin/thread.h --- src.old/winsup/cygwin/thread.h Fri Aug 16 13:44:04 2002 +++ src/winsup/cygwin/thread.h Fri Aug 16 13:52:25 2002 @@ -283,9 +283,13 @@ public: void push_cleanup_handler (__pthread_cleanup_handler *handler); void pop_cleanup_handler (int const execute); - static pthread* self (); + static pthread* self (const bool auto_init = true); static void *thread_init_wrapper (void *); + void init_pthread (void); + + static void destructor (void *value); + private: DWORD thread_id; __pthread_cleanup_handler *cleanup_stack; @@ -361,17 +365,12 @@ class MTinterface { public: // General - DWORD reent_index; - DWORD thread_self_dwTlsIndex; - /* we may get 0 for the Tls index.. grrr */ - int indexallocated; int concurrency; long int threadcount; // Used for main thread data, and sigproc thread struct __reent_t reents; struct _winsup_t winsup_reent; - pthread mainthread; callback *pthread_prepare; callback *pthread_child; @@ -383,18 +382,23 @@ public: class pthread_cond * conds; class semaphore * semaphores; + pthread mainthread; + + pthread_key reent_key; + pthread_key thread_self_key; + void Init (int); void fixup_before_fork (void); void fixup_after_fork (void); void on_thread_detach (void); - MTinterface ():reent_index (0), indexallocated (0), threadcount (1) - { - pthread_prepare = NULL; - pthread_child = NULL; - pthread_parent = NULL; - } + MTinterface (): concurrency (0), threadcount (1), + pthread_prepare (NULL), pthread_child (NULL), pthread_parent (NULL), + keys (NULL), mutexs (NULL), conds (NULL), semaphores (NULL), + mainthread (), reent_key (NULL), thread_self_key (pthread::destructor) + { + } }; void __pthread_atforkprepare(void);