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
|
#ifndef _LINUX_SCHED_MC_H_
#define _LINUX_SCHED_MC_H_
/* criticality levels */
enum crit_level {
/* probably don't need to assign these (paranoid) */
CRIT_LEVEL_A = 0,
CRIT_LEVEL_B = 1,
CRIT_LEVEL_C = 2,
NUM_CRIT_LEVELS = 3,
};
struct mc_task {
enum crit_level crit;
int lvl_a_id;
int lvl_a_eligible;
};
#ifdef __KERNEL__
/*
* These are used only in the kernel. Userspace programs like RTSpin won't see
* them.
*/
struct mc_data {
struct mc_task mc_task;
};
#define tsk_mc_data(t) (tsk_rt(t)->mc_data)
#define tsk_mc_crit(t) \
(tsk_mc_data(t) ? tsk_mc_data(t)->mc_task.crit : CRIT_LEVEL_C)
#define is_ghost(t) \
(get_rt_job(t) < get_user_job(t) && (tsk_rt(t)->completed))
#define ce_sid(ce) \
(-(num_online_cpus() + (ce)->level * num_online_cpus() + crit_cpu(ce)->cpu + 1))
#define TS "(%s/%d:%d:%d:%s)"
#define TA(t) (t) ? is_ghost(t) ? "ghost" : t->comm : "NULL", \
(t) ? t->pid : 1, \
(t) ? get_rt_job(t) : 1, \
(t) ? get_user_job(t) : 1, \
(t && get_task_domain(t)) ? get_task_domain(t)->name : ""
#define TRACE_MC_TASK(t, fmt, args...) \
STRACE(TS " " fmt, TA(t), ##args)
#define TRACE_CRIT_ENTRY(ce, fmt, args...) \
STRACE("%s P%d, linked=" TS " " fmt, \
(ce)->domain->name, crit_cpu(ce)->cpu, TA((ce)->server.linked), ##args)
/*
* The MC-CE scheduler uses this as domain data.
*/
struct ce_dom_data {
int cpu;
struct task_struct *scheduled, *should_schedule;
#ifdef CONFIG_MERGE_TIMERS
struct rt_event event;
#else
struct hrtimer timer;
struct hrtimer_start_on_info timer_info;
#endif
};
/**
* struct crit_entry - State of a CPU within each criticality level system.
* @level Criticality level of this entry
* @linked Logically running task, ghost or regular
* @domain Domain from which to draw tasks
* @usable False if a higher criticality task is running
* @event For ghost task budget enforcement (merge timers)
* @timer For ghost task budget enforcement (not merge timers)
* @node Used to sort crit_entries by preemptability in global domains
*/
struct crit_entry {
struct server server;
enum crit_level level;
struct domain* domain;
#ifdef CONFIG_MERGE_TIMERS
struct rt_event event;
#else
struct hrtimer timer;
#endif
struct bheap_node* node;
};
/**
* struct domain_data - Wrap domains with related CPU state
* @domain A domain for a criticality level
* @heap The preemptable heap of crit entries (for global domains)
* @crit_entry The crit entry for this domain (for partitioned domains)
*/
struct domain_data {
struct domain domain;
struct bheap* heap;
struct crit_entry* crit_entry;
};
/*
* Functions that are used with the MC-CE plugin.
*/
long mc_ce_set_domains(const int, struct domain_data*[]);
unsigned int mc_ce_get_expected_job(const int, const int);
/*
* These functions are (lazily) inserted into the MC plugin code so that it
* manipulates the MC-CE state.
*/
long mc_ce_admit_task_common(struct task_struct*);
void mc_ce_task_exit_common(struct task_struct*);
lt_t mc_ce_timer_callback_common(domain_t*);
void mc_ce_release_at_common(struct task_struct*, lt_t);
long mc_ce_activate_plugin_common(void);
long mc_ce_deactivate_plugin_common(void);
void mc_ce_job_completion(struct domain *dom, struct task_struct *ts);
#endif /* __KERNEL__ */
#endif
|