/** Broadcast a (POSIX threads) signal to all running threads, where the
 *  number of threads can be specified on the command line. This test program
 *  is intended not only to test the correctness of drd but also to test
 *  whether performance does not degrade too much when the number of threads
 *  increases.
 */


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


// Counting semaphore.

struct csema
{
  pthread_mutex_t  m_mutex;
  pthread_cond_t   m_cond;
  int              m_count;
};

void csema_ctr(struct csema* p)
{
  memset(p, 0, sizeof(*p));
  pthread_mutex_init(&p->m_mutex, 0);
  pthread_cond_init(&p->m_cond, 0);
}

void csema_dtr(struct csema* p)
{
  pthread_cond_destroy(&p->m_cond);
  pthread_mutex_destroy(&p->m_mutex);
}

void csema_p(struct csema* p, const int n)
{
  pthread_mutex_lock(&p->m_mutex);
  while (p->m_count < n)
    pthread_cond_wait(&p->m_cond, &p->m_mutex);
  p->m_count -= n;
  pthread_cond_signal(&p->m_cond);
  pthread_mutex_unlock(&p->m_mutex);
}

void csema_v(struct csema* p)
{
  pthread_mutex_lock(&p->m_mutex);
  p->m_count++;
  pthread_cond_signal(&p->m_cond);
  pthread_mutex_unlock(&p->m_mutex);
}


struct cthread
{
  pthread_t     m_thread;
  int           m_threadnum;
  struct csema* m_sema;
};

void cthread_ctr(struct cthread* p)
{
  p->m_thread = 0;
  p->m_sema   = 0;
}

void cthread_dtr(struct cthread* p)
{ }


// Local variables.

static int s_debug = 0;
static int s_trace = 0;
static int s_signal_count;
static pthread_mutex_t s_mutex;
static pthread_cond_t  s_cond;


// Function definitions.

static void thread_func(struct cthread* thread_info)
{
  int i;

  pthread_mutex_lock(&s_mutex);

  for (i = 0; i < s_signal_count; i++)
  {
    if (s_trace)
    {
      printf("thread %d [%d] (1)\n", thread_info->m_threadnum, i);
    }
    csema_v(thread_info->m_sema);

    // Wait until the main thread signals us via pthread_cond_broadcast().
    pthread_cond_wait(&s_cond, &s_mutex);
    if (s_trace)
    {
      printf("thread %d [%d] (2)\n", thread_info->m_threadnum, i);
    }
  }

  pthread_mutex_unlock(&s_mutex);
}

int main(int argc, char** argv)
{
  int optchar;
  int thread_count;

  while ((optchar = getopt(argc, argv, "d")) != EOF)
  {
    switch (optchar)
    {
    case 'd':
      s_debug = 1;
      break;
    default:
      assert(0);
      break;
    }
  }

  /* This test should complete in 15s or less. If the test does not complete */
  /* within that time, abort the test via the signal SIGALRM.                */
  alarm(100);

  s_signal_count = argc > optind ? atoi(argv[optind]) : 10;
  thread_count = argc > optind + 1 ? atoi(argv[optind + 1]) : 10;

  if (s_debug)
    printf("&s_cond = %p\n", &s_cond);

  pthread_mutex_init(&s_mutex, 0);
  pthread_cond_init(&s_cond, 0);
  {
    int i;
    struct csema sema;
    struct cthread* p;
    struct cthread* thread_vec;

    csema_ctr(&sema);
    thread_vec = malloc(sizeof(struct cthread) * thread_count);
    for (p = thread_vec; p != thread_vec + thread_count; p++)
    {
      cthread_ctr(p);
      p->m_threadnum = p - thread_vec;
      p->m_sema = &sema;
      pthread_create(&p->m_thread, 0,
                     (void*(*)(void*))thread_func, &*p);
    }
    for (i = 0; i < s_signal_count; i++)
    {
      if (s_trace)
        printf("main [%d] (1)\n", i);
      csema_p(&sema, thread_count);
      if (s_trace)
        printf("main [%d] (2)\n", i);
      pthread_mutex_lock(&s_mutex);
      pthread_cond_broadcast(&s_cond);
      pthread_mutex_unlock(&s_mutex);
      if (s_trace)
        printf("main [%d] (3)\n", i);
    }
    for (i = 0; i < thread_count; i++)
    {
      pthread_join(thread_vec[i].m_thread, 0);
      cthread_dtr(&thread_vec[i]);
    }
    free(thread_vec);
    csema_dtr(&sema);
  }
  pthread_cond_destroy(&s_cond);
  pthread_mutex_destroy(&s_mutex);

  fprintf(stderr, "Done.\n");

  return 0;
}
