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

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

Author: bonefish
Date: 2011-06-06 22:37:05 +0200 (Mon, 06 Jun 2011)
New Revision: 41984
Changeset: https://dev.haiku-os.org/changeset/41984

Modified:
   haiku/branches/developer/bonefish/signals/headers/private/kernel/ksignal.h
   haiku/branches/developer/bonefish/signals/headers/private/kernel/thread.h
   
haiku/branches/developer/bonefish/signals/headers/private/kernel/thread_types.h
   haiku/branches/developer/bonefish/signals/headers/private/system/syscalls.h
   haiku/branches/developer/bonefish/signals/src/system/kernel/signal.cpp
   haiku/branches/developer/bonefish/signals/src/system/kernel/thread.cpp
   
haiku/branches/developer/bonefish/signals/src/system/libroot/posix/pthread/pthread_cancel.cpp
Log:
* Added syscall _kern_cancel_thread() for asynchronous thread cancellation.
* Added Thread::cancel_function, which temporarily stores the function to be
  called upon thread cancellation.
* Added kernel-internal signal SIGNAL_CANCEL_THREAD which is used to deliver the
  message. It is handled by invoking Thread::cancel_function as a signal
  handler.
* Finished implementation of pthread_cancel().

Asynchronous thread cancellation should work now.


Modified: 
haiku/branches/developer/bonefish/signals/headers/private/kernel/ksignal.h
===================================================================
--- haiku/branches/developer/bonefish/signals/headers/private/kernel/ksignal.h  
2011-06-06 20:34:52 UTC (rev 41983)
+++ haiku/branches/developer/bonefish/signals/headers/private/kernel/ksignal.h  
2011-06-06 20:37:05 UTC (rev 41984)
@@ -35,9 +35,12 @@
 
 #define SYSCALL_RESTART_PARAMETER_SIZE 32
 
-// Kernel internal signal to continue a thread. Used by resume_thread().
-// Non-blockable, prevents syscall restart.
+// kernel-internal signals
+#define SIGNAL_CANCEL_THREAD   63
+       // Cancel a thread. Non-blockable.
 #define SIGNAL_CONTINUE_THREAD 64
+       // Continue a thread. Used by resume_thread(). Non-blockable, prevents
+       // syscall restart.
 
 
 struct signal_frame_data {

Modified: 
haiku/branches/developer/bonefish/signals/headers/private/kernel/thread.h
===================================================================
--- haiku/branches/developer/bonefish/signals/headers/private/kernel/thread.h   
2011-06-06 20:34:52 UTC (rev 41983)
+++ haiku/branches/developer/bonefish/signals/headers/private/kernel/thread.h   
2011-06-06 20:37:05 UTC (rev 41984)
@@ -149,6 +149,7 @@
 status_t _user_snooze_etc(bigtime_t timeout, int timebase, uint32 flags,
        bigtime_t* _remainingTime);
 status_t _user_kill_thread(thread_id thread);
+status_t _user_cancel_thread(thread_id threadID, void (*cancelFunction)(int));
 void _user_thread_yield(void);
 void _user_exit_thread(status_t return_value);
 bool _user_has_data(thread_id thread);

Modified: 
haiku/branches/developer/bonefish/signals/headers/private/kernel/thread_types.h
===================================================================
--- 
haiku/branches/developer/bonefish/signals/headers/private/kernel/thread_types.h 
    2011-06-06 20:34:52 UTC (rev 41983)
+++ 
haiku/branches/developer/bonefish/signals/headers/private/kernel/thread_types.h 
    2011-06-06 20:37:05 UTC (rev 41984)
@@ -450,6 +450,8 @@
                                                                                
// modified by the thread itself and
                                                                                
// thus freely readable by it
 
+       void                    (*cancel_function)(int);
+
        struct {
                uint8           parameters[SYSCALL_RESTART_PARAMETER_SIZE];
        } syscall_restart;

Modified: 
haiku/branches/developer/bonefish/signals/headers/private/system/syscalls.h
===================================================================
--- haiku/branches/developer/bonefish/signals/headers/private/system/syscalls.h 
2011-06-06 20:34:52 UTC (rev 41983)
+++ haiku/branches/developer/bonefish/signals/headers/private/system/syscalls.h 
2011-06-06 20:37:05 UTC (rev 41984)
@@ -157,6 +157,8 @@
                                                int32 newPriority);
 extern status_t                _kern_kill_thread(thread_id thread);
 extern void                    _kern_exit_thread(status_t returnValue);
+extern status_t                _kern_cancel_thread(thread_id threadID,
+                                               void (*cancelFunction)(int));
 extern void                    _kern_thread_yield(void);
 extern status_t                _kern_wait_for_thread(thread_id thread,
                                                status_t *_returnCode);

Modified: haiku/branches/developer/bonefish/signals/src/system/kernel/signal.cpp
===================================================================
--- haiku/branches/developer/bonefish/signals/src/system/kernel/signal.cpp      
2011-06-06 20:34:52 UTC (rev 41983)
+++ haiku/branches/developer/bonefish/signals/src/system/kernel/signal.cpp      
2011-06-06 20:37:05 UTC (rev 41984)
@@ -42,8 +42,10 @@
 #endif
 
 
-#define BLOCKABLE_SIGNALS              (~(KILL_SIGNALS | 
SIGNAL_TO_MASK(SIGSTOP) \
-                                                                       | 
SIGNAL_TO_MASK(SIGNAL_CONTINUE_THREAD)))
+#define BLOCKABLE_SIGNALS      \
+       (~(KILL_SIGNALS | SIGNAL_TO_MASK(SIGSTOP)       \
+       | SIGNAL_TO_MASK(SIGNAL_CONTINUE_THREAD)        \
+       | SIGNAL_TO_MASK(SIGNAL_CANCEL_THREAD)))
 #define STOP_SIGNALS \
        (SIGNAL_TO_MASK(SIGSTOP) | SIGNAL_TO_MASK(SIGTSTP) \
        | SIGNAL_TO_MASK(SIGTTIN) | SIGNAL_TO_MASK(SIGTTOU))
@@ -127,7 +129,7 @@
        {"invalid 60",          0},
        {"invalid 61",          0},
        {"invalid 62",          0},
-       {"invalid 63",          0},
+       {"CANCEL_THREAD",       0},
        {"CONTINUE_THREAD",     0}      // priority must be <= that of SIGSTOP
 };
 
@@ -1031,6 +1033,14 @@
                                                notify_debugger(thread, signal, 
handler, false);
                                        continue;
 
+                               case SIGNAL_CANCEL_THREAD:
+                                       // set up the signal handler
+                                       handler.sa_handler = 
thread->cancel_function;
+                                       handler.sa_flags = 0;
+                                       handler.sa_mask = 0;
+                                       handler.sa_userdata = NULL;
+                                       break;
+
                                case SIGNAL_CONTINUE_THREAD:
                                        // prevent syscall restart, but 
otherwise ignore
                                        restart = false;

Modified: haiku/branches/developer/bonefish/signals/src/system/kernel/thread.cpp
===================================================================
--- haiku/branches/developer/bonefish/signals/src/system/kernel/thread.cpp      
2011-06-06 20:34:52 UTC (rev 41983)
+++ haiku/branches/developer/bonefish/signals/src/system/kernel/thread.cpp      
2011-06-06 20:37:05 UTC (rev 41984)
@@ -3326,6 +3326,33 @@
 
 
 status_t
+_user_cancel_thread(thread_id threadID, void (*cancelFunction)(int))
+{
+       // check the cancel function
+       if (cancelFunction == NULL || !IS_USER_ADDRESS(cancelFunction))
+               return B_BAD_VALUE;
+
+       // get and lock the thread
+       Thread* thread = Thread::GetAndLock(threadID);
+       if (thread == NULL)
+               return B_BAD_THREAD_ID;
+       BReference<Thread> threadReference(thread, true);
+       ThreadLocker threadLocker(thread, true);
+
+       // only threads of the same team can be canceled
+       if (thread->team != thread_get_current_thread()->team)
+               return B_NOT_ALLOWED;
+
+       // set the cancel function
+       thread->cancel_function = cancelFunction;
+
+       // send the cancellation signal to the thread
+       InterruptsSpinLocker schedulerLocker(gSchedulerLock);
+       return send_signal_to_thread_locked(thread, SIGNAL_CANCEL_THREAD, NULL, 
0);
+}
+
+
+status_t
 _user_resume_thread(thread_id thread)
 {
        // TODO: Don't allow kernel threads to be resumed!

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 20:34:52 UTC (rev 41983)
+++ 
haiku/branches/developer/bonefish/signals/src/system/libroot/posix/pthread/pthread_cancel.cpp
       2011-06-06 20:37:05 UTC (rev 41984)
@@ -7,7 +7,9 @@
 
 #include "pthread_private.h"
 
+#include <syscalls.h>
 
+
 static inline void
 test_asynchronous_cancel(int32 flags)
 {
@@ -19,6 +21,17 @@
 }
 
 
+/*!    Invoked when the thread is canceled asynchronously.
+       Has the simple signal handler signature, since it is invoked just like a
+       signal handler.
+*/
+static void
+asynchronous_cancel_thread(int)
+{
+       pthread_exit(PTHREAD_CANCELED);
+}
+
+
 // #pragma mark - public API
 
 
@@ -36,9 +49,8 @@
        static const int32 kFlags = THREAD_CANCEL_ENABLED
                | THREAD_CANCEL_ASYNCHRONOUS;
 
-       if ((~oldFlags & kFlags) == 0) {
-               // TODO: Cancel asynchronously!
-       }
+       if ((~oldFlags & kFlags) == 0)
+               return _kern_cancel_thread(thread->id, 
&asynchronous_cancel_thread);
 
        return 0;
 }


Other related posts:

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