drd: Add semaphore annotations (#333072)
This is a slightly modified version of a patch from Ivo Raisr <ivosh@ivosh.net>
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13984 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/drd/drd.h b/drd/drd.h
index fa511e0..f82c2b2 100644
--- a/drd/drd.h
+++ b/drd/drd.h
@@ -271,6 +271,31 @@
*/
#define ANNOTATE_WRITERLOCK_RELEASED(rwlock) ANNOTATE_RWLOCK_RELEASED(rwlock, 1)
+/** Tell DRD that a semaphore object is going to be initialized. */
+#define ANNOTATE_SEM_INIT_PRE(sem, value) \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_SEM_INIT_PRE, \
+ sem, value, 0, 0, 0);
+
+/** Tell DRD that a semaphore object has been destroyed. */
+#define ANNOTATE_SEM_DESTROY_POST(sem) \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_SEM_DESTROY_POST, \
+ sem, 0, 0, 0, 0);
+
+/** Tell DRD that a semaphore is going to be acquired. */
+#define ANNOTATE_SEM_WAIT_PRE(sem) \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_SEM_WAIT_PRE, \
+ sem, 0, 0, 0, 0)
+
+/** Tell DRD that a semaphore has been acquired. */
+#define ANNOTATE_SEM_WAIT_POST(sem) \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_SEM_WAIT_POST, \
+ sem, 0, 0, 0, 0)
+
+/** Tell DRD that a semaphore is going to be released. */
+#define ANNOTATE_SEM_POST_PRE(sem) \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_SEM_POST_PRE, \
+ sem, 0, 0, 0, 0)
+
/*
* Report that a barrier has been initialized with a given barrier count. The
* third argument specifies whether or not reinitialization is allowed, that
@@ -442,6 +467,27 @@
VG_USERREQ__DRD_ANNOTATION_UNIMP,
/* args: char*. */
+ /* Tell DRD that a user-defined semaphore synchronization object
+ * is about to be created. */
+ VG_USERREQ__DRD_ANNOTATE_SEM_INIT_PRE,
+ /* args: Addr, UInt value. */
+ /* Tell DRD that a user-defined semaphore synchronization object
+ * has been destroyed. */
+ VG_USERREQ__DRD_ANNOTATE_SEM_DESTROY_POST,
+ /* args: Addr. */
+ /* Tell DRD that a user-defined semaphore synchronization
+ * object is going to be acquired (semaphore wait). */
+ VG_USERREQ__DRD_ANNOTATE_SEM_WAIT_PRE,
+ /* args: Addr. */
+ /* Tell DRD that a user-defined semaphore synchronization
+ * object has been acquired (semaphore wait). */
+ VG_USERREQ__DRD_ANNOTATE_SEM_WAIT_POST,
+ /* args: Addr. */
+ /* Tell DRD that a user-defined semaphore synchronization
+ * object is about to be released (semaphore post). */
+ VG_USERREQ__DRD_ANNOTATE_SEM_POST_PRE,
+ /* args: Addr. */
+
/* Tell DRD that a user-defined reader-writer synchronization object
* has been created. */
VG_USERREQ__DRD_ANNOTATE_RWLOCK_CREATE
diff --git a/drd/drd_clientreq.c b/drd/drd_clientreq.c
index 0c97f41..92ac92a 100644
--- a/drd/drd_clientreq.c
+++ b/drd/drd_clientreq.c
@@ -225,6 +225,26 @@
DRD_(rwlock_pre_unlock)(arg[1], user_rwlock);
break;
+ case VG_USERREQ__DRD_ANNOTATE_SEM_INIT_PRE:
+ DRD_(semaphore_init)(arg[1], 0, arg[2]);
+ break;
+
+ case VG_USERREQ__DRD_ANNOTATE_SEM_DESTROY_POST:
+ DRD_(semaphore_destroy)(arg[1]);
+ break;
+
+ case VG_USERREQ__DRD_ANNOTATE_SEM_WAIT_PRE:
+ DRD_(semaphore_pre_wait)(arg[1]);
+ break;
+
+ case VG_USERREQ__DRD_ANNOTATE_SEM_WAIT_POST:
+ DRD_(semaphore_post_wait)(drd_tid, arg[1], True /* waited */);
+ break;
+
+ case VG_USERREQ__DRD_ANNOTATE_SEM_POST_PRE:
+ DRD_(semaphore_pre_post)(drd_tid, arg[1]);
+ break;
+
case VG_USERREQ__SET_PTHREAD_COND_INITIALIZER:
DRD_(pthread_cond_initializer) = (Addr)arg[1];
DRD_(pthread_cond_initializer_size) = arg[2];
diff --git a/drd/tests/Makefile.am b/drd/tests/Makefile.am
index 24cd089..0ebee2f 100644
--- a/drd/tests/Makefile.am
+++ b/drd/tests/Makefile.am
@@ -67,6 +67,8 @@
annotate_trace_memory_xml.stderr.exp-64bit \
annotate_trace_memory_xml.stderr.exp-mips32 \
annotate_trace_memory_xml.vgtest \
+ annotate_sem.stderr.exp \
+ annotate_sem.vgtest \
annotate_static.stderr.exp \
annotate_static.vgtest \
atomic_var.stderr.exp \
@@ -375,6 +377,7 @@
check_PROGRAMS += \
annotate_barrier \
annotate_rwlock \
+ annotate_sem \
atomic_var \
circular_buffer
endif
diff --git a/drd/tests/annotate_sem.c b/drd/tests/annotate_sem.c
new file mode 100644
index 0000000..016e8b5
--- /dev/null
+++ b/drd/tests/annotate_sem.c
@@ -0,0 +1,96 @@
+/**
+ * @file annotate_sem.c
+ *
+ * @brief Multithreaded test program that triggers various access patterns
+ * without triggering any race conditions using a binary semaphore
+ * implemented via busy-waiting. Annotations are used to tell DRD
+ * which higher-level semaphore operations are being performed.
+ */
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdio.h>
+#include "../../config.h"
+#include "../../drd/drd.h"
+
+#define THREADS 10
+#define ITERATIONS 1000
+
+typedef struct {
+ volatile unsigned value;
+} sem_t;
+
+static sem_t s_sem;
+static unsigned int s_counter;
+
+static void sem_init(sem_t *p, unsigned value)
+{
+ DRD_IGNORE_VAR(*p);
+ p->value = value;
+ ANNOTATE_SEM_INIT_PRE(p, value);
+}
+
+static void sem_destroy(sem_t *p)
+{
+ ANNOTATE_SEM_DESTROY_POST(p);
+}
+
+static void sem_wait(sem_t *p)
+{
+ unsigned old, new;
+ struct timespec ts = { 0, 0 };
+
+ ANNOTATE_SEM_WAIT_PRE(p);
+ do {
+ old = p->value;
+ new = old - 1;
+ nanosleep(&ts, NULL);
+ ts.tv_nsec = 1;
+ } while (!old || !__sync_bool_compare_and_swap(&p->value, old, new));
+ ANNOTATE_SEM_WAIT_POST(p);
+}
+
+static void sem_post(sem_t *p)
+{
+ ANNOTATE_SEM_POST_PRE(p);
+ __sync_fetch_and_add(&p->value, 1);
+}
+
+static void *thread_func(void *arg)
+{
+ unsigned int i;
+ unsigned int sum = 0;
+
+ for (i = 0; i < ITERATIONS; i++) {
+ sem_wait(&s_sem);
+ sum += s_counter;
+ sem_post(&s_sem);
+
+ sem_wait(&s_sem);
+ s_counter++;
+ sem_post(&s_sem);
+ }
+
+ return 0;
+}
+
+int main(int argc, const char *argv[])
+{
+ pthread_t tid[THREADS];
+ unsigned int i;
+
+ sem_init(&s_sem, 1);
+ for (i = 0; i < THREADS; i++)
+ pthread_create(&tid[i], 0, thread_func, 0);
+
+ for (i = 0; i < THREADS; i++)
+ pthread_join(tid[i], 0);
+
+ assert(s_counter == THREADS * ITERATIONS);
+ assert(s_sem.value == 1);
+ sem_destroy(&s_sem);
+
+ fprintf(stderr, "Finished.\n");
+
+ return 0;
+}
diff --git a/drd/tests/annotate_sem.stderr.exp b/drd/tests/annotate_sem.stderr.exp
new file mode 100644
index 0000000..a7089bb
--- /dev/null
+++ b/drd/tests/annotate_sem.stderr.exp
@@ -0,0 +1,4 @@
+
+Finished.
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/annotate_sem.vgtest b/drd/tests/annotate_sem.vgtest
new file mode 100644
index 0000000..3c5071c
--- /dev/null
+++ b/drd/tests/annotate_sem.vgtest
@@ -0,0 +1,4 @@
+prereq: test -e annotate_sem && ./supported_libpthread
+vgopts: --fair-sched=try --read-var-info=yes --check-stack-var=yes --show-confl-seg=no
+prog: annotate_sem
+stderr_filter: filter_stderr_and_thread_no