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