Skip to content

Commit 2fdb1ea

Browse files
committed
Add test program: condvar-two-mutexes.c
1 parent 26d3723 commit 2fdb1ea

1 file changed

Lines changed: 96 additions & 0 deletions

File tree

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#include <assert.h>
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
#include <pthread.h>
5+
#include <unistd.h>
6+
7+
#define NUM_WRITERS 3
8+
#define ITERATIONS 1
9+
10+
int shared_data = 0;
11+
int writer_count_db1 = 0;
12+
int writer_count_db2 = 0;
13+
int waiting_writer_count_db1 = 0;
14+
int waiting_writer_count_db2 = 0;
15+
pthread_mutex_t mutex_lock_db1;
16+
pthread_mutex_t mutex_lock_db2;
17+
// One condition variable, but two mutexes
18+
pthread_cond_t writers_cond;
19+
20+
void *writer(void *not_used) {
21+
for (int i = 0; i < ITERATIONS; i++) {
22+
// We're doing two acquire-release paradigms,
23+
// but with one condition variable and two mutexes.
24+
// This is a bug.
25+
26+
// ACQUIRE for db1
27+
pthread_mutex_lock(&mutex_lock_db1);
28+
waiting_writer_count_db1++;
29+
while (writer_count_db1 > 0) {
30+
pthread_cond_wait(&writers_cond, &mutex_lock_db1);
31+
}
32+
waiting_writer_count_db1--;
33+
assert(writer_count_db1 == 0);
34+
writer_count_db1++;
35+
pthread_mutex_unlock(&mutex_lock_db1);
36+
// USE (DO_TASK) for db1
37+
shared_data++;
38+
usleep(200000);
39+
printf("I wrote to db #1\n");
40+
// RELEASE for db1
41+
pthread_mutex_lock(&mutex_lock_db1);
42+
writer_count_db1--;
43+
assert(writer_count_db1 == 0);
44+
if (waiting_writer_count_db1 > 0) {
45+
pthread_cond_signal(&writers_cond);
46+
}
47+
pthread_mutex_unlock(&mutex_lock_db1);
48+
usleep(500000);
49+
50+
// ACQUIRE for db2
51+
pthread_mutex_lock(&mutex_lock_db2);
52+
waiting_writer_count_db2++;
53+
while (writer_count_db2 > 0) {
54+
pthread_cond_wait(&writers_cond, &mutex_lock_db2);
55+
}
56+
waiting_writer_count_db2--;
57+
assert(writer_count_db2 == 0);
58+
writer_count_db2++;
59+
pthread_mutex_unlock(&mutex_lock_db2);
60+
// USE (DO_TASK) for db2
61+
shared_data++;
62+
usleep(200000);
63+
printf("I wrote to db #2\n");
64+
// RELEASE for db2
65+
pthread_mutex_lock(&mutex_lock_db2);
66+
writer_count_db2--;
67+
assert(writer_count_db2 == 0);
68+
if (waiting_writer_count_db2 > 0) {
69+
pthread_cond_signal(&writers_cond);
70+
}
71+
pthread_mutex_unlock(&mutex_lock_db2);
72+
usleep(500000);
73+
}
74+
return NULL;
75+
}
76+
77+
int main() {
78+
pthread_t writers[NUM_WRITERS];
79+
int writer_ids[NUM_WRITERS];
80+
pthread_mutex_init(&mutex_lock_db1, NULL);
81+
pthread_mutex_init(&mutex_lock_db2, NULL);
82+
pthread_cond_init(&writers_cond, NULL);
83+
for (int i = 0; i < NUM_WRITERS; i++) {
84+
writer_ids[i] = i + 1;
85+
if (pthread_create(&writers[i], NULL, writer, &writer_ids[i]) != 0) {
86+
return 1;
87+
}
88+
}
89+
for (int i = 0; i < NUM_WRITERS; i++) {
90+
pthread_join(writers[i], NULL);
91+
}
92+
pthread_mutex_destroy(&mutex_lock_db1);
93+
pthread_mutex_destroy(&mutex_lock_db2);
94+
pthread_cond_destroy(&writers_cond);
95+
return 0;
96+
}

0 commit comments

Comments
 (0)