Fixup handling of pthread_mutex*() error returns
[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;
4fa6d0f8 25 int fd, ret;
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
4fa6d0f8
JA
51 ret = pthread_mutexattr_init(&attr);
52 if (ret) {
53 log_err("pthread_mutexattr_init: %s\n", strerror(ret));
07739b57
JA
54 goto err;
55 }
4fa6d0f8
JA
56 ret = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
57 if (ret) {
58 log_err("pthread_mutexattr_setpshared: %s\n", strerror(ret));
07739b57
JA
59 goto err;
60 }
108fcc11
ZY
61
62 pthread_condattr_init(&cond);
63 pthread_condattr_setpshared(&cond, PTHREAD_PROCESS_SHARED);
cdd18ad8 64 pthread_cond_init(&mutex->cond, &cond);
108fcc11 65
4fa6d0f8
JA
66 ret = pthread_mutex_init(&mutex->lock, &attr);
67 if (ret) {
68 log_err("pthread_mutex_init: %s\n", strerror(ret));
07739b57
JA
69 goto err;
70 }
71
cdd18ad8 72 return mutex;
07739b57 73err:
cdd18ad8
JA
74 if (mutex)
75 fio_mutex_remove(mutex);
f7c9e00e 76
cdd18ad8 77 unlink(mutex_name);
07739b57
JA
78 return NULL;
79}
80
cdd18ad8 81void fio_mutex_down(struct fio_mutex *mutex)
07739b57 82{
cdd18ad8 83 pthread_mutex_lock(&mutex->lock);
4d4e80f2
JA
84
85 while (!mutex->value) {
86 mutex->waiters++;
cdd18ad8 87 pthread_cond_wait(&mutex->cond, &mutex->lock);
4d4e80f2
JA
88 mutex->waiters--;
89 }
90
cdd18ad8
JA
91 mutex->value--;
92 pthread_mutex_unlock(&mutex->lock);
07739b57
JA
93}
94
cdd18ad8 95void fio_mutex_up(struct fio_mutex *mutex)
07739b57 96{
cdd18ad8 97 pthread_mutex_lock(&mutex->lock);
4d4e80f2
JA
98 read_barrier();
99 if (!mutex->value && mutex->waiters)
cdd18ad8
JA
100 pthread_cond_signal(&mutex->cond);
101 mutex->value++;
102 pthread_mutex_unlock(&mutex->lock);
07739b57 103}
64d4d313
JA
104
105void fio_mutex_down_write(struct fio_mutex *mutex)
106{
107 pthread_mutex_lock(&mutex->lock);
4d4e80f2
JA
108
109 while (mutex->value != 0) {
110 mutex->waiters++;
64d4d313 111 pthread_cond_wait(&mutex->cond, &mutex->lock);
4d4e80f2
JA
112 mutex->waiters--;
113 }
114
64d4d313
JA
115 mutex->value--;
116 pthread_mutex_unlock(&mutex->lock);
117}
118
119void fio_mutex_down_read(struct fio_mutex *mutex)
120{
121 pthread_mutex_lock(&mutex->lock);
4d4e80f2
JA
122
123 while (mutex->value < 0) {
124 mutex->waiters++;
64d4d313 125 pthread_cond_wait(&mutex->cond, &mutex->lock);
4d4e80f2
JA
126 mutex->waiters--;
127 }
128
64d4d313
JA
129 mutex->value++;
130 pthread_mutex_unlock(&mutex->lock);
131}
132
133void fio_mutex_up_read(struct fio_mutex *mutex)
134{
135 pthread_mutex_lock(&mutex->lock);
136 mutex->value--;
4d4e80f2
JA
137 read_barrier();
138 if (mutex->value >= 0 && mutex->waiters)
64d4d313
JA
139 pthread_cond_signal(&mutex->cond);
140 pthread_mutex_unlock(&mutex->lock);
141}
142
143void fio_mutex_up_write(struct fio_mutex *mutex)
144{
145 pthread_mutex_lock(&mutex->lock);
146 mutex->value++;
4d4e80f2
JA
147 read_barrier();
148 if (mutex->value >= 0 && mutex->waiters)
64d4d313
JA
149 pthread_cond_signal(&mutex->cond);
150 pthread_mutex_unlock(&mutex->lock);
151}