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