/* * kerneltimer_PartAandB.c * * @author * Benjamin Bertka - 21306103 * bbertka@mss.icics.ubc.ca * * CICS505 - OS5 * This program implements Part A and B of kernel timer project */ #include #include #include #include #include #include #include #include /*Long integer valuese used to keep track of real, prof, and virt timer times. These values are updated whenevera signal is is received by the handler. */ long rsecs = 0; long vsecs = 0; long psecs = 0; /* Itimerval structs which maintain timer times for the real, profile, and virtual timers. */ struct itimerval realTimer; struct itimerval virtualTimer; struct itimerval profileTimer; /* These are the signals for the parent */ struct sigaction realSignalAction; /* Function prototypes that read the current status of the timers and save the info to the tv_Sec and tv_usec values */ void getItime(); /* These are the signal handler function */ void realTimeHandler (int signum); /* * computes elapsed time in milliseconds from seconds and microseconds */ long int elapsed(long int secs, long int microsecs); /* * Prints the timer values from the itimers for the calling type (p, ch1, ch2) */ void printItime(char *type, long r, long v, long p, struct itimerval real, struct itimerval virt, struct itimerval prof); /* * This method computed the elapsed time in milliseconds using the two input * times which asre in real seconds, and microseconds. It uses a case by case * basis to avoid any bad computations of zero or negative values. * Subtracts the microseconds from countdown maximum to get actual time. * PRE: secs and microsecs are not NULL * POST: the output is milliseconds */ long int elapsed(long int secs, long int microsecs){ if(secs == 0 && microsecs == 0){ return 0; }else if(secs == 0 && microsecs > 0){ return (999999 - microsecs)/1000; }else if(secs > 0 && microsecs == 0){ return (secs*1000); }else if(secs > 0 && microsecs > 0){ return (secs*1000) + (999999 - microsecs)/1000; }else{ return -1; } } /* * This methods prints out the process profile as per the assignment page's * specifications, and in a format readable. It uses the * elapsed() method to compute the millisecond times. * PRE: all input values are defined * POST: The profile for the calling process is printed to stdout */ void printItime(char * type, long r, long v, long p, struct itimerval rt, struct itimerval vt, struct itimerval pt){ struct timeval time; struct timezone zone; struct tm *tm; gettimeofday(&time, &zone); tm = localtime(&time.tv_sec); printf("TIME OF DAY: Hrs:%d Min:%02d Sec:%02d Msec:%d\n", tm->tm_hour, tm->tm_min, tm->tm_sec, time.tv_usec); printf("\t%s: REAL: sec:%ld msec:%ld\n",type, r, elapsed(rt.it_value.tv_sec, rt.it_value.tv_usec)); printf("\t%s: CPU: sec:%ld msec:%ld\n", type, p, elapsed(pt.it_value.tv_sec, pt.it_value.tv_usec)); printf("\t%s: USER: sec:%ld msec:%ld\n", type, v, elapsed(vt.it_value.tv_sec, vt.it_value.tv_usec)); long temp = elapsed(pt.it_value.tv_sec, pt.it_value.tv_usec) - elapsed(vt.it_value.tv_sec, vt.it_value.tv_usec); if(temp < 0){ printf("\t%s: KERN: sec:%ld msec:%ld\n", type, p-v-1, temp + 1000); }else{ printf("\t%s: KERN: sec:%ld msec:%ld\n", type, p-v, elapsed(pt.it_value.tv_sec, pt.it_value.tv_usec) - elapsed(vt.it_value.tv_sec, vt.it_value.tv_usec)); } } /* * The handler for the parent process. When a signal is called, the appropriate * value is updated for the corresponding itimer */ void realTimeHandler (int signum) { switch(signum){ case SIGALRM: getItime(); //get and print the values for r, v, p timers printf("\n"); printItime((char*)"Process: ", rsecs, vsecs, psecs, realTimer, virtualTimer, profileTimer); ++rsecs; //updates the real seconds break; case SIGVTALRM: ++vsecs; //updates the virtual seconds break; case SIGPROF: ++psecs; //updates the profile seconds break; } } /* * A wrapper for the getitimer call for the parent timer. Updates the * tv_sec and tv_usec values with the most recent itimer times */ void getItime(){ getitimer(ITIMER_REAL,&realTimer); getitimer(ITIMER_VIRTUAL,&virtualTimer); getitimer(ITIMER_PROF,&profileTimer); } /* * Initializes the itimers for the parent, and sets them */ void timerInit(){ realTimer.it_value.tv_sec = 0; realTimer.it_value.tv_usec = 999999; realTimer.it_interval.tv_sec = 0; realTimer.it_interval.tv_usec = 999999; setitimer (ITIMER_REAL, &realTimer, NULL); virtualTimer.it_value.tv_sec = 0; virtualTimer.it_value.tv_usec = 999999; virtualTimer.it_interval.tv_sec = 0; virtualTimer.it_interval.tv_usec = 999999; setitimer (ITIMER_VIRTUAL, &virtualTimer, NULL); profileTimer.it_value.tv_sec = 0; profileTimer.it_value.tv_usec = 999999; profileTimer.it_interval.tv_sec = 0; profileTimer.it_interval.tv_usec = 999999; setitimer (ITIMER_PROF, &profileTimer, NULL); } /* *Initializes the signalaction struct for the parent timers */ void signalInit(){ bzero (&realSignalAction, sizeof (realSignalAction)); realSignalAction.sa_handler = &realTimeHandler; sigaction(SIGALRM, &realSignalAction, NULL); sigaction(SIGVTALRM, &realSignalAction, NULL); sigaction(SIGPROF, &realSignalAction, NULL); } /* * The main entry point to the program. */ int main (int argc, char **argv){ timerInit(); signalInit(); while(1); return 0; }