blob: 186e99c6bb88527e45db2bd00a64108e6a7d62ac (
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
|
/*
* Definition of the scheduler plugin interface.
*
*/
#ifndef _LINUX_SCHED_PLUGIN_H_
#define _LINUX_SCHED_PLUGIN_H_
#include <linux/sched.h>
#ifdef CONFIG_PI_SEMAPHORES
/* struct for semaphore with priority inheritance */
struct pi_semaphore {
atomic_t count;
int sleepers;
wait_queue_head_t wait;
struct {
/* highest-prio holder/waiter */
struct task_struct *task;
struct task_struct* cpu_task[NR_CPUS];
} hp;
/* lock stack */
struct pi_sem_record stack_node;
};
static inline struct pi_semaphore* to_pi(void *sem) {
return (struct pi_semaphore*)sem;
}
#endif
#ifdef CONFIG_FMLP
struct fmlp_semaphore {
struct pi_semaphore pi; /* must always be first. */
/* current lock holder */
struct task_struct *holder;
};
static inline struct fmlp_semaphore* to_fmlp(struct pi_semaphore* sem) {
return (struct fmlp_semaphore*)sem;
}
#endif
#ifdef CONFIG_OMLP
struct omlp_semaphore {
/* NOTE: first part of struct matchs fmlp_semaphore, so
* omlp_struct can be cast to fmlp_struct
*/
struct pi_semaphore pi; /* must always be first. */
/* current lock holder */
struct task_struct *holder;
/* PQ - just a single list since we only support G-EDF for now */
struct list_head pq_task_list;
};
static inline struct omlp_semaphore* to_omlp(struct pi_semaphore* sem) {
return (struct omlp_semaphore*)sem;
}
#endif
/************************ setup/tear down ********************/
typedef long (*activate_plugin_t) (void);
typedef long (*deactivate_plugin_t) (void);
/********************* scheduler invocation ******************/
/* Plugin-specific realtime tick handler */
typedef void (*scheduler_tick_t) (struct task_struct *cur);
/* Novell make sched decision function */
typedef struct task_struct* (*schedule_t)(struct task_struct * prev);
/* Clean up after the task switch has occured.
* This function is called after every (even non-rt) task switch.
*/
typedef void (*finish_switch_t)(struct task_struct *prev);
/********************* task state changes ********************/
/* Called to setup a new real-time task.
* Release the first job, enqueue, etc.
* Task may already be running.
*/
typedef void (*task_new_t) (struct task_struct *task,
int on_rq,
int running);
/* Called to re-introduce a task after blocking.
* Can potentially be called multiple times.
*/
typedef void (*task_wake_up_t) (struct task_struct *task);
/* called to notify the plugin of a blocking real-time task
* it will only be called for real-time tasks and before schedule is called */
typedef void (*task_block_t) (struct task_struct *task);
/* Called when a real-time task exits or changes to a different scheduling
* class.
* Free any allocated resources
*/
typedef void (*task_exit_t) (struct task_struct *);
#ifdef CONFIG_PI_SEMAPHORES
/* Called when the new_owner is released from the wait queue
* it should now inherit the priority from sem, _before_ it gets readded
* to any queue
*/
typedef long (*inherit_priority_t) (struct pi_semaphore *sem,
struct task_struct *new_owner);
/* Called when the current task releases a semahpore where it might have
* inherited a piority from
*/
typedef long (*return_priority_t) (struct pi_semaphore *sem);
/* Called when a task tries to acquire a semaphore and fails. Check if its
* priority is higher than that of the current holder.
*/
typedef long (*pi_block_t) (struct pi_semaphore *sem, struct task_struct *t);
#endif
/********************* sys call backends ********************/
/* This function causes the caller to sleep until the next release */
typedef long (*complete_job_t) (void);
typedef long (*admit_task_t)(struct task_struct* tsk);
typedef void (*release_at_t)(struct task_struct *t, lt_t start);
struct sched_plugin {
struct list_head list;
/* basic info */
char *plugin_name;
/* setup */
activate_plugin_t activate_plugin;
deactivate_plugin_t deactivate_plugin;
#ifdef CONFIG_SRP
unsigned int srp_active;
#endif
/* scheduler invocation */
scheduler_tick_t tick;
schedule_t schedule;
finish_switch_t finish_switch;
/* syscall backend */
complete_job_t complete_job;
release_at_t release_at;
/* task state changes */
admit_task_t admit_task;
task_new_t task_new;
task_wake_up_t task_wake_up;
task_block_t task_block;
task_exit_t task_exit;
#ifdef CONFIG_FMLP
/* priority inheritance */
unsigned int fmlp_active;
inherit_priority_t fmlp_inherit_priority;
return_priority_t fmlp_return_priority;
pi_block_t fmlp_pi_block;
#endif
#ifdef CONFIG_OMLP
unsigned int omlp_active;
inherit_priority_t omlp_inherit_priority;
return_priority_t omlp_return_priority;
pi_block_t omlp_pi_block;
#endif
} __attribute__ ((__aligned__(SMP_CACHE_BYTES)));
extern struct sched_plugin *litmus;
/* cluster size: cache_index = 2 L2, cache_index = 3 L3 */
extern int cluster_cache_index;
int register_sched_plugin(struct sched_plugin* plugin);
struct sched_plugin* find_sched_plugin(const char* name);
int print_sched_plugins(char* buf, int max);
static inline int srp_active(void)
{
#ifdef CONFIG_SRP
return litmus->srp_active;
#else
return 0;
#endif
}
static inline int fmlp_active(void)
{
#ifdef CONFIG_FMLP
return litmus->fmlp_active;
#else
return 0;
#endif
}
static inline int omlp_active(void)
{
#ifdef CONFIG_OMLP
return litmus->omlp_active;
#else
return 0;
#endif
}
extern struct sched_plugin linux_sched_plugin;
#endif
|