#include "scheduler_edf.h"
#include <rtems.h>
+
+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];
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;
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;
}
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;
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;
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;
}
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;
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;
+}
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
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);
}
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;
-}
//=======================================================================================