2002-11-05 Thomas Pfaff <tpfaff@gmx.net>

* dcrt0.cc (dll_crt0_1): Add call to pthread::initMainThread to
        initialize mainthread when it is safe to call new.
        * init.cc (dll_entry): Change call to store reents in tls key.
        * thread.cc (_reent_clib) : Change call to get reents from tls
        key.
        (_reent_winsup): Ditto.
        (MTinterface::Init): Key handling changed. Remove initialization
        of member variables.
        (MTinterface::fixup_after_fork): Reinitialize mainthread object
        after fork. Reset threadount to 1.
        (pthread::initMainThread): Create mainthread object dynamically.
        and initialize with valid handles.
        (pthread::self): Remove calls to create thread objects.
        (pthread::setTlsSelfPointer): Change call to store thread self
        handle in tls key.
        (pthread::getTlsSelfPointer): New static method.
        (pthread::exit): Remove setTlsSelfPointer call.
        (pthread::initCurrentThread): New method.
        (pthread::thread_init_wrapper): Change call to store thread self
        handle in tls key.
        (pthread::join): Check for a valid joiner.
        (pthreadNull::pthreadNull): Mark Null object as detached.
        (pthreadNull::exit): Terminate thread via ExitThread.
        * thread.h (pthread::initMainThread): Change parameter in function
        call.
        (pthread::getTlsSelfPointer): New static method.
        (pthread::initCurrentThread): New method.
        (MTinterface::reent_key): Remove.
        (MTinterface::thread_self_dwTlsIndex): Ditto..
        (MTinterface::indexallocated): Ditto.
        (MTinterface::mainthread): Ditto.
        (MTinterface::reent_key): New member.
        (MTinterface::thread_self_key): Ditto.
        (MTinterface::MTinterface): Initialize all members.
This commit is contained in:
Robert Collins 2002-11-24 13:54:14 +00:00
parent 4f0de34d37
commit f8c8e13b7e
5 changed files with 110 additions and 78 deletions

View File

@ -1,3 +1,40 @@
2002-11-05 Thomas Pfaff <tpfaff@gmx.net>
* dcrt0.cc (dll_crt0_1): Add call to pthread::initMainThread to
initialize mainthread when it is safe to call new.
* init.cc (dll_entry): Change call to store reents in tls key.
* thread.cc (_reent_clib) : Change call to get reents from tls
key.
(_reent_winsup): Ditto.
(MTinterface::Init): Key handling changed. Remove initialization
of member variables.
(MTinterface::fixup_after_fork): Reinitialize mainthread object
after fork. Reset threadount to 1.
(pthread::initMainThread): Create mainthread object dynamically.
and initialize with valid handles.
(pthread::self): Remove calls to create thread objects.
(pthread::setTlsSelfPointer): Change call to store thread self
handle in tls key.
(pthread::getTlsSelfPointer): New static method.
(pthread::exit): Remove setTlsSelfPointer call.
(pthread::initCurrentThread): New method.
(pthread::thread_init_wrapper): Change call to store thread self
handle in tls key.
(pthread::join): Check for a valid joiner.
(pthreadNull::pthreadNull): Mark Null object as detached.
(pthreadNull::exit): Terminate thread via ExitThread.
* thread.h (pthread::initMainThread): Change parameter in function
call.
(pthread::getTlsSelfPointer): New static method.
(pthread::initCurrentThread): New method.
(MTinterface::reent_key): Remove.
(MTinterface::thread_self_dwTlsIndex): Ditto..
(MTinterface::indexallocated): Ditto.
(MTinterface::mainthread): Ditto.
(MTinterface::reent_key): New member.
(MTinterface::thread_self_key): Ditto.
(MTinterface::MTinterface): Initialize all members.
2002-11-23 Christopher Faylor <cgf@redhat.com> 2002-11-23 Christopher Faylor <cgf@redhat.com>
* wait.cc (wait4): Force pending signal delivery before waiting for * wait.cc (wait4): Force pending signal delivery before waiting for

View File

@ -628,6 +628,8 @@ dll_crt0_1 ()
ProtectHandle (hMainThread); ProtectHandle (hMainThread);
cygthread::init (); cygthread::init ();
pthread::initMainThread (!user_data->forkee);
/* Initialize debug muto, if DLL is built with --enable-debugging. /* Initialize debug muto, if DLL is built with --enable-debugging.
Need to do this before any helper threads start. */ Need to do this before any helper threads start. */
debug_init (); debug_init ();

View File

@ -27,12 +27,8 @@ WINAPI dll_entry (HANDLE h, DWORD reason, void *static_load)
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
break; break;
case DLL_THREAD_ATTACH: case DLL_THREAD_ATTACH:
if (user_data->threadinterface) if (MT_INTERFACE->reent_key.set (&MT_INTERFACE->reents))
{
if (!TlsSetValue (user_data->threadinterface->reent_index,
&user_data->threadinterface->reents))
api_fatal ("thread initialization failed"); api_fatal ("thread initialization failed");
}
break; break;
case DLL_THREAD_DETACH: case DLL_THREAD_DETACH:
/* not invoked */; /* not invoked */;

View File

@ -46,35 +46,29 @@ details. */
extern int threadsafe; extern int threadsafe;
#define MT_INTERFACE user_data->threadinterface
struct _reent * struct _reent *
_reent_clib () _reent_clib ()
{ {
int tmp = GetLastError ();
struct __reent_t *_r = struct __reent_t *_r =
(struct __reent_t *) TlsGetValue (MT_INTERFACE->reent_index); (struct __reent_t *) MT_INTERFACE->reent_key.get ();
#ifdef _CYG_THREAD_FAILSAFE #ifdef _CYG_THREAD_FAILSAFE
if (_r == 0) if (_r == 0)
system_printf ("local thread storage not inited"); system_printf ("local thread storage not inited");
#endif #endif
SetLastError (tmp);
return _r->_clib; return _r->_clib;
} }
struct _winsup_t * struct _winsup_t *
_reent_winsup () _reent_winsup ()
{ {
int tmp = GetLastError (); struct __reent_t *_r =
struct __reent_t *_r; (struct __reent_t *) MT_INTERFACE->reent_key.get ();
_r = (struct __reent_t *) TlsGetValue (MT_INTERFACE->reent_index);
#ifdef _CYG_THREAD_FAILSAFE #ifdef _CYG_THREAD_FAILSAFE
if (_r == 0) if (_r == 0)
system_printf ("local thread storage not inited"); system_printf ("local thread storage not inited");
#endif #endif
SetLastError (tmp);
return _r->_winsup; return _r->_winsup;
} }
@ -166,39 +160,14 @@ ResourceLocks::Delete ()
void void
MTinterface::Init (int forked) MTinterface::Init (int forked)
{ {
reent_index = TlsAlloc ();
reents._clib = _impure_ptr; reents._clib = _impure_ptr;
reents._winsup = &winsup_reent; reents._winsup = &winsup_reent;
winsup_reent._process_logmask = LOG_UPTO (LOG_DEBUG); winsup_reent._process_logmask = LOG_UPTO (LOG_DEBUG);
TlsSetValue (reent_index, &reents); if (!forked)
// the static reent_data will be used in the main thread reent_key.set (&reents);
if (!indexallocated)
{
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!");
else
indexallocated = (-1);
}
concurrency = 0;
threadcount = 1; /* 1 current thread when Init occurs.*/
pthread::initMainThread (&mainthread, myself->hProcess);
pthread_mutex::initMutex (); pthread_mutex::initMutex ();
if (forked)
return;
mutexs = NULL;
conds = NULL;
semaphores = NULL;
} }
void void
@ -233,40 +202,51 @@ MTinterface::fixup_after_fork (void)
sem->fixup_after_fork (); sem->fixup_after_fork ();
sem = sem->next; sem = sem->next;
} }
pthread::initMainThread (true);
threadcount = 1;
} }
/* pthread calls */ /* pthread calls */
/* static methods */ /* static methods */
void void
pthread::initMainThread (pthread *mainThread, HANDLE win32_obj_id) pthread::initMainThread (bool do_init)
{ {
mainThread->win32_obj_id = win32_obj_id; if (!do_init)
mainThread->setThreadIdtoCurrent (); return;
setTlsSelfPointer (mainThread);
pthread *thread = getTlsSelfPointer ();
if (!thread)
{
thread = new pthread ();
if (!thread)
api_fatal ("failed to create mainthread object");
}
thread->initCurrentThread ();
} }
pthread * pthread *
pthread::self () pthread::self ()
{ {
pthread *temp = (pthread *) TlsGetValue (MT_INTERFACE->thread_self_dwTlsIndex); pthread *thread = getTlsSelfPointer ();
if (temp) if (thread)
return temp; return thread;
temp = new pthread (); return pthreadNull::getNullpthread ();
temp->precreate (NULL);
if (!temp->magic) {
delete temp;
return pthreadNull::getNullpthread ();
}
temp->postcreate ();
return temp;
} }
void void
pthread::setTlsSelfPointer (pthread *thisThread) pthread::setTlsSelfPointer (pthread *thisThread)
{ {
/* the OS doesn't check this for <= 64 Tls entries (pre win2k) */ MT_INTERFACE->thread_self_key.set (thisThread);
TlsSetValue (MT_INTERFACE->thread_self_dwTlsIndex, thisThread); }
pthread *
pthread::getTlsSelfPointer ()
{
return (pthread *) MT_INTERFACE->thread_self_key.get ();
} }
@ -384,9 +364,6 @@ pthread::exit (void *value_ptr)
mutex.UnLock (); mutex.UnLock ();
} }
/* Prevent DLL_THREAD_DETACH Attempting to clean us up */
setTlsSelfPointer (0);
if (InterlockedDecrement (&MT_INTERFACE->threadcount) == 0) if (InterlockedDecrement (&MT_INTERFACE->threadcount) == 0)
::exit (0); ::exit (0);
else else
@ -715,6 +692,18 @@ pthread::getThreadId ()
return thread_id; return thread_id;
} }
void
pthread::initCurrentThread ()
{
cancel_event = ::CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
GetCurrentProcess (), &win32_obj_id,
0, FALSE, DUPLICATE_SAME_ACCESS))
win32_obj_id = NULL;
setThreadIdtoCurrent ();
setTlsSelfPointer (this);
}
/* static members */ /* static members */
bool bool
pthread_attr::isGoodObject (pthread_attr_t const *attr) pthread_attr::isGoodObject (pthread_attr_t const *attr)
@ -1411,16 +1400,15 @@ pthread::thread_init_wrapper (void *_arg)
local_winsup._process_logmask = LOG_UPTO (LOG_DEBUG); local_winsup._process_logmask = LOG_UPTO (LOG_DEBUG);
/* This is not checked by the OS !! */ MT_INTERFACE->reent_key.set (&local_reent);
if (!TlsSetValue (MT_INTERFACE->reent_index, &local_reent))
system_printf ("local storage for thread couldn't be set");
thread->setThreadIdtoCurrent ();
setTlsSelfPointer (thread); setTlsSelfPointer (thread);
thread->mutex.Lock (); thread->mutex.Lock ();
// if thread is detached force cleanup on exit // if thread is detached force cleanup on exit
if (thread->attr.joinable == PTHREAD_CREATE_DETACHED && thread->joiner == NULL) if (thread->attr.joinable == PTHREAD_CREATE_DETACHED && thread->joiner == NULL)
thread->joiner = pthread::self (); thread->joiner = thread;
thread->mutex.UnLock (); thread->mutex.UnLock ();
#ifdef _CYG_THREAD_FAILSAFE #ifdef _CYG_THREAD_FAILSAFE
@ -1787,6 +1775,9 @@ pthread::join (pthread_t *thread, void **return_val)
{ {
pthread_t joiner = self (); pthread_t joiner = self ();
if (!isGoodObject (&joiner))
return EINVAL;
// Initialize return val with NULL // Initialize return val with NULL
if (return_val) if (return_val)
*return_val = NULL; *return_val = NULL;
@ -2594,6 +2585,7 @@ pthreadNull::getNullpthread ()
pthreadNull::pthreadNull () pthreadNull::pthreadNull ()
{ {
attr.joinable = PTHREAD_CREATE_DETACHED;
/* Mark ourselves as invalid */ /* Mark ourselves as invalid */
magic = 0; magic = 0;
} }
@ -2610,6 +2602,7 @@ pthreadNull::create (void *(*)(void *), pthread_attr *, void *)
void void
pthreadNull::exit (void *value_ptr) pthreadNull::exit (void *value_ptr)
{ {
ExitThread (0);
} }
int int

View File

@ -344,7 +344,7 @@ public:
pthread (); pthread ();
virtual ~pthread (); virtual ~pthread ();
static void initMainThread(pthread *, HANDLE); static void initMainThread (bool);
static bool isGoodObject(pthread_t const *); static bool isGoodObject(pthread_t const *);
static void atforkprepare(); static void atforkprepare();
static void atforkparent(); static void atforkparent();
@ -387,10 +387,12 @@ private:
void pop_all_cleanup_handlers (void); void pop_all_cleanup_handlers (void);
void precreate (pthread_attr *); void precreate (pthread_attr *);
void postcreate (); void postcreate ();
void setThreadIdtoCurrent(); void setThreadIdtoCurrent ();
static void setTlsSelfPointer(pthread *); static void setTlsSelfPointer (pthread *);
static pthread *getTlsSelfPointer ();
void cancel_self (); void cancel_self ();
DWORD getThreadId (); DWORD getThreadId ();
void initCurrentThread ();
}; };
class pthreadNull : public pthread class pthreadNull : public pthread
@ -493,17 +495,12 @@ class MTinterface
{ {
public: public:
// General // General
DWORD reent_index;
DWORD thread_self_dwTlsIndex;
/* we may get 0 for the Tls index.. grrr */
int indexallocated;
int concurrency; int concurrency;
long int threadcount; long int threadcount;
// Used for main thread data, and sigproc thread // Used for main thread data, and sigproc thread
struct __reent_t reents; struct __reent_t reents;
struct _winsup_t winsup_reent; struct _winsup_t winsup_reent;
pthread mainthread;
callback *pthread_prepare; callback *pthread_prepare;
callback *pthread_child; callback *pthread_child;
@ -514,18 +511,25 @@ public:
class pthread_cond * conds; class pthread_cond * conds;
class semaphore * semaphores; class semaphore * semaphores;
pthread_key reent_key;
pthread_key thread_self_key;
void Init (int); void Init (int);
void fixup_before_fork (void); void fixup_before_fork (void);
void fixup_after_fork (void); void fixup_after_fork (void);
MTinterface ():reent_index (0), indexallocated (0), threadcount (1) MTinterface () :
concurrency (0), threadcount (1),
pthread_prepare (NULL), pthread_child (NULL), pthread_parent (NULL),
mutexs (NULL), conds (NULL), semaphores (NULL),
reent_key (NULL), thread_self_key (NULL)
{ {
pthread_prepare = NULL;
pthread_child = NULL;
pthread_parent = NULL;
} }
}; };
#define MT_INTERFACE user_data->threadinterface
extern "C" extern "C"
{ {
int __pthread_attr_init (pthread_attr_t * attr); int __pthread_attr_init (pthread_attr_t * attr);