blob: 0f13064af8f26929d3aeac09a22de8331d0e9fa3 [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>
6#include <pthread.h>
7#include <sys/mman.h>
8
9#include "mutex.h"
Jens Axboe4d4e80f2008-03-04 10:18:56 +010010#include "arch/arch.h"
Jens Axboe07739b52007-03-08 20:25:46 +010011
Jens Axboecdd18ad2008-02-27 18:58:00 +010012void fio_mutex_remove(struct fio_mutex *mutex)
Jens Axboe07739b52007-03-08 20:25:46 +010013{
Jens Axboecdd18ad2008-02-27 18:58:00 +010014 close(mutex->mutex_fd);
Jens Axboe5921e802008-05-30 15:02:38 +020015 munmap((void *) mutex, sizeof(*mutex));
Jens Axboe07739b52007-03-08 20:25:46 +010016}
17
Jens Axboecdd18ad2008-02-27 18:58:00 +010018struct fio_mutex *fio_mutex_init(int value)
Jens Axboe07739b52007-03-08 20:25:46 +010019{
Jens Axboecdd18ad2008-02-27 18:58:00 +010020 char mutex_name[] = "/tmp/.fio_mutex.XXXXXX";
21 struct fio_mutex *mutex = NULL;
Jens Axboe07739b52007-03-08 20:25:46 +010022 pthread_mutexattr_t attr;
Zhang, Yanmin108fcc12008-02-04 09:17:52 +010023 pthread_condattr_t cond;
Jens Axboe07739b52007-03-08 20:25:46 +010024 int fd;
25
Jens Axboecdd18ad2008-02-27 18:58:00 +010026 fd = mkstemp(mutex_name);
Jens Axboe07739b52007-03-08 20:25:46 +010027 if (fd < 0) {
Jens Axboecdd18ad2008-02-27 18:58:00 +010028 perror("open mutex");
Jens Axboe07739b52007-03-08 20:25:46 +010029 return NULL;
30 }
31
Jens Axboecdd18ad2008-02-27 18:58:00 +010032 if (ftruncate(fd, sizeof(struct fio_mutex)) < 0) {
33 perror("ftruncate mutex");
Jens Axboee53bd0b2007-03-08 20:29:11 +010034 goto err;
Jens Axboe07739b52007-03-08 20:25:46 +010035 }
36
Jens Axboe5921e802008-05-30 15:02:38 +020037 mutex = (void *) mmap(NULL, sizeof(struct fio_mutex),
38 PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
Jens Axboecdd18ad2008-02-27 18:58:00 +010039 if (mutex == MAP_FAILED) {
40 perror("mmap mutex");
Jens Axboe07739b52007-03-08 20:25:46 +010041 close(fd);
Jens Axboecdd18ad2008-02-27 18:58:00 +010042 mutex = NULL;
Jens Axboee53bd0b2007-03-08 20:29:11 +010043 goto err;
Jens Axboe07739b52007-03-08 20:25:46 +010044 }
45
Jens Axboecdd18ad2008-02-27 18:58:00 +010046 unlink(mutex_name);
47 mutex->mutex_fd = fd;
48 mutex->value = value;
Jens Axboe07739b52007-03-08 20:25:46 +010049
Jens Axboe42124d32008-06-02 12:50:10 +020050 if (pthread_mutexattr_init(&attr) < 0) {
Jens Axboe07739b52007-03-08 20:25:46 +010051 perror("pthread_mutexattr_init");
52 goto err;
53 }
Jens Axboe42124d32008-06-02 12:50:10 +020054 if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED) < 0) {
Jens Axboe07739b52007-03-08 20:25:46 +010055 perror("pthread_mutexattr_setpshared");
56 goto err;
57 }
Zhang, Yanmin108fcc12008-02-04 09:17:52 +010058
59 pthread_condattr_init(&cond);
60 pthread_condattr_setpshared(&cond, PTHREAD_PROCESS_SHARED);
Jens Axboecdd18ad2008-02-27 18:58:00 +010061 pthread_cond_init(&mutex->cond, &cond);
Zhang, Yanmin108fcc12008-02-04 09:17:52 +010062
Jens Axboe42124d32008-06-02 12:50:10 +020063 if (pthread_mutex_init(&mutex->lock, &attr) < 0) {
Jens Axboe07739b52007-03-08 20:25:46 +010064 perror("pthread_mutex_init");
65 goto err;
66 }
67
Jens Axboecdd18ad2008-02-27 18:58:00 +010068 return mutex;
Jens Axboe07739b52007-03-08 20:25:46 +010069err:
Jens Axboecdd18ad2008-02-27 18:58:00 +010070 if (mutex)
71 fio_mutex_remove(mutex);
Jens Axboef7c9e002007-03-09 12:40:02 +010072
Jens Axboecdd18ad2008-02-27 18:58:00 +010073 unlink(mutex_name);
Jens Axboe07739b52007-03-08 20:25:46 +010074 return NULL;
75}
76
Jens Axboecdd18ad2008-02-27 18:58:00 +010077void fio_mutex_down(struct fio_mutex *mutex)
Jens Axboe07739b52007-03-08 20:25:46 +010078{
Jens Axboecdd18ad2008-02-27 18:58:00 +010079 pthread_mutex_lock(&mutex->lock);
Jens Axboe4d4e80f2008-03-04 10:18:56 +010080
81 while (!mutex->value) {
82 mutex->waiters++;
Jens Axboecdd18ad2008-02-27 18:58:00 +010083 pthread_cond_wait(&mutex->cond, &mutex->lock);
Jens Axboe4d4e80f2008-03-04 10:18:56 +010084 mutex->waiters--;
85 }
86
Jens Axboecdd18ad2008-02-27 18:58:00 +010087 mutex->value--;
88 pthread_mutex_unlock(&mutex->lock);
Jens Axboe07739b52007-03-08 20:25:46 +010089}
90
Jens Axboecdd18ad2008-02-27 18:58:00 +010091void fio_mutex_up(struct fio_mutex *mutex)
Jens Axboe07739b52007-03-08 20:25:46 +010092{
Jens Axboecdd18ad2008-02-27 18:58:00 +010093 pthread_mutex_lock(&mutex->lock);
Jens Axboe4d4e80f2008-03-04 10:18:56 +010094 read_barrier();
95 if (!mutex->value && mutex->waiters)
Jens Axboecdd18ad2008-02-27 18:58:00 +010096 pthread_cond_signal(&mutex->cond);
97 mutex->value++;
98 pthread_mutex_unlock(&mutex->lock);
Jens Axboe07739b52007-03-08 20:25:46 +010099}
Jens Axboe64d4d312008-03-03 10:36:27 +0100100
101void fio_mutex_down_write(struct fio_mutex *mutex)
102{
103 pthread_mutex_lock(&mutex->lock);
Jens Axboe4d4e80f2008-03-04 10:18:56 +0100104
105 while (mutex->value != 0) {
106 mutex->waiters++;
Jens Axboe64d4d312008-03-03 10:36:27 +0100107 pthread_cond_wait(&mutex->cond, &mutex->lock);
Jens Axboe4d4e80f2008-03-04 10:18:56 +0100108 mutex->waiters--;
109 }
110
Jens Axboe64d4d312008-03-03 10:36:27 +0100111 mutex->value--;
112 pthread_mutex_unlock(&mutex->lock);
113}
114
115void fio_mutex_down_read(struct fio_mutex *mutex)
116{
117 pthread_mutex_lock(&mutex->lock);
Jens Axboe4d4e80f2008-03-04 10:18:56 +0100118
119 while (mutex->value < 0) {
120 mutex->waiters++;
Jens Axboe64d4d312008-03-03 10:36:27 +0100121 pthread_cond_wait(&mutex->cond, &mutex->lock);
Jens Axboe4d4e80f2008-03-04 10:18:56 +0100122 mutex->waiters--;
123 }
124
Jens Axboe64d4d312008-03-03 10:36:27 +0100125 mutex->value++;
126 pthread_mutex_unlock(&mutex->lock);
127}
128
129void fio_mutex_up_read(struct fio_mutex *mutex)
130{
131 pthread_mutex_lock(&mutex->lock);
132 mutex->value--;
Jens Axboe4d4e80f2008-03-04 10:18:56 +0100133 read_barrier();
134 if (mutex->value >= 0 && mutex->waiters)
Jens Axboe64d4d312008-03-03 10:36:27 +0100135 pthread_cond_signal(&mutex->cond);
136 pthread_mutex_unlock(&mutex->lock);
137}
138
139void fio_mutex_up_write(struct fio_mutex *mutex)
140{
141 pthread_mutex_lock(&mutex->lock);
142 mutex->value++;
Jens Axboe4d4e80f2008-03-04 10:18:56 +0100143 read_barrier();
144 if (mutex->value >= 0 && mutex->waiters)
Jens Axboe64d4d312008-03-03 10:36:27 +0100145 pthread_cond_signal(&mutex->cond);
146 pthread_mutex_unlock(&mutex->lock);
147}