#ifndef _LITMUS_BUDGET_H_ #define _LITMUS_BUDGET_H_ #include #include #define budget_exhausted(t) \ (get_exec_time(t) >= get_exec_cost(t)) #define budget_remaining(t) \ ((!budget_exhausted(t)) ? (get_exec_cost(t) - get_exec_time(t)) : 0) #define budget_enforced(t) (\ tsk_rt(t)->task_params.budget_policy != NO_ENFORCEMENT) #define budget_precisely_tracked(t) (\ tsk_rt(t)->task_params.budget_policy == PRECISE_ENFORCEMENT || \ tsk_rt(t)->task_params.budget_signal_policy == PRECISE_SIGNALS) #define budget_quantum_tracked(t) (\ tsk_rt(t)->task_params.budget_policy == QUANTUM_ENFORCEMENT || \ tsk_rt(t)->task_params.budget_signal_policy == QUANTUM_SIGNALS) #define budget_signalled(t) (\ tsk_rt(t)->task_params.budget_signal_policy != NO_SIGNALS) #define budget_precisely_signalled(t) (\ tsk_rt(t)->task_params.budget_policy == PRECISE_SIGNALS) #define bt_flag_is_set(t, flag_nr) (\ test_bit(flag_nr, &tsk_rt(t)->budget.flags)) #define bt_flag_test_and_set(t, flag_nr) (\ test_and_set_bit(flag_nr, &tsk_rt(t)->budget.flags)) #define bt_flag_set(t, flag_nr) (\ set_bit(flag_nr, &tsk_rt(t)->budget.flags)) #define bt_flag_clear(t, flag_nr) (\ clear_bit(flag_nr, &tsk_rt(t)->budget.flags)) #define bt_flags_reset(t) (\ tsk_rt(t)->budget.flags = 0) #define requeue_preempted_job(t) \ (t && (!budget_exhausted(t) || !budget_enforced(t))) struct enforcement_timer { raw_spinlock_t lock; struct hrtimer timer; int armed:1; }; typedef void (*scheduled_t)(struct task_struct* t); typedef void (*blocked_t)(struct task_struct* t); typedef void (*preempt_t)(struct task_struct* t); typedef void (*sleep_t)(struct task_struct* t); typedef enum hrtimer_restart (*exhausted_t)(struct task_struct* t); typedef void (*exit_t)(struct task_struct* t); typedef void (*inherit_t)(struct task_struct* t, struct task_struct* prio_inh); typedef void (*disinherit_t)(struct task_struct* t, struct task_struct* prio_inh); struct budget_tracker_ops { scheduled_t on_scheduled; /* called from litmus_schedule(). */ blocked_t on_blocked; /* called from plugin::schedule() */ preempt_t on_preempt; /* called from plugin::schedule() */ sleep_t on_sleep; /* called from plugin::schedule() */ exit_t on_exit; /* task exiting rt mode */ exhausted_t on_exhausted; /* called by plugin::tick() or timer interrupt */ inherit_t on_inherit; disinherit_t on_disinherit; }; struct budget_tracker { struct enforcement_timer timer; const struct budget_tracker_ops* ops; unsigned long flags; }; /* budget tracker flags */ enum BT_FLAGS { BTF_BUDGET_EXHAUSTED = 0, BTF_SIG_BUDGET_SENT = 1, }; /* Functions for simple DRAIN_SIMPLE policy common * to every scheduler. Scheduler must provide * implementation for simple_on_exhausted(). */ void simple_on_scheduled(struct task_struct* t); void simple_on_blocked(struct task_struct* t); void simple_on_preempt(struct task_struct* t); void simple_on_sleep(struct task_struct* t); void simple_on_exit(struct task_struct* t); /* Functions for DRAIN_SOBLIV policy common * to every scheduler. Scheduler must provide * implementation for sobliv_on_exhausted(). * * Limitation: Quantum budget tracking is unsupported. */ void sobliv_on_scheduled(struct task_struct* t); void sobliv_on_blocked(struct task_struct* t); void sobliv_on_sleep(struct task_struct* t); /* Use the DRAIN_SIMPLE implementations */ #define sobliv_on_preempt simple_on_preempt #define sobliv_on_exit simple_on_exit void sobliv_on_inherit(struct task_struct* t, struct task_struct* prio_inh); void sobliv_on_disinherit(struct task_struct* t, struct task_struct* prio_inh); void init_budget_tracker(struct budget_tracker* bt, const struct budget_tracker_ops* ops); /* Send SIG_BUDGET to a real-time task. */ void send_sigbudget(struct task_struct* t); #endif