Mutex fixes
[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>
656b1393 6#include <time.h>
07739b57
JA
7#include <pthread.h>
8#include <sys/mman.h>
9
4fa6d0f8 10#include "log.h"
07739b57 11#include "mutex.h"
4d4e80f2 12#include "arch/arch.h"
3c2d93ed 13#include "os/os.h"
3b2e1464 14#include "helpers.h"
07739b57 15
cdd18ad8 16void fio_mutex_remove(struct fio_mutex *mutex)
07739b57 17{
58a157d4 18 pthread_cond_destroy(&mutex->cond);
5921e80c 19 munmap((void *) mutex, sizeof(*mutex));
07739b57
JA
20}
21
cdd18ad8 22struct fio_mutex *fio_mutex_init(int value)
07739b57 23{
cdd18ad8 24 struct fio_mutex *mutex = NULL;
07739b57 25 pthread_mutexattr_t attr;
108fcc11 26 pthread_condattr_t cond;
e721c57f 27 int ret;
07739b57 28
5921e80c 29 mutex = (void *) mmap(NULL, sizeof(struct fio_mutex),
b6f6abc6
JA
30 PROT_READ | PROT_WRITE,
31 OS_MAP_ANON | MAP_SHARED, -1, 0);
cdd18ad8
JA
32 if (mutex == MAP_FAILED) {
33 perror("mmap mutex");
cdd18ad8 34 mutex = NULL;
e53bd0b3 35 goto err;
07739b57
JA
36 }
37
cdd18ad8 38 mutex->value = value;
07739b57 39
4fa6d0f8
JA
40 ret = pthread_mutexattr_init(&attr);
41 if (ret) {
42 log_err("pthread_mutexattr_init: %s\n", strerror(ret));
07739b57
JA
43 goto err;
44 }
e721c57f
JA
45
46 /*
47 * Not all platforms support process shared mutexes (FreeBSD)
48 */
7452440e 49#ifdef FIO_HAVE_PSHARED_MUTEX
e721c57f 50 ret = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
4fa6d0f8
JA
51 if (ret) {
52 log_err("pthread_mutexattr_setpshared: %s\n", strerror(ret));
07739b57
JA
53 goto err;
54 }
7452440e 55#endif
108fcc11
ZY
56
57 pthread_condattr_init(&cond);
7452440e 58#ifdef FIO_HAVE_PSHARED_MUTEX
e721c57f 59 pthread_condattr_setpshared(&cond, PTHREAD_PROCESS_SHARED);
7452440e 60#endif
ceab2ea2
JA
61#ifdef FIO_HAVE_CLOCK_MONOTONIC
62 pthread_condattr_setclock(&cond, CLOCK_MONOTONIC);
63#else
64 pthread_condattr_setclock(&cond, CLOCK_REALTIME);
65#endif
58a157d4 66 pthread_cond_init(&mutex->cond, &cond);
108fcc11 67
4fa6d0f8
JA
68 ret = pthread_mutex_init(&mutex->lock, &attr);
69 if (ret) {
70 log_err("pthread_mutex_init: %s\n", strerror(ret));
07739b57
JA
71 goto err;
72 }
73
03e20d68
BC
74 pthread_condattr_destroy(&cond);
75 pthread_mutexattr_destroy(&attr);
76
cdd18ad8 77 return mutex;
07739b57 78err:
cdd18ad8
JA
79 if (mutex)
80 fio_mutex_remove(mutex);
f7c9e00e 81
07739b57
JA
82 return NULL;
83}
84
656b1393
JA
85int fio_mutex_down_timeout(struct fio_mutex *mutex, unsigned int seconds)
86{
87 struct timespec t;
88 int ret = 0;
89
ceab2ea2
JA
90#ifdef FIO_HAVE_CLOCK_MONOTONIC
91 clock_gettime(CLOCK_MONOTONIC, &t);
92#else
d481e006 93 clock_gettime(CLOCK_REALTIME, &t);
ceab2ea2 94#endif
656b1393
JA
95 t.tv_sec += seconds;
96
97 pthread_mutex_lock(&mutex->lock);
98
99 while (!mutex->value && !ret) {
100 mutex->waiters++;
101 ret = pthread_cond_timedwait(&mutex->cond, &mutex->lock, &t);
102 mutex->waiters--;
103 }
104
105 if (!ret) {
106 mutex->value--;
107 pthread_mutex_unlock(&mutex->lock);
108 }
109
110 return ret;
111}
112
cdd18ad8 113void fio_mutex_down(struct fio_mutex *mutex)
07739b57 114{
cdd18ad8 115 pthread_mutex_lock(&mutex->lock);
4d4e80f2
JA
116
117 while (!mutex->value) {
118 mutex->waiters++;
cdd18ad8 119 pthread_cond_wait(&mutex->cond, &mutex->lock);
4d4e80f2
JA
120 mutex->waiters--;
121 }
122
cdd18ad8
JA
123 mutex->value--;
124 pthread_mutex_unlock(&mutex->lock);
07739b57
JA
125}
126
cdd18ad8 127void fio_mutex_up(struct fio_mutex *mutex)
07739b57 128{
cdd18ad8 129 pthread_mutex_lock(&mutex->lock);
4d4e80f2
JA
130 read_barrier();
131 if (!mutex->value && mutex->waiters)
cdd18ad8
JA
132 pthread_cond_signal(&mutex->cond);
133 mutex->value++;
134 pthread_mutex_unlock(&mutex->lock);
07739b57 135}
64d4d313
JA
136
137void fio_mutex_down_write(struct fio_mutex *mutex)
138{
139 pthread_mutex_lock(&mutex->lock);
4d4e80f2
JA
140
141 while (mutex->value != 0) {
142 mutex->waiters++;
64d4d313 143 pthread_cond_wait(&mutex->cond, &mutex->lock);
4d4e80f2
JA
144 mutex->waiters--;
145 }
146
64d4d313
JA
147 mutex->value--;
148 pthread_mutex_unlock(&mutex->lock);
149}
150
151void fio_mutex_down_read(struct fio_mutex *mutex)
152{
153 pthread_mutex_lock(&mutex->lock);
4d4e80f2
JA
154
155 while (mutex->value < 0) {
156 mutex->waiters++;
64d4d313 157 pthread_cond_wait(&mutex->cond, &mutex->lock);
4d4e80f2
JA
158 mutex->waiters--;
159 }
160
64d4d313
JA
161 mutex->value++;
162 pthread_mutex_unlock(&mutex->lock);
163}
164
165void fio_mutex_up_read(struct fio_mutex *mutex)
166{
167 pthread_mutex_lock(&mutex->lock);
168 mutex->value--;
4d4e80f2
JA
169 read_barrier();
170 if (mutex->value >= 0 && mutex->waiters)
64d4d313
JA
171 pthread_cond_signal(&mutex->cond);
172 pthread_mutex_unlock(&mutex->lock);
173}
174
175void fio_mutex_up_write(struct fio_mutex *mutex)
176{
177 pthread_mutex_lock(&mutex->lock);
178 mutex->value++;
4d4e80f2
JA
179 read_barrier();
180 if (mutex->value >= 0 && mutex->waiters)
64d4d313
JA
181 pthread_cond_signal(&mutex->cond);
182 pthread_mutex_unlock(&mutex->lock);
183}