10 #include <libkern/OSAtomic.h>
11 #include <dispatch/dispatch.h>
15 pthread_mutex_t mutex
;
20 void *wait_thread(void *ptr
) {
22 struct context
*context
= ptr
;
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);
36 res
= pthread_mutex_lock(&context
->mutex
);
38 fprintf(stderr
, "[%ld] pthread_mutex_lock: %s\n", context
->count
, strerror(res
));
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
));
53 res
= pthread_mutex_unlock(&context
->mutex
);
55 fprintf(stderr
, "[%ld] pthread_mutex_unlock: %s\n", context
->count
, strerror(res
));
63 int main(int argc
, char *argv
[])
65 const int threads
= 8;
66 struct context context
= {
67 .cond
= PTHREAD_COND_INITIALIZER
,
68 .mutex
= PTHREAD_MUTEX_INITIALIZER
,
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
);
81 for (i
= 0; i
< threads
; ++i
) {
82 res
= pthread_create(&p
[i
], NULL
, wait_thread
, &context
);
89 res
= pthread_mutex_lock(&context
.mutex
);
91 fprintf(stderr
, "[%ld] pthread_mutex_lock: %s\n", context
.count
, strerror(res
));
94 if (context
.count
<= 0) {
97 res
= pthread_mutex_unlock(&context
.mutex
);
99 fprintf(stderr
, "[%ld] pthread_mutex_unlock: %s\n", context
.count
, strerror(res
));
104 for (i
= 0; i
< threads
; ++i
) {
105 res
= pthread_join(p
[i
], NULL
);
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
);