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.