2002-09-11 Robert Collins <rbtcollins@hotmail.com>

* init.cc (dll_entry): On thread detach, if the thread hasn't
        exit()ed, do so.
        * pthread.cc (pthread_getsequence_np): Remove the
        __pthread_getsequence_np wrapper. This requires errno.h.
        * thread.cc (pthread::self): Instantiate a new pthread object
        when called and none exists. return a NULL object if instantiation
        fails.
        (pthread::precreate): Factor out common code.
        (pthread::postcreate): Ditto.
        (pthread::create): Ditto.
        (pthread::exit): Remove the TLS value when we exit to prevent
        double exits.
        (MTinterface::Init): Bugfix - don't mark the TLS index as created
        if one was not allocated.
        Apply Extract Method to move pthread specific initialisation into
        pthread.
        (pthread::initMainThread): Extracted method from MTinterface::Init.
        (pthread::setTlsSelfPointer): Extracted method from various pthread
        calls, to make reading those functions easier.
        (pthread::setThreadIdtoCurrent): Ditto.
        (pthread::cancel_self): Bring into the .cc file, it's only used
        within the class.
        (pthread::getThreadId): Ditto.
        (pthread::thread_init_wrapper): Apply Extract Method to the TLS
        setting logic.
        (pthread::isGoodObject): Extracted method from various pthread
        wrapper calls, for clarity of reading.
        (pthread::getsequence_np): Converted from __pthread_getsquence_np.
        (__pthread_create): Apply Extract Method to the object validation.
        (__pthread_cancel): Ditto.
        (__pthread_join): Ditto.
        (__pthread_detach): Ditto.
        (__pthread_suspend): Ditto.
        (__pthread_continue): Ditto.
        (__pthread_getschedparam): Ditto.
        (__pthread_getsequence_np): Remove.
        (__pthread_setschedparam): Apply Extract Method to the object
        validation.
        (pthreadNull::getNullpthread): New method, return the pthreadNull
        object.
        (pthreadNull::pthreadNull): Private constructor to prevent accidental
        use.
        (pthreadNull::~pthreadNull): Prevent compile warnings.
        (pthreadNull::create): Override pthread behaviour.
        (pthreadNull::exit): Ditto.
        (pthreadNull::cancel): Ditto.
        (pthreadNull::testcancel): Ditto.
        (pthreadNull::setcancelstate): Ditto.
        (pthreadNull::setcanceltype): Ditto.
        (pthreadNull::push_cleanup_handler): Ditto.
        (pthreadNull::pop_cleanup_handler): Ditto.
        (pthreadNull::getsequence_np): Ditto.
        (pthreadNull::_instance): Ditto.
        * thread.h (pthread): Declare pre- and post-create.
        Move GetThreadId to private scope and rename to getThreadId.
        Move setThreadIdtoCurrent to private scope.
        Make create virtual.
        Make ~pthread virtual.
        Declare initMainThread.
        Declare isGoodObject.
        Make exit virtual.
        Make cancel virtual.
        Make testcancel virtual.
        Make setcancelstate virtual.
        Make setcanceltype virtual.
        Make push_cleanup_handler virtual.
        Make pop_cleanup_handler virtual.
        Declare getsequence_np.
        Declare setTlsSelfPointer.
        (pthreadNull): New null object class for pthread.
        (__pthread_getsequence_np): Remove.
This commit is contained in:
Robert Collins 2002-09-16 10:53:29 +00:00
parent 0812076923
commit 4e78617321
5 changed files with 298 additions and 66 deletions

View File

@ -1,3 +1,77 @@
2002-09-11 Robert Collins <rbtcollins@hotmail.com>
* init.cc (dll_entry): On thread detach, if the thread hasn't
exit()ed, do so.
* pthread.cc (pthread_getsequence_np): Remove the
__pthread_getsequence_np wrapper. This requires errno.h.
* thread.cc (pthread::self): Instantiate a new pthread object
when called and none exists. return a NULL object if instantiation
fails.
(pthread::precreate): Factor out common code.
(pthread::postcreate): Ditto.
(pthread::create): Ditto.
(pthread::exit): Remove the TLS value when we exit to prevent
double exits.
(MTinterface::Init): Bugfix - don't mark the TLS index as created
if one was not allocated.
Apply Extract Method to move pthread specific initialisation into
pthread.
(pthread::initMainThread): Extracted method from MTinterface::Init.
(pthread::setTlsSelfPointer): Extracted method from various pthread
calls, to make reading those functions easier.
(pthread::setThreadIdtoCurrent): Ditto.
(pthread::cancel_self): Bring into the .cc file, it's only used
within the class.
(pthread::getThreadId): Ditto.
(pthread::thread_init_wrapper): Apply Extract Method to the TLS
setting logic.
(pthread::isGoodObject): Extracted method from various pthread
wrapper calls, for clarity of reading.
(pthread::getsequence_np): Converted from __pthread_getsquence_np.
(__pthread_create): Apply Extract Method to the object validation.
(__pthread_cancel): Ditto.
(__pthread_join): Ditto.
(__pthread_detach): Ditto.
(__pthread_suspend): Ditto.
(__pthread_continue): Ditto.
(__pthread_getschedparam): Ditto.
(__pthread_getsequence_np): Remove.
(__pthread_setschedparam): Apply Extract Method to the object
validation.
(pthreadNull::getNullpthread): New method, return the pthreadNull
object.
(pthreadNull::pthreadNull): Private constructor to prevent accidental
use.
(pthreadNull::~pthreadNull): Prevent compile warnings.
(pthreadNull::create): Override pthread behaviour.
(pthreadNull::exit): Ditto.
(pthreadNull::cancel): Ditto.
(pthreadNull::testcancel): Ditto.
(pthreadNull::setcancelstate): Ditto.
(pthreadNull::setcanceltype): Ditto.
(pthreadNull::push_cleanup_handler): Ditto.
(pthreadNull::pop_cleanup_handler): Ditto.
(pthreadNull::getsequence_np): Ditto.
(pthreadNull::_instance): Ditto.
* thread.h (pthread): Declare pre- and post-create.
Move GetThreadId to private scope and rename to getThreadId.
Move setThreadIdtoCurrent to private scope.
Make create virtual.
Make ~pthread virtual.
Declare initMainThread.
Declare isGoodObject.
Make exit virtual.
Make cancel virtual.
Make testcancel virtual.
Make setcancelstate virtual.
Make setcanceltype virtual.
Make push_cleanup_handler virtual.
Make pop_cleanup_handler virtual.
Declare getsequence_np.
Declare setTlsSelfPointer.
(pthreadNull): New null object class for pthread.
(__pthread_getsequence_np): Remove.
2002-09-13 Corinna Vinschen <corinna@vinschen.de>
* syscalls.cc (seteuid32): Treat ILLEGAL_UID invalid.

View File

@ -35,6 +35,13 @@ WINAPI dll_entry (HANDLE h, DWORD reason, void *static_load)
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_DETACH:
pthread *thisthread = (pthread *) TlsGetValue (
user_data->threadinterface->thread_self_dwTlsIndex);
if (thisthread) {
/* Some non-pthread call created this thread,
* but we need to clean it up */
thisthread->exit(0);
}
#if 0 // FIXME: REINSTATE SOON
waitq *w;
if ((w = waitq_storage.get ()) != NULL)

View File

@ -12,6 +12,7 @@
#include "winsup.h"
#include "thread.h"
#include "errno.h"
extern "C"
{
@ -173,7 +174,9 @@ pthread_continue (pthread_t thread)
unsigned long
pthread_getsequence_np (pthread_t * thread)
{
return __pthread_getsequence_np (thread);
if (!pthread::isGoodObject (thread))
return EINVAL;
return (*thread)->getsequence_np();
}
/* Thread SpecificData */

View File

@ -283,20 +283,18 @@ MTinterface::Init (int forked)
if (!indexallocated)
{
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!");
else
indexallocated = (-1);
}
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);
pthread::initMainThread(&mainthread, myself->hProcess);
if (forked)
return;
@ -346,11 +344,35 @@ MTinterface::fixup_after_fork (void)
/* pthread calls */
/* static methods */
void
pthread::initMainThread(pthread *mainThread, HANDLE win32_obj_id)
{
mainThread->win32_obj_id = win32_obj_id;
mainThread->setThreadIdtoCurrent ();
setTlsSelfPointer(mainThread);
}
pthread *
pthread::self ()
{
return (pthread *) TlsGetValue (MT_INTERFACE->thread_self_dwTlsIndex);
pthread *temp = (pthread *) TlsGetValue (MT_INTERFACE->thread_self_dwTlsIndex);
if (temp)
return temp;
temp = new pthread ();
temp->precreate (NULL);
if (!temp->magic) {
delete temp;
return pthreadNull::getNullpthread();
}
temp->postcreate ();
return temp;
}
void
pthread::setTlsSelfPointer(pthread *thisThread)
{
/*the OS doesn't check this for <= 64 Tls entries (pre win2k) */
TlsSetValue (MT_INTERFACE->thread_self_dwTlsIndex, thisThread);
}
/* member methods */
@ -368,10 +390,14 @@ pthread::~pthread ()
CloseHandle (cancel_event);
}
void
pthread::setThreadIdtoCurrent ()
{
thread_id = GetCurrentThreadId ();
}
void
pthread::create (void *(*func) (void *), pthread_attr *newattr,
void *threadarg)
pthread::precreate (pthread_attr *newattr)
{
pthread_mutex *verifyable_mutex_obj = &mutex;
@ -386,8 +412,6 @@ pthread::create (void *(*func) (void *), pthread_attr *newattr,
attr.inheritsched = newattr->inheritsched;
attr.stacksize = newattr->stacksize;
}
function = func;
arg = threadarg;
if (verifyable_object_isvalid (&verifyable_mutex_obj, PTHREAD_MUTEX_MAGIC) != VALID_OBJECT)
{
@ -405,6 +429,17 @@ pthread::create (void *(*func) (void *), pthread_attr *newattr,
magic = 0;
return;
}
}
void
pthread::create (void *(*func) (void *), pthread_attr *newattr,
void *threadarg)
{
precreate (newattr);
if (!magic)
return;
function = func;
arg = threadarg;
win32_obj_id = ::CreateThread (&sec_none_nih, attr.stacksize,
(LPTHREAD_START_ROUTINE) thread_init_wrapper,
@ -415,17 +450,22 @@ pthread::create (void *(*func) (void *), pthread_attr *newattr,
thread_printf ("CreateThread failed: this %p LastError %E", this);
magic = 0;
}
else
{
InterlockedIncrement (&MT_INTERFACE->threadcount);
/*FIXME: set the priority appropriately for system contention scope */
if (attr.inheritsched == PTHREAD_EXPLICIT_SCHED)
{
/*FIXME: set the scheduling settings for the new thread */
/*sched_thread_setparam (win32_obj_id, attr.schedparam); */
}
else {
postcreate ();
ResumeThread (win32_obj_id);
}
}
}
void
pthread::postcreate ()
{
InterlockedIncrement (&MT_INTERFACE->threadcount);
/*FIXME: set the priority appropriately for system contention scope */
if (attr.inheritsched == PTHREAD_EXPLICIT_SCHED)
{
/*FIXME: set the scheduling settings for the new thread */
/*sched_thread_setparam (win32_obj_id, attr.schedparam); */
}
}
void
@ -448,6 +488,9 @@ pthread::exit (void *value_ptr)
mutex.UnLock ();
}
/* Prevent DLL_THREAD_DETACH Attempting to clean us up */
setTlsSelfPointer(0);
if (InterlockedDecrement (&MT_INTERFACE->threadcount) == 0)
::exit (0);
else
@ -764,6 +807,18 @@ pthread::pop_all_cleanup_handlers ()
pop_cleanup_handler (1);
}
void
pthread::cancel_self()
{
exit (PTHREAD_CANCELED);
}
DWORD
pthread::getThreadId()
{
return thread_id;
}
pthread_attr::pthread_attr ():verifyable_object (PTHREAD_ATTR_MAGIC),
joinable (PTHREAD_CREATE_JOINABLE), contentionscope (PTHREAD_SCOPE_PROCESS),
inheritsched (PTHREAD_INHERIT_SCHED), stacksize (0)
@ -1278,8 +1333,7 @@ pthread::thread_init_wrapper (void *_arg)
if (!TlsSetValue (MT_INTERFACE->reent_index, &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);
setTlsSelfPointer(thread);
thread->mutex.Lock ();
// if thread is detached force cleanup on exit
@ -1308,6 +1362,20 @@ pthread::thread_init_wrapper (void *_arg)
return 0;
}
bool
pthread::isGoodObject (pthread_t *thread)
{
if (verifyable_object_isvalid (thread, PTHREAD_MAGIC) != VALID_OBJECT)
return false;
return true;
}
unsigned long
pthread::getsequence_np ()
{
return getThreadId ();
}
int
__pthread_create (pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg)
@ -1318,7 +1386,7 @@ __pthread_create (pthread_t *thread, const pthread_attr_t *attr,
*thread = new pthread ();
(*thread)->create (start_routine, attr ? *attr : NULL, arg);
if (verifyable_object_isvalid (thread, PTHREAD_MAGIC) != VALID_OBJECT)
if (!pthread::isGoodObject (thread))
{
delete (*thread);
*thread = NULL;
@ -1355,7 +1423,7 @@ __pthread_once (pthread_once_t *once_control, void (*init_routine) (void))
int
__pthread_cancel (pthread_t thread)
{
if (verifyable_object_isvalid (&thread, PTHREAD_MAGIC) != VALID_OBJECT)
if (!pthread::isGoodObject (&thread))
return ESRCH;
return thread->cancel ();
@ -1642,7 +1710,7 @@ __pthread_join (pthread_t *thread, void **return_val)
*return_val = NULL;
/*FIXME: wait on the thread cancellation event as well - we are a cancellation point*/
if (verifyable_object_isvalid (thread, PTHREAD_MAGIC) != VALID_OBJECT)
if (!pthread::isGoodObject (thread))
return ESRCH;
if (__pthread_equal(thread,&joiner))
@ -1675,7 +1743,7 @@ __pthread_join (pthread_t *thread, void **return_val)
int
__pthread_detach (pthread_t *thread)
{
if (verifyable_object_isvalid (thread, PTHREAD_MAGIC) != VALID_OBJECT)
if (!pthread::isGoodObject (thread))
return ESRCH;
(*thread)->mutex.Lock ();
@ -1706,7 +1774,7 @@ __pthread_detach (pthread_t *thread)
int
__pthread_suspend (pthread_t *thread)
{
if (verifyable_object_isvalid (thread, PTHREAD_MAGIC) != VALID_OBJECT)
if (!pthread::isGoodObject (thread))
return ESRCH;
if ((*thread)->suspended == false)
@ -1722,7 +1790,7 @@ __pthread_suspend (pthread_t *thread)
int
__pthread_continue (pthread_t *thread)
{
if (verifyable_object_isvalid (thread, PTHREAD_MAGIC) != VALID_OBJECT)
if (!pthread::isGoodObject (thread))
return ESRCH;
if ((*thread)->suspended == true)
@ -1746,7 +1814,7 @@ int
__pthread_getschedparam (pthread_t thread, int *policy,
struct sched_param *param)
{
if (verifyable_object_isvalid (&thread, PTHREAD_MAGIC) != VALID_OBJECT)
if (!pthread::isGoodObject (&thread))
return ESRCH;
*policy = SCHED_FIFO;
/*we don't return the current effective priority, we return the current requested
@ -1755,15 +1823,6 @@ __pthread_getschedparam (pthread_t thread, int *policy,
return 0;
}
unsigned long
__pthread_getsequence_np (pthread_t *thread)
{
if (verifyable_object_isvalid (thread, PTHREAD_MAGIC) != VALID_OBJECT)
return EINVAL;
return (*thread)->GetThreadId ();
}
/*Thread SpecificData */
int
__pthread_key_create (pthread_key_t *key, void (*destructor) (void *))
@ -1812,7 +1871,7 @@ int
__pthread_setschedparam (pthread_t thread, int policy,
const struct sched_param *param)
{
if (verifyable_object_isvalid (&thread, PTHREAD_MAGIC) != VALID_OBJECT)
if (!pthread::isGoodObject (&thread))
return ESRCH;
if (policy != SCHED_FIFO)
return ENOTSUP;
@ -2045,7 +2104,7 @@ __pthread_kill (pthread_t thread, int sig)
// lock myself, for the use of thread2signal
// two different kills might clash: FIXME
if (verifyable_object_isvalid (&thread, PTHREAD_MAGIC) != VALID_OBJECT)
if (!pthread::isGoodObject (&thread))
return EINVAL;
if (thread->sigs)
@ -2401,4 +2460,73 @@ __sem_post (sem_t *sem)
return 0;
}
/* pthreadNull */
pthread *
pthreadNull::getNullpthread()
{
/* because of weird entry points */
_instance.magic = 0;
return &_instance;
}
pthreadNull::pthreadNull()
{
/* Mark ourselves as invalid */
magic = 0;
}
pthreadNull::~pthreadNull()
{
}
void
pthreadNull::create (void *(*)(void *), pthread_attr *, void *)
{
}
void
pthreadNull::exit (void *value_ptr)
{
}
int
pthreadNull::cancel ()
{
return 0;
}
void
pthreadNull::testcancel ()
{
}
int
pthreadNull::setcancelstate (int state, int *oldstate)
{
return EINVAL;
}
int
pthreadNull::setcanceltype (int type, int *oldtype)
{
return EINVAL;
}
void
pthreadNull::push_cleanup_handler (__pthread_cleanup_handler *handler)
{
}
void
pthreadNull::pop_cleanup_handler (int const execute)
{
}
unsigned long
pthreadNull::getsequence_np()
{
return 0;
}
pthreadNull pthreadNull::_instance = pthreadNull ();
#endif // MT_SAFE

View File

@ -270,43 +270,35 @@ public:
pthread_t joiner;
// int joinable;
DWORD GetThreadId ()
{
return thread_id;
}
void setThreadIdtoCurrent ()
{
thread_id = GetCurrentThreadId ();
}
/* signal handling */
struct sigaction *sigs;
sigset_t *sigmask;
LONG *sigtodo;
void create (void *(*)(void *), pthread_attr *, void *);
virtual void create (void *(*)(void *), pthread_attr *, void *);
pthread ();
~pthread ();
pthread ();
virtual ~pthread ();
void exit (void *value_ptr);
static void initMainThread(pthread *, HANDLE);
static bool isGoodObject(pthread_t *);
int cancel ();
void testcancel ();
void cancel_self ()
{
exit (PTHREAD_CANCELED);
}
virtual void exit (void *value_ptr);
virtual int cancel ();
virtual void testcancel ();
static void static_cancel_self ();
int setcancelstate (int state, int *oldstate);
int setcanceltype (int type, int *oldtype);
virtual int setcancelstate (int state, int *oldstate);
virtual int setcanceltype (int type, int *oldtype);
void push_cleanup_handler (__pthread_cleanup_handler *handler);
void pop_cleanup_handler (int const execute);
virtual void push_cleanup_handler (__pthread_cleanup_handler *handler);
virtual void pop_cleanup_handler (int const execute);
static pthread* self ();
static void *thread_init_wrapper (void *);
virtual unsigned long getsequence_np();
private:
DWORD thread_id;
__pthread_cleanup_handler *cleanup_stack;
@ -316,6 +308,36 @@ private:
friend int __pthread_detach (pthread_t * thread);
void pop_all_cleanup_handlers (void);
void precreate (pthread_attr *);
void postcreate ();
void setThreadIdtoCurrent();
static void setTlsSelfPointer(pthread *);
void cancel_self ();
DWORD getThreadId ();
};
class pthreadNull : public pthread
{
public:
static pthread *getNullpthread();
~pthreadNull();
/* From pthread These should never get called
* as the ojbect is not verifyable
*/
void create (void *(*)(void *), pthread_attr *, void *);
void exit (void *value_ptr);
int cancel ();
void testcancel ();
int setcancelstate (int state, int *oldstate);
int setcanceltype (int type, int *oldtype);
void push_cleanup_handler (__pthread_cleanup_handler *handler);
void pop_cleanup_handler (int const execute);
unsigned long getsequence_np();
private:
pthreadNull ();
static pthreadNull _instance;
};
class pthread_condattr:public verifyable_object
@ -458,8 +480,6 @@ int __pthread_attr_setstackaddr (pthread_attr_t *, void *);
int __pthread_suspend (pthread_t * thread);
int __pthread_continue (pthread_t * thread);
unsigned long __pthread_getsequence_np (pthread_t * thread);
/* Thread SpecificData */
int __pthread_key_create (pthread_key_t * key, void (*destructor) (void *));
int __pthread_key_delete (pthread_key_t key);