diff options
author | Jens Axboe <jens.axboe@oracle.com> | 2007-03-08 20:25:46 +0100 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2007-03-08 20:25:46 +0100 |
commit | 07739b57f09886b41323c605b0dbda7d2c12522b (patch) | |
tree | 409d5f6aa8930f6ed738a98e82af8ba80f77bafd /mutex.c | |
parent | de64df05bb69d38b7ecf548d9e15573b9010704a (diff) | |
download | fio-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.c | 85 |
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); +} |