]> git.saurik.com Git - apple/libpthread.git/blame - tests/cond_timed.c
libpthread-218.1.3.tar.gz
[apple/libpthread.git] / tests / cond_timed.c
CommitLineData
964d3577
A
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
2546420a
A
13#include <darwintest.h>
14
15#define NUM_THREADS 8
16
964d3577
A
17struct context {
18 pthread_cond_t cond;
19 pthread_mutex_t mutex;
20 long udelay;
21 long count;
22};
23
2546420a 24static void *wait_thread(void *ptr) {
964d3577
A
25 int res;
26 struct context *context = ptr;
27
964d3577
A
28 bool loop = true;
29 while (loop) {
30 struct timespec ts;
31 struct timeval tv;
32 gettimeofday(&tv, NULL);
2546420a
A
33 tv.tv_sec += (tv.tv_usec + context->udelay) / (__typeof(tv.tv_sec)) USEC_PER_SEC;
34 tv.tv_usec = (tv.tv_usec + context->udelay) % (__typeof(tv.tv_usec)) USEC_PER_SEC;
35 TIMEVAL_TO_TIMESPEC(&tv, &ts);
964d3577
A
36
37 res = pthread_mutex_lock(&context->mutex);
38 if (res) {
39 fprintf(stderr, "[%ld] pthread_mutex_lock: %s\n", context->count, strerror(res));
40 abort();
41 }
42
43 if (context->count > 0) {
44 res = pthread_cond_timedwait(&context->cond, &context->mutex, &ts);
45 if (res != ETIMEDOUT) {
46 fprintf(stderr, "[%ld] pthread_cond_timedwait: %s\n", context->count, strerror(res));
47 abort();
48 }
49 --context->count;
50 } else {
51 loop = false;
52 }
53
54 res = pthread_mutex_unlock(&context->mutex);
55 if (res) {
56 fprintf(stderr, "[%ld] pthread_mutex_unlock: %s\n", context->count, strerror(res));
57 abort();
58 }
59 }
60
61 return NULL;
62}
63
2546420a 64T_DECL(cond_timedwait_timeout, "pthread_cond_timedwait() timeout")
964d3577 65{
2546420a
A
66 // This testcase launches 8 threads that all perform timed wait on the same
67 // conditional variable that is not being signaled in a loop. Ater the total
68 // of 8000 timeouts all threads finish and the testcase prints out the
69 // expected time (5[ms]*8000[timeouts]/8[threads]=5s) vs elapsed time.
964d3577
A
70 struct context context = {
71 .cond = PTHREAD_COND_INITIALIZER,
72 .mutex = PTHREAD_MUTEX_INITIALIZER,
73 .udelay = 5000,
74 .count = 8000,
75 };
964d3577 76
2546420a
A
77 long uexpected = (context.udelay * context.count) / NUM_THREADS;
78 T_LOG("waittime expected: %ld us", uexpected);
964d3577
A
79 struct timeval start, end;
80 gettimeofday(&start, NULL);
81
2546420a
A
82 pthread_t p[NUM_THREADS];
83 for (int i = 0; i < NUM_THREADS; ++i) {
84 T_ASSERT_POSIX_ZERO(pthread_create(&p[i], NULL, wait_thread, &context),
85 "pthread_create");
964d3577
A
86 }
87
2546420a 88 usleep((useconds_t) uexpected);
964d3577
A
89 bool loop = true;
90 while (loop) {
2546420a
A
91 T_ASSERT_POSIX_ZERO(pthread_mutex_lock(&context.mutex),
92 "pthread_mutex_lock");
964d3577
A
93 if (context.count <= 0) {
94 loop = false;
95 }
2546420a
A
96 T_ASSERT_POSIX_ZERO(pthread_mutex_unlock(&context.mutex),
97 "pthread_mutex_unlock");
964d3577
A
98 }
99
2546420a
A
100 for (int i = 0; i < NUM_THREADS; ++i) {
101 T_ASSERT_POSIX_ZERO(pthread_join(p[i], NULL), "pthread_join");
964d3577
A
102 }
103
104 gettimeofday(&end, NULL);
2546420a
A
105 uint64_t uelapsed =
106 ((uint64_t) end.tv_sec * USEC_PER_SEC + (uint64_t) end.tv_usec) -
107 ((uint64_t) start.tv_sec * USEC_PER_SEC + (uint64_t) start.tv_usec);
108 T_LOG("waittime actual: %llu us", uelapsed);
964d3577 109}