OSDN Git Service

2002-09-11 Robert Collins <rbtcollins@hotmail.com>
authorrbcollins <rbcollins>
Mon, 16 Sep 2002 10:53:29 +0000 (10:53 +0000)
committerrbcollins <rbcollins>
Mon, 16 Sep 2002 10:53:29 +0000 (10:53 +0000)
        * 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.

winsup/cygwin/ChangeLog
winsup/cygwin/init.cc
winsup/cygwin/pthread.cc
winsup/cygwin/thread.cc
winsup/cygwin/thread.h

index 8e375a9..e7afe62 100644 (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.
index 525ec29..2e08f11 100644 (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)
index 0484f04..d7c8fcc 100644 (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 */
index 618fa7a..3d9c40b 100644 (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
index a00ad90..ce45850 100644 (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 ();
+   virtual ~pthread ();
 
-    pthread ();
-   ~pthread ();
+   static void initMainThread(pthread *, HANDLE);
+   static bool isGoodObject(pthread_t *);
 
-   void exit (void *value_ptr);
+   virtual void exit (void *value_ptr);
 
-   int cancel ();
-   void testcancel ();
-   void cancel_self ()
-   {
-     exit (PTHREAD_CANCELED);
-   }
+   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);