smash-MPI

A runtime library for injecting faults and delays into Open MPI.
git clone git@git.mpah.dev/smash-MPI.git
Log | Files | Refs | README | LICENSE

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 }