« Measuring context switches :: a small expedition. Part I | Main | Measuring context switches :: a small expedition. Part III »

Measuring context switches :: a small expedition. Part II

Here is the main routine, that is used for testing. Can't really say more than what's in the comments. The program will wait until a number (currently 23) context switches have hit it. It then prints out the number of seconds elapsed and a list with the durations of said context switches.
#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>


extern unsigned long long   _rdtsc();
extern unsigned int         _apicID();


typedef struct
{
   unsigned int   gap;
   unsigned int   apicID;
} context_switch_record;


static int   compare_context_switch_record( context_switch_record *a, 
                                            context_switch_record *b)
{
   return( (int) a->gap - (int) b->gap);
}


int   main( int argc, char *argv[]) 
{
   context_switch_record   infos[ 23];
   unsigned long long  a, b;
   unsigned long long  normal;
   unsigned long long  diff;
   unsigned int        i;
   struct timeval      start;
   struct timeval      stop;
   struct timeval      elapsed;
   
   gettimeofday( &start, NULL);

   //
   // establish a "gap" between two rdtsc() calls, that 
   // should be considered as normal (no interrupt)
   //
   a      = _rdtsc();
   b      = _rdtsc();
   normal = (b - a) * 20;
   printf( "(%qd -> %qd) ", b - a, normal);
   
   for( i = 0; i < sizeof( infos) / sizeof( context_switch_record); i++)
   {
      b  = _rdtsc();
      for(;;)
      {
         a    = b;
         b    = _rdtsc();
         diff = b - a;

	 //
	 // if the delay between a and b is to large
	 // then record it
	 //
         if( diff > normal)
            break;
      }
      assert( diff <= INT_MAX);
      
      // 
      // record cycles spent and current cpuID
      // 
      infos[ i].gap    = diff;
      infos[ i].apicID = _apicID();
   }
   
   gettimeofday( &stop, NULL);

   //
   // compute time spent waiting for n context switches
   //   
   elapsed.tv_sec  = stop.tv_sec - start.tv_sec;
   elapsed.tv_usec = stop.tv_usec - start.tv_usec;
   if( stop.tv_usec < start.tv_usec)
   {
      elapsed.tv_sec -= 1;
      elapsed.tv_usec = 1000000L - start.tv_usec + stop.tv_usec;
   }
   printf( "%d.%06lds\n\n", (int) elapsed.tv_sec, (long) elapsed.tv_usec);
   
   //
   // output data and done
   //   
   qsort( &infos, sizeof( infos) / sizeof( context_switch_record), 
          sizeof( context_switch_record), 
          (void *) compare_context_switch_record);
   
   for( i = 0; i < sizeof( infos) / sizeof( context_switch_record); i++)
      printf( "%u : %u\n", infos[ i].gap, infos[ i].apicID);

   return( 0);
}
Here is the Xcode Project.

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)

About

This page contains a single entry from the blog posted on December 1, 2011 1:44 AM.

The previous post in this blog was Measuring context switches :: a small expedition. Part I.

The next post in this blog is Measuring context switches :: a small expedition. Part III.

Many more can be found on the main index page or by looking through the archives.