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

/* Test __findfirst() and __findnext() with multiple threads. */

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <emx/syscalls.h>
#define INCL_DOSSEMAPHORES
#include <os2.h>


static volatile int n_complete;
static int pace_flag;
static int n_threads;
static HEV *ahev;


static void usage (void)
{
  fputs ("Usage: mtff [-p] <threads> <mask>...\n", stderr);
  exit (1);
}


static void pace (int idx)
{
  ULONG tmp;

  if (pace_flag)
    {
      DosResetEventSem (ahev[idx-1], &tmp);
      if (idx == n_threads)
        DosPostEventSem (ahev[0]);
      else
        DosPostEventSem (ahev[idx]);
      DosWaitEventSem (ahev[idx-1], SEM_INDEFINITE_WAIT);
    }
  else
    _sleep2 (50);
}


static void thread (void *arg)
{
  int tid, rc;
  struct _find buf;

  tid = *_threadid - 1;
  pace (tid);
  rc = __findfirst ((const char *)arg, _A_SUBDIR|_A_HIDDEN|_A_SYSTEM, &buf);
  while (rc == 0)
    {
      printf ("%d: %s\n", tid, buf.name);
      pace (tid);
      rc = __findnext (&buf);
    }
  ++n_complete;
  while (pace_flag)
    pace (tid);
}


int main (int argc, char *argv[])
{
  int i, j;
  ULONG rc;

  if (_osmode != OS2_MODE)
    {
      fputs ("This program requires OS/2.\n", stderr);
      return 0;
    }

  pace_flag = 0; j = 1;
  if (j < argc && strcmp (argv[j], "-p") == 0)
    pace_flag = 1, ++j;

  if (argc - j < 2)
    usage ();
  n_threads = atoi (argv[j++]);
  if (n_threads < 1)
    usage ();

  if (pace_flag)
    {
      ahev = malloc (n_threads * sizeof (*ahev));
      for (i = 0; i < n_threads; ++i)
        {
          rc = DosCreateEventSem (NULL, &ahev[i], DC_SEM_SHARED, FALSE);
          if (rc != 0)
            {
              fprintf (stderr, "DosCreateEventSem failed, rc=%lu\n", rc);
              return 2;
            }
        }
    }

  n_complete = 0;
  for (i = 0; i < n_threads; ++i)
    {
      if (_beginthread (thread, NULL, 0x8000, argv[j]) < 0)
        {
          fputs ("_beginthread() failed\n", stderr);
          return 2;
        }
      if (j < argc - 1)
        ++j;
    }
  if (pace_flag)
    DosPostEventSem (ahev[n_threads-1]);
  while (n_complete < n_threads)
    _sleep2 (100);
  return 0;
}
