#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; pthread_mutex_t shared_resources; 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->precedency_blocking=0; p->non_preemptive=0; p->preemption_delay=0; p->asynchronous=0; p->self_suspension=0; p->shared_resources=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); status=pthread_mutex_init(&shared_resources, 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, departure, preemption, preemption_delay; 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(params.asynchronous == 1){ 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); } //management of the delaying of a task selfsuspension of a task if (params.preemption_delay==1){ preemption=pthread_monano_attr_getpreemption_time(attr); if ((preemption.tv_sec!=0)||(preemption.tv_nsec!=0)){ preemption_delay=pthread_monano_attr_getpreemption_delay(attr); nanosleep(&preemption_delay, NULL); } } //lock 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, self_suspension, preemption_delay, global_time; struct timespec execution_time, preemption; 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); preemption_delay=pthread_monano_attr_getpreemption_delay(attr); self_suspension=pthread_monano_attr_getselfsuspension(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); preemption=pthread_monano_attr_getpreemption_time(attr); global_time = ts_add(execution_time,preemption); if ((preemption.tv_sec!=0)||(preemption.tv_nsec!=0)) global_time = ts_add(global_time,preemption_delay); if ((self_suspension.tv_sec!=0)||(self_suspension.tv_nsec!=0)) global_time = ts_add(global_time,self_suspension); }while (ts_compare(ts_substract(currenttime,starttime),global_time)<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)+999876543210); //generate a random number between 1000 and ns-1 range = ns - (ns / 2 + 300000000) +1 ; rs = rand() % range; rs = rs + (ns / 2 +300000000); return benchmark_nanoseconds_to_timespec(rs); }