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

#include <stdio.h>
#include <stdlib.h>
#include <io.h>

#define FALSE 0
#define TRUE  1

static int pages;
static long *count;
static char *mem;

static void usage (void)
{
  fprintf (stderr, "Usage: swaptest <pages>\n");
  exit (1);
}


static void test (int i, int flag)
{
  long *pm;

  pm = (long *)(mem + 4096 * i);
  if (count[i] == 0)
    {
      if (flag)
        {
          if (*pm != 0)
            {
              fprintf (stderr, "Page contents not zero\n");
              exit (2);
            }
          pm[0] = i;
          pm[1] = 1;
          count[i] = 1;
        }
    }
  else
    {
      if (pm[0] != i)
        {
          fprintf (stderr, "Pages confused\n");
          exit (2);
        }
      if (pm[1] != count[i])
        {
          fprintf (stderr, "Dirty page not restored from swap file\n");
          exit (2);
        }
      if (flag && rand () < RAND_MAX / 3)
        pm[1] = ++count[i];
    }
}


int main (int argc, char *argv[])
{
  long l, iter, w;
  char *p;
  int c, i, d, u, m;
  int interactive;

  interactive = _isterm (fileno (stdout));
  if (argc != 2)
    usage ();
  errno = 0;
  l = strtol (argv[1], &p, 0);
  if (errno != 0 || l <= 0 || l >= 0x7fff || *p != 0)
    usage ();
  pages = (int)l;
  count = malloc (pages * sizeof (*count));
  if (count == NULL)
    {
      fprintf (stderr, "malloc: Out of memory\n");
      exit (2);
    }
  for (i = 0; i < pages; ++i)
    count[i] = 0;
  d = pages * (RAND_MAX / pages);
  fprintf (stdout, "This is swaptest\n"); fflush (stdout);
  fprintf (stderr, "\n"); fflush (stderr);
  mem = sbrk (pages * 4096);
  if ((int)mem == -1)
    {
      perror ("sbrk");
      exit (2);
    }
  m = 0;
  for (iter = 0; ; ++iter)
    {
      c = _read_kbd (0, 0, 1);
      switch (c)
        {
        case 0x1b:
          return 0;
        case ' ':
          u = 0; w = 0;
          for (i = 0; i < pages; ++i)
            {
              w += count[i];
              if (count[i] == m)
                ++u;
            }
          printf ("%ld iterations, count=%d for %d pages, average count=%g\n",
                  iter, m, u, (double)w / (double)pages);
          if (u == 0)
            ++m;
          break;
        case 'b':
          __asm__ ("int $3");
          break;
        case 't':
          printf ("Testing..."); fflush (stdout);
          for (i = 0; i < pages; ++i)
            {
              test (i, FALSE);
              if (interactive && (i % 10 == 0))
                {
                  printf ("\rTesting (%d)...", i); fflush (stdout);
                }
            }
          if (interactive)
            printf ("\rTesting...OK     \n");
          else
            printf ("OK\n");
          fflush (stdout);
          break;
        }
      do
        {
          i = rand ();
        } while (i >= d);
      test (i % pages, TRUE);
    }
  return 0;
}
