[2] | 1 | /*
|
---|
| 2 | * Rick van der Zwet
|
---|
| 3 | * 0433373
|
---|
| 4 | * OS Assigment 3 - Part B
|
---|
| 5 | * Licence: BSD
|
---|
| 6 | * $Id: partBCD.c 508 2008-03-02 14:18:40Z rick $
|
---|
| 7 | */
|
---|
| 8 |
|
---|
| 9 | /* XXX: Code is rather verbose and has got a lot of duplicate lines */
|
---|
| 10 |
|
---|
| 11 | #include <sys/time.h>
|
---|
| 12 | #include <sys/types.h>
|
---|
| 13 | #include <sys/wait.h>
|
---|
| 14 | #include <signal.h>
|
---|
| 15 | #include <unistd.h>
|
---|
| 16 | #include <stdio.h>
|
---|
| 17 | #include <stdlib.h>
|
---|
| 18 | #include <sysexits.h>
|
---|
| 19 |
|
---|
| 20 | long unsigned int elapsed_usecs(long sec, long usec);
|
---|
| 21 | long unsigned int fibonacci(unsigned int n);
|
---|
| 22 | long unsigned int delta_time(struct itimerval proft, struct itimerval
|
---|
| 23 | realt);
|
---|
| 24 | static void p_sig_handler(int);
|
---|
| 25 | static void c1_sig_handler(int);
|
---|
| 26 | static void c2_sig_handler(int);
|
---|
| 27 |
|
---|
| 28 | //These variables are used to record the accumulated times. They are set
|
---|
| 29 | //by the signal handlers and read by the process when the report the
|
---|
| 30 | //results
|
---|
| 31 |
|
---|
| 32 | static long p_realt_secs = 0, c1_realt_secs = 0, c2_realt_secs = 0;
|
---|
| 33 | static long p_virtt_secs = 0, c1_virtt_secs = 0, c2_virtt_secs = 0;
|
---|
| 34 | static long p_proft_secs = 0, c1_proft_secs = 0, c2_proft_secs = 0;
|
---|
| 35 | static struct itimerval p_realt, c1_realt, c2_realt;
|
---|
| 36 | static struct itimerval p_virtt, c1_virtt, c2_virtt;
|
---|
| 37 | static struct itimerval p_proft, c1_proft, c2_proft;
|
---|
| 38 |
|
---|
| 39 | int main(int argc, char ** argv) {
|
---|
| 40 | long unsigned fib = 0;
|
---|
| 41 | int pid1, pid2;
|
---|
| 42 | unsigned int fibarg;
|
---|
| 43 | int status;
|
---|
| 44 |
|
---|
| 45 | //Get command line argument, fibarg (the value N in the problem
|
---|
| 46 | //statement)
|
---|
| 47 | if (argc < 2) {
|
---|
| 48 | fprintf(stderr, "Usage: %s <number>\n", argv[0]);
|
---|
| 49 | exit(EX_USAGE);
|
---|
| 50 | }
|
---|
| 51 |
|
---|
| 52 | fibarg = atoi(argv[1]);
|
---|
| 53 | printf("Calculating fibonacci number: %i\n", fibarg);
|
---|
| 54 |
|
---|
| 55 | //Initialize parent, child1 and child 2 timer values
|
---|
| 56 | //XXX: Any quicker way of doing this?
|
---|
| 57 | p_realt.it_interval.tv_sec = 1;
|
---|
| 58 | p_realt.it_interval.tv_usec = 0;
|
---|
| 59 | p_realt.it_value.tv_sec = 1;
|
---|
| 60 | p_realt.it_value.tv_usec = 0;
|
---|
| 61 | p_virtt.it_interval.tv_sec = 1;
|
---|
| 62 | p_virtt.it_interval.tv_usec = 0;
|
---|
| 63 | p_virtt.it_value.tv_sec = 1;
|
---|
| 64 | p_virtt.it_value.tv_usec = 0;
|
---|
| 65 | p_proft.it_interval.tv_sec = 1;
|
---|
| 66 | p_proft.it_interval.tv_usec = 0;
|
---|
| 67 | p_proft.it_value.tv_sec = 1;
|
---|
| 68 | p_proft.it_value.tv_usec = 0;
|
---|
| 69 |
|
---|
| 70 | c1_realt.it_interval.tv_sec = 1;
|
---|
| 71 | c1_realt.it_interval.tv_usec = 0;
|
---|
| 72 | c1_realt.it_value.tv_sec = 1;
|
---|
| 73 | c1_realt.it_value.tv_usec = 0;
|
---|
| 74 | c1_virtt.it_interval.tv_sec = 1;
|
---|
| 75 | c1_virtt.it_interval.tv_usec = 0;
|
---|
| 76 | c1_virtt.it_value.tv_sec = 1;
|
---|
| 77 | c1_virtt.it_value.tv_usec = 0;
|
---|
| 78 | c1_proft.it_interval.tv_sec = 1;
|
---|
| 79 | c1_proft.it_interval.tv_usec = 0;
|
---|
| 80 | c1_proft.it_value.tv_sec = 1;
|
---|
| 81 | c1_proft.it_value.tv_usec = 0;
|
---|
| 82 |
|
---|
| 83 | c2_realt.it_interval.tv_sec = 1;
|
---|
| 84 | c2_realt.it_interval.tv_usec = 0;
|
---|
| 85 | c2_realt.it_value.tv_sec = 1;
|
---|
| 86 | c2_realt.it_value.tv_usec = 0;
|
---|
| 87 | c2_virtt.it_interval.tv_sec = 1;
|
---|
| 88 | c2_virtt.it_interval.tv_usec = 0;
|
---|
| 89 | c2_virtt.it_value.tv_sec = 1;
|
---|
| 90 | c2_virtt.it_value.tv_usec = 0;
|
---|
| 91 | c2_proft.it_interval.tv_sec = 1;
|
---|
| 92 | c2_proft.it_interval.tv_usec = 0;
|
---|
| 93 | c2_proft.it_value.tv_sec = 1;
|
---|
| 94 | c2_proft.it_value.tv_usec = 0;
|
---|
| 95 |
|
---|
| 96 | //Enable parent's signal handlers
|
---|
| 97 | signal(SIGALRM, p_sig_handler);
|
---|
| 98 | signal(SIGVTALRM, p_sig_handler);
|
---|
| 99 | signal(SIGPROF, p_sig_handler);
|
---|
| 100 |
|
---|
| 101 | //Set parent itimers
|
---|
| 102 | if(setitimer(ITIMER_REAL, &p_realt, NULL) == -1)
|
---|
| 103 | perror("parent real timer set error");
|
---|
| 104 | if(setitimer(ITIMER_VIRTUAL, &p_virtt, NULL) == -1)
|
---|
| 105 | perror("parent virtual timer set error");
|
---|
| 106 | if(setitimer(ITIMER_PROF, &p_proft, NULL) == -1)
|
---|
| 107 | perror("parent profile timer set error");
|
---|
| 108 |
|
---|
| 109 | pid1 = fork();
|
---|
| 110 | if (pid1 == 0) {
|
---|
| 111 | // Enable child 1 signal handlers (disable parent handlers)
|
---|
| 112 | signal(SIGALRM, c1_sig_handler);
|
---|
| 113 | signal(SIGVTALRM, c1_sig_handler);
|
---|
| 114 | signal(SIGPROF, c1_sig_handler);
|
---|
| 115 |
|
---|
| 116 | // Enable child 1 signal handlers
|
---|
| 117 |
|
---|
| 118 | // Set child 1 itimers
|
---|
| 119 | if(setitimer(ITIMER_REAL, &c1_realt, NULL) == -1)
|
---|
| 120 | perror("parent real timer set error");
|
---|
| 121 | if(setitimer(ITIMER_VIRTUAL, &c1_virtt, NULL) == -1)
|
---|
| 122 | perror("parent virtual timer set error");
|
---|
| 123 | if(setitimer(ITIMER_PROF, &c1_proft, NULL) == -1)
|
---|
| 124 | perror("parent profile timer set error");
|
---|
| 125 |
|
---|
| 126 | // Start child 1 on the fibonacci program
|
---|
| 127 | fib = fibonacci(fibarg);
|
---|
| 128 |
|
---|
| 129 | // Read child 1 itimer values and report them
|
---|
| 130 | getitimer(ITIMER_PROF, &c1_proft);
|
---|
| 131 | getitimer(ITIMER_REAL, &c1_realt);
|
---|
| 132 | getitimer(ITIMER_VIRTUAL, &c1_virtt);
|
---|
| 133 | printf("\n");
|
---|
| 134 | printf("Child 1 fib = %ld, real time = %ld sec, %ld msec\n",
|
---|
| 135 | fib, c1_realt_secs,
|
---|
| 136 | elapsed_usecs(c1_realt.it_value.tv_sec,
|
---|
| 137 | c2_realt.it_value.tv_usec) / 1000);
|
---|
| 138 | printf("Child 1 fib = %ld, cpu time = %ld sec, %ld msec\n",
|
---|
| 139 | fib, c1_proft_secs,
|
---|
| 140 | elapsed_usecs(c1_proft.it_value.tv_sec,
|
---|
| 141 | c2_proft.it_value.tv_usec) / 1000);
|
---|
| 142 | printf("Child 1 fib = %ld, user time = %ld sec, %ld msec\n",
|
---|
| 143 | fib, c1_virtt_secs,
|
---|
| 144 | elapsed_usecs(c1_virtt.it_value.tv_sec,
|
---|
| 145 | c2_virtt.it_value.tv_usec) / 1000);
|
---|
| 146 |
|
---|
| 147 | printf("Child 1 fib = %ld, kernel time = %ld sec, %ld msec\n",
|
---|
| 148 | fib, delta_time(c1_proft, c1_virtt),
|
---|
| 149 | (elapsed_usecs(c1_proft.it_value.tv_sec,
|
---|
| 150 | c1_proft.it_value.tv_usec) / 1000) -
|
---|
| 151 | (elapsed_usecs(c1_virtt.it_value.tv_sec,
|
---|
| 152 | c1_virtt.it_value.tv_usec) / 1000));
|
---|
| 153 | fflush(stdout);
|
---|
| 154 | exit(0);
|
---|
| 155 | } else {
|
---|
| 156 | pid2 = fork();
|
---|
| 157 | if (pid2 == 0) {
|
---|
| 158 | //Enable child 2 signal handlers
|
---|
| 159 | signal(SIGALRM, c2_sig_handler);
|
---|
| 160 | signal(SIGVTALRM, c2_sig_handler);
|
---|
| 161 | signal(SIGPROF, c2_sig_handler);
|
---|
| 162 |
|
---|
| 163 | //Set child 2 itimers
|
---|
| 164 | if(setitimer(ITIMER_REAL, &c2_realt, NULL) == -1)
|
---|
| 165 | perror("parent real timer set error");
|
---|
| 166 | if(setitimer(ITIMER_VIRTUAL, &c2_virtt, NULL) == -1)
|
---|
| 167 | perror("parent virtual timer set error");
|
---|
| 168 | if(setitimer(ITIMER_PROF, &c2_proft, NULL) == -1)
|
---|
| 169 | perror("parent profile timer set error");
|
---|
| 170 |
|
---|
| 171 | //Start child 2 on the fibonacci program
|
---|
| 172 | fib = fibonacci(fibarg);
|
---|
| 173 |
|
---|
| 174 | //Read child 2 itimer values and report them
|
---|
| 175 | getitimer(ITIMER_PROF, &c2_proft);
|
---|
| 176 | getitimer(ITIMER_REAL, &c2_realt);
|
---|
| 177 | getitimer(ITIMER_VIRTUAL, &c2_virtt);
|
---|
| 178 | printf("\n");
|
---|
| 179 | printf("Child 2 fib = %ld, real time = %ld sec, %ld msec\n",
|
---|
| 180 | fib, c2_realt_secs,
|
---|
| 181 | elapsed_usecs(c2_realt.it_value.tv_sec,
|
---|
| 182 | c2_realt.it_value.tv_usec) / 1000);
|
---|
| 183 | printf("Child 2 fib = %ld, cpu time = %ld sec, %ld msec\n",
|
---|
| 184 | fib, c2_proft_secs,
|
---|
| 185 | elapsed_usecs(c2_proft.it_value.tv_sec,
|
---|
| 186 | c2_proft.it_value.tv_usec) / 1000);
|
---|
| 187 | printf("Child 2 fib = %ld, user time = %ld sec, %ld msec\n",
|
---|
| 188 | fib, c2_virtt_secs,
|
---|
| 189 | elapsed_usecs(c2_virtt.it_value.tv_sec,
|
---|
| 190 | c2_virtt.it_value.tv_usec) / 1000);
|
---|
| 191 |
|
---|
| 192 | printf("Child 2 fib = %ld, kernel time = %ld sec, %ld msec\n",
|
---|
| 193 | fib, delta_time(c2_proft, c2_virtt),
|
---|
| 194 | (elapsed_usecs(c2_proft.it_value.tv_sec,
|
---|
| 195 | c2_proft.it_value.tv_usec) / 1000) -
|
---|
| 196 | (elapsed_usecs(c2_virtt.it_value.tv_sec,
|
---|
| 197 | c2_virtt.it_value.tv_usec) / 1000));
|
---|
| 198 | fflush(stdout);
|
---|
| 199 | exit(0);
|
---|
| 200 | } else { /*This is the parent */
|
---|
| 201 | //Start parent on the fibonacci program
|
---|
| 202 | fib = fibonacci(fibarg);
|
---|
| 203 |
|
---|
| 204 | // Wait for childen to terminate
|
---|
| 205 | waitpid(0, &status, 0);
|
---|
| 206 | waitpid(0, &status, 0);
|
---|
| 207 |
|
---|
| 208 | // Read parent itimer values and report them
|
---|
| 209 | getitimer(ITIMER_PROF, &p_proft);
|
---|
| 210 | getitimer(ITIMER_REAL, &p_realt);
|
---|
| 211 | getitimer(ITIMER_VIRTUAL, &p_virtt);
|
---|
| 212 | printf("\n");
|
---|
| 213 | printf("Parent fib = %ld, real time = %ld sec, %ld msec\n",
|
---|
| 214 | fib, p_realt_secs,
|
---|
| 215 | elapsed_usecs(p_realt.it_value.tv_sec,
|
---|
| 216 | p_realt.it_value.tv_usec) / 1000);
|
---|
| 217 | printf("Parent fib = %ld, cpu time = %ld sec, %ld msec\n",
|
---|
| 218 | fib, p_proft_secs,
|
---|
| 219 | elapsed_usecs(p_proft.it_value.tv_sec,
|
---|
| 220 | p_proft.it_value.tv_usec) / 1000);
|
---|
| 221 | printf("Parent fib = %ld, user time = %ld sec, %ld msec\n",
|
---|
| 222 | fib, p_virtt_secs,
|
---|
| 223 | elapsed_usecs(p_virtt.it_value.tv_sec,
|
---|
| 224 | p_virtt.it_value.tv_usec) / 1000);
|
---|
| 225 |
|
---|
| 226 | printf("Parent fib = %ld, kernel time = %ld sec, %ld msec\n",
|
---|
| 227 | fib, delta_time(p_proft, p_virtt),
|
---|
| 228 | (elapsed_usecs(p_proft.it_value.tv_sec,
|
---|
| 229 | p_proft.it_value.tv_usec) / 1000) -
|
---|
| 230 | (elapsed_usecs(p_virtt.it_value.tv_sec,
|
---|
| 231 | p_virtt.it_value.tv_usec) / 1000));
|
---|
| 232 | fflush(stdout);
|
---|
| 233 | exit(0);
|
---|
| 234 | }
|
---|
| 235 | }
|
---|
| 236 | return(0);
|
---|
| 237 | }
|
---|
| 238 |
|
---|
| 239 | static void p_sig_handler(int signo) {
|
---|
| 240 | printf("Signal handler parent, signal %i\n", signo);
|
---|
| 241 | switch (signo) {
|
---|
| 242 | case SIGALRM:
|
---|
| 243 | p_realt_secs++;
|
---|
| 244 | break;
|
---|
| 245 | ;;
|
---|
| 246 | case SIGVTALRM:
|
---|
| 247 | p_virtt_secs++;
|
---|
| 248 | break;
|
---|
| 249 | case SIGPROF:
|
---|
| 250 | p_proft_secs++;
|
---|
| 251 | break;
|
---|
| 252 | ;;
|
---|
| 253 | }
|
---|
| 254 | }
|
---|
| 255 |
|
---|
| 256 | static void c1_sig_handler(int signo) {
|
---|
| 257 | printf("Signal handler child 1, signal %i\n", signo);
|
---|
| 258 | switch (signo) {
|
---|
| 259 | case SIGALRM:
|
---|
| 260 | c1_realt_secs++;
|
---|
| 261 | break;
|
---|
| 262 | ;;
|
---|
| 263 | case SIGVTALRM:
|
---|
| 264 | c1_virtt_secs++;
|
---|
| 265 | break;
|
---|
| 266 | case SIGPROF:
|
---|
| 267 | c1_proft_secs++;
|
---|
| 268 | break;
|
---|
| 269 | ;;
|
---|
| 270 | }
|
---|
| 271 | }
|
---|
| 272 |
|
---|
| 273 | static void c2_sig_handler(int signo) {
|
---|
| 274 | printf("Signal handler child 2, signal %i\n", signo);
|
---|
| 275 | switch (signo) {
|
---|
| 276 | case SIGALRM:
|
---|
| 277 | c2_realt_secs++;
|
---|
| 278 | break;
|
---|
| 279 | ;;
|
---|
| 280 | case SIGVTALRM:
|
---|
| 281 | c2_virtt_secs++;
|
---|
| 282 | break;
|
---|
| 283 | case SIGPROF:
|
---|
| 284 | c2_proft_secs++;
|
---|
| 285 | break;
|
---|
| 286 | ;;
|
---|
| 287 | }
|
---|
| 288 | }
|
---|
| 289 |
|
---|
| 290 | long unsigned int elapsed_usecs(long sec, long usec) {
|
---|
| 291 | return( sec * 1000 + usec);
|
---|
| 292 | }
|
---|
| 293 |
|
---|
| 294 | long unsigned int delta_time(struct itimerval proft,
|
---|
| 295 | struct itimerval realt) {
|
---|
| 296 | long p_usec = proft.it_value.tv_usec;
|
---|
| 297 | long r_usec = proft.it_value.tv_usec;
|
---|
| 298 | if ( p_usec > r_usec )
|
---|
| 299 | return (p_usec - r_usec);
|
---|
| 300 | /* else */
|
---|
| 301 | return (p_usec - r_usec);
|
---|
| 302 | }
|
---|
| 303 |
|
---|
| 304 | long unsigned int fibonacci(unsigned int n) {
|
---|
| 305 | if (n == 0)
|
---|
| 306 | return 0;
|
---|
| 307 | else if (n == 1 || n == 2)
|
---|
| 308 | return 1;
|
---|
| 309 | else
|
---|
| 310 | return(fibonacci(n-1) + fibonacci(n-2));
|
---|
| 311 | }
|
---|
| 312 |
|
---|