1 /** Trigger two kinds of errors: once that condition variable s_cond is
2 * associated with two different mutexes (s_mutex1 and s_mutex2), and two
3 * times that pthread_cond_signal() is called without that the mutex
4 * associated with the condition variable is locked.
8 #include <errno.h> // ETIMEDOUT
10 #include <semaphore.h>
12 #include <stdlib.h> // malloc()
13 #include <string.h> // memset()
14 #include <sys/time.h> // gettimeofday()
15 #include <time.h> // struct timespec
16 #include <fcntl.h> // O_CREAT
18 #include "../../config.h"
21 #define PTH_CALL(expr) \
25 if (! s_quiet && err) \
28 "%s:%d %s returned error code %d (%s)\n", \
38 static pthread_cond_t s_cond
;
39 static pthread_mutex_t s_mutex1
;
40 static pthread_mutex_t s_mutex2
;
45 static sem_t
* create_semaphore(const char* const name
)
48 char name_and_pid
[32];
49 snprintf(name_and_pid
, sizeof(name_and_pid
), "%s-%d", name
, getpid());
50 sem_t
* p
= sem_open(name_and_pid
, O_CREAT
| O_EXCL
, 0600, 0);
51 if (p
== SEM_FAILED
) {
57 sem_t
* p
= malloc(sizeof(*p
));
64 static void destroy_semaphore(const char* const name
, sem_t
* p
)
75 static void* thread_func(void* mutex
)
78 struct timespec deadline
;
80 PTH_CALL(pthread_mutex_lock(mutex
));
82 gettimeofday(&now
, 0);
83 memset(&deadline
, 0, sizeof(deadline
));
84 deadline
.tv_sec
= now
.tv_sec
+ 2;
85 deadline
.tv_nsec
= now
.tv_usec
* 1000;
86 PTH_CALL(pthread_cond_timedwait(&s_cond
, mutex
, &deadline
));
87 PTH_CALL(pthread_mutex_unlock(mutex
));
91 int main(int argc
, char** argv
)
93 char semaphore_name
[32];
98 while ((optchar
= getopt(argc
, argv
, "q")) != EOF
)
102 case 'q': s_quiet
= 1; break;
104 fprintf(stderr
, "Error: unknown option '%c'.\n", optchar
);
109 /* Initialize synchronization objects. */
110 snprintf(semaphore_name
, sizeof(semaphore_name
), "semaphore-%ld",
112 s_sem
= create_semaphore(semaphore_name
);
113 PTH_CALL(pthread_cond_init(&s_cond
, 0));
114 PTH_CALL(pthread_mutex_init(&s_mutex1
, 0));
115 PTH_CALL(pthread_mutex_init(&s_mutex2
, 0));
117 /* Create two threads. */
118 PTH_CALL(pthread_create(&tid1
, 0, &thread_func
, &s_mutex1
));
119 PTH_CALL(pthread_create(&tid2
, 0, &thread_func
, &s_mutex2
));
121 /* Wait until both threads have called sem_post(). */
124 destroy_semaphore(semaphore_name
, s_sem
);
127 /* Wait until both threads are waiting inside pthread_cond_wait(). */
128 PTH_CALL(pthread_mutex_lock(&s_mutex1
));
129 PTH_CALL(pthread_mutex_lock(&s_mutex2
));
130 PTH_CALL(pthread_mutex_unlock(&s_mutex2
));
131 PTH_CALL(pthread_mutex_unlock(&s_mutex1
));
133 /* Signal s_cond twice. */
134 PTH_CALL(pthread_cond_signal(&s_cond
));
135 PTH_CALL(pthread_cond_signal(&s_cond
));
137 /* Join both threads. */
138 PTH_CALL(pthread_join(tid1
, 0));
139 PTH_CALL(pthread_join(tid2
, 0));