]> git.saurik.com Git - apple/libpthread.git/blob - tests/once_cancel.c
libpthread-218.30.1.tar.gz
[apple/libpthread.git] / tests / once_cancel.c
1 #include <pthread.h>
2
3 #include <darwintest.h>
4
5 static volatile int once_invoked = 0;
6
7 static void
8 cancelation_handler(void * __unused arg)
9 {
10 T_LOG("cancelled");
11 }
12
13 __attribute__((noreturn))
14 static void
15 await_cancelation(void)
16 {
17 pthread_cleanup_push(cancelation_handler, NULL);
18 T_LOG("waiting for cancellation");
19
20 // can't use darwintest once cancellation is enabled
21 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
22
23 while (true) {
24 pthread_testcancel();
25 sched_yield();
26 }
27
28 pthread_cleanup_pop(0);
29 }
30
31 static void *
32 await_cancelation_in_once(void *arg)
33 {
34 // disable cancellation until pthread_once to protect darwintest
35 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
36
37 T_LOG("starting the thread");
38 pthread_once_t *once = (pthread_once_t *)arg;
39 pthread_once(once, await_cancelation);
40 return NULL;
41 }
42
43 static void
44 oncef(void)
45 {
46 T_LOG("once invoked");
47 once_invoked++;
48 }
49
50 T_DECL(once_cancel, "pthread_once is re-executed if cancelled")
51 {
52 pthread_once_t once = PTHREAD_ONCE_INIT;
53 pthread_t t;
54 void *join_result = NULL;
55
56 T_ASSERT_POSIX_ZERO(
57 pthread_create(&t, NULL, await_cancelation_in_once, &once), NULL);
58 T_ASSERT_POSIX_ZERO(pthread_cancel(t), NULL);
59 T_ASSERT_POSIX_ZERO(pthread_join(t, &join_result), NULL);
60 T_ASSERT_EQ(join_result, PTHREAD_CANCELED, NULL);
61
62 T_ASSERT_POSIX_ZERO(pthread_once(&once, oncef), NULL);
63 T_ASSERT_EQ(once_invoked, 1, NULL);
64 }