blob: e33e7cc8f2611a42256e72a3bceddf9e7560b1ef [file] [log] [blame]
Jens Axboe07739b52007-03-08 20:25:46 +01001#include <stdio.h>
2#include <string.h>
3#include <unistd.h>
4#include <stdlib.h>
5#include <fcntl.h>
Jens Axboe656b1392009-07-01 23:02:10 +02006#include <time.h>
Jens Axboe07739b52007-03-08 20:25:46 +01007#include <pthread.h>
8#include <sys/mman.h>
9
Jens Axboe4fa6d0f2009-01-05 09:45:13 +010010#include "log.h"
Jens Axboe07739b52007-03-08 20:25:46 +010011#include "mutex.h"
Jens Axboe4d4e80f2008-03-04 10:18:56 +010012#include "arch/arch.h"
Jens Axboe3c2d93e2009-01-05 19:04:15 +010013#include "os/os.h"
Jens Axboe3b2e1462009-12-15 08:58:10 +010014#include "helpers.h"
Jens Axboe07739b52007-03-08 20:25:46 +010015
Jens Axboecdd18ad2008-02-27 18:58:00 +010016void fio_mutex_remove(struct fio_mutex *mutex)
Jens Axboe07739b52007-03-08 20:25:46 +010017{
Jens Axboecdd18ad2008-02-27 18:58:00 +010018 close(mutex->mutex_fd);
Jens Axboe5921e802008-05-30 15:02:38 +020019 munmap((void *) mutex, sizeof(*mutex));
Jens Axboe07739b52007-03-08 20:25:46 +010020}
21
Jens Axboecdd18ad2008-02-27 18:58:00 +010022struct fio_mutex *fio_mutex_init(int value)
Jens Axboe07739b52007-03-08 20:25:46 +010023{
Jens Axboecdd18ad2008-02-27 18:58:00 +010024 char mutex_name[] = "/tmp/.fio_mutex.XXXXXX";
25 struct fio_mutex *mutex = NULL;
Jens Axboe07739b52007-03-08 20:25:46 +010026 pthread_mutexattr_t attr;
Zhang, Yanmin108fcc12008-02-04 09:17:52 +010027 pthread_condattr_t cond;
Jens Axboef356d012009-01-05 09:56:29 +010028 int fd, ret, mflag;
Jens Axboe07739b52007-03-08 20:25:46 +010029
Jens Axboecdd18ad2008-02-27 18:58:00 +010030 fd = mkstemp(mutex_name);
Jens Axboe07739b52007-03-08 20:25:46 +010031 if (fd < 0) {
Jens Axboecdd18ad2008-02-27 18:58:00 +010032 perror("open mutex");
Jens Axboe07739b52007-03-08 20:25:46 +010033 return NULL;
34 }
35
Greg Edwards3a8600b2010-06-25 09:24:19 -060036#ifdef FIO_HAVE_FALLOCATE
Bruce Cran9b836562011-01-08 19:49:54 +010037 posix_fallocate(fd, 0, sizeof(struct fio_mutex));
Greg Edwards3a8600b2010-06-25 09:24:19 -060038#endif
39
Jens Axboecdd18ad2008-02-27 18:58:00 +010040 if (ftruncate(fd, sizeof(struct fio_mutex)) < 0) {
41 perror("ftruncate mutex");
Jens Axboee53bd0b2007-03-08 20:29:11 +010042 goto err;
Jens Axboe07739b52007-03-08 20:25:46 +010043 }
44
Jens Axboe5921e802008-05-30 15:02:38 +020045 mutex = (void *) mmap(NULL, sizeof(struct fio_mutex),
46 PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
Jens Axboecdd18ad2008-02-27 18:58:00 +010047 if (mutex == MAP_FAILED) {
48 perror("mmap mutex");
Jens Axboe07739b52007-03-08 20:25:46 +010049 close(fd);
Jens Axboecdd18ad2008-02-27 18:58:00 +010050 mutex = NULL;
Jens Axboee53bd0b2007-03-08 20:29:11 +010051 goto err;
Jens Axboe07739b52007-03-08 20:25:46 +010052 }
53
Jens Axboecdd18ad2008-02-27 18:58:00 +010054 unlink(mutex_name);
55 mutex->mutex_fd = fd;
56 mutex->value = value;
Jens Axboe07739b52007-03-08 20:25:46 +010057
Jens Axboef356d012009-01-05 09:56:29 +010058 /*
59 * Not all platforms support process shared mutexes (FreeBSD)
60 */
61#ifdef FIO_HAVE_PSHARED_MUTEX
62 mflag = PTHREAD_PROCESS_SHARED;
63#else
64 mflag = PTHREAD_PROCESS_PRIVATE;
65#endif
66
Jens Axboe4fa6d0f2009-01-05 09:45:13 +010067 ret = pthread_mutexattr_init(&attr);
68 if (ret) {
69 log_err("pthread_mutexattr_init: %s\n", strerror(ret));
Jens Axboe07739b52007-03-08 20:25:46 +010070 goto err;
71 }
YAMAMOTO Takashi74524402010-05-12 15:06:46 +020072#ifdef FIO_HAVE_PSHARED_MUTEX
Jens Axboef356d012009-01-05 09:56:29 +010073 ret = pthread_mutexattr_setpshared(&attr, mflag);
Jens Axboe4fa6d0f2009-01-05 09:45:13 +010074 if (ret) {
75 log_err("pthread_mutexattr_setpshared: %s\n", strerror(ret));
Jens Axboe07739b52007-03-08 20:25:46 +010076 goto err;
77 }
YAMAMOTO Takashi74524402010-05-12 15:06:46 +020078#endif
Zhang, Yanmin108fcc12008-02-04 09:17:52 +010079
80 pthread_condattr_init(&cond);
YAMAMOTO Takashi74524402010-05-12 15:06:46 +020081#ifdef FIO_HAVE_PSHARED_MUTEX
Jens Axboef356d012009-01-05 09:56:29 +010082 pthread_condattr_setpshared(&cond, mflag);
YAMAMOTO Takashi74524402010-05-12 15:06:46 +020083#endif
Jens Axboecdd18ad2008-02-27 18:58:00 +010084 pthread_cond_init(&mutex->cond, &cond);
Zhang, Yanmin108fcc12008-02-04 09:17:52 +010085
Jens Axboe4fa6d0f2009-01-05 09:45:13 +010086 ret = pthread_mutex_init(&mutex->lock, &attr);
87 if (ret) {
88 log_err("pthread_mutex_init: %s\n", strerror(ret));
Jens Axboe07739b52007-03-08 20:25:46 +010089 goto err;
90 }
91
Bruce Cran03e20d62011-01-02 20:14:54 +010092 pthread_condattr_destroy(&cond);
93 pthread_mutexattr_destroy(&attr);
94
Jens Axboecdd18ad2008-02-27 18:58:00 +010095 return mutex;
Jens Axboe07739b52007-03-08 20:25:46 +010096err:
Jens Axboecdd18ad2008-02-27 18:58:00 +010097 if (mutex)
98 fio_mutex_remove(mutex);
Jens Axboef7c9e002007-03-09 12:40:02 +010099
Jens Axboecdd18ad2008-02-27 18:58:00 +0100100 unlink(mutex_name);
Jens Axboe07739b52007-03-08 20:25:46 +0100101 return NULL;
102}
103
Jens Axboe656b1392009-07-01 23:02:10 +0200104int fio_mutex_down_timeout(struct fio_mutex *mutex, unsigned int seconds)
105{
106 struct timespec t;
107 int ret = 0;
108
Jens Axboed481e002009-12-04 09:56:32 +0100109 clock_gettime(CLOCK_REALTIME, &t);
Jens Axboe656b1392009-07-01 23:02:10 +0200110 t.tv_sec += seconds;
111
112 pthread_mutex_lock(&mutex->lock);
113
114 while (!mutex->value && !ret) {
115 mutex->waiters++;
116 ret = pthread_cond_timedwait(&mutex->cond, &mutex->lock, &t);
117 mutex->waiters--;
118 }
119
120 if (!ret) {
121 mutex->value--;
122 pthread_mutex_unlock(&mutex->lock);
123 }
124
125 return ret;
126}
127
Jens Axboecdd18ad2008-02-27 18:58:00 +0100128void fio_mutex_down(struct fio_mutex *mutex)
Jens Axboe07739b52007-03-08 20:25:46 +0100129{
Jens Axboecdd18ad2008-02-27 18:58:00 +0100130 pthread_mutex_lock(&mutex->lock);
Jens Axboe4d4e80f2008-03-04 10:18:56 +0100131
132 while (!mutex->value) {
133 mutex->waiters++;
Jens Axboecdd18ad2008-02-27 18:58:00 +0100134 pthread_cond_wait(&mutex->cond, &mutex->lock);
Jens Axboe4d4e80f2008-03-04 10:18:56 +0100135 mutex->waiters--;
136 }
137
Jens Axboecdd18ad2008-02-27 18:58:00 +0100138 mutex->value--;
139 pthread_mutex_unlock(&mutex->lock);
Jens Axboe07739b52007-03-08 20:25:46 +0100140}
141
Jens Axboecdd18ad2008-02-27 18:58:00 +0100142void fio_mutex_up(struct fio_mutex *mutex)
Jens Axboe07739b52007-03-08 20:25:46 +0100143{
Jens Axboecdd18ad2008-02-27 18:58:00 +0100144 pthread_mutex_lock(&mutex->lock);
Jens Axboe4d4e80f2008-03-04 10:18:56 +0100145 read_barrier();
146 if (!mutex->value && mutex->waiters)
Jens Axboecdd18ad2008-02-27 18:58:00 +0100147 pthread_cond_signal(&mutex->cond);
148 mutex->value++;
149 pthread_mutex_unlock(&mutex->lock);
Jens Axboe07739b52007-03-08 20:25:46 +0100150}
Jens Axboe64d4d312008-03-03 10:36:27 +0100151
152void fio_mutex_down_write(struct fio_mutex *mutex)
153{
154 pthread_mutex_lock(&mutex->lock);
Jens Axboe4d4e80f2008-03-04 10:18:56 +0100155
156 while (mutex->value != 0) {
157 mutex->waiters++;
Jens Axboe64d4d312008-03-03 10:36:27 +0100158 pthread_cond_wait(&mutex->cond, &mutex->lock);
Jens Axboe4d4e80f2008-03-04 10:18:56 +0100159 mutex->waiters--;
160 }
161
Jens Axboe64d4d312008-03-03 10:36:27 +0100162 mutex->value--;
163 pthread_mutex_unlock(&mutex->lock);
164}
165
166void fio_mutex_down_read(struct fio_mutex *mutex)
167{
168 pthread_mutex_lock(&mutex->lock);
Jens Axboe4d4e80f2008-03-04 10:18:56 +0100169
170 while (mutex->value < 0) {
171 mutex->waiters++;
Jens Axboe64d4d312008-03-03 10:36:27 +0100172 pthread_cond_wait(&mutex->cond, &mutex->lock);
Jens Axboe4d4e80f2008-03-04 10:18:56 +0100173 mutex->waiters--;
174 }
175
Jens Axboe64d4d312008-03-03 10:36:27 +0100176 mutex->value++;
177 pthread_mutex_unlock(&mutex->lock);
178}
179
180void fio_mutex_up_read(struct fio_mutex *mutex)
181{
182 pthread_mutex_lock(&mutex->lock);
183 mutex->value--;
Jens Axboe4d4e80f2008-03-04 10:18:56 +0100184 read_barrier();
185 if (mutex->value >= 0 && mutex->waiters)
Jens Axboe64d4d312008-03-03 10:36:27 +0100186 pthread_cond_signal(&mutex->cond);
187 pthread_mutex_unlock(&mutex->lock);
188}
189
190void fio_mutex_up_write(struct fio_mutex *mutex)
191{
192 pthread_mutex_lock(&mutex->lock);
193 mutex->value++;
Jens Axboe4d4e80f2008-03-04 10:18:56 +0100194 read_barrier();
195 if (mutex->value >= 0 && mutex->waiters)
Jens Axboe64d4d312008-03-03 10:36:27 +0100196 pthread_cond_signal(&mutex->cond);
197 pthread_mutex_unlock(&mutex->lock);
198}