/* * Rick van der Zwet * 0433373 * OS Assigment 3 - Part B * Licence: BSD * $Id: partBCD.c 508 2008-03-02 14:18:40Z rick $ */ /* XXX: Code is rather verbose and has got a lot of duplicate lines */ #include #include #include #include #include #include #include #include long unsigned int elapsed_usecs(long sec, long usec); long unsigned int fibonacci(unsigned int n); long unsigned int delta_time(struct itimerval proft, struct itimerval realt); static void p_sig_handler(int); static void c1_sig_handler(int); static void c2_sig_handler(int); //These variables are used to record the accumulated times. They are set //by the signal handlers and read by the process when the report the //results static long p_realt_secs = 0, c1_realt_secs = 0, c2_realt_secs = 0; static long p_virtt_secs = 0, c1_virtt_secs = 0, c2_virtt_secs = 0; static long p_proft_secs = 0, c1_proft_secs = 0, c2_proft_secs = 0; static struct itimerval p_realt, c1_realt, c2_realt; static struct itimerval p_virtt, c1_virtt, c2_virtt; static struct itimerval p_proft, c1_proft, c2_proft; int main(int argc, char ** argv) { long unsigned fib = 0; int pid1, pid2; unsigned int fibarg; int status; //Get command line argument, fibarg (the value N in the problem //statement) if (argc < 2) { fprintf(stderr, "Usage: %s \n", argv[0]); exit(EX_USAGE); } fibarg = atoi(argv[1]); printf("Calculating fibonacci number: %i\n", fibarg); //Initialize parent, child1 and child 2 timer values //XXX: Any quicker way of doing this? p_realt.it_interval.tv_sec = 1; p_realt.it_interval.tv_usec = 0; p_realt.it_value.tv_sec = 1; p_realt.it_value.tv_usec = 0; p_virtt.it_interval.tv_sec = 1; p_virtt.it_interval.tv_usec = 0; p_virtt.it_value.tv_sec = 1; p_virtt.it_value.tv_usec = 0; p_proft.it_interval.tv_sec = 1; p_proft.it_interval.tv_usec = 0; p_proft.it_value.tv_sec = 1; p_proft.it_value.tv_usec = 0; c1_realt.it_interval.tv_sec = 1; c1_realt.it_interval.tv_usec = 0; c1_realt.it_value.tv_sec = 1; c1_realt.it_value.tv_usec = 0; c1_virtt.it_interval.tv_sec = 1; c1_virtt.it_interval.tv_usec = 0; c1_virtt.it_value.tv_sec = 1; c1_virtt.it_value.tv_usec = 0; c1_proft.it_interval.tv_sec = 1; c1_proft.it_interval.tv_usec = 0; c1_proft.it_value.tv_sec = 1; c1_proft.it_value.tv_usec = 0; c2_realt.it_interval.tv_sec = 1; c2_realt.it_interval.tv_usec = 0; c2_realt.it_value.tv_sec = 1; c2_realt.it_value.tv_usec = 0; c2_virtt.it_interval.tv_sec = 1; c2_virtt.it_interval.tv_usec = 0; c2_virtt.it_value.tv_sec = 1; c2_virtt.it_value.tv_usec = 0; c2_proft.it_interval.tv_sec = 1; c2_proft.it_interval.tv_usec = 0; c2_proft.it_value.tv_sec = 1; c2_proft.it_value.tv_usec = 0; //Enable parent's signal handlers signal(SIGALRM, p_sig_handler); signal(SIGVTALRM, p_sig_handler); signal(SIGPROF, p_sig_handler); //Set parent itimers if(setitimer(ITIMER_REAL, &p_realt, NULL) == -1) perror("parent real timer set error"); if(setitimer(ITIMER_VIRTUAL, &p_virtt, NULL) == -1) perror("parent virtual timer set error"); if(setitimer(ITIMER_PROF, &p_proft, NULL) == -1) perror("parent profile timer set error"); pid1 = fork(); if (pid1 == 0) { // Enable child 1 signal handlers (disable parent handlers) signal(SIGALRM, c1_sig_handler); signal(SIGVTALRM, c1_sig_handler); signal(SIGPROF, c1_sig_handler); // Enable child 1 signal handlers // Set child 1 itimers if(setitimer(ITIMER_REAL, &c1_realt, NULL) == -1) perror("parent real timer set error"); if(setitimer(ITIMER_VIRTUAL, &c1_virtt, NULL) == -1) perror("parent virtual timer set error"); if(setitimer(ITIMER_PROF, &c1_proft, NULL) == -1) perror("parent profile timer set error"); // Start child 1 on the fibonacci program fib = fibonacci(fibarg); // Read child 1 itimer values and report them getitimer(ITIMER_PROF, &c1_proft); getitimer(ITIMER_REAL, &c1_realt); getitimer(ITIMER_VIRTUAL, &c1_virtt); printf("\n"); printf("Child 1 fib = %ld, real time = %ld sec, %ld msec\n", fib, c1_realt_secs, elapsed_usecs(c1_realt.it_value.tv_sec, c2_realt.it_value.tv_usec) / 1000); printf("Child 1 fib = %ld, cpu time = %ld sec, %ld msec\n", fib, c1_proft_secs, elapsed_usecs(c1_proft.it_value.tv_sec, c2_proft.it_value.tv_usec) / 1000); printf("Child 1 fib = %ld, user time = %ld sec, %ld msec\n", fib, c1_virtt_secs, elapsed_usecs(c1_virtt.it_value.tv_sec, c2_virtt.it_value.tv_usec) / 1000); printf("Child 1 fib = %ld, kernel time = %ld sec, %ld msec\n", fib, delta_time(c1_proft, c1_virtt), (elapsed_usecs(c1_proft.it_value.tv_sec, c1_proft.it_value.tv_usec) / 1000) - (elapsed_usecs(c1_virtt.it_value.tv_sec, c1_virtt.it_value.tv_usec) / 1000)); fflush(stdout); exit(0); } else { pid2 = fork(); if (pid2 == 0) { //Enable child 2 signal handlers signal(SIGALRM, c2_sig_handler); signal(SIGVTALRM, c2_sig_handler); signal(SIGPROF, c2_sig_handler); //Set child 2 itimers if(setitimer(ITIMER_REAL, &c2_realt, NULL) == -1) perror("parent real timer set error"); if(setitimer(ITIMER_VIRTUAL, &c2_virtt, NULL) == -1) perror("parent virtual timer set error"); if(setitimer(ITIMER_PROF, &c2_proft, NULL) == -1) perror("parent profile timer set error"); //Start child 2 on the fibonacci program fib = fibonacci(fibarg); //Read child 2 itimer values and report them getitimer(ITIMER_PROF, &c2_proft); getitimer(ITIMER_REAL, &c2_realt); getitimer(ITIMER_VIRTUAL, &c2_virtt); printf("\n"); printf("Child 2 fib = %ld, real time = %ld sec, %ld msec\n", fib, c2_realt_secs, elapsed_usecs(c2_realt.it_value.tv_sec, c2_realt.it_value.tv_usec) / 1000); printf("Child 2 fib = %ld, cpu time = %ld sec, %ld msec\n", fib, c2_proft_secs, elapsed_usecs(c2_proft.it_value.tv_sec, c2_proft.it_value.tv_usec) / 1000); printf("Child 2 fib = %ld, user time = %ld sec, %ld msec\n", fib, c2_virtt_secs, elapsed_usecs(c2_virtt.it_value.tv_sec, c2_virtt.it_value.tv_usec) / 1000); printf("Child 2 fib = %ld, kernel time = %ld sec, %ld msec\n", fib, delta_time(c2_proft, c2_virtt), (elapsed_usecs(c2_proft.it_value.tv_sec, c2_proft.it_value.tv_usec) / 1000) - (elapsed_usecs(c2_virtt.it_value.tv_sec, c2_virtt.it_value.tv_usec) / 1000)); fflush(stdout); exit(0); } else { /*This is the parent */ //Start parent on the fibonacci program fib = fibonacci(fibarg); // Wait for childen to terminate waitpid(0, &status, 0); waitpid(0, &status, 0); // Read parent itimer values and report them getitimer(ITIMER_PROF, &p_proft); getitimer(ITIMER_REAL, &p_realt); getitimer(ITIMER_VIRTUAL, &p_virtt); printf("\n"); printf("Parent fib = %ld, real time = %ld sec, %ld msec\n", fib, p_realt_secs, elapsed_usecs(p_realt.it_value.tv_sec, p_realt.it_value.tv_usec) / 1000); printf("Parent fib = %ld, cpu time = %ld sec, %ld msec\n", fib, p_proft_secs, elapsed_usecs(p_proft.it_value.tv_sec, p_proft.it_value.tv_usec) / 1000); printf("Parent fib = %ld, user time = %ld sec, %ld msec\n", fib, p_virtt_secs, elapsed_usecs(p_virtt.it_value.tv_sec, p_virtt.it_value.tv_usec) / 1000); printf("Parent fib = %ld, kernel time = %ld sec, %ld msec\n", fib, delta_time(p_proft, p_virtt), (elapsed_usecs(p_proft.it_value.tv_sec, p_proft.it_value.tv_usec) / 1000) - (elapsed_usecs(p_virtt.it_value.tv_sec, p_virtt.it_value.tv_usec) / 1000)); fflush(stdout); exit(0); } } return(0); } static void p_sig_handler(int signo) { printf("Signal handler parent, signal %i\n", signo); switch (signo) { case SIGALRM: p_realt_secs++; break; ;; case SIGVTALRM: p_virtt_secs++; break; case SIGPROF: p_proft_secs++; break; ;; } } static void c1_sig_handler(int signo) { printf("Signal handler child 1, signal %i\n", signo); switch (signo) { case SIGALRM: c1_realt_secs++; break; ;; case SIGVTALRM: c1_virtt_secs++; break; case SIGPROF: c1_proft_secs++; break; ;; } } static void c2_sig_handler(int signo) { printf("Signal handler child 2, signal %i\n", signo); switch (signo) { case SIGALRM: c2_realt_secs++; break; ;; case SIGVTALRM: c2_virtt_secs++; break; case SIGPROF: c2_proft_secs++; break; ;; } } long unsigned int elapsed_usecs(long sec, long usec) { return( sec * 1000 + usec); } long unsigned int delta_time(struct itimerval proft, struct itimerval realt) { long p_usec = proft.it_value.tv_usec; long r_usec = proft.it_value.tv_usec; if ( p_usec > r_usec ) return (p_usec - r_usec); /* else */ return (p_usec - r_usec); } long unsigned int fibonacci(unsigned int n) { if (n == 0) return 0; else if (n == 1 || n == 2) return 1; else return(fibonacci(n-1) + fibonacci(n-2)); }