12 void __fio_sem_remove(struct fio_sem *sem)
14 assert(sem->magic == FIO_SEM_MAGIC);
15 pthread_cond_destroy(&sem->cond);
18 * Ensure any subsequent attempt to grab this semaphore will fail
19 * with an assert, instead of just silently hanging.
21 memset(sem, 0, sizeof(*sem));
24 void fio_sem_remove(struct fio_sem *sem)
26 __fio_sem_remove(sem);
27 munmap((void *) sem, sizeof(*sem));
30 int __fio_sem_init(struct fio_sem *sem, int value)
35 sem->magic = FIO_SEM_MAGIC;
37 ret = mutex_cond_init_pshared(&sem->lock, &sem->cond);
44 struct fio_sem *fio_sem_init(int value)
46 struct fio_sem *sem = NULL;
48 sem = (void *) mmap(NULL, sizeof(struct fio_sem),
49 PROT_READ | PROT_WRITE,
50 OS_MAP_ANON | MAP_SHARED, -1, 0);
51 if (sem == MAP_FAILED) {
52 perror("mmap semaphore");
56 if (!__fio_sem_init(sem, value))
63 static bool sem_timed_out(struct timespec *t, unsigned int msecs)
68 gettimeofday(&tv, NULL);
69 now.tv_sec = tv.tv_sec;
70 now.tv_nsec = tv.tv_usec * 1000;
72 return mtime_since(t, &now) >= msecs;
75 int fio_sem_down_timeout(struct fio_sem *sem, unsigned int msecs)
82 assert(sem->magic == FIO_SEM_MAGIC);
84 gettimeofday(&tv_s, NULL);
85 base.tv_sec = t.tv_sec = tv_s.tv_sec;
86 base.tv_nsec = t.tv_nsec = tv_s.tv_usec * 1000;
88 t.tv_sec += msecs / 1000;
89 t.tv_nsec += ((msecs * 1000000ULL) % 1000000000);
90 if (t.tv_nsec >= 1000000000) {
91 t.tv_nsec -= 1000000000;
95 pthread_mutex_lock(&sem->lock);
98 while (!sem->value && !ret) {
100 * Some platforms (FreeBSD 9?) seems to return timed out
101 * way too early, double check.
103 ret = pthread_cond_timedwait(&sem->cond, &sem->lock, &t);
104 if (ret == ETIMEDOUT && !sem_timed_out(&base, msecs))
111 pthread_mutex_unlock(&sem->lock);
115 pthread_mutex_unlock(&sem->lock);
119 bool fio_sem_down_trylock(struct fio_sem *sem)
123 assert(sem->magic == FIO_SEM_MAGIC);
125 pthread_mutex_lock(&sem->lock);
130 pthread_mutex_unlock(&sem->lock);
135 void fio_sem_down(struct fio_sem *sem)
137 assert(sem->magic == FIO_SEM_MAGIC);
139 pthread_mutex_lock(&sem->lock);
141 while (!sem->value) {
143 pthread_cond_wait(&sem->cond, &sem->lock);
148 pthread_mutex_unlock(&sem->lock);
151 void fio_sem_up(struct fio_sem *sem)
155 assert(sem->magic == FIO_SEM_MAGIC);
157 pthread_mutex_lock(&sem->lock);
159 if (!sem->value && sem->waiters)
164 pthread_cond_signal(&sem->cond);
166 pthread_mutex_unlock(&sem->lock);