#include #include #include #include #include #include #include #include #include #include "returncode.h" #include "monano.h" #include "monano_data.h" #include "measure.h" #include "time_conversion.h" #include "task_parameter.h" #include "nthread.h" #include "benchmark.h" sem_t prec_const; pthread_mutex_t non_preemptive; int preemption_delay_execution = 0; void* benchmark_my_callback(int anomaly_number, pthread_monano_id_t id) { printf("Type anomaly : %d Anomaly is detected of thread number %d\n", anomaly_number, id); return 0; } void benchmark_periodic_activation_parameter_init(struct periodic_activation_parameters* p){ p->ego=0; p->non_preemptive=0; p->preemption_delay=0; p->delay_execution=0; p->precedency_blocking=0; p->asynchronous=0; } void benchmark_init(void){ int status; status=sem_init(&prec_const,0,0); if (status <0) returncode("sem_init",status); status=pthread_mutex_init(&non_preemptive, NULL); if (status < 0) returncode("pthread_mutex_init", status); } void* benchmark_periodic_activation(void* arg){ struct periodic_activation_parameters params = *(periodic_activation_parameters*)arg; int status; struct timespec measure_ts_start, delay, departure, dep; pthread_monano_attr_t attr; attr=pthread_monano_get_attribute(&my_monano, my_monano_id[params.ego]); // printf("params.ego = %d \n", params.ego); // printf("params.precedency_blocking = %d \n", params.precedency_blocking); // printf("params.non_preemptive = %d \n", params.non_preemptive); //management of an asynchronous task if((pthread_monano_attr_getdeparture(attr).tv_sec!=0)||(pthread_monano_attr_getdeparture(attr).tv_nsec!=0)){ departure = pthread_monano_attr_getdeparture(attr); printf("en attente du departure = %d :%d\n", (int)departure.tv_sec, (int)departure.tv_nsec); nanosleep(&departure, NULL); } if (params.preemption_delay==1){ preemption_delay_execution = 1; } //block the thread for precedence constraints if (params.precedency_blocking==1) { // printf("SEMAPHORE : BLOCKING OF THREAD N°EGO== %d WAITING T3 EXECUTION \n", params.ego); status=sem_wait(&prec_const); if(status<0) returncode("sem_wait",status); } //lock the thread for no preemption if (params.non_preemptive==1){ // printf("MUTEX LOCK OF THREAD N°EGO=%d\n", params.ego); status=pthread_mutex_lock(&non_preemptive); if (status<0) returncode("pthread_mutex_lock", status); } // measure_start(&measure_ts_start); status=pthread_monano_signal_departure_time(&my_monano, my_monano_id[params.ego]); // measure_end(measure_ts_start, "end_time_signal_departure_time"); if(status<0) returncode("pthread_monano_signal_departure_time",status); // printf("EXECUTION OF THREAD N°EGO== %d \n", params.ego); // attr=pthread_monano_get_attribute(&my_monano, my_monano_id[params.ego]); status=benchmark_simulate_thread_execution(&my_monano, my_monano_id[params.ego]); if(status<0) returncode("pthread_monano_thread_execution",status); // measure_start(&measure_ts_start); status=pthread_monano_signal_end_time(&my_monano, my_monano_id[params.ego]); // measure_end(measure_ts_start, "end_time_signal_end_time"); if(status<0) returncode("pthread_monano_signal_end_time",status); //unlock the thread for no preemption if (params.non_preemptive==1){ // printf("MUTEX UNLOCK OF THREAD N°EGO=%d\n", params.ego); status=pthread_mutex_unlock(&non_preemptive); if (status<0) returncode("pthread_mutex_unlock", status); } int j=0, sortie=0; //unblock the thread of precedence constraints if (my_monano.nb_precedencies!=0) do{ if (params.ego == my_monano.pthread_precedencies[j].source){ // printf("SEMAPHORE : EXECUTION OF THREAD N°EGO== %d AND UNBLOCKING THE SEMAPHORE \n", params.ego); status=sem_post(&prec_const); sortie=1; } j++; }while ( j< my_monano.nb_precedencies && sortie ==0); return 0; } int benchmark_simulate_thread_execution(pthread_monano_t* t, pthread_monano_id_t id) { struct timespec starttime, currenttime, endtime, measure_ts_start; pthread_monano_attr_t attr; struct timespec wcet, delay, preemption; struct timespec execution_time; int i, status; clock_gettime(CLOCK_REALTIME, &starttime); printf("debut de thread_execution de %x \n",pthread_self() ); attr=pthread_monano_get_attribute(t, id); wcet=pthread_monano_attr_getwcet(attr); delay=pthread_monano_attr_getdelay(attr); // random value between 1 and wcet execution_time=benchmark_random_execution_time(wcet); do{ clock_gettime(CLOCK_REALTIME, ¤ttime); attr=pthread_monano_get_attribute(t, id); //a task will be delay while it has been preempted preemption=pthread_monano_attr_getpreemption_time(attr); if(preemption_delay_execution == 1) if((preemption.tv_sec!=0)||(preemption.tv_nsec!=0)) if ((delay.tv_sec!=0)|(delay.tv_nsec!=0)){ // printf("en attente \n"); nanosleep(&delay, NULL); } }while (ts_compare(ts_substract(currenttime,starttime),ts_add(ts_add(execution_time,pthread_monano_attr_getpreemption_time(attr)),delay))<0); endtime=ts_substract(currenttime,starttime); printf("fin de thread_execution de %x wcet=%d:%d et temps execution global = %d:%d\n ",pthread_self(), (int)wcet.tv_sec, (int)wcet.tv_nsec,(int)endtime.tv_sec, (int)endtime.tv_nsec ); return 0; } int benchmark_simulate_thread_interruption(struct timespec h) { struct timespec starttime_interruption, currenttime; clock_gettime(CLOCK_REALTIME, &starttime_interruption); do{ clock_gettime(CLOCK_REALTIME, ¤ttime); }while (ts_compare(ts_substract(currenttime,starttime_interruption),h)<0); return 0; } long long benchmark_timespec_to_nanoseconds(struct timespec ts){ return ((long long)ts.tv_sec * 1000000000LL) + ts.tv_nsec; } struct timespec benchmark_nanoseconds_to_timespec(long long ns){ struct timespec ts; ts.tv_sec = ns / 1000000000; ts.tv_nsec = ns % 1000000000; return ts; } struct timespec benchmark_random_execution_time(struct timespec ts){ long long ns = benchmark_timespec_to_nanoseconds(ts); long long range, rs; //initialize the generator srand(time(NULL)); //generate a random number between n/2 and ns-1 range = ns - (ns / 2) +1 ; rs = rand() % range; rs = rs + (ns / 2); return benchmark_nanoseconds_to_timespec(rs); }