Skip to content

Commit 04f6a67

Browse files
author
Jan Pechanec
committed
New example on POSIX semaphores.
1 parent ae4c7c7 commit 04f6a67

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed

semaphores/posix-sem-fixed-race.c

+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/*
2+
* See ../race/race.c and ../race/sem-fixed-race.c for more information.
3+
*
4+
* This version uses POSIX semaphores for synchronization. After you run this
5+
* and kill it with Ctrl-C you see some statistics as to how many loops were
6+
* run. Compare with implementations mentioned above. You will POSIX
7+
* semaphores are an order of magnitude more efficient than Sys V semaphores.
8+
*
9+
* You must link with -pthread on Linux.
10+
*
11+
* (c) jp@devnull.cz
12+
*/
13+
14+
#define _XOPEN_SOURCE 700
15+
16+
#include <assert.h>
17+
#include <err.h>
18+
#include <errno.h>
19+
#include <fcntl.h>
20+
#include <semaphore.h>
21+
#include <signal.h>
22+
#include <stdio.h>
23+
#include <stdlib.h>
24+
#include <sys/mman.h>
25+
#include <sys/wait.h>
26+
#include <unistd.h>
27+
28+
sem_t *sem;
29+
int fd, parent;
30+
char *addr = NULL;
31+
unsigned long loops_done;
32+
unsigned int races_detected;
33+
volatile sig_atomic_t run = 1;
34+
35+
static void
36+
print_stats(void)
37+
{
38+
printf("\nstats: inconsistencies %u out of %lu\n", races_detected,
39+
loops_done);
40+
}
41+
42+
void
43+
finish(int sig)
44+
{
45+
run = 0;
46+
}
47+
48+
static void
49+
cleanup(void)
50+
{
51+
if (parent)
52+
sem_destroy(sem);
53+
54+
munmap(addr, 2);
55+
close(fd);
56+
}
57+
58+
int
59+
main(int argc, char **argv)
60+
{
61+
char c = 0;
62+
int dbg = 0;
63+
pid_t pid, ret_pid;
64+
struct sigaction act = { 0 };
65+
66+
if (argc == 1)
67+
printf("Run with any argument to see some debugging info.\n");
68+
else
69+
dbg = 1;
70+
71+
/* Get a semaphore. */
72+
sem = sem_open("/mysem", O_CREAT, S_IRWXU, 1);
73+
if (sem == SEM_FAILED)
74+
err(1, "sem_open");
75+
76+
act.sa_handler = finish;
77+
sigaction(SIGINT, &act, NULL);
78+
79+
if ((fd = open("test.dat", O_CREAT | O_RDWR | O_TRUNC, 0666)) == -1)
80+
err(1, "open");
81+
82+
/* extend the file to 2 bytes */
83+
write(fd, &c, 1);
84+
write(fd, &c, 1);
85+
86+
addr = mmap(0, 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
87+
if (addr == MAP_FAILED)
88+
err(1, "mmap");
89+
90+
if ((pid = fork()) == -1)
91+
err(1, "fork");
92+
93+
/* Child */
94+
if (pid == 0) {
95+
while (run) {
96+
sem_wait(sem);
97+
if (addr[0] != addr[1]) {
98+
if (dbg) {
99+
fprintf(stderr, "[child (%d/%d)] ",
100+
addr[0], addr[1]);
101+
}
102+
++races_detected;
103+
}
104+
addr[0] = addr[1] = 2;
105+
sem_post(sem);
106+
++loops_done;
107+
}
108+
print_stats();
109+
cleanup();
110+
return (0);
111+
}
112+
113+
/* Parent only. */
114+
assert(pid > 0);
115+
parent = 1;
116+
while (run) {
117+
sem_wait(sem);
118+
if (addr[0] != addr[1]) {
119+
if (dbg) {
120+
fprintf(stderr, "[PARENT (%d/%d)] ",
121+
addr[0], addr[1]);
122+
}
123+
++races_detected;
124+
}
125+
addr[0] = addr[1] = 1;
126+
sem_post(sem);
127+
++loops_done;
128+
}
129+
ret_pid = waitpid(pid, NULL, 0);
130+
assert(ret_pid == pid);
131+
132+
print_stats();
133+
if (sem_destroy(sem) == -1)
134+
warn("sem_destroy");
135+
cleanup();
136+
137+
return (0);
138+
}

0 commit comments

Comments
 (0)