]> git.saurik.com Git - apple/libdispatch.git/blob - testing/dispatch_starfish.c
libdispatch-84.5.3.tar.gz
[apple/libdispatch.git] / testing / dispatch_starfish.c
1 #include <mach/mach.h>
2 #include <mach/mach_time.h>
3 #include <dispatch/dispatch.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <assert.h>
7 #include <TargetConditionals.h>
8
9 #include "dispatch_test.h"
10
11 #if TARGET_OS_EMBEDDED
12 #define COUNT 300ul
13 #define LAPS 10ul
14 #else
15 #define COUNT 1000ul
16 #define LAPS 10ul
17 #endif
18
19 static dispatch_queue_t queues[COUNT];
20 static size_t lap_count_down = LAPS;
21 static size_t count_down;
22 static uint64_t start;
23 static mach_timebase_info_data_t tbi;
24
25 static void do_test(void);
26
27 static void
28 collect(void *context __attribute__((unused)))
29 {
30 uint64_t delta;
31 long double math;
32 size_t i;
33
34 if (--count_down) {
35 return;
36 }
37
38 delta = mach_absolute_time() - start;
39 delta *= tbi.numer;
40 delta /= tbi.denom;
41 math = delta;
42 math /= COUNT * COUNT * 2ul + COUNT * 2ul;
43
44 printf("lap: %ld\n", lap_count_down);
45 printf("count: %lu\n", COUNT);
46 printf("delta: %llu ns\n", delta);
47 printf("math: %Lf ns / lap\n", math);
48
49 for (i = 0; i < COUNT; i++) {
50 dispatch_release(queues[i]);
51 }
52
53 // our malloc could be a lot better,
54 // this result is really a malloc torture test
55 test_long_less_than("Latency" , (unsigned long)math, 1000);
56
57 if (--lap_count_down) {
58 return do_test();
59 }
60
61 // give the threads some time to settle before test_stop() runs "leaks"
62 // ...also note, this is a total cheat. dispatch_after lets this
63 // thread go idle, so dispatch cleans up the continuations cache.
64 // Doign the "old style" sleep left that stuff around and leaks
65 // took a LONG TIME to complete. Long enough that the test harness
66 // decided to kill us.
67 dispatch_after_f(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), NULL, test_stop_after_delay);
68 }
69
70 static void
71 pong(void *context)
72 {
73 dispatch_queue_t this_q = context;
74 size_t replies = (size_t)dispatch_get_context(this_q);
75
76 dispatch_set_context(this_q, (void *)--replies);
77 if (!replies) {
78 //printf("collect from: %s\n", dispatch_queue_get_label(dispatch_get_current_queue()));
79 dispatch_async_f(dispatch_get_main_queue(), NULL, collect);
80 }
81 }
82
83 static void
84 ping(void *context)
85 {
86 dispatch_queue_t reply_q = context;
87
88 dispatch_async_f(reply_q, reply_q, pong);
89 }
90
91 static void
92 start_node(void *context)
93 {
94 dispatch_queue_t this_q = context;
95 size_t i;
96
97 dispatch_set_context(this_q, (void *)COUNT);
98
99 for (i = 0; i < COUNT; i++) {
100 dispatch_async_f(queues[i], this_q, ping);
101 }
102 }
103
104 void
105 do_test(void)
106 {
107 size_t i;
108 kern_return_t kr;
109
110 count_down = COUNT;
111
112 kr = mach_timebase_info(&tbi);
113 assert(kr == 0);
114
115 start = mach_absolute_time();
116
117 for (i = 0; i < COUNT; i++) {
118 char buf[1000];
119 snprintf(buf, sizeof(buf), "com.example.starfish-node#%ld", i);
120 queues[i] = dispatch_queue_create(buf, NULL);
121 dispatch_suspend(queues[i]);
122 }
123
124 for (i = 0; i < COUNT; i++) {
125 dispatch_async_f(queues[i], queues[i], start_node);
126 }
127
128 for (i = 0; i < COUNT; i++) {
129 dispatch_resume(queues[i]);
130 }
131 }
132
133 int
134 main(void)
135 {
136 test_start("Dispatch Starfish");
137
138 do_test();
139
140 dispatch_main();
141 }