From c8b2e12a6bcc5b8e953506790b5bf2e767b019c5 Mon Sep 17 00:00:00 2001 From: Petr Benes Date: Sun, 15 May 2011 14:36:41 +0200 Subject: [PATCH] Budget and overrun handling moved from EDF part to CBS part Moreover, a bug regarding disabled dispatching fixed. --- src/edf/reps_lib.c | 50 ++++++++++++++++++++++++++++++++++++++--- src/edf/scheduler_edf.c | 21 ++--------------- src/edf/scheduler_edf.h | 3 --- 3 files changed, 49 insertions(+), 25 deletions(-) diff --git a/src/edf/reps_lib.c b/src/edf/reps_lib.c index 8ac58a1..bb2fcac 100644 --- a/src/edf/reps_lib.c +++ b/src/edf/reps_lib.c @@ -2,6 +2,12 @@ #include "scheduler_edf.h" #include + +Thread_CPU_budget_algorithm_callout edf_budget_overrun_callout(); + +rtems_timer_service_routine_entry edf_budget_overrun_reenable(Thread_Control *the_thread); + + /// List of servers where @p reps_sid_t is the index reps_server_t server_list[REPS_MAX_SERVERS]; @@ -29,6 +35,8 @@ reps_rv reps_set_params(reps_sid_t sid, reps_params_t *p_params){ if (server_list[sid].task) { Objects_Locations location; Thread_Control *the_thread = _Thread_Get(server_list[sid].task, &location); + // the routine _Thread_Get may disable dispatch and not enable again + _Thread_Enable_dispatch(); RBT_Node *node = (RBT_Node*)the_thread->scheduler_info; node->rel_deadline = p_params->P; node->cmp_time = p_params->Q; @@ -42,10 +50,14 @@ reps_rv reps_attach_thread(reps_sid_t server_id, tid_t tid){ server_list[server_id].task = tid; Objects_Locations location; Thread_Control *the_thread = _Thread_Get(tid, &location); + // the routine _Thread_Get may disable dispatch and not enable again + _Thread_Enable_dispatch(); RBT_Node *node = (RBT_Node*)the_thread->scheduler_info; node->rel_deadline = server_list[server_id].params.P; node->cmp_time = server_list[server_id].params.Q; + the_thread->budget_callout = (void *) edf_budget_overrun_callout; the_thread->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_CALLOUT; + the_thread->is_preemptible = true; rtems_timer_create(rtems_build_name( 'C', 'B', 'S', 'T' ), &node->timer_id); return REPS_OK; } @@ -64,12 +76,14 @@ reps_rv reps_get_sid(tid_t tid, reps_sid_t *p_sid){ reps_rv reps_detach_thread(reps_sid_t sid, tid_t tid) { Objects_Locations location; Thread_Control *the_thread = _Thread_Get(tid, &location); + // the routine _Thread_Get may disable dispatch and not enable again + _Thread_Enable_dispatch(); RBT_Node *node = (RBT_Node*)the_thread->scheduler_info; node->cmp_time = 0; rtems_timer_delete(node->timer_id); - the_thread->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE; - the_thread->budget_callout = NULL; - + the_thread->budget_algorithm = the_thread->Start.budget_algorithm; + the_thread->budget_callout = the_thread->Start.budget_callout; + the_thread->is_preemptible = the_thread->Start.is_preemptible; if (sid >= REPS_MAX_SERVERS) return REPS_E_INVALID_SID; server_list[sid].task = 0; @@ -79,6 +93,8 @@ reps_rv reps_detach_thread(reps_sid_t sid, tid_t tid) { reps_rv reps_get_exec_time (reps_sid_t sid, reps_time_t *exec_time){ Objects_Locations location; Thread_Control *the_thread = _Thread_Get(server_list[sid].task, &location); + // the routine _Thread_Get may disable dispatch and not enable again + _Thread_Enable_dispatch(); RBT_Node *node = (RBT_Node*)the_thread->scheduler_info; *exec_time = node->cmp_time - the_thread->cpu_time_budget; return REPS_OK; @@ -92,6 +108,8 @@ reps_rv reps_get_params(reps_sid_t sid, reps_params_t *p_params){ reps_rv reps_get_curr_budget(reps_sid_t sid, reps_time_t *curr_budget){ Objects_Locations location; Thread_Control *the_thread = _Thread_Get(server_list[sid].task, &location); + // the routine _Thread_Get may disable dispatch and not enable again + _Thread_Enable_dispatch(); *curr_budget = the_thread->cpu_time_budget; return REPS_OK; } @@ -103,6 +121,8 @@ reps_rv reps_reserve_spare(reps_params_t *p_params){ reps_rv reps_get_appr_budget (reps_sid_t sid, reps_time_t *appr_budget){ Objects_Locations location; Thread_Control *the_thread = _Thread_Get(server_list[sid].task, &location); + // the routine _Thread_Get may disable dispatch and not enable again + _Thread_Enable_dispatch(); RBT_Node *node = (RBT_Node*)the_thread->scheduler_info; *appr_budget = node->cmp_time; return REPS_OK; @@ -121,3 +141,27 @@ reps_rv reps_init(void){ reps_rv reps_cleanup(void){ return REPS_OK; } + +// ======================================================================= + +// invoked when a limited time quantum (cmp_time) is exceeded +Thread_CPU_budget_algorithm_callout edf_budget_overrun_callout() { + printf(" overrun %d \n", _Watchdog_Ticks_since_boot); + Thread_Control *the_thread = _Per_CPU_Information.executing; + RBT_Node *node = (RBT_Node*)the_thread->scheduler_info; + rtems_signal_send(the_thread->Object.id, RTEMS_SIGNAL_15); + _Thread_Suspend (the_thread); + /*TODO: the thread gets suspended forever, so it is not released in the next period again, + * but does not even service the registered signal. Try to disable _Thread_Suspend, the signal + * is serviced but the thread just continues. + */ + uint32_t ticks = node->abs_deadline - _Watchdog_Ticks_since_boot; //FIXME: wrong calc? + rtems_timer_fire_after(node->timer_id, ticks, (void *) edf_budget_overrun_reenable, the_thread); + return 0; +} + +rtems_timer_service_routine_entry edf_budget_overrun_reenable(Thread_Control *the_thread) { + _Thread_Resume(the_thread, false); + printf(" Come back %d\n", _Watchdog_Ticks_since_boot); + return 0; +} diff --git a/src/edf/scheduler_edf.c b/src/edf/scheduler_edf.c index 03f6a32..e80cebf 100644 --- a/src/edf/scheduler_edf.c +++ b/src/edf/scheduler_edf.c @@ -27,10 +27,8 @@ rtems_status_code edf_next_period(rtems_id period_id, uint32_t __rel_deadline__, node->flags = flags; + // FIXME: remove cmp_time from EDF completely if (node->cmp_time) { -// rtems_signal_catch(budget_overrun_handler, RTEMS_DEFAULT_MODES); // register this in frsh - the_thread->is_preemptible = true; - the_thread->budget_callout = (void *) edf_budget_overrun_callout; the_thread->cpu_time_budget = node->cmp_time; // do not allow changing the rel_deadline when using a server @@ -41,7 +39,7 @@ rtems_status_code edf_next_period(rtems_id period_id, uint32_t __rel_deadline__, edf_postpone_deadlines(the_thread); //_Scheduler_edf_Update(the_thread); - return rtems_rate_monotonic_period(period_id, __rel_deadline__); + return rtems_rate_monotonic_period(period_id, node->rel_deadline); } @@ -60,22 +58,7 @@ rtems_status_code edf_deadline_cancel(rtems_id period_id) { return rtems_rate_monotonic_delete(period_id); } -// invoked when a limited time quantum (cmp_time) is exceeded -Thread_CPU_budget_algorithm_callout edf_budget_overrun_callout() { - Thread_Control *the_thread = _Per_CPU_Information.executing; - RBT_Node *node = (RBT_Node*)the_thread->scheduler_info; - rtems_signal_send(the_thread->Object.id, RTEMS_SIGNAL_15); - _Thread_Suspend (the_thread); //TODO: make options on suspension - uint32_t ticks = node->abs_deadline - _Watchdog_Ticks_since_boot; //FIXME: wrong calc - rtems_timer_fire_after(node->timer_id, ticks, (void *) edf_budget_overrun_reenable, the_thread); - return 0; -} -rtems_timer_service_routine_entry edf_budget_overrun_reenable(Thread_Control *the_thread) { - _Thread_Resume(the_thread, false); - printf("Come back\n"); //FIXME: Continue here - return 0; -} //======================================================================================= diff --git a/src/edf/scheduler_edf.h b/src/edf/scheduler_edf.h index bd84554..5dc2010 100644 --- a/src/edf/scheduler_edf.h +++ b/src/edf/scheduler_edf.h @@ -22,9 +22,6 @@ rtems_status_code edf_deadline_init(rtems_name name, rtems_id *period_id); /// Changes scheduling policy from deadlines to priorities rtems_status_code edf_deadline_cancel(rtems_id period_id); -Thread_CPU_budget_algorithm_callout edf_budget_overrun_callout(); - -rtems_timer_service_routine_entry edf_budget_overrun_reenable(Thread_Control *the_thread); /// Pluggable scheduler callback functions -- 2.39.2