#include <stdio.h>
#include <assert.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>

static pthread_t threads[2];

static int data;

static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

// 1 when A is finished. Protected by lock.
static int a_stopped = 1;

void *threadB(void *arg) {
    int stop = 0;
    // Wait for A to stop.
    do {
        /* In reality, some real work happens here */
        pthread_mutex_lock(&lock);
        stop = a_stopped;
        pthread_mutex_unlock(&lock);
    } while (!stop);
    // A has stopped, and waits for B to broadcast. Hence, it's safe
    // to touch data. Helgrind reports this as a data race.
    data = 2;
    // Cleanup: Signal to A that we're done.
    pthread_cond_broadcast(&cond);
    return NULL;
}

void *threadA(void *arg) {
    // Thread owns data exclusively, and manipulates it.
    data = 1;

    // Stop and wait for B to finish.
    pthread_mutex_lock(&lock);
    a_stopped = 1;
    pthread_cond_wait(&cond, &lock);
    // Cleanup.
    pthread_mutex_unlock(&lock);
    return NULL;
}

int main() {
  int i;

  data = 2;

  pthread_create(&threads[1], NULL, threadA, NULL);
  pthread_create(&threads[0], NULL, threadB, NULL);

  for (i = 0; i < 2; i++) {
      pthread_join(threads[i], NULL);
  }

  return 0;
}


