#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define NUMTHREADS 5

/* Based on the thread code in memcached */
static volatile int init_cnt = 0;
static pthread_cond_t init_cond;
static pthread_mutex_t init_mutex;
static pthread_t threads[NUMTHREADS];

#define TBLEN 1024*1024

volatile char tracebuffer[TBLEN];
volatile char* tbptr;

void *worker(void* a) {
  *(tbptr++)=(char)((int)a | 0x30);
  pthread_mutex_lock(&init_mutex);
  *(tbptr++)=(char)((int)a | 0x40);
  init_cnt++;
  *(tbptr++)=(char)((int)a | 0x50);
  pthread_cond_signal(&init_cond);
  *(tbptr++)=(char)((int)a | 0x60);
  pthread_mutex_unlock(&init_mutex);
  *(tbptr++)=(char)((int)a | 0x70);

  sleep(3600);

  return NULL;
}

void printtb() {
    char *tmp;
    fprintf(stderr,"Trace buffer: ");
    for(tmp=tracebuffer;tmp<tbptr;tmp++)
      fprintf(stderr,"%02x ", *tmp);
    fprintf(stderr,"\n");
}

void thread_init() {
  pthread_attr_t attr;
  int i,ret;

  pthread_cond_init(&init_cond, NULL);
  pthread_mutex_init(&init_mutex, NULL);


  for(i=0;i<NUMTHREADS;i++) {
    pthread_attr_init(&attr);
    ret = pthread_create(&(threads[i]), &attr, worker, (void *)i);

    if (ret!=0) {
      fprintf(stderr,"Failed to create thread %d\n", ret);
      exit(1);
    }
  }

  *(tbptr++)=(char)init_cnt;
  pthread_mutex_lock(&init_mutex);
  *(tbptr++)=(char)init_cnt;
  while (init_cnt < NUMTHREADS) {
    *(tbptr++)=(char)(init_cnt | 0x10);
    pthread_cond_wait(&init_cond, &init_mutex);
    *(tbptr++)=(char)(init_cnt | 0x20);
  };

  pthread_mutex_unlock(&init_mutex);

  fprintf(stderr,"All threads started\n");
  printtb();
  exit(0);
}

int main()
{
  tbptr=tracebuffer;
  fprintf(stderr,"Start thread test %p %p\n", tracebuffer, tbptr);
  memset(tracebuffer,0xff,TBLEN);
  thread_init();

    
  return (0);
}

