/* stdio3.c (emx+gcc) */

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

static int counts[256];
static int ready;
static FILE *f;

/* Atomically increment *p. */

static __inline__ void incr (int *p)
{
  __asm__ ("lock;incl %0" : "=m"(*p) : : "cc");
}


static void thread (void *arg)
{
  int c;

  for (;;)
    {
      c = fgetc (f);
      if (c == EOF)
        break;
      incr (&counts[c]);
    }
  incr (&ready);
}


int main (void)
{
  int i, nloops, nthreads, pfd[2];
  static char msg[256];

  nloops = 50000;
  nthreads = 7;
  assert (pipe (pfd) == 0);
  for (i = 0; i < 256; ++i)
    counts[i] = 0;
  for (i = 0; i < 256; ++i)
    msg[i] = (char)i;
  f = fdopen (pfd[0], "r");
  assert (f != NULL);
  for (i = 0; i < nthreads; ++i)
    if (_beginthread (thread, NULL, 0x8000, NULL) == -1)
      abort ();
  for (i = 0; i < nloops / 1000; ++i)
    putchar ('.');
  putchar ('\r');
  for (i = 0; i < nloops; ++i)
    {
      if (i % 1000 == 0)
        {
          putchar ('='); fflush (stdout);
        }
      assert (write (pfd[1], msg, sizeof (msg)) == sizeof (msg));
    }
  close (pfd[1]);
  while (ready < nthreads)
    _sleep2 (10);
  fclose (f);
  putchar ('\n');
  for (i = 0; i < 256; ++i)
    if (counts[i] != nloops)
      abort ();
  return 0;
}
