3 #include <pthread/introspection_private.h>
4 #include <dispatch/dispatch.h>
6 #include "darwintest_defaults.h"
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";
15 key_destructor(void *ctx
)
17 T_EXPECT_EQ(ctx
, (void *)value_for_key
, "check value");
21 #define THREAD_COUNT 3
23 static void my_pthread_introspection_hook(unsigned int event
, pthread_t thread
,
24 void *addr
, size_t size
)
26 static atomic_int create_count
;
27 static atomic_int terminate_count
;
28 static atomic_int destroy_count
;
31 pthread_threadid_np(NULL
, &tid
);
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
);
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
);
43 T_ASSERT_GE(create_count
, THREAD_COUNT
, NULL
);
44 T_PASS("Got termination events");
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
);
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");
55 if (prev_pthread_introspection_hook
!= NULL
){
56 prev_pthread_introspection_hook(event
, thread
, addr
, size
);
60 T_DECL(pthread_introspection
, "PR-25679871",
61 T_META_TIMEOUT(30), T_META_ALL_VALID_ARCHS(YES
))
63 prev_pthread_introspection_hook
= pthread_introspection_hook_install(&my_pthread_introspection_hook
);
64 pthread_key_create(&key
, key_destructor
);
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
);
74 dispatch_queue_t serial_queue
= dispatch_queue_create("test queue", NULL
);
75 __block dispatch_block_t looping_block
= ^{
78 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, 50 * NSEC_PER_MSEC
), serial_queue
, looping_block
);
80 T_LOG("Looping block complete");
83 T_LOG("Starting looping block");
84 dispatch_async(serial_queue
, looping_block
);
88 T_FAIL("Why are we still alive?");