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 |
|
---|