]> git.saurik.com Git - apple/libpthread.git/blob - tests/rdar_32848402.c
65cd56e5395b34dc455b18a7922ecf21dbc4bdb5
[apple/libpthread.git] / tests / rdar_32848402.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <dispatch/dispatch.h>
4 #include <dispatch/private.h>
5 #include <sys/time.h>
6 #include <sys/sysctl.h>
7
8 #include "darwintest_defaults.h"
9 #include <darwintest_utils.h>
10
11 static uint64_t end_spin;
12
13 static uint32_t
14 get_ncpu(void)
15 {
16 static uint32_t activecpu;
17 if (!activecpu) {
18 uint32_t n;
19 size_t s = sizeof(activecpu);
20 sysctlbyname("hw.activecpu", &n, &s, NULL, 0);
21 activecpu = n;
22 }
23 return activecpu;
24 }
25
26 static void
27 spin_and_pause(void *ctx)
28 {
29 long i = (long)ctx;
30
31 printf("Thread %ld starts\n", i);
32
33 while (clock_gettime_nsec_np(CLOCK_MONOTONIC) < end_spin) {
34 #if defined(__x86_64__) || defined(__i386__)
35 __asm__("pause");
36 #elif defined(__arm__) || defined(__arm64__)
37 __asm__("wfe");
38 #endif
39 }
40 printf("Thread %ld blocks\n", i);
41 pause();
42 }
43
44 static void
45 spin(void *ctx)
46 {
47 long i = (long)ctx;
48
49 printf("Thread %ld starts\n", i);
50
51 while (clock_gettime_nsec_np(CLOCK_MONOTONIC)) {
52 #if defined(__x86_64__) || defined(__i386__)
53 __asm__("pause");
54 #elif defined(__arm__) || defined(__arm64__)
55 __asm__("wfe");
56 #endif
57 }
58 }
59
60 T_DECL(thread_request_32848402, "repro for rdar://32848402")
61 {
62 dispatch_queue_attr_t bg_attr, in_attr;
63
64 bg_attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT,
65 QOS_CLASS_BACKGROUND, 0);
66 in_attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT,
67 QOS_CLASS_USER_INITIATED, 0);
68
69 dispatch_queue_t a = dispatch_queue_create_with_target("in", in_attr, NULL);
70 dispatch_queue_t b = dispatch_queue_create_with_target("bg", bg_attr, NULL);
71
72 end_spin = clock_gettime_nsec_np(CLOCK_MONOTONIC) + 2 * NSEC_PER_SEC;
73
74 dispatch_async_f(a, (void *)0, spin_and_pause);
75 for (long i = 1; i < get_ncpu(); i++) {
76 dispatch_async_f(b, (void *)i, spin);
77 }
78
79 dispatch_async(b, ^{
80 T_PASS("The NCPU+1-nth block got scheduled");
81 T_END;
82 });
83
84 sleep(10);
85 T_FAIL("The NCPU+1-nth block didn't get scheduled");
86 }