callout.c (2515B)
1 #include "callout.h" 2 3 #include <err.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <semaphore.h> 8 #include <time.h> 9 10 struct callo callout[NCALL] = { 0 }; 11 extern timer_t smash_timer_id; 12 13 void 14 smash_print_callout(void) 15 { 16 size_t i; 17 18 for (i = 0; callout[i].c_func != NULL; ++i) 19 printf("c_time: %lli\nc_arg: %i\nc_func @ %p\n\n", 20 callout[i].c_time, callout[i].c_arg, 21 (void *)callout[i].c_func); 22 } 23 24 void 25 smash_set_timer(int time) 26 { 27 int t, s, ns; 28 struct itimerspec curr; 29 30 timer_gettime(smash_timer_id, &curr); 31 32 if (time == -1 || (curr.it_value.tv_nsec == 0 && curr.it_value.tv_sec == 0)) { 33 t = time == -1 ? callout[0].c_time : time; 34 s = t / 1000; 35 ns = (t % 1000) * 1000000; 36 37 if (s == 0 && ns == 0) 38 return; 39 40 struct itimerspec its; 41 42 its.it_value.tv_sec = s; 43 its.it_value.tv_nsec = ns; 44 45 its.it_interval.tv_sec = 0; 46 its.it_interval.tv_nsec = 0; 47 if (timer_settime(smash_timer_id, 0, &its, NULL) < 0) 48 err(1, "timer_settime"); 49 } 50 } 51 52 sem_t * 53 smash_timeout(int (*func)(), int arg, int time, struct mpi_send_args *args) 54 { 55 int t; 56 struct callo *p1, *p2; 57 58 59 t = time; 60 p1 = &callout[0]; 61 while (p1->c_func != 0 && p1->c_time <= t) { 62 t -= p1->c_time; 63 p1++; 64 } 65 p1->c_time -= t; 66 p2 = p1; 67 while (p2->c_func != 0) 68 p2++; 69 while (p2 >= p1) { 70 (p2+1)->c_time = p2->c_time; 71 (p2+1)->c_func = p2->c_func; 72 (p2+1)->c_arg = p2->c_arg; 73 (p2+1)->c_send_args = p2->c_send_args; 74 p2--; 75 } 76 p1->c_time = t; 77 p1->c_func = func; 78 p1->c_arg = arg; 79 if (args != NULL) 80 memcpy(&p1->c_send_args, args, sizeof(struct mpi_send_args)); 81 82 smash_set_timer(t); 83 84 return &p1->c_lock; 85 } 86 87 void 88 smash_clock(void) 89 { 90 struct callo *p1, *p2; 91 92 if (callout[0].c_func != 0) { 93 p1 = p2 = &callout[0]; 94 p1->c_time = 0; 95 96 while (p1->c_func != 0 && p1->c_time == 0) { 97 switch (p1->c_arg) { 98 case 6: 99 p1->c_func(p1->c_send_args.buf, p1->c_send_args.count, 100 p1->c_send_args.datatype, p1->c_send_args.dest, 101 p1->c_send_args.tag, p1->c_send_args.comm); 102 free(p1->c_send_args.buf); 103 sem_post(&p1->c_lock); 104 break; 105 case 0: 106 p1->c_func(); 107 break; 108 } 109 p1++; 110 } 111 112 while ((p2->c_func = p1->c_func)) { 113 p2->c_time = p1->c_time; 114 p2->c_arg = p1->c_arg; 115 p2->c_send_args = p1->c_send_args; 116 p1++; 117 p2++; 118 } 119 smash_set_timer(-1); 120 } 121 }