Only use process shared mutexes on support platforms
[fio.git] / mutex.c
CommitLineData
07739b57
JA
1#include <stdio.h>
2#include <string.h>
3#include <unistd.h>
4#include <stdlib.h>
5#include <fcntl.h>
6#include <pthread.h>
7#include <sys/mman.h>
8
4fa6d0f8 9#include "log.h"
07739b57 10#include "mutex.h"
4d4e80f2 11#include "arch/arch.h"
07739b57 12
cdd18ad8 13void fio_mutex_remove(struct fio_mutex *mutex)
07739b57 14{
cdd18ad8 15 close(mutex->mutex_fd);
5921e80c 16 munmap((void *) mutex, sizeof(*mutex));
07739b57
JA
17}
18
cdd18ad8 19struct fio_mutex *fio_mutex_init(int value)
07739b57 20{
cdd18ad8
JA
21 char mutex_name[] = "/tmp/.fio_mutex.XXXXXX";
22 struct fio_mutex *mutex = NULL;
07739b57 23 pthread_mutexattr_t attr;
108fcc11 24 pthread_condattr_t cond;
f356d01d 25 int fd, ret, mflag;
07739b57 26
cdd18ad8 27 fd = mkstemp(mutex_name);
07739b57 28 if (fd < 0) {
cdd18ad8 29 perror("open mutex");
07739b57
JA
30 return NULL;
31 }
32
cdd18ad8
JA
33 if (ftruncate(fd, sizeof(struct fio_mutex)) < 0) {
34 perror("ftruncate mutex");
e53bd0b3 35 goto err;
07739b57
JA
36 }
37
5921e80c
JA
38 mutex = (void *) mmap(NULL, sizeof(struct fio_mutex),
39 PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
cdd18ad8
JA
40 if (mutex == MAP_FAILED) {
41 perror("mmap mutex");
07739b57 42 close(fd);
cdd18ad8 43 mutex = NULL;
e53bd0b3 44 goto err;
07739b57
JA
45 }
46
cdd18ad8
JA
47 unlink(mutex_name);
48 mutex->mutex_fd = fd;
49 mutex->value = value;
07739b57 50
f356d01d
JA
51 /*
52 * Not all platforms support process shared mutexes (FreeBSD)
53 */
54#ifdef FIO_HAVE_PSHARED_MUTEX
55 mflag = PTHREAD_PROCESS_SHARED;
56#else
57 mflag = PTHREAD_PROCESS_PRIVATE;
58#endif
59
4fa6d0f8
JA
60 ret = pthread_mutexattr_init(&attr);
61 if (ret) {
62 log_err("pthread_mutexattr_init: %s\n", strerror(ret));
07739b57
JA
63 goto err;
64 }
f356d01d 65 ret = pthread_mutexattr_setpshared(&attr, mflag);
4fa6d0f8
JA
66 if (ret) {
67 log_err("pthread_mutexattr_setpshared: %s\n", strerror(ret));
07739b57
JA
68 goto err;
69 }
108fcc11
ZY
70
71 pthread_condattr_init(&cond);
f356d01d 72 pthread_condattr_setpshared(&cond, mflag);
cdd18ad8 73 pthread_cond_init(&mutex->cond, &cond);
108fcc11 74
4fa6d0f8
JA
75 ret = pthread_mutex_init(&mutex->lock, &attr);
76 if (ret) {
77 log_err("pthread_mutex_init: %s\n", strerror(ret));
07739b57
JA
78 goto err;
79 }
80
cdd18ad8 81 return mutex;
07739b57 82err:
cdd18ad8
JA
83 if (mutex)
84 fio_mutex_remove(mutex);
f7c9e00e 85
cdd18ad8 86 unlink(mutex_name);
07739b57
JA
87 return NULL;
88}
89
cdd18ad8 90void fio_mutex_down(struct fio_mutex *mutex)
07739b57 91{
cdd18ad8 92 pthread_mutex_lock(&mutex->lock);
4d4e80f2
JA
93
94 while (!mutex->value) {
95 mutex->waiters++;
cdd18ad8 96 pthread_cond_wait(&mutex->cond, &mutex->lock);
4d4e80f2
JA
97 mutex->waiters--;
98 }
99
cdd18ad8
JA
100 mutex->value--;
101 pthread_mutex_unlock(&mutex->lock);
07739b57
JA
102}
103
cdd18ad8 104void fio_mutex_up(struct fio_mutex *mutex)
07739b57 105{
cdd18ad8 106 pthread_mutex_lock(&mutex->lock);
4d4e80f2
JA
107 read_barrier();
108 if (!mutex->value && mutex->waiters)
cdd18ad8
JA
109 pthread_cond_signal(&mutex->cond);
110 mutex->value++;
111 pthread_mutex_unlock(&mutex->lock);
07739b57 112}
64d4d313
JA
113
114void fio_mutex_down_write(struct fio_mutex *mutex)
115{
116 pthread_mutex_lock(&mutex->lock);
4d4e80f2
JA
117
118 while (mutex->value != 0) {
119 mutex->waiters++;
64d4d313 120 pthread_cond_wait(&mutex->cond, &mutex->lock);
4d4e80f2
JA
121 mutex->waiters--;
122 }
123
64d4d313
JA
124 mutex->value--;
125 pthread_mutex_unlock(&mutex->lock);
126}
127
128void fio_mutex_down_read(struct fio_mutex *mutex)
129{
130 pthread_mutex_lock(&mutex->lock);
4d4e80f2
JA
131
132 while (mutex->value < 0) {
133 mutex->waiters++;
64d4d313 134 pthread_cond_wait(&mutex->cond, &mutex->lock);
4d4e80f2
JA
135 mutex->waiters--;
136 }
137
64d4d313
JA
138 mutex->value++;
139 pthread_mutex_unlock(&mutex->lock);
140}
141
142void fio_mutex_up_read(struct fio_mutex *mutex)
143{
144 pthread_mutex_lock(&mutex->lock);
145 mutex->value--;
4d4e80f2
JA
146 read_barrier();
147 if (mutex->value >= 0 && mutex->waiters)
64d4d313
JA
148 pthread_cond_signal(&mutex->cond);
149 pthread_mutex_unlock(&mutex->lock);
150}
151
152void fio_mutex_up_write(struct fio_mutex *mutex)
153{
154 pthread_mutex_lock(&mutex->lock);
155 mutex->value++;
4d4e80f2
JA
156 read_barrier();
157 if (mutex->value >= 0 && mutex->waiters)
64d4d313
JA
158 pthread_cond_signal(&mutex->cond);
159 pthread_mutex_unlock(&mutex->lock);
160}