]> git.saurik.com Git - apple/libpthread.git/blame - tests/once_cancel.c
libpthread-416.40.3.tar.gz
[apple/libpthread.git] / tests / once_cancel.c
CommitLineData
2546420a
A
1#include <pthread.h>
2
a0619f9c 3#include "darwintest_defaults.h"
2546420a
A
4
5static volatile int once_invoked = 0;
6
7static void
8cancelation_handler(void * __unused arg)
9{
10 T_LOG("cancelled");
11}
12
13__attribute__((noreturn))
14static void
15await_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
31static void *
32await_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
43static void
44oncef(void)
45{
46 T_LOG("once invoked");
47 once_invoked++;
48}
49
50T_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}