Instantly share code, notes, and snippets.
Created
July 12, 2017 19:25
-
Star
(8)
8
You must be signed in to star a gist -
Fork
(3)
3
You must be signed in to fork a gist
-
Save ben-cohen/67d41a917ffbf7a5da99fd622feb346b to your computer and use it in GitHub Desktop.
Mutex in mmap memory shared between processes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* shared_mutex: Mutex in mmap memory shared between processes. | |
* | |
* Ben Cohen, July 2017. | |
* | |
* Compile using: | |
* gcc -o shared_mutex shared_mutex.c -ggdb -Wall -std=c99 -pthread | |
* | |
* Two processes are created with an mmap shared memory region | |
* containing an array of chars and a mutex. The mutex is created with | |
* the attribute PTHREAD_PROCESS_SHARED. | |
* | |
* One process writes increasing numbers into an array and the other | |
* prints the contents once a second. | |
* | |
* By default the mutex will prevent the first process updating while | |
* the second is reading so all the value in each row will be the same, | |
* for example: | |
* | |
* 0 0 0 0 0 0 0 0 0 0 | |
* 79 79 79 79 79 79 79 79 79 79 | |
* 209 209 209 209 209 209 209 209 209 209 | |
* 122 122 122 122 122 122 122 122 122 122 | |
* 106 106 106 106 106 106 106 106 106 106 | |
* ... | |
* | |
* If invoked with the argument --no-mutex then it does not obtain the | |
* mutex so the values are modified while the second process reads the | |
* array and the values in each row will not all be the same: | |
* | |
* 130 206 230 236 241 247 253 3 12 20 | |
* 16 22 28 34 39 45 51 57 63 69 | |
* 196 186 193 200 206 211 217 223 228 234 | |
* 133 104 112 118 123 128 133 138 144 150 | |
* 136 111 116 122 128 133 138 143 149 154 | |
* ... | |
*/ | |
#define _BSD_SOURCE | |
#include <sys/mman.h> | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <pthread.h> | |
#include <string.h> | |
#define MMAP_NAME "/tmp/mmaptest" | |
#define LENGTH sizeof(struct mapped) | |
#define ARRAY_ELEMENTS 10 | |
struct mapped | |
{ | |
unsigned char array[ARRAY_ELEMENTS]; | |
int use_mutex; | |
pthread_mutex_t mutex; | |
}; | |
void die(char *msg) | |
{ | |
perror(msg); | |
exit(1); | |
} | |
void child(struct mapped *mapping) | |
{ | |
unsigned int n = 0; | |
while (1) | |
{ | |
if (mapping->use_mutex) | |
pthread_mutex_lock(&mapping->mutex); | |
for (int i = 0; i < 10; i ++) | |
{ | |
mapping->array[i] = n; | |
} | |
n ++; | |
if (mapping->use_mutex) | |
pthread_mutex_unlock(&mapping->mutex); | |
} | |
} | |
void parent(struct mapped *mapping) | |
{ | |
while (1) | |
{ | |
if (mapping->use_mutex) | |
pthread_mutex_lock(&mapping->mutex); | |
for (int i = 0; i < 10; i ++) | |
{ | |
printf("%4d", mapping->array[i]); | |
} | |
printf("\n"); | |
if (mapping->use_mutex) | |
pthread_mutex_unlock(&mapping->mutex); | |
sleep(1); | |
} | |
} | |
int main(int argc, char **argv) | |
{ | |
int rc; | |
unlink(MMAP_NAME); | |
int fd = open(MMAP_NAME, O_CREAT|O_RDWR, 00600); | |
if (fd == -1) | |
die("open"); | |
rc = ftruncate(fd, LENGTH); | |
if (rc != 0) | |
die("ftruncate"); | |
struct mapped *mapping = (struct mapped *)mmap(NULL, | |
LENGTH, | |
PROT_READ|PROT_WRITE, | |
MAP_SHARED, | |
fd, | |
0); | |
if (mapping == MAP_FAILED) | |
die("mmap"); | |
close(fd); | |
pthread_mutexattr_t mutexattr; | |
rc = pthread_mutexattr_init(&mutexattr); | |
if (rc != 0) | |
die("pthread_mutexattr_init"); | |
rc = pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED); | |
if (rc != 0) | |
die("pthread_mutexattr_setpshared"); | |
pthread_mutex_init(&mapping->mutex, &mutexattr); | |
if (rc != 0) | |
die("pthread_mutex_init"); | |
if (argc >= 2 | |
&& strcmp(argv[1], "--no-mutex") == 0) | |
mapping->use_mutex = 0; | |
else | |
mapping->use_mutex = 1; | |
switch (fork()) | |
{ | |
case -1: | |
die("fork"); | |
case 0: | |
child(mapping); | |
break; | |
default: | |
parent(mapping); | |
break; | |
} | |
rc = munmap(mapping, LENGTH); | |
if (rc != 0) | |
die("munmap"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment