blob: fb95fd8a910f85532c447d1f382c486dee27ca12 [file] [log] [blame]
bart6b0e2dd2008-06-28 16:06:01 +00001/** 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.
5 */
6
7
bart76baf212009-07-21 11:36:46 +00008#include <errno.h> // ETIMEDOUT
bart3bb1cec2008-06-28 16:01:43 +00009#include <pthread.h>
10#include <semaphore.h>
bart76baf212009-07-21 11:36:46 +000011#include <stdio.h>
bartd658a042009-07-23 17:50:02 +000012#include <stdlib.h> // malloc()
bart76baf212009-07-21 11:36:46 +000013#include <string.h> // memset()
14#include <sys/time.h> // gettimeofday()
15#include <time.h> // struct timespec
tomd759a832010-04-29 09:36:35 +000016#include <fcntl.h> // O_CREAT
bart3bb1cec2008-06-28 16:01:43 +000017#include <unistd.h>
bart0ccdc4a2010-04-29 06:28:43 +000018#include "../../config.h"
bart3bb1cec2008-06-28 16:01:43 +000019
bart6970e6a2009-07-21 16:19:34 +000020
21#define PTH_CALL(expr) \
22 do \
23 { \
24 int err = (expr); \
bart9ccf35f2009-07-24 06:29:57 +000025 if (! s_quiet && err) \
bart6970e6a2009-07-21 16:19:34 +000026 { \
27 fprintf(stderr, \
28 "%s:%d %s returned error code %d (%s)\n", \
29 __FILE__, \
30 __LINE__, \
31 #expr, \
32 err, \
33 strerror(err)); \
34 } \
35 } while (0)
36
37
bart9ccf35f2009-07-24 06:29:57 +000038static pthread_cond_t s_cond;
39static pthread_mutex_t s_mutex1;
40static pthread_mutex_t s_mutex2;
41static sem_t* s_sem;
42static int s_quiet;
bart3bb1cec2008-06-28 16:01:43 +000043
bart6970e6a2009-07-21 16:19:34 +000044
bart23d23a52009-07-23 18:02:52 +000045static sem_t* create_semaphore(const char* const name)
bartd658a042009-07-23 17:50:02 +000046{
bart3e7c4022011-03-05 14:11:40 +000047#ifdef VGO_darwin
bart8c7213f2011-03-05 14:49:12 +000048 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) {
52 perror("sem_open");
53 return NULL;
54 }
bart23d23a52009-07-23 18:02:52 +000055 return p;
56#else
bartd658a042009-07-23 17:50:02 +000057 sem_t* p = malloc(sizeof(*p));
58 if (p)
59 sem_init(p, 0, 0);
60 return p;
bart23d23a52009-07-23 18:02:52 +000061#endif
bartd658a042009-07-23 17:50:02 +000062}
63
bart23d23a52009-07-23 18:02:52 +000064static void destroy_semaphore(const char* const name, sem_t* p)
bartd658a042009-07-23 17:50:02 +000065{
bart3e7c4022011-03-05 14:11:40 +000066#ifdef VGO_darwin
bart23d23a52009-07-23 18:02:52 +000067 sem_close(p);
68 sem_unlink(name);
69#else
bartd658a042009-07-23 17:50:02 +000070 sem_destroy(p);
71 free(p);
bart23d23a52009-07-23 18:02:52 +000072#endif
bartd658a042009-07-23 17:50:02 +000073}
74
bart76baf212009-07-21 11:36:46 +000075static void* thread_func(void* mutex)
bart3bb1cec2008-06-28 16:01:43 +000076{
bart76baf212009-07-21 11:36:46 +000077 struct timeval now;
78 struct timespec deadline;
bart3bb1cec2008-06-28 16:01:43 +000079
bart6970e6a2009-07-21 16:19:34 +000080 PTH_CALL(pthread_mutex_lock(mutex));
bartd658a042009-07-23 17:50:02 +000081 sem_post(s_sem);
bart76baf212009-07-21 11:36:46 +000082 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;
bart6970e6a2009-07-21 16:19:34 +000086 PTH_CALL(pthread_cond_timedwait(&s_cond, mutex, &deadline));
87 PTH_CALL(pthread_mutex_unlock(mutex));
bart3bb1cec2008-06-28 16:01:43 +000088 return 0;
89}
90
91int main(int argc, char** argv)
92{
bart9ccf35f2009-07-24 06:29:57 +000093 char semaphore_name[32];
94 int optchar;
bart3bb1cec2008-06-28 16:01:43 +000095 pthread_t tid1;
96 pthread_t tid2;
97
bart9ccf35f2009-07-24 06:29:57 +000098 while ((optchar = getopt(argc, argv, "q")) != EOF)
99 {
100 switch (optchar)
101 {
102 case 'q': s_quiet = 1; break;
103 default:
104 fprintf(stderr, "Error: unknown option '%c'.\n", optchar);
105 return 1;
106 }
107 }
108
bart83d509a2008-09-09 18:18:26 +0000109 /* Initialize synchronization objects. */
bart23d23a52009-07-23 18:02:52 +0000110 snprintf(semaphore_name, sizeof(semaphore_name), "semaphore-%d", getpid());
111 s_sem = create_semaphore(semaphore_name);
bart6970e6a2009-07-21 16:19:34 +0000112 PTH_CALL(pthread_cond_init(&s_cond, 0));
113 PTH_CALL(pthread_mutex_init(&s_mutex1, 0));
114 PTH_CALL(pthread_mutex_init(&s_mutex2, 0));
bart83d509a2008-09-09 18:18:26 +0000115
116 /* Create two threads. */
bart6970e6a2009-07-21 16:19:34 +0000117 PTH_CALL(pthread_create(&tid1, 0, &thread_func, &s_mutex1));
118 PTH_CALL(pthread_create(&tid2, 0, &thread_func, &s_mutex2));
bart83d509a2008-09-09 18:18:26 +0000119
120 /* Wait until both threads have called sem_post(). */
bartd658a042009-07-23 17:50:02 +0000121 sem_wait(s_sem);
122 sem_wait(s_sem);
bart23d23a52009-07-23 18:02:52 +0000123 destroy_semaphore(semaphore_name, s_sem);
bartd658a042009-07-23 17:50:02 +0000124 s_sem = 0;
bart83d509a2008-09-09 18:18:26 +0000125
126 /* Wait until both threads are waiting inside pthread_cond_wait(). */
bart6970e6a2009-07-21 16:19:34 +0000127 PTH_CALL(pthread_mutex_lock(&s_mutex1));
128 PTH_CALL(pthread_mutex_lock(&s_mutex2));
129 PTH_CALL(pthread_mutex_unlock(&s_mutex2));
130 PTH_CALL(pthread_mutex_unlock(&s_mutex1));
bart83d509a2008-09-09 18:18:26 +0000131
132 /* Signal s_cond twice. */
bart6970e6a2009-07-21 16:19:34 +0000133 PTH_CALL(pthread_cond_signal(&s_cond));
134 PTH_CALL(pthread_cond_signal(&s_cond));
bart83d509a2008-09-09 18:18:26 +0000135
136 /* Join both threads. */
bart6970e6a2009-07-21 16:19:34 +0000137 PTH_CALL(pthread_join(tid1, 0));
138 PTH_CALL(pthread_join(tid2, 0));
bart83d509a2008-09-09 18:18:26 +0000139
bart3bb1cec2008-06-28 16:01:43 +0000140 return 0;
141}