Blame tests/timeloop-basic.c

Packit ae235b
#undef G_DISABLE_ASSERT
Packit ae235b
#undef G_LOG_DOMAIN
Packit ae235b
Packit ae235b
#include <errno.h>
Packit ae235b
#include <stdlib.h>
Packit ae235b
#include <stdio.h>
Packit ae235b
#include <string.h>
Packit ae235b
#include <unistd.h>
Packit ae235b
#include <sys/resource.h>
Packit ae235b
#include <sys/time.h>
Packit ae235b
#include <poll.h>
Packit ae235b
Packit ae235b
#define TRUE 1
Packit ae235b
#define FALSE 0
Packit ae235b
Packit ae235b
static int n_children = 3;
Packit ae235b
static int n_active_children;
Packit ae235b
static int n_iters = 10000;
Packit ae235b
Packit ae235b
static int write_fds[1024];
Packit ae235b
static struct pollfd poll_fds[1024];
Packit ae235b
Packit ae235b
void
Packit ae235b
my_pipe (int *fds)
Packit ae235b
{
Packit ae235b
  if (pipe(fds) < 0)
Packit ae235b
    {
Packit ae235b
      int errsv = errno;
Packit ae235b
      fprintf (stderr, "Cannot create pipe %s\n", strerror (errsv));
Packit ae235b
      exit (1);
Packit ae235b
    }
Packit ae235b
}
Packit ae235b
Packit ae235b
int
Packit ae235b
read_all (int fd, char *buf, int len)
Packit ae235b
{
Packit ae235b
  size_t bytes_read = 0;
Packit ae235b
  gssize count;
Packit ae235b
Packit ae235b
  while (bytes_read < len)
Packit ae235b
    {
Packit ae235b
      count = read (fd, buf + bytes_read, len - bytes_read);
Packit ae235b
      if (count < 0)
Packit ae235b
	{
Packit ae235b
	  if (errno != EAGAIN)
Packit ae235b
	    return FALSE;
Packit ae235b
	}
Packit ae235b
      else if (count == 0)
Packit ae235b
	return FALSE;
Packit ae235b
Packit ae235b
      bytes_read += count;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
int
Packit ae235b
write_all (int fd, char *buf, int len)
Packit ae235b
{
Packit ae235b
  size_t bytes_written = 0;
Packit ae235b
  gssize count;
Packit ae235b
Packit ae235b
  while (bytes_written < len)
Packit ae235b
    {
Packit ae235b
      count = write (fd, buf + bytes_written, len - bytes_written);
Packit ae235b
      if (count < 0)
Packit ae235b
	{
Packit ae235b
	  if (errno != EAGAIN)
Packit ae235b
	    return FALSE;
Packit ae235b
	}
Packit ae235b
Packit ae235b
      bytes_written += count;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
void
Packit ae235b
run_child (int in_fd, int out_fd)
Packit ae235b
{
Packit ae235b
  int i;
Packit ae235b
  int val = 1;
Packit ae235b
Packit ae235b
  for (i = 0; i < n_iters; i++)
Packit ae235b
    {
Packit ae235b
      write_all (out_fd, (char *)&val, sizeof (val));
Packit ae235b
      read_all (in_fd, (char *)&val, sizeof (val));
Packit ae235b
    }
Packit ae235b
Packit ae235b
  val = 0;
Packit ae235b
  write_all (out_fd, (char *)&val, sizeof (val));
Packit ae235b
Packit ae235b
  exit (0);
Packit ae235b
}
Packit ae235b
Packit ae235b
int
Packit ae235b
input_callback (int source, int dest)
Packit ae235b
{
Packit ae235b
  int val;
Packit ae235b
  
Packit ae235b
  if (!read_all (source, (char *)&val, sizeof(val)))
Packit ae235b
    {
Packit ae235b
      fprintf (stderr,"Unexpected EOF\n");
Packit ae235b
      exit (1);
Packit ae235b
    }
Packit ae235b
Packit ae235b
  if (val)
Packit ae235b
    {
Packit ae235b
      write_all (dest, (char *)&val, sizeof(val));
Packit ae235b
      return TRUE;
Packit ae235b
    }
Packit ae235b
  else
Packit ae235b
    {
Packit ae235b
      close (source);
Packit ae235b
      close (dest);
Packit ae235b
      
Packit ae235b
      n_active_children--;
Packit ae235b
      return FALSE;
Packit ae235b
    }
Packit ae235b
}
Packit ae235b
Packit ae235b
void
Packit ae235b
create_child (int pos)
Packit ae235b
{
Packit ae235b
  int pid, errsv;
Packit ae235b
  int in_fds[2];
Packit ae235b
  int out_fds[2];
Packit ae235b
  
Packit ae235b
  my_pipe (in_fds);
Packit ae235b
  my_pipe (out_fds);
Packit ae235b
Packit ae235b
  pid = fork ();
Packit ae235b
  errsv = errno;
Packit ae235b
Packit ae235b
  if (pid > 0)			/* Parent */
Packit ae235b
    {
Packit ae235b
      close (in_fds[0]);
Packit ae235b
      close (out_fds[1]);
Packit ae235b
Packit ae235b
      write_fds[pos] = in_fds[1];
Packit ae235b
      poll_fds[pos].fd = out_fds[0];
Packit ae235b
      poll_fds[pos].events = POLLIN;
Packit ae235b
    }
Packit ae235b
  else if (pid == 0)		/* Child */
Packit ae235b
    {
Packit ae235b
      close (in_fds[1]);
Packit ae235b
      close (out_fds[0]);
Packit ae235b
Packit ae235b
      setsid ();
Packit ae235b
Packit ae235b
      run_child (in_fds[0], out_fds[1]);
Packit ae235b
    }
Packit ae235b
  else				/* Error */
Packit ae235b
    {
Packit ae235b
      fprintf (stderr,"Cannot fork: %s\n", strerror (errsv));
Packit ae235b
      exit (1);
Packit ae235b
    }
Packit ae235b
}
Packit ae235b
Packit ae235b
static double 
Packit ae235b
difftimeval (struct timeval *old, struct timeval *new)
Packit ae235b
{
Packit ae235b
  return
Packit ae235b
    (new->tv_sec - old->tv_sec) * 1000. + (new->tv_usec - old->tv_usec) / 1000;
Packit ae235b
}
Packit ae235b
Packit ae235b
int 
Packit ae235b
main (int argc, char **argv)
Packit ae235b
{
Packit ae235b
  int i, j;
Packit ae235b
  struct rusage old_usage;
Packit ae235b
  struct rusage new_usage;
Packit ae235b
  
Packit ae235b
  if (argc > 1)
Packit ae235b
    n_children = atoi(argv[1]);
Packit ae235b
Packit ae235b
  if (argc > 2)
Packit ae235b
    n_iters = atoi(argv[2]);
Packit ae235b
Packit ae235b
  printf ("Children: %d     Iters: %d\n", n_children, n_iters);
Packit ae235b
Packit ae235b
  n_active_children = n_children;
Packit ae235b
  for (i = 0; i < n_children; i++)
Packit ae235b
    create_child (i);
Packit ae235b
Packit ae235b
  getrusage (RUSAGE_SELF, &old_usage);
Packit ae235b
Packit ae235b
  while (n_active_children > 0)
Packit ae235b
    {
Packit ae235b
      int old_n_active_children = n_active_children;
Packit ae235b
Packit ae235b
      poll (poll_fds, n_active_children, -1);
Packit ae235b
Packit ae235b
      for (i=0; i
Packit ae235b
	{
Packit ae235b
	  if (poll_fds[i].events & (POLLIN | POLLHUP))
Packit ae235b
	    {
Packit ae235b
	      if (!input_callback (poll_fds[i].fd, write_fds[i]))
Packit ae235b
		write_fds[i] = -1;
Packit ae235b
	    }
Packit ae235b
	}
Packit ae235b
Packit ae235b
      if (old_n_active_children > n_active_children)
Packit ae235b
	{
Packit ae235b
	  j = 0;
Packit ae235b
	  for (i=0; i
Packit ae235b
	    {
Packit ae235b
	      if (write_fds[i] != -1)
Packit ae235b
		{
Packit ae235b
		  if (j < i)
Packit ae235b
		    {
Packit ae235b
		      poll_fds[j] = poll_fds[i];
Packit ae235b
		      write_fds[j] = write_fds[i];
Packit ae235b
		    }
Packit ae235b
		  j++;
Packit ae235b
		}
Packit ae235b
	    }
Packit ae235b
	}
Packit ae235b
    }
Packit ae235b
Packit ae235b
  getrusage (RUSAGE_SELF, &new_usage);
Packit ae235b
Packit ae235b
  printf ("Elapsed user: %g\n",
Packit ae235b
	   difftimeval (&old_usage.ru_utime, &new_usage.ru_utime));
Packit ae235b
  printf ("Elapsed system: %g\n",
Packit ae235b
	   difftimeval (&old_usage.ru_stime, &new_usage.ru_stime));
Packit ae235b
  printf ("Elapsed total: %g\n",
Packit ae235b
	  difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) +	   
Packit ae235b
	   difftimeval (&old_usage.ru_stime, &new_usage.ru_stime));
Packit ae235b
  printf ("total / iteration: %g\n",
Packit ae235b
	   (difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) +	   
Packit ae235b
	    difftimeval (&old_usage.ru_stime, &new_usage.ru_stime)) /
Packit ae235b
	   (n_iters * n_children));
Packit ae235b
Packit ae235b
  return 0;
Packit ae235b
}
Packit ae235b