[prev in list] [next in list] [prev in thread] [next in thread] 

List:       cygwin-patches
Subject:    [PATCH] cancellation revised
From:       Thomas Pfaff <tpfaff () gmx ! net>
Date:       2002-12-20 9:57:37
[Download RAW message or body]

While Chris is waiting on Rob (or vice versa) i got a new pthread related
patch which will make pthread_join and sem_wait real cancellation points.

TODO: Add testcancel to other cancelation points.

Thomas

2002-12-20  Thomas Pfaff  <tpfaff@gmx.net>

	* thread.h (WAIT_CANCELED): New define.
	(pthread::cancelable_wait): New static method.
	* thread.cc (pthread::cancelable_wait): Implement.
	(semaphore::Wait): Wait on semaphore and thread cancellation.
	(pthread::join): Wait on joined thread and thread cancellation.
	(semaphore::wait): Add testcancel to check for thread cancellation
	even if the semaphore is available.

["cancel.patch" (TEXT/plain)]

diff -urp src.old/winsup/cygwin/thread.cc src/winsup/cygwin/thread.cc
--- src.old/winsup/cygwin/thread.cc	2002-12-11 11:10:28.000000000 +0100
+++ src/winsup/cygwin/thread.cc	2002-12-20 09:37:11.000000000 +0100
@@ -471,7 +471,7 @@ pwrite ()
 read ()
 readv ()
 select ()
-sem_wait ()
+*sem_wait ()
 sigpause ()
 sigsuspend ()
 sigtimedwait ()
@@ -632,6 +632,27 @@ pthread::static_cancel_self (void)
 }
 
 
+DWORD pthread::cancelable_wait (HANDLE object, DWORD timeout, const bool do_cancel)
+{
+  DWORD res;
+  HANDLE wait_objects[2];
+  pthread_t thread = self ();
+
+  if (!isGoodObject (&thread) || thread->cancelstate == PTHREAD_CANCEL_DISABLE)
+    return WaitForSingleObject (object, timeout);
+
+  // Do not change the wait order
+  // The object must have higher priority than the cancel event,
+  // that means WaitForMultipleObjects signales the smallest index
+  wait_objects[0] = object;
+  wait_objects[1] = thread->cancel_event;
+
+  res = WaitForMultipleObjects (2, wait_objects, FALSE, timeout);
+  if (do_cancel && res == WAIT_CANCELED)
+    pthread::static_cancel_self ();
+  return res;
+}
+
 int
 pthread::setcancelstate (int state, int *oldstate)
 {
@@ -1390,8 +1411,15 @@ semaphore::TryWait ()
 void
 semaphore::Wait ()
 {
-  WaitForSingleObject (win32_obj_id, INFINITE);
-  currentvalue--;
+  switch (pthread::cancelable_wait (win32_obj_id, INFINITE))
+    {
+    case WAIT_OBJECT_0:
+      currentvalue--;
+      break;
+    default:
+      debug_printf ("cancelable_wait failed. %E");
+      return;
+    }
 }
 
 void
@@ -1850,14 +1878,15 @@ pthread::join (pthread_t *thread, void *
 {
    pthread_t joiner = self ();
 
-   if (!isGoodObject (&joiner))
-     return EINVAL;
+   joiner->testcancel ();
 
    // Initialize return val with NULL
    if (return_val)
      *return_val = NULL;
 
-  /* FIXME: wait on the thread cancellation event as well - we are a cancellation point*/
+   if (!isGoodObject (&joiner))
+     return EINVAL;
+
   if (!isGoodObject (thread))
     return ESRCH;
 
@@ -1876,14 +1905,26 @@ pthread::join (pthread_t *thread, void *
       (*thread)->joiner = joiner;
       (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED;
       (*thread)->mutex.UnLock ();
-      WaitForSingleObject ((*thread)->win32_obj_id, INFINITE);
-      if (return_val)
-	 *return_val = (*thread)->return_ptr;
-      // cleanup
-      delete (*thread);
-    }	/* End if */
 
-  pthread_testcancel ();
+      switch (cancelable_wait ((*thread)->win32_obj_id, INFINITE, false))
+        {
+        case WAIT_OBJECT_0:
+          if (return_val)
+            *return_val = (*thread)->return_ptr;
+          delete (*thread);
+          break;
+        case WAIT_CANCELED:
+          // set joined thread back to joinable since we got canceled
+          (*thread)->joiner = NULL;
+          (*thread)->attr.joinable = PTHREAD_CREATE_JOINABLE;
+          joiner->cancel_self ();
+          // never reached
+          break;
+        default:
+          // should never happen
+          return EINVAL;
+        }
+    }
 
   return 0;
 }
@@ -2629,6 +2670,8 @@ semaphore::destroy (sem_t *sem)
 int
 semaphore::wait (sem_t *sem)
 {
+  pthread::self ()->testcancel ();
+
   if (!isGoodObject (sem))
     {
       set_errno (EINVAL);
diff -urp src.old/winsup/cygwin/thread.h src/winsup/cygwin/thread.h
--- src.old/winsup/cygwin/thread.h	2002-12-10 14:38:23.000000000 +0100
+++ src/winsup/cygwin/thread.h	2002-12-20 09:37:13.000000000 +0100
@@ -332,6 +332,8 @@ private:
   static nativeMutex mutexInitializationLock;
 };
 
+#define WAIT_CANCELED   (WAIT_OBJECT_0 + 1)
+
 class pthread:public verifyable_object
 {
 public:
@@ -379,6 +381,8 @@ public:
   virtual void testcancel ();
   static void static_cancel_self ();
 
+  static DWORD cancelable_wait (HANDLE object, DWORD timeout, const bool do_cancel = true);
+
   virtual int setcancelstate (int state, int *oldstate);
   virtual int setcanceltype (int type, int *oldtype);
 


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic