15bd9f2d42ba9440b528b1f926dd57b4652cb0583bart/** Cause a race inside code protected by a reader lock.
25bd9f2d42ba9440b528b1f926dd57b4652cb0583bart */
35bd9f2d42ba9440b528b1f926dd57b4652cb0583bart
45bd9f2d42ba9440b528b1f926dd57b4652cb0583bart
55bd9f2d42ba9440b528b1f926dd57b4652cb0583bart/* Needed for older glibc's (2.3 and older, at least) who don't
65bd9f2d42ba9440b528b1f926dd57b4652cb0583bart   otherwise "know" about pthread_rwlock_anything or about
75bd9f2d42ba9440b528b1f926dd57b4652cb0583bart   PTHREAD_MUTEX_RECURSIVE (amongst things). */
85bd9f2d42ba9440b528b1f926dd57b4652cb0583bart
95bd9f2d42ba9440b528b1f926dd57b4652cb0583bart#define _GNU_SOURCE 1
105bd9f2d42ba9440b528b1f926dd57b4652cb0583bart
115bd9f2d42ba9440b528b1f926dd57b4652cb0583bart#include <pthread.h>
1268a8a20a384dcc5027e35c76fbe4f8e422dbbcdebart#include <stdio.h>
1368a8a20a384dcc5027e35c76fbe4f8e422dbbcdebart#include <unistd.h>
145f57be90d2e42dff4588ea099a78c64d72ffa19ebart
155bd9f2d42ba9440b528b1f926dd57b4652cb0583bart
165bd9f2d42ba9440b528b1f926dd57b4652cb0583bart
175bd9f2d42ba9440b528b1f926dd57b4652cb0583bartstatic pthread_rwlock_t s_rwlock;
185bd9f2d42ba9440b528b1f926dd57b4652cb0583bartstatic int s_racy;
195bd9f2d42ba9440b528b1f926dd57b4652cb0583bart
2068a8a20a384dcc5027e35c76fbe4f8e422dbbcdebartstatic void sleep_ms(const int ms)
2168a8a20a384dcc5027e35c76fbe4f8e422dbbcdebart{
2268a8a20a384dcc5027e35c76fbe4f8e422dbbcdebart  struct timespec delay = { ms / 1000, (ms % 1000) * 1000 * 1000 };
2368a8a20a384dcc5027e35c76fbe4f8e422dbbcdebart  nanosleep(&delay, 0);
2468a8a20a384dcc5027e35c76fbe4f8e422dbbcdebart}
2568a8a20a384dcc5027e35c76fbe4f8e422dbbcdebart
2668a8a20a384dcc5027e35c76fbe4f8e422dbbcdebartstatic void* thread_func(void* arg)
275bd9f2d42ba9440b528b1f926dd57b4652cb0583bart{
285bd9f2d42ba9440b528b1f926dd57b4652cb0583bart  pthread_rwlock_rdlock(&s_rwlock);
295bd9f2d42ba9440b528b1f926dd57b4652cb0583bart  s_racy++;
305bd9f2d42ba9440b528b1f926dd57b4652cb0583bart  pthread_rwlock_unlock(&s_rwlock);
3168a8a20a384dcc5027e35c76fbe4f8e422dbbcdebart  sleep_ms(100);
325bd9f2d42ba9440b528b1f926dd57b4652cb0583bart  return 0;
335bd9f2d42ba9440b528b1f926dd57b4652cb0583bart}
345bd9f2d42ba9440b528b1f926dd57b4652cb0583bart
355bd9f2d42ba9440b528b1f926dd57b4652cb0583bartint main(int argc, char** argv)
365bd9f2d42ba9440b528b1f926dd57b4652cb0583bart{
375bd9f2d42ba9440b528b1f926dd57b4652cb0583bart  pthread_t thread1;
385bd9f2d42ba9440b528b1f926dd57b4652cb0583bart  pthread_t thread2;
395bd9f2d42ba9440b528b1f926dd57b4652cb0583bart
405bd9f2d42ba9440b528b1f926dd57b4652cb0583bart#if 0
41575ce8ef8fa86a502dabe152293320676922dcfebart
424b3a74204894e943c43cb8e8aae39d813040702csewardj  VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_TRACE_ADDR,
43575ce8ef8fa86a502dabe152293320676922dcfebart                                  &s_racy, 0, 0, 0, 0);
445bd9f2d42ba9440b528b1f926dd57b4652cb0583bart#endif
455bd9f2d42ba9440b528b1f926dd57b4652cb0583bart
465bd9f2d42ba9440b528b1f926dd57b4652cb0583bart  pthread_rwlock_init(&s_rwlock, 0);
4768a8a20a384dcc5027e35c76fbe4f8e422dbbcdebart  pthread_create(&thread1, 0, thread_func, 0);
4868a8a20a384dcc5027e35c76fbe4f8e422dbbcdebart  pthread_create(&thread2, 0, thread_func, 0);
495bd9f2d42ba9440b528b1f926dd57b4652cb0583bart  pthread_join(thread1, 0);
505bd9f2d42ba9440b528b1f926dd57b4652cb0583bart  pthread_join(thread2, 0);
515bd9f2d42ba9440b528b1f926dd57b4652cb0583bart  pthread_rwlock_destroy(&s_rwlock);
525bd9f2d42ba9440b528b1f926dd57b4652cb0583bart
535bd9f2d42ba9440b528b1f926dd57b4652cb0583bart  fprintf(stderr, "Result: %d\n", s_racy);
545bd9f2d42ba9440b528b1f926dd57b4652cb0583bart
555bd9f2d42ba9440b528b1f926dd57b4652cb0583bart  return 0;
565bd9f2d42ba9440b528b1f926dd57b4652cb0583bart}
57