void *wakeup_test_thread(void *thread_arg) { struct ThreadState *thread = thread_arg; ANNOTATE_IGNORE_WRITES_BEGIN(); thread->state = STATE_ABOUT_TO_WAIT; ANNOTATE_IGNORE_WRITES_END(); int rc = futex_wait(thread->futex_value, *thread->futex_value, NULL); ASSERT_EQ(rc, 0); ANNOTATE_IGNORE_WRITES_BEGIN(); thread->state = STATE_WAIT_RETURNED; ANNOTATE_IGNORE_WRITES_END(); return NULL; }
int main(int argc, char** argv) { const struct timespec delay = { 0, 100 * 1000 * 1000 }; int optchar; int ign_rw = 1; pthread_t tid; while ((optchar = getopt(argc, argv, "r")) != EOF) { switch (optchar) { case 'r': ign_rw = 0; break; default: assert(0); } } pthread_create(&tid, 0, thread_func, 0); /* Let the code in the created thread run first. */ nanosleep(&delay, 0); if (ign_rw) ANNOTATE_IGNORE_WRITES_BEGIN(); /* Read s_b and modify s_a. */ s_a = s_b; if (ign_rw) ANNOTATE_IGNORE_WRITES_END(); /* * Insert a delay here in order to make sure the load of s_c happens * after s_c has been modified. */ nanosleep(&delay, 0); /* Read s_c and modify s_a. */ s_a = s_c; pthread_join(tid, 0); fprintf(stderr, "Finished.\n"); return 0; }
void check_futex_wake(volatile int *futex_value, int nwake, int expected_woken) { /* * Change *futex_value just in case our nanosleep() call did not * wait long enough for futex_wait() to enter the wait queue, * although that is unlikely. This prevents the test from hanging * if that happens, though the test will fail because futex_wake() * will return a count of 0. */ ANNOTATE_IGNORE_WRITES_BEGIN(); (*futex_value)++; ANNOTATE_IGNORE_WRITES_END(); int count = 9999; /* Dummy value: should be overwritten. */ int rc = futex_wake(futex_value, nwake, &count); ASSERT_EQ(rc, 0); /* This could fail if futex_wait() gets a spurious wakeup. */ ASSERT_EQ(count, expected_woken); }