print_config "strndup" "$strndup"
##########################################
+# <valgrind/drd.h> probe
+# Note: presence of <valgrind/drd.h> implies that <valgrind/valgrind.h> is
+# also available but not the other way around.
+if test "$valgrind_dev" != "yes" ; then
+ valgrind_dev="no"
+fi
+cat > $TMPC << EOF
+#include <valgrind/drd.h>
+int main(int argc, char **argv)
+{
+ return 0;
+}
+EOF
+if compile_prog "" "" "valgrind_dev"; then
+ valgrind_dev="yes"
+fi
+print_config "Valgrind headers" "$valgrind_dev"
+
# check march=armv8-a+crc+crypto
if test "$march_armv8_a_crc_crypto" != "yes" ; then
march_armv8_a_crc_crypto="no"
if test "$disable_opt" = "yes" ; then
output_sym "CONFIG_DISABLE_OPTIMIZATIONS"
fi
+if test "$valgrind_dev" = "yes"; then
+ output_sym "CONFIG_VALGRIND_DEV"
+fi
if test "$zlib" = "no" ; then
echo "Consider installing zlib-dev (zlib-devel, some fio features depend on it."
if test "$build_static" = "yes"; then
#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"
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);
void fio_rwlock_remove(struct fio_rwlock *lock)
{
assert(lock->magic == FIO_RWLOCK_MAGIC);
+ pthread_rwlock_destroy(&lock->lock);
munmap((void *) lock, sizeof(*lock));
}
#include <sys/types.h>
#include <limits.h>
#include <fcntl.h>
+#ifdef CONFIG_VALGRIND_DEV
+#include <valgrind/valgrind.h>
+#else
+#define RUNNING_ON_VALGRIND 0
+#define VALGRIND_MALLOCLIKE_BLOCK(addr, size, rzB, is_zeroed) do { } while (0)
+#define VALGRIND_FREELIKE_BLOCK(addr, rzB) do { } while (0)
+#endif
#include "fio.h"
#include "fio_sem.h"
size_t mmap_size;
};
+#ifdef SMALLOC_REDZONE
+#define REDZONE_SIZE sizeof(unsigned int)
+#else
+#define REDZONE_SIZE 0
+#endif
+
struct block_hdr {
size_t size;
#ifdef SMALLOC_REDZONE
{
unsigned int *postred = postred_ptr(hdr);
+ /* Let Valgrind fill the red zones. */
+ if (RUNNING_ON_VALGRIND)
+ return;
+
hdr->prered = SMALLOC_PRE_RED;
*postred = SMALLOC_POST_RED;
}
{
unsigned int *postred = postred_ptr(hdr);
+ /* Let Valgrind check the red zones. */
+ if (RUNNING_ON_VALGRIND)
+ return;
+
if (hdr->prered != SMALLOC_PRE_RED) {
log_err("smalloc pre redzone destroyed!\n"
" ptr=%p, prered=%x, expected %x\n",
}
if (pool) {
+ VALGRIND_FREELIKE_BLOCK(ptr, REDZONE_SIZE);
sfree_pool(pool, ptr);
return;
}
return ptr;
}
-void *smalloc(size_t size)
+static void *__smalloc(size_t size, bool is_zeroed)
{
unsigned int i, end_pool;
if (ptr) {
last_pool = i;
+ VALGRIND_MALLOCLIKE_BLOCK(ptr, size,
+ REDZONE_SIZE,
+ is_zeroed);
return ptr;
}
}
return NULL;
}
+void *smalloc(size_t size)
+{
+ return __smalloc(size, false);
+}
+
void *scalloc(size_t nmemb, size_t size)
{
- return smalloc(nmemb * size);
+ return __smalloc(nmemb * size, true);
}
char *smalloc_strdup(const char *str)