]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/drd/tests/pth_inconsistent_cond_wait.c
update
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / drd / tests / pth_inconsistent_cond_wait.c
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.
5  */
6
7
8 #include <errno.h>     // ETIMEDOUT
9 #include <pthread.h>
10 #include <semaphore.h>
11 #include <stdio.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
17 #include <unistd.h>
18 #include "../../config.h"
19
20
21 #define PTH_CALL(expr)                                  \
22   do                                                    \
23   {                                                     \
24     int err = (expr);                                   \
25     if (! s_quiet && err)                               \
26     {                                                   \
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
38 static pthread_cond_t  s_cond;
39 static pthread_mutex_t s_mutex1;
40 static pthread_mutex_t s_mutex2;
41 static sem_t*          s_sem;
42 static int             s_quiet;
43
44
45 static sem_t* create_semaphore(const char* const name)
46 {
47 #ifdef VGO_darwin
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) {
52     perror("sem_open");
53     return NULL;
54   }
55   return p;
56 #else
57   sem_t* p = malloc(sizeof(*p));
58   if (p)
59     sem_init(p, 0, 0);
60   return p;
61 #endif
62 }
63
64 static void destroy_semaphore(const char* const name, sem_t* p)
65 {
66 #ifdef VGO_darwin
67   sem_close(p);
68   sem_unlink(name);
69 #else
70   sem_destroy(p);
71   free(p);
72 #endif
73 }
74
75 static void* thread_func(void* mutex)
76 {
77   struct timeval now;
78   struct timespec deadline;
79
80   PTH_CALL(pthread_mutex_lock(mutex));
81   sem_post(s_sem);
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));
88   return 0;
89 }
90
91 int main(int argc, char** argv)
92 {
93   char semaphore_name[32];
94   int optchar;
95   pthread_t tid1;
96   pthread_t tid2;
97
98   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
109   /* Initialize synchronization objects. */
110   snprintf(semaphore_name, sizeof(semaphore_name), "semaphore-%d", getpid());
111   s_sem = create_semaphore(semaphore_name);
112   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));
115
116   /* Create two threads. */
117   PTH_CALL(pthread_create(&tid1, 0, &thread_func, &s_mutex1));
118   PTH_CALL(pthread_create(&tid2, 0, &thread_func, &s_mutex2));
119
120   /* Wait until both threads have called sem_post(). */
121   sem_wait(s_sem);
122   sem_wait(s_sem);
123   destroy_semaphore(semaphore_name, s_sem);
124   s_sem = 0;
125
126   /* Wait until both threads are waiting inside pthread_cond_wait(). */
127   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));
131
132   /* Signal s_cond twice. */
133   PTH_CALL(pthread_cond_signal(&s_cond));
134   PTH_CALL(pthread_cond_signal(&s_cond));
135
136   /* Join both threads. */
137   PTH_CALL(pthread_join(tid1, 0));
138   PTH_CALL(pthread_join(tid2, 0));
139
140   return 0;
141 }