+#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <assert.h>
+#ifdef CONFIG_VALGRIND_DEV
+#include <valgrind/valgrind.h>
+#else
+#define RUNNING_ON_VALGRIND 0
+#endif
-#include "log.h"
#include "fio_sem.h"
#include "pshared.h"
#include "os/os.h"
void __fio_sem_remove(struct fio_sem *sem)
{
assert(sem->magic == FIO_SEM_MAGIC);
+ pthread_mutex_destroy(&sem->lock);
pthread_cond_destroy(&sem->cond);
/*
- * Ensure any subsequent attempt to grab this semaphore will fail
- * with an assert, instead of just silently hanging.
- */
- memset(sem, 0, sizeof(*sem));
+ * When not running on Valgrind, ensure any subsequent attempt to grab
+ * this semaphore will fail with an assert, instead of just silently
+ * hanging. When running on Valgrind, let Valgrind detect
+ * use-after-free.
+ */
+ if (!RUNNING_ON_VALGRIND)
+ memset(sem, 0, sizeof(*sem));
}
void fio_sem_remove(struct fio_sem *sem)
int ret;
sem->value = value;
+ /* Initialize .waiters explicitly for Valgrind. */
+ sem->waiters = 0;
sem->magic = FIO_SEM_MAGIC;
ret = mutex_cond_init_pshared(&sem->lock, &sem->cond);
int fio_sem_down_timeout(struct fio_sem *sem, unsigned int msecs)
{
- struct timeval tv_s;
struct timespec base;
struct timespec t;
int ret = 0;
assert(sem->magic == FIO_SEM_MAGIC);
- gettimeofday(&tv_s, NULL);
- base.tv_sec = t.tv_sec = tv_s.tv_sec;
- base.tv_nsec = t.tv_nsec = tv_s.tv_usec * 1000;
+#ifdef CONFIG_PTHREAD_CONDATTR_SETCLOCK
+ clock_gettime(CLOCK_MONOTONIC, &t);
+#else
+ clock_gettime(CLOCK_REALTIME, &t);
+#endif
+
+ base = t;
t.tv_sec += msecs / 1000;
t.tv_nsec += ((msecs * 1000000ULL) % 1000000000);
assert(sem->magic == FIO_SEM_MAGIC);
pthread_mutex_lock(&sem->lock);
- read_barrier();
if (!sem->value && sem->waiters)
do_wake = 1;
sem->value++;