| #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) |
| { |
| close(sem->sem_fd); |
| munmap(sem, sizeof(*sem)); |
| } |
| |
| struct fio_sem *fio_sem_init(int value) |
| { |
| char sem_name[] = "/tmp/.fio_sem.XXXXXX"; |
| struct fio_sem *sem = NULL; |
| pthread_mutexattr_t attr; |
| int fd; |
| |
| fd = mkstemp(sem_name); |
| if (fd < 0) { |
| perror("open sem"); |
| return NULL; |
| } |
| |
| if (ftruncate(fd, sizeof(struct fio_sem)) < 0) { |
| perror("ftruncate sem"); |
| goto err; |
| } |
| |
| sem = mmap(NULL, sizeof(struct fio_sem), PROT_READ | PROT_WRITE, |
| MAP_SHARED, fd, 0); |
| if (sem == MAP_FAILED) { |
| perror("mmap sem"); |
| close(fd); |
| sem = NULL; |
| goto err; |
| } |
| |
| unlink(sem_name); |
| sem->sem_fd = fd; |
| sem->value = value; |
| |
| 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: |
| if (sem) |
| fio_sem_remove(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); |
| } |