[haiku-commits] r41980 - in haiku/branches/developer/bonefish/signals: headers/private/libroot src/system/libroot/posix/pthread

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 6 Jun 2011 20:45:45 +0200 (CEST)

Author: bonefish
Date: 2011-06-06 20:45:44 +0200 (Mon, 06 Jun 2011)
New Revision: 41980
Changeset: https://dev.haiku-os.org/changeset/41980

Modified:
   
haiku/branches/developer/bonefish/signals/headers/private/libroot/pthread_private.h
   
haiku/branches/developer/bonefish/signals/src/system/libroot/posix/pthread/pthread.cpp
   
haiku/branches/developer/bonefish/signals/src/system/libroot/posix/pthread/pthread_cancel.cpp
Log:
* Reimplemented the pthread cancellation functions. The _pthread_thread::cancel*
  fields have been removed. Instead three more flags are used.
* Partially implemented pthread_cancel(). The syscall for asynchronous
  cancellation is still missing, though.


Modified: 
haiku/branches/developer/bonefish/signals/headers/private/libroot/pthread_private.h
===================================================================
--- 
haiku/branches/developer/bonefish/signals/headers/private/libroot/pthread_private.h
 2011-06-06 18:20:38 UTC (rev 41979)
+++ 
haiku/branches/developer/bonefish/signals/headers/private/libroot/pthread_private.h
 2011-06-06 18:45:44 UTC (rev 41980)
@@ -12,8 +12,12 @@
 #include <OS.h>
 
 
-#define THREAD_DETACHED        0x01
-#define THREAD_DEAD            0x02
+// _pthread_thread::flags values
+#define THREAD_DETACHED                                0x01
+#define THREAD_DEAD                                    0x02
+#define THREAD_CANCELED                                0x04
+#define THREAD_CANCEL_ENABLED          0x08
+#define THREAD_CANCEL_ASYNCHRONOUS     0x10
 
 
 struct thread_creation_attributes;
@@ -62,9 +66,6 @@
        void            *(*entry)(void*);
        void            *entry_argument;
        void            *exit_value;
-       int                     cancel_state;
-       int                     cancel_type;
-       bool            cancelled;
        struct pthread_key_data specific[PTHREAD_KEYS_MAX];
        struct __pthread_cleanup_handler *cleanup_handlers;
 } pthread_thread;

Modified: 
haiku/branches/developer/bonefish/signals/src/system/libroot/posix/pthread/pthread.cpp
===================================================================
--- 
haiku/branches/developer/bonefish/signals/src/system/libroot/posix/pthread/pthread.cpp
      2011-06-06 18:20:38 UTC (rev 41979)
+++ 
haiku/branches/developer/bonefish/signals/src/system/libroot/posix/pthread/pthread.cpp
      2011-06-06 18:45:44 UTC (rev 41980)
@@ -85,11 +85,9 @@
        thread->entry = entry;
        thread->entry_argument = data;
        thread->exit_value = NULL;
-       thread->cancel_state = PTHREAD_CANCEL_ENABLE;
-       thread->cancel_type = PTHREAD_CANCEL_DEFERRED;
-       thread->cancelled = false;
        thread->cleanup_handlers = NULL;
-       thread->flags = 0;
+       thread->flags = THREAD_CANCEL_ENABLED;
+               // thread cancellation enabled, but deferred
 
        memset(thread->specific, 0, sizeof(thread->specific));
 }

Modified: 
haiku/branches/developer/bonefish/signals/src/system/libroot/posix/pthread/pthread_cancel.cpp
===================================================================
--- 
haiku/branches/developer/bonefish/signals/src/system/libroot/posix/pthread/pthread_cancel.cpp
       2011-06-06 18:20:38 UTC (rev 41979)
+++ 
haiku/branches/developer/bonefish/signals/src/system/libroot/posix/pthread/pthread_cancel.cpp
       2011-06-06 18:45:44 UTC (rev 41980)
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2011, Ingo Weinhold, ingo_weinhold@xxxxxxx
  * Copyright 2008, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx All rights reserved.
  * Distributed under the terms of the MIT License.
  */
@@ -6,32 +7,67 @@
 
 #include "pthread_private.h"
 
-#include <stdio.h>
 
+static inline void
+test_asynchronous_cancel(int32 flags)
+{
+       static const int32 kFlags = THREAD_CANCELED | THREAD_CANCEL_ENABLED
+               | THREAD_CANCEL_ASYNCHRONOUS;
 
+       if ((~flags & kFlags) == 0)
+               pthread_exit(PTHREAD_CANCELED);
+}
+
+
+// #pragma mark - public API
+
+
 int
 pthread_cancel(pthread_t thread)
 {
-       // TODO: notify thread of being cancelled.
-       fprintf(stderr, "pthread_cancel() is not yet implemented!\n");
-       return EINVAL;
+       // set the canceled flag
+       int32 oldFlags = atomic_or(&thread->flags, THREAD_CANCELED);
+
+       // If the flag was already set, we're done.
+       if ((oldFlags & THREAD_CANCELED) != 0)
+               return 0;
+
+       // check whether the thread is supposed to be canceled asynchronously
+       static const int32 kFlags = THREAD_CANCEL_ENABLED
+               | THREAD_CANCEL_ASYNCHRONOUS;
+
+       if ((~oldFlags & kFlags) == 0) {
+               // TODO: Cancel asynchronously!
+       }
+
+       return 0;
 }
 
 
 int
 pthread_setcancelstate(int state, int *_oldState)
 {
-       if (state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE)
-               return EINVAL;
-
        pthread_thread* thread = pthread_self();
        if (thread == NULL)
                return EINVAL;
 
-       if (_oldState != NULL)
-               *_oldState = thread->cancel_state;
+       // set the new flags
+       int32 oldFlags;
+       if (state == PTHREAD_CANCEL_ENABLE) {
+               oldFlags = atomic_or(&thread->flags, THREAD_CANCEL_ENABLED);
+               test_asynchronous_cancel(oldFlags | THREAD_CANCEL_ENABLED);
+       } else if (state == PTHREAD_CANCEL_DISABLE) {
+               oldFlags = atomic_and(&thread->flags, 
~(int32)THREAD_CANCEL_ENABLED);
+               test_asynchronous_cancel(oldFlags);
+       } else
+               return EINVAL;
 
-       thread->cancel_state = state;
+       // return the old state
+       if (_oldState != NULL) {
+               *_oldState = (oldFlags & PTHREAD_CANCEL_ENABLE) != 0
+                       ? PTHREAD_CANCEL_ENABLE : PTHREAD_CANCEL_DISABLE;
+       }
+
        return 0;
 }
 
@@ -39,17 +75,28 @@
 int
 pthread_setcanceltype(int type, int *_oldType)
 {
-       if (type != PTHREAD_CANCEL_DEFERRED && type != 
PTHREAD_CANCEL_ASYNCHRONOUS)
-               return EINVAL;
-
        pthread_thread* thread = pthread_self();
        if (thread == NULL)
                return EINVAL;
 
-       if (_oldType != NULL)
-               *_oldType = thread->cancel_type;
+       // set the new type
+       int32 oldFlags;
+       if (type == PTHREAD_CANCEL_DEFERRED) {
+               oldFlags = atomic_and(&thread->flags,
+                       ~(int32)THREAD_CANCEL_ASYNCHRONOUS);
+               test_asynchronous_cancel(oldFlags);
+       } else if (type == PTHREAD_CANCEL_ASYNCHRONOUS) {
+               oldFlags = atomic_or(&thread->flags, 
THREAD_CANCEL_ASYNCHRONOUS);
+               test_asynchronous_cancel(oldFlags | THREAD_CANCEL_ASYNCHRONOUS);
+       } else
+               return EINVAL;
 
-       thread->cancel_type = type;
+       // return the old type
+       if (_oldType != NULL) {
+               *_oldType = (oldFlags & THREAD_CANCEL_ASYNCHRONOUS) != 0
+                       ? PTHREAD_CANCEL_ASYNCHRONOUS : PTHREAD_CANCEL_DEFERRED;
+       }
+
        return 0;
 }
 
@@ -61,7 +108,8 @@
        if (thread == NULL)
                return;
 
-       if (thread->cancelled && thread->cancel_state == PTHREAD_CANCEL_ENABLE)
+       static const int32 kFlags = THREAD_CANCELED | THREAD_CANCEL_ENABLED;
+
+       if ((~atomic_get(&thread->flags) & kFlags) == 0)
                pthread_exit(NULL);
 }
-


Other related posts:

  • » [haiku-commits] r41980 - in haiku/branches/developer/bonefish/signals: headers/private/libroot src/system/libroot/posix/pthread - ingo_weinhold