text: #include <stdio.h>
  #include <stdint.h>
  #include <stdlib.h>
  #include <string.h>
  #include <math.h>
  #include "dreadthread.h"
  
  #define NTHREADS  1000
  #define STACKSIZE (8 * 1024)
  #define COUNT     100
  
  int                   count = COUNT;
  int                   nthreads = NTHREADS;
  int                   stacksize = STACKSIZE;
  
  int                   all_at_once = 0;
  int                   all_go = 0;
  struct dthr_event     go_eva;
  struct dthr_semaphore go_sema;
  
  struct thread_specifics {
    int thread_num;
    int counter;
    double  val;
  };
  
  void *myThread(void *arg)
  {
    int                     index = (uintptr_t) arg;
    struct thread_specifics *info;
    int                     th_num;
    double                  v;
  
    if (all_at_once) {
      dthr_semaphore_take(&go_sema);
      while (!all_go) {
        dthr_event_wait(&go_eva,&go_sema);
      }
      dthr_semaphore_drop(&go_sema);
    }
  
    info = (struct thread_specifics *) dthr_cur_thread->data;
    th_num = info->thread_num;
    if (index != th_num) {
      fprintf(stderr,"Thread %d: arg %d != thread data\n",th_num,index);
    }
    v = info->val;
    while (info->counter < count) {
      dthr_thread_yield();
      printf("Thread %d: count %d, val-1.0=%g\n",th_num,info->counter,v-1.0);
      v = sqrt(v);
      info->counter++;
    }
    return 0;
  }
  
  struct dthr_thread      *th, main_th;
  struct thread_specifics *priv;
  
  void *goForIt(void *unused)
  {
    int i;
  
    if (all_at_once) {
      dthr_semaphore_init(&go_sema,1);
      dthr_event_init(&go_eva);
    }
    for (i = 0; i < nthreads; i++)
      (void) dthr_thread_detach(dthr_thread_run(&th[i]));
    (void) dthr_thread_detach(dthr_cur_thread);
    if (all_at_once) {
      dthr_semaphore_take(&go_sema);
      all_go = 1;
      dthr_semaphore_drop(&go_sema);
      dthr_event_broadcast(&go_eva);
    }
    return 0;
  }
  
  extern int  getopt();
  extern char *optarg, *rindex();
  
  char    *me;
  
  void usage()
  {
    fprintf(stderr,
            "Usage: %s [-aA] [-s stackbytes] [-c count] [-t nthreads]\n",
            me);
  }
  
  int main(int ac, char **av)
  {
    int   opt;
    int   i;
  
    if (!(me = strrchr(*av,'/'))) me = *av;
    else ++me;
  
    while ((opt = getopt(ac,av,"aAc:s:t:")) != EOF) switch (opt) {
    case 'a': all_at_once = 1;    break;
    case 'A': all_at_once = 0;    break;
    case 'c': count = atoi(optarg);   break;
    case 's': stacksize = atoi(optarg); break;
    case 't': nthreads = atoi(optarg);  break;
    default:  usage(); exit(1);
    }
  
    th = (struct dthr_thread *) malloc(nthreads * sizeof *th);
    if (!th) {
      perror(me);
      fprintf(stderr,"%s:  insufficient space for thread descriptors\n", me);
      exit(1);
    }
    priv = (struct thread_specifics *) malloc(nthreads * sizeof *priv);
    if (!priv) {
      perror(me);
      fprintf(stderr,"%s:  insufficient space for thread private data\n", me);
      exit(1);
    }
  
    dthr_init();
  
    for (i = 0; i < nthreads; i++) {
      (void) dthr_thread_init(&th[i],myThread,(void *) (uintptr_t) i,stacksize);
  
      th[i].data = (void *) &priv[i];
      priv[i].thread_num = i;
      priv[i].counter = 0;
      priv[i].val = 100.0 * i;
    }
  
    printf("main: dthr_thread_init (main thread)\n");
    dthr_thread_init(&main_th, goForIt, (void *) 0, stacksize);
    printf("main: dthr_thread_multithread ***\n");
  
    dthr_thread_multithread(&main_th);
    fprintf(stderr,"All threads exited, all done!\n");
    return 0;
  }
  