forked from cirosantilli/cpp-cheat
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsemaphore_sysv.c
68 lines (65 loc) · 1.87 KB
/
semaphore_sysv.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/* # SYSV semaphore
*
* In this example, processes communicate through `mmap`.
*
* Implemented in Linux by equally named system calls.
*
* This example uses a semaphore to ensure that mmaped read / write
* is synchronized across two processes.
*/
#include "common.h"
int main(void) {
/* Not defined in any header, we must define it ourselves! TODO why? */
union semun mysemun;
int fd;
int *map;
char *name = "/" TMPFILE();
/* ID to a set of semaphores. */
int semid;
enum Constexpr { size = sizeof(int) };
struct sembuf mysembuf;
/* Operate on first semaphore in set. */
mysembuf.sem_num = 0;
/* No special options for operation */
mysembuf.sem_flg = 0;
/* Returns the ID to a new set of semaphores. */
semid = semget(
/* Create new semaphores, don't reuse existing ones. */
IPC_PRIVATE,
/* How many semaphores to create in the set. */
1,
/* Open-like permissions. */
S_IRUSR | S_IWUSR
);
mysemun.val = 1;
/* Set the semaphore values to 1. */
semctl(semid, 0, SETVAL, mysemun);
fd = shm_open(name, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
ftruncate(fd, size);
map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
*map = 0;
if (fork() == 0) {
*map = 1;
msync(map, size, MS_SYNC);
/* Subtract 1. */
mysembuf.sem_op = -1;
semop(
semid,
/* Array of operations to do. Here a single one. */
&mysembuf,
/* The length of the mysembuf array is 1: single element case. */
1
);
exit(EXIT_SUCCESS);
}
/* Wait for 0. */
mysembuf.sem_op = 0;
semop(semid, &mysembuf, 1);
assert(*map == 1);
wait(NULL);
assert(*map == 1);
munmap(map, size);
close(fd);
shm_unlink(name);
return EXIT_SUCCESS;
}