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.
8 #include "pthread_private.h"
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
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
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)
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
);
63 pthread_setcancelstate(int state
, int *_oldState
)
65 pthread_thread
* thread
= pthread_self();
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
);
80 // return the old state
81 if (_oldState
!= NULL
) {
82 *_oldState
= (oldFlags
& PTHREAD_CANCEL_ENABLE
) != 0
83 ? PTHREAD_CANCEL_ENABLE
: PTHREAD_CANCEL_DISABLE
;
91 pthread_setcanceltype(int type
, int *_oldType
)
93 pthread_thread
* thread
= pthread_self();
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
);
109 // return the old type
110 if (_oldType
!= NULL
) {
111 *_oldType
= (oldFlags
& THREAD_CANCEL_ASYNCHRONOUS
) != 0
112 ? PTHREAD_CANCEL_ASYNCHRONOUS
: PTHREAD_CANCEL_DEFERRED
;
120 pthread_testcancel(void)
122 pthread_thread
* thread
= pthread_self();
126 static const int32 kFlags
= THREAD_CANCELED
| THREAD_CANCEL_ENABLED
;
128 if ((~atomic_get(&thread
->flags
) & kFlags
) == 0)