]> git.saurik.com Git - apple/libpthread.git/blob - tests/pthread_introspection.c
libpthread-454.80.2.tar.gz
[apple/libpthread.git] / tests / pthread_introspection.c
1 #include <stdatomic.h>
2 #include <pthread.h>
3 #include <pthread/introspection_private.h>
4 #include <dispatch/dispatch.h>
5
6 #include "darwintest_defaults.h"
7
8 static pthread_introspection_hook_t prev_pthread_introspection_hook;
9 static pthread_key_t key;
10 static atomic_int keys_set;
11 static atomic_int keys_cleared;
12 static const char value_for_key[] = "used as a TSD value";
13
14 static void
15 key_destructor(void *ctx)
16 {
17 T_EXPECT_EQ(ctx, (void *)value_for_key, "check value");
18 keys_cleared++;
19 }
20
21 #define THREAD_COUNT 3
22
23 static void my_pthread_introspection_hook(unsigned int event, pthread_t thread,
24 void *addr, size_t size)
25 {
26 static atomic_int create_count;
27 static atomic_int terminate_count;
28 static atomic_int destroy_count;
29
30 uint64_t tid;
31 pthread_threadid_np(NULL, &tid);
32
33 switch (event) {
34 case PTHREAD_INTROSPECTION_THREAD_CREATE:
35 atomic_fetch_add(&keys_set, 1);
36 pthread_introspection_setspecific_np(thread, key, value_for_key);
37 T_LOG("event = PTHREAD_INTROSPECTION_THREAD_CREATE, thread = %p:%lld, addr = %p, size = 0x%zx", thread, tid, addr, size);
38 create_count++;
39 break;
40 case PTHREAD_INTROSPECTION_THREAD_TERMINATE:
41 T_LOG("event = PTHREAD_INTROSPECTION_THREAD_TERMINATE, thread = %p:%lld, addr = %p, size = 0x%zx", thread, tid, addr, size);
42 terminate_count++;
43 T_ASSERT_GE(create_count, THREAD_COUNT, NULL);
44 T_PASS("Got termination events");
45 break;
46 case PTHREAD_INTROSPECTION_THREAD_DESTROY:
47 T_LOG("event = PTHREAD_INTROSPECTION_THREAD_DESTROY, thread = %p:%lld, addr = %p, size = 0x%zx", thread, tid, addr, size);
48 destroy_count++;
49 T_ASSERT_NULL(pthread_introspection_getspecific_np(thread, key), "should have cleared");
50 T_ASSERT_NE(keys_cleared, 0, "should have cleared a key");
51 T_PASS("Got destruction events");
52 T_END;
53 }
54
55 if (prev_pthread_introspection_hook != NULL){
56 prev_pthread_introspection_hook(event, thread, addr, size);
57 }
58 }
59
60 T_DECL(pthread_introspection, "PR-25679871",
61 T_META_TIMEOUT(30), T_META_ALL_VALID_ARCHS(YES))
62 {
63 prev_pthread_introspection_hook = pthread_introspection_hook_install(&my_pthread_introspection_hook);
64 pthread_key_create(&key, key_destructor);
65
66 // minus one that comes after this block
67 for (int i = 0; i < THREAD_COUNT - 1; i++) {
68 T_LOG("Creating dispatch_async thread %d.", i);
69 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
70 T_LOG("Started dispatch_async thread %d.", i);
71 sleep(3);
72 });
73 }
74 dispatch_queue_t serial_queue = dispatch_queue_create("test queue", NULL);
75 __block dispatch_block_t looping_block = ^{
76 static int count;
77 if (count++ < 20) {
78 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 50 * NSEC_PER_MSEC), serial_queue, looping_block);
79 } else {
80 T_LOG("Looping block complete");
81 }
82 };
83 T_LOG("Starting looping block");
84 dispatch_async(serial_queue, looping_block);
85
86 sleep(30);
87
88 T_FAIL("Why are we still alive?");
89 }