int set_sched_dl(long period, long exec) { pid_t pid; struct sched_attr dl_attr; struct timespec dl_period, dl_exec; int ret; unsigned int flags = 0; pid = getpid(); dl_period = usec_to_timespec(period); dl_exec = usec_to_timespec(exec); dl_attr.size = sizeof(dl_attr); dl_attr.sched_flags = 0; dl_attr.sched_policy = SCHED_DEADLINE; dl_attr.sched_runtime = timespec_to_nsec(&dl_exec) + (timespec_to_nsec(&dl_exec) / 100) * 5; dl_attr.sched_deadline = timespec_to_nsec(&dl_period); dl_attr.sched_period = timespec_to_nsec(&dl_period); ret = sched_setattr(pid, &dl_attr, flags); if (ret != 0) { perror("sched_setattr"); } return ret; }
void bye(void) { clock_gettime(CLOCK_THREAD_CPUTIME_ID, &task_rst.t_whole_thread_finish); task_rst.t_whole_thread_run = timespec_sub(&task_rst.t_whole_thread_finish, &task_rst.t_whole_thread_start); printf("thread_total= %lld ns\t%3.2f%%\t%3.2f%%\nthread_run= %lld ns\t%3.2f%%\t%3.2f%%\n===end===\n", timespec_to_nsec(&task_rst.t_whole_thread_finish), (double)timespec_to_nsec(&task_rst.t_whole_thread_finish) / (double)timespec_to_nsec(&task_rst.dl_budget) / (double)task_rst.correct_cnt * 100.0, (double)timespec_to_nsec(&task_rst.t_whole_thread_finish) / (double)timespec_to_nsec(&task_rst.dl_period) / (double)task_rst.correct_cnt * 100.0, timespec_to_nsec(&task_rst.t_whole_thread_run), (double)timespec_to_nsec(&task_rst.t_whole_thread_run) / (double)timespec_to_nsec(&task_rst.dl_budget) / (double)task_rst.correct_cnt * 100.0, (double)timespec_to_nsec(&task_rst.t_whole_thread_run) / (double)timespec_to_nsec(&task_rst.dl_period) / (double)task_rst.correct_cnt * 100.0); }
static inline void process_log(task_data_t *p_task, task_result_t *p_rst) { static int first = 1; int64_t i_offset, i_diff, i_slack, i_thread_run, i_thread_remain; int after_middle; i_offset = timespec_to_nsec(&p_task->t_offset); i_diff = timespec_to_nsec(&p_task->t_diff); i_slack = timespec_to_nsec(&p_task->t_slack); i_thread_run = timespec_to_nsec(&p_task->t_thread_run); i_thread_remain = timespec_to_nsec(&p_task->t_thread_remain); after_middle = timespec_lower(&p_rst->t_middle, &p_task->t_begin); ++p_rst->cnt; if (after_middle) { ++p_rst->cnt_after_middle; } if (i_thread_remain > 0) { ++p_rst->lack_cnt; } if (i_slack < 0) { ++p_rst->miss_cnt; if (after_middle) { ++p_rst->miss_cnt_after_middle; } } p_rst->i_whole_thread_runtime += i_thread_run; if (first) { printf("%12s\t%12s\t%12s\t%12s\t%12s\n", "offset", "diff", "slack", "exec_time", "unfinished"); first = 0; } if (g_log) { printf("%12lld\t%12lld\t%12lld\t%12lld\t%12lld\n", i_offset, i_diff, i_slack, i_thread_run, i_thread_remain); } }
static uint64_t perftime(void) { struct timespec ts; int r; r = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); tor_assert(r == 0); return timespec_to_nsec(&ts) - nanostart; }
static void reset_perftime(void) { struct timespec ts; int r; r = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); tor_assert(r == 0); nanostart = timespec_to_nsec(&ts); }
static void accel_data_report_worker(void *arg) { struct sensor_accel_info *info; struct report_info *rinfo; struct report_info_data *rinfo_data; struct sensor_event_data *event_data; struct timespec ts; uint16_t payload_size; payload_size = (PRESSURE_READING_NUM * sizeof(struct sensor_event_data)) + (REPORTING_SENSORS * sizeof(struct report_info)); info = arg; if (info->callback) { rinfo_data = malloc(sizeof(struct report_info_data) + payload_size); if (!rinfo_data) goto out; rinfo_data->num_sensors_reporting = REPORTING_SENSORS; rinfo = rinfo_data->reportinfo; rinfo->id = info->sensor_id; rinfo->flags = 0; event_data = (struct sensor_event_data *)&rinfo->data_payload[0]; up_rtc_gettime(&ts); rinfo->reference_time = timespec_to_nsec(&ts); gb_debug("[%u.%03u]\n", ts.tv_sec, (ts.tv_nsec / 1000000)); #ifdef BATCH_PROCESS_ENABLED /* * Batch sensor data values and its time_deltas * until max fifo event count */ #else /* Single sensor event data */ rinfo->readings = PRESSURE_READING_NUM; event_data->time_delta = 0; event_data->data_value[0] = data++; event_data->data_value[1] = data++; event_data->data_value[2] = data++; #endif gb_debug("report sensor: %d\n", rinfo->id); info->callback(info->sensor_id, rinfo_data, payload_size); free(rinfo_data); } out: /* cancel any work and reset ourselves */ if (!work_available(&info->data_report_work)) work_cancel(LPWORK, &info->data_report_work); /* if not already scheduled, schedule start */ if (work_available(&info->data_report_work)) work_queue(LPWORK, &info->data_report_work, accel_data_report_worker, info, MSEC2TICK(1200)); }
static int sensor_accel_op_flush(struct device *dev, uint8_t id) { struct sensor_event_data *event_data; struct sensor_accel_info *info; struct report_info_data *rinfo_data; struct report_info *rinfo; struct timespec ts; uint16_t payload_size; payload_size = (PRESSURE_READING_NUM * sizeof(struct sensor_event_data)) + (REPORTING_SENSORS * sizeof(struct report_info)); gb_debug("%s:\n", __func__); if (!dev || !device_get_private(dev)) { return -EINVAL; } info = device_get_private(dev); if (info->callback) { rinfo_data = malloc(sizeof(struct report_info) + payload_size); if (!rinfo_data) return -ENOMEM; rinfo_data->num_sensors_reporting = REPORTING_SENSORS; rinfo = rinfo_data->reportinfo; rinfo->id = info->sensor_id; event_data = (struct sensor_event_data *)&rinfo->data_payload[0]; up_rtc_gettime(&ts); rinfo->reference_time = timespec_to_nsec(&ts); gb_debug("[%u.%03u]\n", ts.tv_sec, (ts.tv_nsec / 1000000)); rinfo->flags = REPORT_INFO_FLAG_FLUSHING | REPORT_INFO_FLAG_FLUSH_COMPLETE; #ifdef BATCH_PROCESS_ENABLED /* * Batch sensor data values and its time_deltas * until max fifo event count */ #else /* Single sensor event data */ rinfo->readings = PRESSURE_READING_NUM; event_data->time_delta = 0; event_data->data_value[0] = data++; event_data->data_value[1] = data++; event_data->data_value[2] = data++; #endif info->callback(info->sensor_id, rinfo_data, payload_size); free(rinfo_data); } return OK; }
void print_result_exit(struct timespec *t_now, task_data_t *p_task, task_result_t *p_rst) { struct timespec t_duration; int64_t i_duration; t_duration = timespec_sub(t_now, &p_rst->t_exit); i_duration = timespec_to_nsec(&t_duration) + (int64_t)duration * 1E9; p_rst->i_whole_duration = i_duration; printf("===begin===\nstart=\t%lld ns\nend=\t%lld ns\nduration=\t%lld ns\ncnt=\t%d\ncorrect_cnt=\t%d\nmiss_cnt=\t%d\t%3.2f%%\nmiss_cnt_after_middle=\t%d\t%3.2f%%\nthread_runtime=\t%lld ns\ncorrect_thread_runtime=\t%lld ns\navg_thread_runtime=\t%lldns\t%3.2f%%\t%3.2f%%\t%3.2f%%\n", timespec_to_nsec(&p_rst->t_exit) - (int64_t)(duration * 1E9), timespec_to_nsec(t_now), i_duration, p_rst->cnt, p_rst->correct_cnt,//(int64_t)(duration * 1E9) / timespec_to_nsec(&p_rst->dl_period), p_rst->miss_cnt, (double)p_rst->miss_cnt/(double)p_rst->cnt * 100.0, p_rst->miss_cnt_after_middle, (double)p_rst->miss_cnt_after_middle/(double)p_rst->cnt_after_middle * 100.0, p_rst->i_whole_thread_runtime, p_rst->i_corrent_whole_thread_runtime, p_rst->i_whole_thread_runtime / p_rst->cnt, (double)p_rst->i_whole_thread_runtime / p_rst->cnt / timespec_to_nsec(&p_rst->dl_exec) * 100.0, (double)p_rst->i_whole_thread_runtime / p_rst->cnt / timespec_to_nsec(&p_rst->dl_budget) * 100.0, (double)p_rst->i_whole_thread_runtime / p_rst->cnt / timespec_to_nsec(&p_rst->dl_period) * 100.0); exit(0); }
void signal_handler(int signum) { switch(signum) { case SIGALRM: { struct timespec t_alarm; clock_gettime(CLOCK_REALTIME, &t_alarm); printf("got SIGALARM at %lld ns\n", timespec_to_nsec(&t_alarm)); break; } case SIGINT: { struct timespec t_now; clock_gettime(CLOCK_REALTIME, &t_now); print_result_exit(&t_now, &task, &task_rst); break; } default: { break; } } }
int main(int argc, char* argv[]) { pid_t pid; long long period, budget, exec; char* token; struct sched_attr dl_attr; int ret; unsigned int flags = 0; struct sigaction sa; struct itimerval timer; memset(&task, 0, sizeof(task)); memset(&task_rst, 0, sizeof(task_rst)); ret = atexit(bye); if (ret != 0) { perror("atexit"); exit(1); } if (argc >= 3) { pid = getpid(); printf("%d\t===pid===\n", (int)pid); printf("lock pages in memory\n"); ret = mlockall(MCL_CURRENT | MCL_FUTURE); if (ret < 0) { perror("mlockall"); exit(1); } token = strtok(argv[1], ":"); period = strtoll(token, NULL, 10); token = strtok(NULL, ":"); budget = strtoll(token, NULL, 10); token = strtok(NULL, ":"); exec = strtoll(token, NULL, 10); printf("period = %lld ns, budget = %lld ns, exec = %lld ns\n", period, budget, exec); if (exec == 0) { pure_overhead = 1; } else { pure_overhead = 0; } //duration is a must duration = atoi(argv[2]); clock_gettime(CLOCK_REALTIME, &task_rst.t_exit); memcpy((void*)&task_rst.t_middle, (void*)&task_rst.t_exit, sizeof(task_rst.t_middle)); task_rst.t_exit.tv_sec = task_rst.t_exit.tv_sec + duration; task_rst.t_middle.tv_sec = task_rst.t_middle.tv_sec + duration / 2;//set halfway timestamp if (argc >= 4) { g_log = atoi(argv[3]); } if (argc >= 5) { g_scheduler = atoi(argv[4]); } //set deadline scheduling pid = 0; assert(period >= budget && budget >= exec); // task_rst.dl_period = usec_to_timespec(period); // task_rst.dl_budget = usec_to_timespec(budget); // task_rst.dl_exec = usec_to_timespec(exec); task_rst.dl_period = nsec_to_timespec((unsigned long long)period); task_rst.dl_budget = nsec_to_timespec((unsigned long long)budget); task_rst.dl_exec = nsec_to_timespec((unsigned long long)exec); dl_attr.size = sizeof(dl_attr); dl_attr.sched_flags = 0; dl_attr.sched_policy = SCHED_DEADLINE; dl_attr.sched_priority = 0; dl_attr.sched_runtime = timespec_to_nsec(&task_rst.dl_budget); dl_attr.sched_deadline = timespec_to_nsec(&task_rst.dl_period); dl_attr.sched_period = timespec_to_nsec(&task_rst.dl_period); task_rst.correct_cnt =(int)((int64_t)(duration * 1E9) / timespec_to_nsec(&task_rst.dl_period)); task_rst.i_corrent_whole_thread_runtime = (int64_t)task_rst.correct_cnt * timespec_to_nsec(&task_rst.dl_exec); if (g_scheduler == 0) { printf("using sched_deadline\n"); ret = sched_setattr(pid, &dl_attr, flags); if (ret != 0) { perror("sched_setattr"); exit(1); } } else if (g_scheduler == 1) { printf("using cfs\n"); } else { printf("not implemented\n"); exit(1); } #if 0 memset(&sa, 0, sizeof(sa)); sa.sa_handler = &signal_handler; sigaction(SIGALRM, &sa, NULL); sigaction(SIGINT, &sa, NULL); timer.it_value.tv_sec = dl_period.tv_sec; timer.it_value.tv_usec = dl_period.tv_nsec / 1000; timer.it_interval.tv_sec = dl_period.tv_sec; timer.it_interval.tv_usec = dl_period.tv_nsec / 1000; setitimer(ITIMER_REAL, &timer, NULL); #endif struct timespec t_exec; clock_gettime(CLOCK_REALTIME, &task.t_period); task.t_period = timespec_add(&task.t_period, &task_rst.dl_period);//start from next period task.t_deadline = timespec_add(&task.t_period, &task_rst.dl_period); clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &task.t_period, NULL); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &task_rst.t_whole_thread_start); while(1) { clock_gettime(CLOCK_REALTIME, &task.t_begin); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &task.t_thread_start); t_exec = timespec_add(&task.t_thread_start, &task_rst.dl_exec); if (!pure_overhead) { busy_wait(&t_exec, &task.t_deadline); } clock_gettime(CLOCK_THREAD_CPUTIME_ID, &task.t_thread_finish); clock_gettime(CLOCK_REALTIME, &task.t_end); task.t_thread_run = timespec_sub(&task.t_thread_finish, &task.t_thread_start); task.t_thread_remain = timespec_sub(&t_exec, &task.t_thread_finish); task.t_diff = timespec_sub(&task.t_end, &task.t_begin); task.t_slack = timespec_sub(&task.t_deadline, &task.t_end); task.t_offset = timespec_sub(&task.t_begin, &task.t_period); process_log(&task, &task_rst); task.t_period = timespec_add(&task.t_period, &task_rst.dl_period); task.t_deadline = timespec_add(&task.t_deadline, &task_rst.dl_period); //check total test time struct timespec t_now; clock_gettime(CLOCK_REALTIME, &t_now); if (duration && timespec_lower(&task_rst.t_exit, &t_now)) { print_result_exit(&t_now, &task, &task_rst); } clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &task.t_period, NULL); } } else { printf("usage: rt_task <period>:<budget>:<exec> <duration> [<log_switch>] [<scheduler>]\n"); } return 0; }
int64_t nano_time(){ return timespec_to_nsec(get_current_time()); }
void *thread_body(void *arg) { int ret; int nperiods; struct sched_param param; timing_point_t *timings; pid_t tid; struct sched_attr attr; unsigned int flags = 0; struct timespec t, t_next; timing_point_t tmp_timing; timing_point_t *curr_timing; unsigned long t_start_usec; int i = 0; thread_data_t *data = (thread_data_t*) arg; /* set thread affinity */ if (data->cpuset != NULL) { log_notice("[%d] setting cpu affinity to CPU(s) %s", data->ind, data->cpuset_str); ret = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), data->cpuset); if (ret < 0) { errno = ret; perror("pthread_setaffinity_np"); exit(EXIT_FAILURE); } } /* set scheduling policy and print pretty info on stdout */ log_notice("[%d] Using %s policy:", data->ind, data->sched_policy_descr); switch (data->sched_policy) { case rr: case fifo: fprintf(data->log_handler, "# Policy : %s\n", (data->sched_policy == rr ? "SCHED_RR" : "SCHED_FIFO")); param.sched_priority = data->sched_prio; ret = pthread_setschedparam(pthread_self(), data->sched_policy, ¶m); if (ret != 0) { errno = ret; perror("pthread_setschedparam"); exit(EXIT_FAILURE); } log_notice("[%d] starting thread with period: %" PRIu64 ", exec: %" PRIu64 ",""deadline: %" PRIu64 ", priority: %d", data->ind, timespec_to_usec(&data->period), timespec_to_usec(&data->min_et), timespec_to_usec(&data->deadline), data->sched_prio ); break; case other: fprintf(data->log_handler, "# Policy : SCHED_OTHER\n"); log_notice("[%d] starting thread with period: %" PRIu64 ", exec: %" PRIu64 ",""deadline: %" PRIu64 "", data->ind, timespec_to_usec(&data->period), timespec_to_usec(&data->min_et), timespec_to_usec(&data->deadline) ); data->lock_pages = 0; /* forced off for SCHED_OTHER */ break; case deadline: fprintf(data->log_handler, "# Policy : SCHED_DEADLINE\n"); tid = gettid(); attr.size = sizeof(attr); attr.sched_flags = data->sched_flags; if (data->sched_flags && SCHED_FLAG_SOFT_RSV) fprintf(data->log_handler, "# Type : SOFT_RSV\n"); else fprintf(data->log_handler, "# Type : HARD_RSV\n"); attr.sched_policy = SCHED_DEADLINE; attr.sched_priority = 0; attr.sched_runtime = timespec_to_nsec(&data->max_et) + (timespec_to_nsec(&data->max_et) /100) * BUDGET_OVERP; attr.sched_deadline = timespec_to_nsec(&data->period); attr.sched_period = timespec_to_nsec(&data->period); break; default: log_error("Unknown scheduling policy %d", data->sched_policy); exit(EXIT_FAILURE); } if (data->lock_pages == 1) { log_notice("[%d] Locking pages in memory", data->ind); ret = mlockall(MCL_CURRENT | MCL_FUTURE); if (ret < 0) { errno = ret; perror("mlockall"); exit(EXIT_FAILURE); } } /* if we know the duration we can calculate how many periods we will * do at most, and the log to memory, instead of logging to file. */ timings = NULL; if (data->duration > 0) { nperiods = (int) ceil( (data->duration * 10e6) / (double) timespec_to_usec(&data->period)); timings = malloc ( nperiods * sizeof(timing_point_t)); } fprintf(data->log_handler, "#idx\tperiod\tmin_et\tmax_et\trel_st\tstart" "\t\tend\t\tdeadline\tdur.\tslack\tresp_t" "\tBudget\tUsed Budget\n"); if (data->ind == 0) { clock_gettime(CLOCK_MONOTONIC, &t_zero); #ifdef TRACE_SETS_ZERO_TIME if (opts.ftrace) log_ftrace(ft_data.marker_fd, "[%d] sets zero time", data->ind); #endif } pthread_barrier_wait(&threads_barrier); /* * Set the task to SCHED_DEADLINE as far as possible touching its * budget as little as possible for the first iteration. */ if (data->sched_policy == SCHED_DEADLINE) { ret = sched_setattr(tid, &attr, flags); if (ret != 0) { log_critical("[%d] sched_setattr " "returned %d", data->ind, ret); errno = ret; perror("sched_setattr"); exit(EXIT_FAILURE); } } t = t_zero; t_next = msec_to_timespec(1000LL); t_next = timespec_add(&t, &t_next); clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &t_next, NULL); data->deadline = timespec_add(&t_next, &data->deadline); while (continue_running) { int pn; struct timespec t_start, t_end, t_diff, t_slack, t_resp; /* Thread numeration reported starts with 1 */ #ifdef TRACE_BEGINS_LOOP if (opts.ftrace) log_ftrace(ft_data.marker_fd, "[%d] begins job %d", data->ind+1, i); #endif clock_gettime(CLOCK_MONOTONIC, &t_start); if (data->nphases == 0) { compute(data->ind, &data->min_et, NULL, 0); } else { for (pn = 0; pn < data->nphases; pn++) { log_notice("[%d] phase %d start", data->ind+1, pn); exec_phase(data, pn); log_notice("[%d] phase %d end", data->ind+1, pn); } } clock_gettime(CLOCK_MONOTONIC, &t_end); t_diff = timespec_sub(&t_end, &t_start); t_slack = timespec_sub(&data->deadline, &t_end); t_resp = timespec_sub(&t_end, &t_next); t_start_usec = timespec_to_usec(&t_start); if (i < nperiods) { if (timings) curr_timing = &timings[i]; else curr_timing = &tmp_timing; curr_timing->ind = data->ind; curr_timing->period = timespec_to_usec(&data->period); curr_timing->min_et = timespec_to_usec(&data->min_et); curr_timing->max_et = timespec_to_usec(&data->max_et); curr_timing->rel_start_time = t_start_usec - timespec_to_usec(&data->main_app_start); curr_timing->abs_start_time = t_start_usec; curr_timing->end_time = timespec_to_usec(&t_end); curr_timing->deadline = timespec_to_usec(&data->deadline); curr_timing->duration = timespec_to_usec(&t_diff); curr_timing->slack = timespec_to_lusec(&t_slack); curr_timing->resp_time = timespec_to_usec(&t_resp); } if (!timings) log_timing(data->log_handler, curr_timing); t_next = timespec_add(&t_next, &data->period); data->deadline = timespec_add(&data->deadline, &data->period); #ifdef TRACE_END_LOOP if (opts.ftrace) log_ftrace(ft_data.marker_fd, "[%d] end loop %d", data->ind, i); #endif if (curr_timing->slack < 0) log_notice("[%d] DEADLINE MISS !!!", data->ind+1); i++; } free(timings); }