]> git.saurik.com Git - apple/libpthread.git/blob - tests/cond_timed.c
318b4065281b4635512948728ae2d5655a8a9b76
[apple/libpthread.git] / tests / cond_timed.c
1 #include <assert.h>
2 #include <pthread.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include <stdbool.h>
8 #include <errno.h>
9 #include <sys/time.h>
10 #include <libkern/OSAtomic.h>
11 #include <dispatch/dispatch.h>
12
13 struct context {
14 pthread_cond_t cond;
15 pthread_mutex_t mutex;
16 long udelay;
17 long count;
18 };
19
20 void *wait_thread(void *ptr) {
21 int res;
22 struct context *context = ptr;
23
24 int i = 0;
25 char *str;
26
27 bool loop = true;
28 while (loop) {
29 struct timespec ts;
30 struct timeval tv;
31 gettimeofday(&tv, NULL);
32 uint64_t ns = tv.tv_usec * NSEC_PER_USEC + context->udelay * NSEC_PER_USEC;
33 ts.tv_nsec = ns >= NSEC_PER_SEC ? ns % NSEC_PER_SEC : ns;
34 ts.tv_sec = tv.tv_sec + (ns >= NSEC_PER_SEC ? ns / NSEC_PER_SEC : 0);
35
36 res = pthread_mutex_lock(&context->mutex);
37 if (res) {
38 fprintf(stderr, "[%ld] pthread_mutex_lock: %s\n", context->count, strerror(res));
39 abort();
40 }
41
42 if (context->count > 0) {
43 res = pthread_cond_timedwait(&context->cond, &context->mutex, &ts);
44 if (res != ETIMEDOUT) {
45 fprintf(stderr, "[%ld] pthread_cond_timedwait: %s\n", context->count, strerror(res));
46 abort();
47 }
48 --context->count;
49 } else {
50 loop = false;
51 }
52
53 res = pthread_mutex_unlock(&context->mutex);
54 if (res) {
55 fprintf(stderr, "[%ld] pthread_mutex_unlock: %s\n", context->count, strerror(res));
56 abort();
57 }
58 }
59
60 return NULL;
61 }
62
63 int main(int argc, char *argv[])
64 {
65 const int threads = 8;
66 struct context context = {
67 .cond = PTHREAD_COND_INITIALIZER,
68 .mutex = PTHREAD_MUTEX_INITIALIZER,
69 .udelay = 5000,
70 .count = 8000,
71 };
72 int i;
73 int res;
74
75 uint64_t uexpected = (context.udelay * context.count) / threads;
76 printf("waittime expected: %llu us\n", uexpected);
77 struct timeval start, end;
78 gettimeofday(&start, NULL);
79
80 pthread_t p[threads];
81 for (i = 0; i < threads; ++i) {
82 res = pthread_create(&p[i], NULL, wait_thread, &context);
83 assert(res == 0);
84 }
85
86 usleep(uexpected);
87 bool loop = true;
88 while (loop) {
89 res = pthread_mutex_lock(&context.mutex);
90 if (res) {
91 fprintf(stderr, "[%ld] pthread_mutex_lock: %s\n", context.count, strerror(res));
92 abort();
93 }
94 if (context.count <= 0) {
95 loop = false;
96 }
97 res = pthread_mutex_unlock(&context.mutex);
98 if (res) {
99 fprintf(stderr, "[%ld] pthread_mutex_unlock: %s\n", context.count, strerror(res));
100 abort();
101 }
102 }
103
104 for (i = 0; i < threads; ++i) {
105 res = pthread_join(p[i], NULL);
106 assert(res == 0);
107 }
108
109 gettimeofday(&end, NULL);
110 uint64_t uelapsed = (end.tv_sec * USEC_PER_SEC + end.tv_usec) -
111 (start.tv_sec * USEC_PER_SEC + start.tv_usec);
112 printf("waittime actual: %llu us\n", uelapsed);
113
114 return 0;
115 }