Assorted whitespace cleanup and typo fixes.
[haiku.git] / src / system / libroot / posix / pthread / pthread_cancel.cpp
blob5627b670ba7af0408e59f9b458e06b19c0ab11a8
1 /*
2 * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
4 * Distributed under the terms of the MIT License.
5 */
8 #include "pthread_private.h"
10 #include <syscalls.h>
13 static inline void
14 test_asynchronous_cancel(int32 flags)
16 static const int32 kFlags = THREAD_CANCELED | THREAD_CANCEL_ENABLED
17 | THREAD_CANCEL_ASYNCHRONOUS;
19 if ((~flags & kFlags) == 0)
20 pthread_exit(PTHREAD_CANCELED);
24 /*! Signal handler like function invoked when this thread has been canceled.
25 Has the simple signal handler signature, since it is invoked just like a
26 signal handler.
28 static void
29 asynchronous_cancel_thread(int)
31 pthread_t thread = pthread_self();
33 // Exit when asynchronous cancellation is enabled, otherwise we don't have
34 // to do anything -- the syscall interrupting side effect is all we need.
35 if ((atomic_get(&thread->flags) & THREAD_CANCEL_ASYNCHRONOUS) != 0)
36 pthread_exit(PTHREAD_CANCELED);
40 // #pragma mark - public API
43 int
44 pthread_cancel(pthread_t thread)
46 // set the canceled flag
47 int32 oldFlags = atomic_or(&thread->flags, THREAD_CANCELED);
49 // If the flag was already set, we're done.
50 if ((oldFlags & THREAD_CANCELED) != 0)
51 return 0;
53 // If cancellation is enabled, notify the thread. This will call the
54 // asynchronous_cancel_thread() handler.
55 if ((oldFlags & THREAD_CANCEL_ENABLED) != 0)
56 return _kern_cancel_thread(thread->id, &asynchronous_cancel_thread);
58 return 0;
62 int
63 pthread_setcancelstate(int state, int *_oldState)
65 pthread_thread* thread = pthread_self();
66 if (thread == NULL)
67 return EINVAL;
69 // set the new flags
70 int32 oldFlags;
71 if (state == PTHREAD_CANCEL_ENABLE) {
72 oldFlags = atomic_or(&thread->flags, THREAD_CANCEL_ENABLED);
73 test_asynchronous_cancel(oldFlags | THREAD_CANCEL_ENABLED);
74 } else if (state == PTHREAD_CANCEL_DISABLE) {
75 oldFlags = atomic_and(&thread->flags, ~(int32)THREAD_CANCEL_ENABLED);
76 test_asynchronous_cancel(oldFlags);
77 } else
78 return EINVAL;
80 // return the old state
81 if (_oldState != NULL) {
82 *_oldState = (oldFlags & PTHREAD_CANCEL_ENABLE) != 0
83 ? PTHREAD_CANCEL_ENABLE : PTHREAD_CANCEL_DISABLE;
86 return 0;
90 int
91 pthread_setcanceltype(int type, int *_oldType)
93 pthread_thread* thread = pthread_self();
94 if (thread == NULL)
95 return EINVAL;
97 // set the new type
98 int32 oldFlags;
99 if (type == PTHREAD_CANCEL_DEFERRED) {
100 oldFlags = atomic_and(&thread->flags,
101 ~(int32)THREAD_CANCEL_ASYNCHRONOUS);
102 test_asynchronous_cancel(oldFlags);
103 } else if (type == PTHREAD_CANCEL_ASYNCHRONOUS) {
104 oldFlags = atomic_or(&thread->flags, THREAD_CANCEL_ASYNCHRONOUS);
105 test_asynchronous_cancel(oldFlags | THREAD_CANCEL_ASYNCHRONOUS);
106 } else
107 return EINVAL;
109 // return the old type
110 if (_oldType != NULL) {
111 *_oldType = (oldFlags & THREAD_CANCEL_ASYNCHRONOUS) != 0
112 ? PTHREAD_CANCEL_ASYNCHRONOUS : PTHREAD_CANCEL_DEFERRED;
115 return 0;
119 void
120 pthread_testcancel(void)
122 pthread_thread* thread = pthread_self();
123 if (thread == NULL)
124 return;
126 static const int32 kFlags = THREAD_CANCELED | THREAD_CANCEL_ENABLED;
128 if ((~atomic_get(&thread->flags) & kFlags) == 0)
129 pthread_exit(NULL);