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.