aboutsummaryrefslogtreecommitdiffstats
path: root/include/litmus/budget.h
blob: 72f04777e0b080d40d40731d37ec1d069c77cf13 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#ifndef _LITMUS_BUDGET_H_
#define _LITMUS_BUDGET_H_

#include <linux/hrtimer.h>
#include <linux/semaphore.h>

#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);

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 */
};

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 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