glib/tests/timeloop-basic.c
branchRCL_3
changeset 56 acd3cd4aaceb
equal deleted inserted replaced
54:4332f0f7be53 56:acd3cd4aaceb
       
     1 /* Portions copyright (c) 2009 Nokia Corporation.  All rights reserved.*/
       
     2 #undef G_DISABLE_ASSERT
       
     3 #undef G_LOG_DOMAIN
       
     4 
       
     5 #include <errno.h>
       
     6 #include <stdlib.h>
       
     7 #include <stdio.h>
       
     8 #include <string.h>
       
     9 #include <unistd.h>
       
    10 #include <sys/resource.h>
       
    11 #include <sys/time.h>
       
    12 #include <sys/poll.h>
       
    13 
       
    14 #define TRUE 1
       
    15 #define FALSE 0
       
    16 
       
    17 static int n_children = 3;
       
    18 static int n_active_children;
       
    19 static int n_iters = 10000;
       
    20 
       
    21 static int write_fds[1024];
       
    22 static struct pollfd poll_fds[1024];
       
    23 
       
    24 void
       
    25 my_pipe (int *fds)
       
    26 {
       
    27   if (pipe(fds) < 0)
       
    28     {
       
    29       fprintf (stderr, "Cannot create pipe %s\n", strerror (errno));
       
    30       exit (1);
       
    31     }
       
    32 }
       
    33 
       
    34 int
       
    35 read_all (int fd, char *buf, int len)
       
    36 {
       
    37   size_t bytes_read = 0;
       
    38   ssize_t count;
       
    39 
       
    40   while (bytes_read < len)
       
    41     {
       
    42       count = read (fd, buf + bytes_read, len - bytes_read);
       
    43       if (count < 0)
       
    44 	{
       
    45 	  if (errno != EAGAIN)
       
    46 	    return FALSE;
       
    47 	}
       
    48       else if (count == 0)
       
    49 	return FALSE;
       
    50 
       
    51       bytes_read += count;
       
    52     }
       
    53 
       
    54   return TRUE;
       
    55 }
       
    56 
       
    57 int
       
    58 write_all (int fd, char *buf, int len)
       
    59 {
       
    60   size_t bytes_written = 0;
       
    61   ssize_t count;
       
    62 
       
    63   while (bytes_written < len)
       
    64     {
       
    65       count = write (fd, buf + bytes_written, len - bytes_written);
       
    66       if (count < 0)
       
    67 	{
       
    68 	  if (errno != EAGAIN)
       
    69 	    return FALSE;
       
    70 	}
       
    71 
       
    72       bytes_written += count;
       
    73     }
       
    74 
       
    75   return TRUE;
       
    76 }
       
    77 
       
    78 void
       
    79 run_child (int in_fd, int out_fd)
       
    80 {
       
    81   int i;
       
    82   int val = 1;
       
    83 
       
    84   for (i = 0; i < n_iters; i++)
       
    85     {
       
    86       write_all (out_fd, (char *)&val, sizeof (val));
       
    87       read_all (in_fd, (char *)&val, sizeof (val));
       
    88     }
       
    89 
       
    90   val = 0;
       
    91   write_all (out_fd, (char *)&val, sizeof (val));
       
    92 
       
    93   exit (0);
       
    94 }
       
    95 
       
    96 int
       
    97 input_callback (int source, int dest)
       
    98 {
       
    99   int val;
       
   100   
       
   101   if (!read_all (source, (char *)&val, sizeof(val)))
       
   102     {
       
   103       fprintf (stderr,"Unexpected EOF\n");
       
   104       exit (1);
       
   105     }
       
   106 
       
   107   if (val)
       
   108     {
       
   109       write_all (dest, (char *)&val, sizeof(val));
       
   110       return TRUE;
       
   111     }
       
   112   else
       
   113     {
       
   114       close (source);
       
   115       close (dest);
       
   116       
       
   117       n_active_children--;
       
   118       return FALSE;
       
   119     }
       
   120 }
       
   121 
       
   122 void
       
   123 create_child (int pos)
       
   124 {
       
   125   int pid;
       
   126   int in_fds[2];
       
   127   int out_fds[2];
       
   128   
       
   129   my_pipe (in_fds);
       
   130   my_pipe (out_fds);
       
   131 
       
   132   pid = fork ();
       
   133 
       
   134   if (pid > 0)			/* Parent */
       
   135     {
       
   136       close (in_fds[0]);
       
   137       close (out_fds[1]);
       
   138 
       
   139       write_fds[pos] = in_fds[1];
       
   140       poll_fds[pos].fd = out_fds[0];
       
   141       poll_fds[pos].events = POLLIN;
       
   142     }
       
   143   else if (pid == 0)		/* Child */
       
   144     {
       
   145       close (in_fds[1]);
       
   146       close (out_fds[0]);
       
   147 
       
   148       setsid ();
       
   149 
       
   150       run_child (in_fds[0], out_fds[1]);
       
   151     }
       
   152   else				/* Error */
       
   153     {
       
   154       fprintf (stderr,"Cannot fork: %s\n", strerror (errno));
       
   155       exit (1);
       
   156     }
       
   157 }
       
   158 
       
   159 static double 
       
   160 difftimeval (struct timeval *old, struct timeval *new)
       
   161 {
       
   162   return
       
   163     (new->tv_sec - old->tv_sec) * 1000. + (new->tv_usec - old->tv_usec) / 1000;
       
   164 }
       
   165 
       
   166 int 
       
   167 main (int argc, char **argv)
       
   168 {
       
   169   int i, j;
       
   170   struct rusage old_usage;
       
   171   struct rusage new_usage;
       
   172   
       
   173   if (argc > 1)
       
   174     n_children = atoi(argv[1]);
       
   175 
       
   176   if (argc > 2)
       
   177     n_iters = atoi(argv[2]);
       
   178 
       
   179   printf ("Children: %d     Iters: %d\n", n_children, n_iters);
       
   180 
       
   181   n_active_children = n_children;
       
   182   for (i = 0; i < n_children; i++)
       
   183     create_child (i);
       
   184 
       
   185   getrusage (RUSAGE_SELF, &old_usage);
       
   186 
       
   187   while (n_active_children > 0)
       
   188     {
       
   189       int old_n_active_children = n_active_children;
       
   190 
       
   191       poll (poll_fds, n_active_children, -1);
       
   192 
       
   193       for (i=0; i<n_active_children; i++)
       
   194 	{
       
   195 	  if (poll_fds[i].events & (POLLIN | POLLHUP))
       
   196 	    {
       
   197 	      if (!input_callback (poll_fds[i].fd, write_fds[i]))
       
   198 		write_fds[i] = -1;
       
   199 	    }
       
   200 	}
       
   201 
       
   202       if (old_n_active_children > n_active_children)
       
   203 	{
       
   204 	  j = 0;
       
   205 	  for (i=0; i<old_n_active_children; i++)
       
   206 	    {
       
   207 	      if (write_fds[i] != -1)
       
   208 		{
       
   209 		  if (j < i)
       
   210 		    {
       
   211 		      poll_fds[j] = poll_fds[i];
       
   212 		      write_fds[j] = write_fds[i];
       
   213 		    }
       
   214 		  j++;
       
   215 		}
       
   216 	    }
       
   217 	}
       
   218     }
       
   219 
       
   220   getrusage (RUSAGE_SELF, &new_usage);
       
   221 
       
   222   printf ("Elapsed user: %g\n",
       
   223 	   difftimeval (&old_usage.ru_utime, &new_usage.ru_utime));
       
   224   printf ("Elapsed system: %g\n",
       
   225 	   difftimeval (&old_usage.ru_stime, &new_usage.ru_stime));
       
   226   printf ("Elapsed total: %g\n",
       
   227 	  difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) +	   
       
   228 	   difftimeval (&old_usage.ru_stime, &new_usage.ru_stime));
       
   229   printf ("total / iteration: %g\n",
       
   230 	   (difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) +	   
       
   231 	    difftimeval (&old_usage.ru_stime, &new_usage.ru_stime)) /
       
   232 	   (n_iters * n_children));
       
   233 
       
   234   return 0;
       
   235 }
       
   236