Sunday 15 August 2010

Wait3 system call

The wait3(2) system call is like your shell's time(1) command, but returns more and cooler stuff. Particularly interesting is the number of voluntary and involuntary context switches during program execution!

Wait3 comes from BSD but is also available in Linux

/*
 * Print out getrusage info when a process exits
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/wait.h>

int main(int argc, char *argv[])
{
 int f, p, status;
 struct rusage rusage;

 if (argc == 0)
  errx(1, "USAGE: wait3 <command line>");

 if ((f = fork()) < 0)
  errx(1, "Could not run command");

 if (f == 0) {
  execvp(argv[1], &argv[1]);
  err(1, "Command failed");
 }

 p = wait3(&status, 0, &rusage);
 if (p < 0)
  errx(1, "wait3(2) on command failed");

 printf("Process accounting information for %d:\n", p);
 printf("  user time = %ds, %dus\n", rusage.ru_utime.tv_sec, rusage.ru_utime.tv_usec);
 printf("  system time = %ds, %dus\n", rusage.ru_stime.tv_sec, rusage.ru_stime.tv_usec);
 printf("  maximum resident set size = %lu\n", rusage.ru_maxrss);
 printf("  integral shared memory size = %lu\n", rusage.ru_ixrss);
 printf("  integral unshared data size = %lu\n", rusage.ru_idrss);
 printf("  integral unshared stack size = %lu\n", rusage.ru_isrss);
 printf("  page reclaims = %lu\n", rusage.ru_minflt);
 printf("  page faults = %lu\n", rusage.ru_majflt);
 printf("  swaps = %lu\n", rusage.ru_nswap);
 printf("  block input operations = %lu\n", rusage.ru_inblock);
 printf("  block output operations = %lu\n", rusage.ru_oublock);
 printf("  messages sent = %lu\n", rusage.ru_msgsnd);
 printf("  messages received = %lu\n", rusage.ru_msgrcv);
 printf("  signals received = %lu\n", rusage.ru_nsignals);
 printf("  voluntary context switches = %lu\n", rusage.ru_nvcsw);
 printf("  involuntary context switches = %lu\n", rusage.ru_nivcsw);

 exit(EXIT_SUCCESS);
}

e.g.
[martin@somehost ~/src/wait3]$ uname -a
FreeBSD somehost.somedomain 8.0-RELEASE-p3 FreeBSD 8.0-RELEASE-p3 #0: Tue May 25 20:54:11 UTC 2010     root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC  amd64
[martin@somehost ~/src/wait3]$ gcc wait3.c -o wait3
[martin@somehost ~/src/wait3]$ ./wait3 md5 wait3.c
MD5 (wait3.c) = f63266e7c311fe8fa3ef3ea7cd079185
Process accounting information for 6501:
  user time = 0s, 0us
  system time = 0s, 2981us
  maximum resident set size = 0
  integral shared memory size = 0
  integral unshared data size = 0
  integral unshared stack size = 0
  page reclaims = 97
  page faults = 0
  swaps = 0
  block input operations = 0
  block output operations = 0
  messages sent = 0
  messages received = 0
  signals received = 0
  voluntary context switches = 1
  involuntary context switches = 0

1 comment:

xiaoxia said...

Good example!!!
My OS homework is to implement a program like the time command. Your code helps me a lot. It saves my time to dive into the time source code.