From 6dc3e50fc1916dbc8b8e9cc863217e545ca4159c Mon Sep 17 00:00:00 2001 From: Namhoon Kim Date: Tue, 25 Apr 2017 02:14:29 -0400 Subject: sync bug fixed --- include/litmus/sched_trace.h | 21 +++++- include/trace/events/litmus.h | 22 +++++++ litmus/Kconfig | 2 +- litmus/jobs.c | 16 +++-- litmus/sched_mc2.c | 145 ++++++++++++++++++++++++++---------------- litmus/sched_task_trace.c | 12 ++++ litmus/sync.c | 4 +- 7 files changed, 157 insertions(+), 65 deletions(-) diff --git a/include/litmus/sched_trace.h b/include/litmus/sched_trace.h index fb5d8f33aff5..80d952374f7a 100644 --- a/include/litmus/sched_trace.h +++ b/include/litmus/sched_trace.h @@ -89,6 +89,11 @@ struct st_request_mode_data { u8 __unused[8]; }; +struct st_sys_start_data { + u64 when; + u64 start; +}; + #define DATA(x) struct st_ ## x ## _data x; typedef enum { @@ -104,7 +109,8 @@ typedef enum { ST_ACTION, ST_SYS_RELEASE, ST_ENACT_MODE, - ST_REQUEST_MODE + ST_REQUEST_MODE, + ST_SYS_START, } st_event_record_type_t; struct st_event_record { @@ -124,6 +130,7 @@ struct st_event_record { DATA(sys_release); DATA(enact_mode); DATA(request_mode); + DATA(sys_start); } data; }; @@ -171,6 +178,8 @@ feather_callback void do_sched_trace_enact_mode(unsigned long id, feather_callback void do_sched_trace_request_mode(unsigned long id, struct task_struct* task); +feather_callback void do_sched_trace_sys_start(unsigned long id, + lt_t* start); #endif @@ -198,6 +207,7 @@ feather_callback void do_sched_trace_request_mode(unsigned long id, #define trace_litmus_sys_release(start) #define trace_litmus_enact_mode(t) #define trace_litmus_request_mode(t) +#define trace_litmus_sys_start(start) #endif @@ -286,6 +296,15 @@ feather_callback void do_sched_trace_request_mode(unsigned long id, do_sched_trace_request_mode, t); \ trace_litmus_request_mode(t); \ } while (0) + +/* when is a pointer, it does not need an explicit cast to unsigned long */ +#define sched_trace_sys_start(when) \ + do { \ + SCHED_TRACE(SCHED_TRACE_BASE_ID + 13, \ + do_sched_trace_sys_start, when); \ + trace_litmus_sys_start(when); \ + } while (0) + #endif /* __KERNEL__ */ #endif diff --git a/include/trace/events/litmus.h b/include/trace/events/litmus.h index 3094ddd2210b..ef8d60f2df25 100644 --- a/include/trace/events/litmus.h +++ b/include/trace/events/litmus.h @@ -273,6 +273,28 @@ TRACE_EVENT(litmus_request_mode, TP_printk("Mode request at %Lu\n", __entry->when) ); +/* + * Trace synchronous start + */ +TRACE_EVENT(litmus_sys_start, + + TP_PROTO(lt_t *start), + + TP_ARGS(start), + + TP_STRUCT__entry( + __field( lt_t, rel ) + __field( lt_t, when ) + ), + + TP_fast_assign( + __entry->rel = *start; + __entry->when = litmus_clock(); + ), + + TP_printk("SynStart(%Lu) at %Lu\n", __entry->rel, __entry->when) +); + #endif /* _SCHED_TASK_TRACEPOINT_H */ /* Must stay outside the protection */ diff --git a/litmus/Kconfig b/litmus/Kconfig index 2253be5e74eb..603a28107a74 100644 --- a/litmus/Kconfig +++ b/litmus/Kconfig @@ -243,7 +243,7 @@ config SCHED_TASK_TRACE config SCHED_TASK_TRACE_SHIFT int "Buffer size for sched_trace_xxx() events" depends on SCHED_TASK_TRACE - range 8 14 + range 8 18 default 9 help diff --git a/litmus/jobs.c b/litmus/jobs.c index f075d8ed674a..898c09335b9f 100644 --- a/litmus/jobs.c +++ b/litmus/jobs.c @@ -36,13 +36,17 @@ void prepare_for_next_period(struct task_struct *t) if (tsk_rt(t)->sporadic_release) { TRACE_TASK(t, "sporadic release at %llu\n", - tsk_rt(t)->sporadic_release_time); + tsk_rt(t)->sporadic_release_time + INIT_PHASE_LENGTH_NS*(tsk_rt(t)->job_params.job_no)); /* sporadic release */ - setup_release(t, tsk_rt(t)->sporadic_release_time); - tsk_rt(t)->sporadic_release = 0; - } else if (num_sync_released > 0) { - TRACE_TASK(t, "num_sync_released = %d\n", num_sync_released); - setup_release(t, tsk_rt(t)->sporadic_release_time + INIT_PHASE_LENGTH_NS); + setup_release(t, tsk_rt(t)->sporadic_release_time + INIT_PHASE_LENGTH_NS*(tsk_rt(t)->job_params.job_no)); +/* if (num_sync_released == 0) { + tsk_rt(t)->sporadic_release = 0; + TRACE("num_sync_released is 0\n"); + } +*/ +// } else if (num_sync_released > 0) { +// TRACE_TASK(t, "num_sync_released = %d and job_no = %d\n", num_sync_released, tsk_rt(t)->job_params.job_no); +// setup_release(t, tsk_rt(t)->sporadic_release_time + INIT_PHASE_LENGTH_NS*(tsk_rt(t)->job_params.job_no)); } else { /* periodic release => add period */ setup_release(t, get_release(t) + get_rt_period(t)); diff --git a/litmus/sched_mc2.c b/litmus/sched_mc2.c index 415e5fe3bf12..6723e8a96141 100644 --- a/litmus/sched_mc2.c +++ b/litmus/sched_mc2.c @@ -38,7 +38,7 @@ #define BUDGET_ENFORCEMENT_AT_C 0 -extern int num_sync_released; +extern atomic_t num_sync_released; extern void do_partition(enum crit_level lv, int cpu); /* _global_env - reservation container for level-C tasks*/ @@ -137,8 +137,8 @@ asmlinkage long sys_enact_mode(void) TRACE_TASK(current, "ENACTING SYSCALL\n"); if (state->cpu == 0){ mode_changed = false; - local_irq_save(flags); - if (pending){ //MCR has entered + if (pending){ //MCR has entered + local_irq_save(flags); raw_spin_lock(&state->lock); raw_spin_lock(&global_lock); raw_spin_lock(&mode_lock); @@ -223,10 +223,11 @@ asmlinkage long sys_enact_mode(void) raw_spin_unlock(&mode_lock); raw_spin_unlock(&global_lock); //raw_spin_unlock(&state->lock); + local_irq_restore(flags); mc2_update_timer_and_unlock(state); } this_cpu_inc(mode_counter); - local_irq_restore(flags); + //local_irq_restore(flags); //cpu_0_spin_flag = !cpu_0_spin_flag; } else if (cpu_0_task_exist) { @@ -248,13 +249,13 @@ asmlinkage long sys_enact_mode(void) while (*cpu0_counter == this_cpu_read(mode_counter)) udelay(1); TRACE("CPU%d counter check. %d\n",state->cpu, this_cpu_read(mode_counter)); - local_irq_save(flags); + //local_irq_save(flags); if (mode_changed) { lt_t new_mode_basetime = get_release(current); //TRACE("CPU%d mode changed\n",state->cpu); hrtimer_cancel(&state->timer); //stop listening to old mode timers TRACE("Timer is cancelled at %llu. mode-change\n", litmus_clock()); - //local_irq_save(flags); + local_irq_save(flags); raw_spin_lock(&state->lock); state->sup_env = &state->sup_env_modes[mode]; list_for_each(pos, &state->sup_env->active_reservations){ @@ -271,12 +272,13 @@ asmlinkage long sys_enact_mode(void) } sup_update_time(state->sup_env, litmus_clock()); //raw_spin_unlock(&state->lock); + local_irq_restore(flags); mc2_update_timer_and_unlock(state); //local_irq_restore(flags); } this_cpu_write(mode_counter, *cpu0_counter); - local_irq_restore(flags); + //local_irq_restore(flags); //state->spin_flag = !state->spin_flag; } else { @@ -304,18 +306,21 @@ asmlinkage long sys_enact_mode(void) asmlinkage long sys_request_mode(int new_mode){ preempt_disable(); raw_spin_lock(&mode_lock); + TRACE("MCR received at %llu\n", litmus_clock()); if (pending){ raw_spin_unlock(&mode_lock); preempt_enable(); + TRACE("MCR rejected because the previous MCR is pedning.\n"); return -EAGAIN; } if (mode == new_mode){ raw_spin_unlock(&mode_lock); preempt_enable(); + TRACE("MCR rejected because the system is already in the new mode = %d.\n", new_mode); return 0; } requested_mode = new_mode; - TRACE("MCR received\n"); + TRACE("MCR to %d is accepted.\n", new_mode); res_reported = mode_sizes[mode]; TRACE_CUR("RES_REPORTED = %d\n",res_reported); seen_once = false; @@ -475,7 +480,7 @@ static int get_lowest_prio_cpu(lt_t priority) ce = &_lowest_prio_cpu.cpu_entries[local_cpu_state()->cpu]; if (!ce->will_schedule && !ce->scheduled) { - TRACE("CPU %d (local) is the lowest!\n", ce->cpu); + TRACE("CPU %d (local) is the lowest (Idle)!\n", ce->cpu); return ce->cpu; } else { TRACE("Local CPU will_schedule=%d, scheduled=(%s/%d)\n", ce->will_schedule, ce->scheduled ? (ce->scheduled)->comm : "null", ce->scheduled ? (ce->scheduled)->pid : 0); @@ -485,14 +490,16 @@ static int get_lowest_prio_cpu(lt_t priority) ce = &_lowest_prio_cpu.cpu_entries[cpu]; /* If a CPU will call schedule() in the near future, we don't return that CPU. */ +/* TRACE("CPU %d will_schedule=%d, scheduled=(%s/%d:%d)\n", cpu, ce->will_schedule, ce->scheduled ? (ce->scheduled)->comm : "null", ce->scheduled ? (ce->scheduled)->pid : 0, ce->scheduled ? (ce->scheduled)->rt_param.job_params.job_no : 0); +*/ if (!ce->will_schedule) { if (!ce->scheduled) { /* Idle cpu, return this. */ - TRACE("CPU %d is the lowest!\n", ce->cpu); + TRACE("CPU %d is the lowest (Idle)!\n", ce->cpu); return ce->cpu; } else if (ce->lv == CRIT_LEVEL_C && ce->deadline > latest_deadline) { @@ -502,10 +509,12 @@ static int get_lowest_prio_cpu(lt_t priority) } } - if (priority >= latest_deadline) - ret = NO_CPU; + TRACE("CPU %d is the lowest! deadline = %llu, my priority = %llu\n", ret, latest_deadline, priority); - TRACE("CPU %d is the lowest!\n", ret); + if (priority >= latest_deadline) { + TRACE("CPU %d is running a higher-priority task. return NO_CPU\n", ret); + ret = NO_CPU; + } return ret; } @@ -559,9 +568,10 @@ static void mc2_update_timer_and_unlock(struct mc2_cpu_state *state) //raw_spin_lock(&_lowest_prio_cpu.lock); _lowest_prio_cpu.cpu_entries[cpu].will_schedule = true; //raw_spin_unlock(&_lowest_prio_cpu.lock); - if (cpu == local_cpu_state()->cpu) - litmus_reschedule_local(); - else + + //if (cpu == local_cpu_state()->cpu) + // litmus_reschedule_local(); + //else reschedule[cpu] = 1; } } @@ -735,7 +745,7 @@ static enum hrtimer_restart on_scheduling_timer(struct hrtimer *timer) //raw_spin_unlock(&_lowest_prio_cpu.lock); TRACE("LOWEST CPU = P%d\n", cpu); if (cpu == state->cpu && update > now) - litmus_reschedule_local(); + ;//litmus_reschedule_local(); else reschedule[cpu] = 1; } @@ -765,6 +775,8 @@ static enum hrtimer_restart on_scheduling_timer(struct hrtimer *timer) return restart; } +#define INIT_PHASE_LENGTH_NS (1000000000) + /* mc2_complete_job - syscall backend for job completions */ static long mc2_complete_job(void) @@ -772,14 +784,17 @@ static long mc2_complete_job(void) ktime_t next_release; long err; - enum crit_level lv; + enum crit_level lv = get_task_crit_level(current); raw_spin_lock(&mode_lock); tsk_rt(current)->completed = 1; raw_spin_unlock(&mode_lock); - - lv = get_task_crit_level(current); - + + if (atomic_read(&num_sync_released) == 0 && mode != 0) { + tsk_rt(current)->sporadic_release = 0; + TRACE_CUR("num_sync_released is 0\n"); + } + /* If this the first job instance, we need to reset replenish time to the next release time */ if (tsk_rt(current)->sporadic_release) { @@ -798,7 +813,7 @@ static long mc2_complete_job(void) raw_spin_lock(&state->lock); for (i = 0; isup_env_modes[i].env.time_zero = tsk_rt(current)->sporadic_release_time; + state->sup_env_modes[i].env.time_zero = tsk_rt(current)->sporadic_release_time + INIT_PHASE_LENGTH_NS*(tsk_rt(current)->job_params.job_no); } } res = sup_find_by_id(state->sup_env, tinfo->mc2_param.res_id); @@ -811,7 +826,7 @@ static long mc2_complete_job(void) raw_spin_lock(&global_lock); for (i = 0; i < NR_MODES; i++) { if (in_mode(current,i) || i == 0) { - _global_env_modes[i].env.time_zero = tsk_rt(current)->sporadic_release_time; + _global_env_modes[i].env.time_zero = tsk_rt(current)->sporadic_release_time + INIT_PHASE_LENGTH_NS*(tsk_rt(current)->job_params.job_no); } } res = gmp_find_by_id(_global_env, tinfo->mc2_param.res_id); @@ -821,7 +836,7 @@ static long mc2_complete_job(void) /* set next_replenish to synchronous release time */ BUG_ON(!res); - res->next_replenishment = tsk_rt(current)->sporadic_release_time; + res->next_replenishment = tsk_rt(current)->sporadic_release_time + INIT_PHASE_LENGTH_NS*(tsk_rt(current)->job_params.job_no); /* if (get_task_crit_level(current) == CRIT_LEVEL_A) { struct table_driven_reservation *tdres; @@ -834,7 +849,7 @@ static long mc2_complete_job(void) res->cur_budget = 0; res->env->change_state(res->env, res, RESERVATION_DEPLETED); - // TRACE_CUR("CHANGE NEXT_REP = %llu NEXT_UPDATE = %llu\n", res->next_replenishment, state->sup_env->next_scheduler_update); + TRACE_CUR("CHANGE NEXT_REP = %llu NEXT_UPDATE = %llu\n", res->next_replenishment, state->sup_env->next_scheduler_update); if (lv == CRIT_LEVEL_C) raw_spin_unlock(&global_lock); @@ -863,12 +878,12 @@ static long mc2_complete_job(void) res = gmp_find_by_id(_global_env, tsk_mc2_data(current)->res_id); if (res && !res->reported){ res_reported--; - TRACE_CUR("RES_REPORTED = %d\n",res_reported); + TRACE_CUR("RES_REPORTED = %d\n", res_reported); res->reported = 1; //Current task doesn't exist in new mode - if ( !in_mode(current, requested_mode) ){ - litmus_reschedule_local(); - } + //if ( !in_mode(current, requested_mode) ){ + // litmus_reschedule_local(); + //} } raw_spin_unlock(&mode_lock); } @@ -908,8 +923,10 @@ struct task_struct* mc2_dispatch(struct sup_reservation_environment* sup_env, st list_for_each_entry_safe(res, next, &sup_env->active_reservations, list) { - if (res->state == RESERVATION_ACTIVE) - TRACE_TASK(tsk, "ACT_LIST R%d cur.mode = %d, res->mode = %d budget = %llu\n", res->id, mode, res->mode, res->cur_budget); + if (res->state == RESERVATION_ACTIVE) { + struct task_struct *t = res->ops->dispatch_client(res, &time_slice); + TRACE_TASK(tsk, "CPU%d ACT_LIST R%d cur.mode = %d, res->mode = %d budget = %llu next_repl. = %llu, deadline = %llu\n", state->cpu, res->id, mode, res->mode, res->cur_budget, res->next_replenishment, get_deadline(t)); + } } list_for_each_entry_safe(res, next, &sup_env->active_reservations, list) { @@ -922,7 +939,7 @@ struct task_struct* mc2_dispatch(struct sup_reservation_environment* sup_env, st return tsk; } else { //if (!is_init_finished(tsk)) { - TRACE_TASK(tsk, "num_sync_released = %d, mode = %d\n", num_sync_released, mode); +// TRACE_TASK(tsk, "num_sync_released = %d, mode = %d\n", num_sync_released, mode); // if (num_sync_released != 0 && mode == 0) { //ce = &state->crit_entries[lv]; sup_scheduler_update_after(sup_env, res->cur_budget); @@ -953,6 +970,13 @@ struct task_struct* mc2_global_dispatch(struct mc2_cpu_state* state) enum crit_level lv; lt_t time_slice; + list_for_each_entry_safe(res, next, &_global_env->active_reservations, list) { + if (res->state == RESERVATION_ACTIVE) { + struct task_struct *t = res->ops->dispatch_client(res, &time_slice); + TRACE_TASK(tsk, "GLOBAL ACT_LIST R%d cur.mode = %d, res->mode = %d budget = %llu next_repl. = %llu, deadline = %llu\n", res->id, mode, res->mode, res->cur_budget, res->next_replenishment, get_deadline(t)); + } + } + raw_spin_lock(&mode_lock); list_for_each_entry_safe(res, next, &_global_env->active_reservations, list) { BUG_ON(!res); @@ -1089,9 +1113,15 @@ static struct task_struct* mc2_schedule(struct task_struct * prev) if (is_realtime(prev)) gmp_update_time(_global_env, now); state->scheduled = mc2_global_dispatch(state); + _lowest_prio_cpu.cpu_entries[state->cpu].will_schedule = false; + update_cpu_prio(state); + raw_spin_unlock(&global_lock); + } else { + raw_spin_lock(&global_lock); + _lowest_prio_cpu.cpu_entries[state->cpu].will_schedule = false; + update_cpu_prio(state); raw_spin_unlock(&global_lock); } - /* if (!state->scheduled) { raw_spin_lock(&global_lock); @@ -1161,12 +1191,12 @@ static struct task_struct* mc2_schedule(struct task_struct * prev) } */ post_schedule(state->scheduled, state->cpu); - +/* raw_spin_lock(&global_lock); _lowest_prio_cpu.cpu_entries[state->cpu].will_schedule = false; update_cpu_prio(state); raw_spin_unlock(&global_lock); - +*/ raw_spin_unlock(&state->lock); if (state->scheduled) { TRACE_TASK(state->scheduled, "scheduled.\n"); @@ -1204,7 +1234,6 @@ static void mc2_task_resume(struct task_struct *tsk) TRACE_TASK(tsk, "thread wakes up at %llu\n", litmus_clock()); //local_irq_save(flags); - TRACE_TASK(tsk, "preemptible?? %d\n", preemptible()); preempt_disable(); tinfo = get_mc2_state(tsk); if (tinfo->cpu != -1) @@ -1219,7 +1248,8 @@ static void mc2_task_resume(struct task_struct *tsk) /* Requeue only if self-suspension was already processed. */ if (tinfo->has_departed) { - + raw_spin_lock(&state->lock); + local_irq_save(flags); /* We don't want to consider jobs before synchronous releases */ if (tsk_rt(tsk)->job_params.job_no == 2) { /* @@ -1239,14 +1269,19 @@ static void mc2_task_resume(struct task_struct *tsk) */ TRACE_TASK(tsk, "INIT_FINISHED is SET\n"); tsk_mc2_data(tsk)->init_finished = 1; - raw_spin_lock(&global_lock); - num_sync_released--; - raw_spin_unlock(&global_lock); - TRACE_TASK(tsk, "INIT_FINISHED is SET, num_sync_released decreased to %d\n", num_sync_released); + atomic_dec(&num_sync_released); + //raw_spin_unlock(&global_lock); + if (atomic_read(&num_sync_released) == 0) { + lt_t start = tsk_rt(tsk)->sporadic_release_time + INIT_PHASE_LENGTH_NS*(tsk_rt(tsk)->job_params.job_no); + TRACE("INIT_PHASE FINISHED. CHANGE TO MODE 1\n"); + sys_request_mode(1); + sched_trace_sys_start(&start); + } + TRACE_TASK(tsk, "INIT_FINISHED is SET, num_sync_released decreased to %d\n", atomic_read(&num_sync_released)); } - raw_spin_lock(&state->lock); - local_irq_save(flags); +// raw_spin_lock(&state->lock); +// local_irq_save(flags); /* Assumption: litmus_clock() is synchronized across cores, * since we might not actually be executing on tinfo->cpu * at the moment. */ @@ -1363,9 +1398,7 @@ static long mc2_admit_task(struct task_struct *tsk) if (is_mode_poll_task(tsk) && tinfo->cpu == 0) { cpu_0_task_exist = true; } - raw_spin_lock(&global_lock); - num_sync_released++; - raw_spin_unlock(&global_lock); + atomic_inc(&num_sync_released); local_irq_restore(flags); raw_spin_unlock(&state->lock); //raw_spin_unlock_irqrestore(&state->lock, flags); @@ -1425,15 +1458,16 @@ static long mc2_admit_task(struct task_struct *tsk) tsk_rt(tsk)->plugin_state = tinfo; tsk_rt(tsk)->task_params.budget_policy = NO_ENFORCEMENT; raw_spin_lock(&mode_lock); - for(i = 0; i < NR_MODES; i++){ + for(i = 1; i < NR_MODES; i++){ if (in_mode(tsk, i)){ mode_sizes[i]++; } } + mode_sizes[0]++; raw_spin_unlock(&mode_lock); } - num_sync_released++; + atomic_inc(&num_sync_released); raw_spin_unlock(&global_lock); //raw_spin_unlock_irqrestore(&state->lock, flags); local_irq_restore(flags); @@ -1728,9 +1762,8 @@ static void mc2_task_exit(struct task_struct *tsk) /* NOTE: drops state->lock */ TRACE("mc2_exit()\n"); - raw_spin_lock(&global_lock); - num_sync_released--; - raw_spin_unlock(&global_lock); + atomic_dec(&num_sync_released); + mc2_update_timer_and_unlock(state); } else { raw_spin_unlock(&state->lock); @@ -1738,15 +1771,16 @@ static void mc2_task_exit(struct task_struct *tsk) } if (lv == CRIT_LEVEL_C) { - raw_spin_lock(&global_lock); + //raw_spin_lock(&global_lock); raw_spin_lock(&mode_lock); - for(i = 0; i < NR_MODES; i++){ + for(i = 1; i < NR_MODES; i++){ if ( !(tsk_mc2_data(tsk)->mode_mask & (1<data.sys_start.when = now(); + rec->data.sys_start.start = *start; + put_record(rec); + } +} \ No newline at end of file diff --git a/litmus/sync.c b/litmus/sync.c index f066ea4219a8..7733f6760c52 100644 --- a/litmus/sync.c +++ b/litmus/sync.c @@ -16,7 +16,7 @@ #include -int num_sync_released; +atomic_t num_sync_released; struct ts_release_wait { struct list_head list; @@ -149,6 +149,6 @@ asmlinkage long sys_release_ts(lt_t __user *__delay) start_time *= ONE_MS; ret = do_release_ts(start_time + delay); } - num_sync_released = ret; + atomic_set(&num_sync_released, ret); return ret; } -- cgit v1.2.2