AM_CXXFLAGS = $(AM_CFLAGS)
check_PROGRAMS = \
- abort \
fp_race \
- new_delete \
pth_broadcast \
pth_cond_race \
pth_create_chain \
pth_detached \
- sigalrm \
- std-string
+ sigalrm
-abort_SOURCES = abort.cpp
-abort_LDADD = -lpthread
-
-fp_race_SOURCES = fp_race.cpp
+fp_race_SOURCES = fp_race.c
fp_race_LDADD = -lpthread
-new_delete_SOURCES = new_delete.cpp
-new_delete_LDADD = -lpthread
-
-pth_broadcast_SOURCES = pth_broadcast.cpp
+pth_broadcast_SOURCES = pth_broadcast.c
pth_broadcast_LDADD = -lpthread
-pth_cond_race_SOURCES = pth_cond_race.cpp
+pth_cond_race_SOURCES = pth_cond_race.c
pth_cond_race_LDADD = -lpthread
-pth_create_chain_SOURCES = pth_create_chain.cpp
+pth_create_chain_SOURCES = pth_create_chain.c
pth_create_chain_LDADD = -lpthread
pth_detached_SOURCES = pth_detached.c
pth_detached_LDADD = -lpthread
-sigalrm_SOURCES = sigalrm.cpp
+sigalrm_SOURCES = sigalrm.c
sigalrm_LDADD = -lpthread -lrt
-
-std_string_SOURCES = std-string.cpp
-std_string_LDADD = -lpthread
-// assert(false) calls __assert_fail(), which in turn calls abort() and
-// _IO_flush_all_lockp(). This last function triggers a race. Check that this
-// race is suppressed. Note: the test program below is not sufficient for
-// reproducing this race.
-
-
-#include <iostream>
-#include <fstream>
-#include <cassert>
-#include <pthread.h>
-#include <stdio.h>
-static pthread_mutex_t s_mutex;
-
-void* thread_func(void*)
-{
- pthread_mutex_lock(&s_mutex);
- pthread_mutex_unlock(&s_mutex);
- std::cout << "thread\n";
- assert(false);
- return 0;
-}
-
-int main(int argc, char** argv)
-{
- pthread_mutex_init(&s_mutex, 0);
- pthread_t tid;
- pthread_mutex_lock(&s_mutex);
- pthread_create(&tid, 0, thread_func, 0);
- FILE* fp = fopen("/tmp/valgrind-drd-tests-abort", "w");
- fprintf(fp, "x");
- pthread_mutex_unlock(&s_mutex);
- pthread_join(tid, 0);
- pthread_mutex_destroy(&s_mutex);
- fclose(fp);
-
- return 0;
-}
// Test data race detection between floating point variables.
-#include <cassert>
-#include <cstdio> // printf()
+#include <assert.h>
+#include <stdio.h> // printf()
#include <pthread.h>
#include <unistd.h> // usleep()
#include "../drd_clientreq.h"
static double s_d2; // accessed in the created thread and after the join
// (not a race).
static double s_d3; // accessed simultaneously from both threads (race).
-static bool s_debug = false;
-static bool s_do_printf = false;
-static bool s_use_mutex = false;
-
-
-class CScopedLock
-{
-public:
- CScopedLock()
- { if (s_use_mutex) pthread_mutex_lock(&s_mutex); }
- ~CScopedLock()
- { if (s_use_mutex) pthread_mutex_unlock(&s_mutex); }
-
-private:
- CScopedLock(CScopedLock const&);
- CScopedLock& operator=(CScopedLock const&);
-};
+static int s_debug = 0;
+static int s_do_printf = 0;
+static int s_use_mutex = 0;
// Function definitions.
int main(int argc, char** argv)
{
+ int optchar;
+ pthread_t threadid;
+
set_thread_name("main");
- int optchar;
while ((optchar = getopt(argc, argv, "dmp")) != EOF)
{
switch (optchar)
{
case 'd':
- s_debug = true;
+ s_debug = 1;
break;
case 'm':
- s_use_mutex = true;
+ s_use_mutex = 1;
break;
case 'p':
- s_do_printf = true;
+ s_do_printf = 1;
break;
default:
- assert(false);
+ assert(0);
}
}
s_d1 = 1;
s_d3 = 3;
- pthread_t threadid;
pthread_create(&threadid, 0, thread_func, 0);
// Wait until the printf() in the created thread finished.
{
- CScopedLock ScopedLock;
+ if (s_use_mutex) pthread_mutex_lock(&s_mutex);
s_d3++;
+ if (s_use_mutex) pthread_mutex_unlock(&s_mutex);
}
// Wait until the thread finished.
return 0;
}
-static void* thread_func(void*)
+static void* thread_func(void* thread_arg)
{
set_thread_name("thread_func");
}
s_d2 = 2;
{
- CScopedLock ScopedLock;
+ if (s_use_mutex) pthread_mutex_lock(&s_mutex);
s_d3++;
+ if (s_use_mutex) pthread_mutex_unlock(&s_mutex);
}
return 0;
}
Conflicting load by main at 0x........ size 8
- at 0x........: main (fp_race.cpp:?)
+ at 0x........: main (fp_race.c:?)
Allocation context: s_d3 (offset 0, size 8) in fp_race, NONE:BSS
Other segment start (thread_func)
(thread finished, call stack no longer available)
(thread finished, call stack no longer available)
Conflicting store by main at 0x........ size 8
- at 0x........: main (fp_race.cpp:?)
+ at 0x........: main (fp_race.c:?)
Allocation context: s_d3 (offset 0, size 8) in fp_race, NONE:BSS
Other segment start (thread_func)
(thread finished, call stack no longer available)
Conflicting load by main at 0x........ size 8
- at 0x........: main (fp_race.cpp:?)
+ at 0x........: main (fp_race.c:?)
Allocation context: unknown
Other segment start (thread_func)
(thread finished, call stack no longer available)
(thread finished, call stack no longer available)
Conflicting store by main at 0x........ size 8
- at 0x........: main (fp_race.cpp:?)
+ at 0x........: main (fp_race.c:?)
Allocation context: unknown
Other segment start (thread_func)
(thread finished, call stack no longer available)
+++ /dev/null
-#include <iostream>
-#include <pthread.h>
-
-void* thread_func(void*)
-{
- delete new int;
- return 0;
-}
-
-int main(int argc, char** argv)
-{
- pthread_t tid;
- std::cout << "main, before pthread_create()\n" << std::flush;
- pthread_create(&tid, 0, thread_func, 0);
- std::cout << "main, after pthread_create()\n" << std::flush;
- delete new int;
- std::cout << "main, before pthread_join()\n" << std::flush;
- pthread_join(tid, 0);
- std::cout << "main, after pthread_join()\n" << std::flush;
- return 0;
-}
--- /dev/null
+// Broadcast a (POSIX threads) signal to all running threads, where the
+// number of threads can be specified on the command line. This test program
+// is intended not only to test the correctness of drd but also to test
+// whether performance does not degrade too much when the number of threads
+// increases.
+
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+// Counting semaphore.
+
+struct csema
+{
+ pthread_mutex_t m_mutex;
+ pthread_cond_t m_cond;
+ int m_count;
+};
+
+void csema_ctr(struct csema* p)
+{
+ memset(p, 0, sizeof(*p));
+ pthread_mutex_init(&p->m_mutex, 0);
+ pthread_cond_init(&p->m_cond, 0);
+}
+
+void csema_dtr(struct csema* p)
+{
+ pthread_cond_destroy(&p->m_cond);
+ pthread_mutex_destroy(&p->m_mutex);
+}
+
+void csema_p(struct csema* p, const int n)
+{
+ pthread_mutex_lock(&p->m_mutex);
+ while (p->m_count < n)
+ pthread_cond_wait(&p->m_cond, &p->m_mutex);
+ p->m_count -= n;
+ pthread_cond_signal(&p->m_cond);
+ pthread_mutex_unlock(&p->m_mutex);
+}
+
+void csema_v(struct csema* p)
+{
+ pthread_mutex_lock(&p->m_mutex);
+ p->m_count++;
+ pthread_cond_signal(&p->m_cond);
+ pthread_mutex_unlock(&p->m_mutex);
+}
+
+
+struct cthread
+{
+ pthread_t m_thread;
+ int m_threadnum;
+ struct csema* m_sema;
+};
+
+void cthread_ctr(struct cthread* p)
+{
+ p->m_thread = 0;
+ p->m_sema = 0;
+}
+
+void cthread_dtr(struct cthread* p)
+{ }
+
+
+// Local variables.
+
+static int s_debug = 0;
+static int s_trace = 0;
+static int s_signal_count;
+static pthread_mutex_t s_mutex;
+static pthread_cond_t s_cond;
+
+
+// Function definitions.
+
+static void thread_func(struct cthread* thread_info)
+{
+ int i;
+
+ pthread_mutex_lock(&s_mutex);
+
+ for (i = 0; i < s_signal_count; i++)
+ {
+ if (s_trace)
+ {
+ printf("thread %d [%d] (1)\n", thread_info->m_threadnum, i);
+ }
+ csema_v(thread_info->m_sema);
+
+ // Wait until the main thread signals us via pthread_cond_broadcast().
+ pthread_cond_wait(&s_cond, &s_mutex);
+ if (s_trace)
+ {
+ printf("thread %d [%d] (2)\n", thread_info->m_threadnum, i);
+ }
+ }
+
+ pthread_mutex_unlock(&s_mutex);
+}
+
+int main(int argc, char** argv)
+{
+ int optchar;
+ int thread_count;
+
+ while ((optchar = getopt(argc, argv, "d")) != EOF)
+ {
+ switch (optchar)
+ {
+ case 'd':
+ s_debug = 1;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ s_signal_count = argc > optind ? atoi(argv[optind]) : 10;
+ thread_count = argc > optind + 1 ? atoi(argv[optind + 1]) : 10;
+
+ if (s_debug)
+ printf("&s_cond = %p\n", &s_cond);
+
+ pthread_mutex_init(&s_mutex, 0);
+ pthread_cond_init(&s_cond, 0);
+ {
+ int i;
+ struct csema sema;
+ struct cthread* p;
+ struct cthread* thread_vec;
+
+ csema_ctr(&sema);
+ thread_vec = malloc(sizeof(struct cthread) * thread_count);
+ for (p = thread_vec; p != thread_vec + thread_count; p++)
+ {
+ cthread_ctr(p);
+ p->m_threadnum = p - thread_vec;
+ p->m_sema = &sema;
+ pthread_create(&p->m_thread, 0,
+ (void*(*)(void*))thread_func, &*p);
+ }
+ for (i = 0; i < s_signal_count; i++)
+ {
+ if (s_trace)
+ printf("main [%d] (1)\n", i);
+ csema_p(&sema, thread_count);
+ if (s_trace)
+ printf("main [%d] (2)\n", i);
+ pthread_mutex_lock(&s_mutex);
+ pthread_cond_broadcast(&s_cond);
+ pthread_mutex_unlock(&s_mutex);
+ if (s_trace)
+ printf("main [%d] (3)\n", i);
+ }
+ for (i = 0; i < thread_count; i++)
+ {
+ pthread_join(thread_vec[i].m_thread, 0);
+ cthread_dtr(&thread_vec[i]);
+ }
+ free(thread_vec);
+ csema_dtr(&sema);
+ }
+ pthread_cond_destroy(&s_cond);
+ pthread_mutex_destroy(&s_mutex);
+ return 0;
+}
+++ /dev/null
-// Broadcast a (POSIX threads) signal to all running threads, where the
-// number of threads can be specified on the command line. This test program
-// is intended not only to test the correctness of drd but also to test
-// whether performance does not degrade too much when the number of threads
-// increases.
-
-
-#include <cassert>
-#include <iostream>
-#include <vector>
-#include <pthread.h>
-#include <unistd.h>
-
-// Class definitions.
-
-// Counting semaphore.
-
-class CSema
-{
-public:
- CSema()
- : m_mutex(), m_cond(), m_count(0)
- {
- pthread_mutex_init(&m_mutex, 0);
- pthread_cond_init(&m_cond, 0);
- }
- ~CSema()
- {
- pthread_cond_destroy(&m_cond);
- pthread_mutex_destroy(&m_mutex);
- }
- void p(const int n)
- {
- pthread_mutex_lock(&m_mutex);
- while (m_count < n)
- pthread_cond_wait(&m_cond, &m_mutex);
- m_count -= n;
- pthread_cond_signal(&m_cond);
- pthread_mutex_unlock(&m_mutex);
- }
- void v()
- {
- pthread_mutex_lock(&m_mutex);
- m_count++;
- pthread_cond_signal(&m_cond);
- pthread_mutex_unlock(&m_mutex);
- }
-
-private:
- CSema(CSema const&);
- CSema& operator=(CSema const&);
-
- pthread_mutex_t m_mutex;
- pthread_cond_t m_cond;
- int m_count;
-};
-
-struct CThread
-{
- CThread()
- : m_thread(), m_sema()
- { }
- ~CThread()
- { }
-
- pthread_t m_thread;
- int m_threadnum;
- CSema* m_sema;
-};
-
-
-// Local variables.
-
-static bool s_debug = false;
-static bool s_trace = false;
-static int s_signal_count;
-static pthread_mutex_t s_mutex;
-static pthread_cond_t s_cond;
-
-
-// Function definitions.
-
-static void thread_func(CThread* thread_info)
-{
- pthread_mutex_lock(&s_mutex);
-
- for (int i = 0; i < s_signal_count; i++)
- {
- if (s_trace)
- {
- std::cout << "thread " << thread_info->m_threadnum
- << " [" << i << "] (1)" << std::endl;
- }
- thread_info->m_sema->v();
-
- // Wait until the main thread signals us via pthread_cond_broadcast().
- pthread_cond_wait(&s_cond, &s_mutex);
- if (s_trace)
- {
- std::cout << "thread " << thread_info->m_threadnum
- << " [" << i << "] (2)" << std::endl;
- }
- }
-
- pthread_mutex_unlock(&s_mutex);
-}
-
-int main(int argc, char** argv)
-{
- int optchar;
- while ((optchar = getopt(argc, argv, "d")) != EOF)
- {
- switch (optchar)
- {
- case 'd':
- s_debug = true;
- break;
- default:
- assert(false);
- break;
- }
- }
- s_signal_count = argc > optind ? atoi(argv[optind]) : 10;
- const int thread_count = argc > optind + 1 ? atoi(argv[optind + 1]) : 10;
-
- if (s_debug)
- std::cout << "&s_cond = " << &s_cond << std::endl;
-
- pthread_mutex_init(&s_mutex, 0);
- pthread_cond_init(&s_cond, 0);
- {
- CSema sema;
- std::vector<CThread> thread_vec(thread_count);
- for (std::vector<CThread>::iterator p = thread_vec.begin();
- p != thread_vec.end(); p++)
- {
- p->m_threadnum = std::distance(thread_vec.begin(), p);
- p->m_sema = &sema;
- pthread_create(&p->m_thread, 0,
- (void*(*)(void*))thread_func, &*p);
- }
- for (int i = 0; i < s_signal_count; i++)
- {
- if (s_trace)
- std::cout << "main [" << i << "] (1)\n";
- sema.p(thread_count);
- if (s_trace)
- std::cout << "main [" << i << "] (2)\n";
- pthread_mutex_lock(&s_mutex);
- pthread_cond_broadcast(&s_cond);
- pthread_mutex_unlock(&s_mutex);
- if (s_trace)
- std::cout << "main [" << i << "] (3)\n";
- }
- for (int i = 0; i < thread_count; i++)
- {
- pthread_join(thread_vec[i].m_thread, 0);
- }
- }
- pthread_cond_destroy(&s_cond);
- pthread_mutex_destroy(&s_mutex);
- return 0;
-}
variable. By Bart Van Assche.
*/
-#include <cassert>
-#include <cstdio> // printf()
+#include <assert.h>
+#include <stdio.h> // printf()
#include <pthread.h>
#include <unistd.h> // usleep()
#include "../drd_clientreq.h"
// Local functions declarations.
-static void* thread_func(void*);
+static void* thread_func(void* thread_arg);
// Local variables.
static pthread_mutex_t s_mutex;
static pthread_cond_t s_cond;
-static bool s_use_mutex = false;
-
-
-class CScopedLock
-{
-public:
- CScopedLock()
- { if (s_use_mutex) pthread_mutex_lock(&s_mutex); }
- ~CScopedLock()
- { if (s_use_mutex) pthread_mutex_unlock(&s_mutex); }
-
-private:
- CScopedLock(CScopedLock const&);
- CScopedLock& operator=(CScopedLock const&);
-};
+static int s_use_mutex = 0;
// Function definitions.
int main(int argc, char** argv)
{
+ int optchar;
+ pthread_t threadid;
+
set_thread_name("main");
- int optchar;
while ((optchar = getopt(argc, argv, "m")) != EOF)
{
switch (optchar)
{
case 'm':
- s_use_mutex = true;
+ s_use_mutex = 1;
break;
default:
- assert(false);
+ assert(0);
}
}
pthread_mutex_init(&s_mutex, 0);
pthread_mutex_lock(&s_mutex);
- pthread_t threadid;
pthread_create(&threadid, 0, thread_func, 0);
pthread_cond_wait(&s_cond, &s_mutex);
return 0;
}
-static void* thread_func(void*)
+static void* thread_func(void* thread_arg)
{
set_thread_name("thread_func");
Thread 2:
Race condition: condition variable 0x........ has been signalled but the associated mutex 0x........ is not locked by the signalling thread
at 0x........: pthread_cond_signal@* (drd_preloaded.c:?)
- by 0x........: thread_func(void*) (pth_cond_race.cpp:?)
+ by 0x........: thread_func (pth_cond_race.c:?)
by 0x........: vg_thread_wrapper (drd_preloaded.c:?)
by 0x........: start_thread (in libpthread-?.?.so)
by 0x........: clone (in /...libc...)
// Create threads in such a way that there is a realistic chance that the
// parent thread finishes before the created thread finishes.
-#include <cassert>
-#include <cstdlib>
-#include <iostream>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
#include <pthread.h>
+
static pthread_t s_thread[1000];
static int s_arg[1000];
static void* thread_func(void* p)
{
- int thread_count = *reinterpret_cast<int*>(p);
+ int thread_count = *(int*)(p);
if (thread_count > 0)
{
thread_count--;
int main(int argc, char** argv)
{
- unsigned thread_count = argc > 1 ? atoi(argv[1]) : 50;
+ int thread_count;
+ int i;
+
+ thread_count = argc > 1 ? atoi(argv[1]) : 50;
assert(thread_count <= sizeof(s_thread) / sizeof(s_thread[0]));
assert(thread_count >= 1);
thread_count--;
// std::cout << "create " << thread_count << std::endl;
pthread_create(&s_thread[thread_count], 0, thread_func,
- const_cast<unsigned*>(&thread_count));
+ &thread_count);
#if 0
std::cout << "created " << thread_count << "(" << s_thread[thread_count]
<< ")" << std::endl;
#endif
- for (int i = thread_count; i >= 0; i--)
+ for (i = thread_count; i >= 0; i--)
{
// std::cout << "join " << i << "(" << s_thread[i] << ")" << std::endl;
pthread_join(s_thread[i], 0);
-#include <cassert>
-#include <cerrno>
-#include <cstdio>
-#include <cstdlib>
-#include <ctime>
-#include <iostream>
-#include <features.h>
+#include <assert.h>
+#include <errno.h>
#include <pthread.h>
#include <signal.h>
-#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-#include "../drd_clientreq.h"
+#include <time.h>
+#include <unistd.h>
#include <asm/unistd.h>
+#include "../drd_clientreq.h"
-#if !defined(__GLIBC_PREREQ)
-# error "This program requires __GLIBC_PREREQ (in /usr/include/features.h)"
-#endif
-
-#if __GLIBC_PREREQ(2,3)
-
-#define VALGRIND_START_NEW_SEGMENT \
-{ \
- int res; \
- VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_START_NEW_SEGMENT, \
- pthread_self(), 0, 0,0,0); \
-}
-static bool s_debug = false;
+static int s_debug = 0;
static int getktid()
}
}
-void* thread_func(void*)
+void* thread_func(void* thread_arg)
{
+ struct timespec tsRemain, tsDelay;
+
if (s_debug)
{
- std::cout << "thread: kernel thread ID " << getktid()
- << " / Valgrind thread ID " << getvgtid() << "\n";
+ printf("thread: kernel thread ID %d / Valgrind thread ID %d\n",
+ getktid(), getvgtid());
}
- const timespec tsDelay = { 10, 0 };
- timespec tsRemain;
+ tsDelay.tv_sec = 10;
+ tsDelay.tv_nsec = 0;
clock_nanosleep(CLOCK_MONOTONIC, 0, &tsDelay, &tsRemain);
//assert(result < 0 && errno == EINTR);
return 0;
}
-int main(int argc, char** )
+int main(int argc, char** argv)
{
+ int vgthreadid;
+ pthread_t threadid;
+ struct timespec tsDelay;
+
// Primitive argument parsing.
if (argc > 1)
- s_debug = true;
+ s_debug = 1;
- const int vgthreadid = getvgtid();
+ vgthreadid = getvgtid();
if (s_debug)
{
- std::cout << "main: kernel thread ID " << getktid()
- << " / Valgrind thread ID " << vgthreadid << std::endl;
+ printf("main: kernel thread ID %d / Valgrind thread ID %d\n",
+ getktid(), vgthreadid);
}
{
sigaction(SIGALRM, &sa, 0);
}
- pthread_t threadid;
pthread_create(&threadid, 0, thread_func, 0);
// Wait until the thread is inside clock_nanosleep().
- const timespec tsDelay = { 0, 20 * 1000 * 1000 };
+ tsDelay.tv_sec = 0;
+ tsDelay.tv_nsec = 20 * 1000 * 1000;
clock_nanosleep(CLOCK_MONOTONIC, 0, &tsDelay, 0);
// And send SIGALRM to the thread.
pthread_kill(threadid, SIGALRM);
return 0;
}
-
-#else /* !__GLIBC_PREREQ(2,3) */
-
-int main(int argc, char** )
-{
- std::cout << "program does not work on glibc < 2.3" << std::endl;
- return 0;
-}
-
-#endif /* __GLIBC_PREREQ(2,3) */
+++ /dev/null
-// Note: the code below is not yet sufficient for reproducing the race on
-// basic_string<>::_Rep_base::_M_refcount
-
-
-#include <iostream>
-#include <pthread.h>
-#include <string>
-#include <unistd.h>
-
-
-static std::string s_string;
-
-static void* thread_func(void*)
-{
- std::cout << "thread: string = " << s_string << std::endl;
- return 0;
-}
-
-int main(int argc, char** argv)
-{
- const bool detached = argc <= 1;
-
- s_string = "(allocated by main thread)";
-
- pthread_t tid;
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr,
- detached
- ? PTHREAD_CREATE_DETACHED
- : PTHREAD_CREATE_JOINABLE);
- pthread_create(&tid, &attr, thread_func, 0);
- pthread_attr_destroy(&attr);
-
- std::cout << std::flush;
-
- if (detached)
- sleep(1);
- else
- pthread_join(tid, 0);
-
- std::cout << std::flush;
-
- return 0;
-}
exp-drd:ConflictingAccess
fun:start_thread
fun:clone
-}
+}
{
pthread
exp-drd:ConflictingAccess