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);
}