aboutsummaryrefslogtreecommitdiffstats
path: root/include/litmus/sched_mc.h
blob: 70f57cfd270693602f120ea546eb63741729be00 (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
#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;
#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