summaryrefslogtreecommitdiff
path: root/mutex.c
diff options
context:
space:
mode:
authorJens Axboe <jens.axboe@oracle.com>2007-03-08 20:25:46 +0100
committerJens Axboe <jens.axboe@oracle.com>2007-03-08 20:25:46 +0100
commit07739b57f09886b41323c605b0dbda7d2c12522b (patch)
tree409d5f6aa8930f6ed738a98e82af8ba80f77bafd /mutex.c
parentde64df05bb69d38b7ecf548d9e15573b9010704a (diff)
downloadfio-07739b57f09886b41323c605b0dbda7d2c12522b.tar.gz
Add a real semaphore implemtation
I've seen races where job N+1 got started before N, this breaks for dependent jobs. So give up and implement a real semaphore in mmap'ed shared storage. Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'mutex.c')
-rw-r--r--mutex.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/mutex.c b/mutex.c
new file mode 100644
index 00000000..bb417c27
--- /dev/null
+++ b/mutex.c
@@ -0,0 +1,85 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <sys/mman.h>
+
+#include "mutex.h"
+
+void fio_sem_remove(struct fio_sem *sem)
+{
+ unlink(sem->sem_name);
+ munmap(sem, sizeof(*sem));
+}
+
+struct fio_sem *fio_sem_init(int value)
+{
+ pthread_mutexattr_t attr;
+ struct fio_sem *sem;
+ char sem_name[32];
+ int fd;
+
+ sprintf(sem_name, "/tmp/.fio_lock.XXXXXX");
+ fd = mkstemp(sem_name);
+ if (fd < 0) {
+ perror("open sem");
+ return NULL;
+ }
+
+ if (ftruncate(fd, sizeof(struct fio_sem)) < 0) {
+ perror("ftruncate sem");
+ return NULL;
+ }
+
+ sem = mmap(NULL, sizeof(struct fio_sem), PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ if (sem == MAP_FAILED) {
+ perror("mmap sem");
+ close(fd);
+ unlink(sem_name);
+ return NULL;
+ }
+
+ close(fd);
+ sem->value = value;
+ strcpy(sem->sem_name, sem_name);
+
+ if (pthread_mutexattr_init(&attr)) {
+ perror("pthread_mutexattr_init");
+ goto err;
+ }
+ if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
+ perror("pthread_mutexattr_setpshared");
+ goto err;
+ }
+ if (pthread_mutex_init(&sem->lock, &attr)) {
+ perror("pthread_mutex_init");
+ goto err;
+ }
+
+ return sem;
+err:
+ munmap(sem, sizeof(*sem));
+ unlink(sem_name);
+ return NULL;
+}
+
+void fio_sem_down(struct fio_sem *sem)
+{
+ pthread_mutex_lock(&sem->lock);
+ while (sem->value == 0)
+ pthread_cond_wait(&sem->cond, &sem->lock);
+ sem->value--;
+ pthread_mutex_unlock(&sem->lock);
+}
+
+void fio_sem_up(struct fio_sem *sem)
+{
+ pthread_mutex_lock(&sem->lock);
+ if (!sem->value)
+ pthread_cond_signal(&sem->cond);
+ sem->value++;
+ pthread_mutex_unlock(&sem->lock);
+}