aboutsummaryrefslogtreecommitdiffstats
path: root/include/litmus/budget.h
blob: 0ae9c9f300237a1f513edafa9cead501117132a5 (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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#ifndef _LITMUS_BUDGET_H_
#define _LITMUS_BUDGET_H_

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

#include <litmus/binheap.h>

struct enforcement_timer
{
	raw_spinlock_t lock;
	struct hrtimer timer;
	int armed:1;
	unsigned int job_when_armed;
};

int cancel_enforcement_timer(struct task_struct* t);

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 void (*wakeup_t)(struct task_struct* t);

#define IN_SCHEDULE 1

typedef enum hrtimer_restart (*exhausted_t)(struct task_struct* t, int in_schedule);
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);

typedef void (*enter_top_m_t)(struct task_struct* t);
typedef void (*exit_top_m_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() */
	wakeup_t			on_wakeup;

	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;

	enter_top_m_t		on_enter_top_m;
	exit_top_m_t		on_exit_top_m;
};

struct budget_tracker
{
	struct enforcement_timer timer;
	const struct budget_tracker_ops* ops;
	unsigned long flags;

	struct binheap_node top_m_node;
	lt_t suspend_timestamp;
};

/* budget tracker flags */
enum BT_FLAGS
{
	BTF_BUDGET_EXHAUSTED	= 0,
	BTF_SIG_BUDGET_SENT		= 1,
	BTF_IS_TOP_M			= 2,
	BTF_WAITING_FOR_RELEASE = 3,
};

/* 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_SIMPLE_IO policy common
 * to every scheduler. Scheduler must provide
 * implementation for simple_io_on_exhausted().
 */
#define simple_io_on_scheduled	simple_on_scheduled
void simple_io_on_blocked(struct task_struct* t);
void simple_io_on_wakeup(struct task_struct* t);
#define simple_io_on_preempt	simple_on_preempt
#define simple_io_on_sleep	simple_on_sleep
#define simple_io_on_exit	simple_on_exit


/* 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_blocked(struct task_struct* t);
void sobliv_on_wakeup(struct task_struct* t);
#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 sobliv_on_enter_top_m(struct task_struct* t);
void sobliv_on_exit_top_m(struct task_struct* t);

void reevaluate_inheritance(struct task_struct* t);

#define budget_state_machine(t, evt) \
	do { \
		if (get_budget_timer(t).ops && \
			get_budget_timer(t).ops->evt != NULL) { \
			get_budget_timer(t).ops->evt(t); \
		} \
	}while(0)

#define budget_state_machine2(t, evt, param) \
	do { \
		if (get_budget_timer(t).ops && \
			get_budget_timer(t).ops->evt != NULL) { \
			get_budget_timer(t).ops->evt(t, param); \
		} \
	}while(0)

#define budget_state_machine_chgprio(a, b, evt) \
	do { \
		if (get_budget_timer(a).ops && \
			get_budget_timer(b).ops && \
			get_budget_timer(a).ops->evt != NULL && \
			get_budget_timer(b).ops->evt != NULL) {\
			get_budget_timer(a).ops->evt(a, b); \
		} \
	}while(0)


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