Rev 674 | Rev 678 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
671 | giacomo | 1 | /* |
2 | * Project: S.Ha.R.K. |
||
3 | * |
||
4 | * Coordinators: |
||
5 | * Giorgio Buttazzo <giorgio@sssup.it> |
||
6 | * Paolo Gai <pj@gandalf.sssup.it> |
||
7 | * |
||
8 | * Authors : |
||
9 | * Giacomo Guidi <giacomo@gandalf.sssup.it> |
||
10 | * Mauro Marinoni |
||
11 | * Anton Cervin |
||
12 | * |
||
13 | * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy) |
||
14 | * |
||
15 | * http://www.sssup.it |
||
16 | * http://retis.sssup.it |
||
17 | * http://shark.sssup.it |
||
18 | */ |
||
19 | |||
20 | /* |
||
21 | * This program is free software; you can redistribute it and/or modify |
||
22 | * it under the terms of the GNU General Public License as published by |
||
23 | * the Free Software Foundation; either version 2 of the License, or |
||
24 | * (at your option) any later version. |
||
25 | * |
||
26 | * This program is distributed in the hope that it will be useful, |
||
27 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
29 | * GNU General Public License for more details. |
||
30 | * |
||
31 | * You should have received a copy of the GNU General Public License |
||
32 | * along with this program; if not, write to the Free Software |
||
33 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||
34 | * |
||
35 | */ |
||
36 | |||
37 | #include <kernel/model.h> |
||
38 | #include <kernel/descr.h> |
||
39 | #include <kernel/var.h> |
||
40 | #include <kernel/func.h> |
||
41 | |||
42 | #include <stdlib.h> |
||
43 | |||
44 | #include <modules/elastic.h> |
||
45 | |||
46 | #include <tracer.h> |
||
47 | |||
673 | giacomo | 48 | #define ELASTIC_EMPTY_SLOT 0 |
49 | #define ELASTIC_PRESENT 1 |
||
50 | #define ELASTIC_SAVE_ARRIVALS 2 |
||
671 | giacomo | 51 | |
676 | giacomo | 52 | #define ELASTIC_DEBUG |
53 | |||
671 | giacomo | 54 | typedef struct { |
55 | |||
56 | struct timespec dline; |
||
57 | |||
58 | TIME Tmin; |
||
59 | TIME Tmax; |
||
60 | |||
61 | TIME period; |
||
62 | TIME wcet; |
||
673 | giacomo | 63 | |
64 | bandwidth_t Up; |
||
671 | giacomo | 65 | |
66 | int kelastic; |
||
67 | int beta; |
||
68 | |||
69 | int nact; |
||
70 | |||
71 | int flags; |
||
72 | |||
676 | giacomo | 73 | int arrivals; |
74 | |||
671 | giacomo | 75 | } ELASTIC_task_descr; |
76 | |||
77 | typedef struct { |
||
78 | level_des l; /*+ the standard level descriptor +*/ |
||
79 | |||
80 | bandwidth_t U; /*+ the used bandwidth by the server +*/ |
||
81 | |||
82 | ELASTIC_task_descr *elist; |
||
83 | |||
84 | LEVEL scheduling_level; |
||
85 | |||
86 | LEVEL current_level; |
||
87 | |||
88 | int flags; |
||
89 | |||
90 | } ELASTIC_level_des; |
||
91 | |||
676 | giacomo | 92 | static int ELASTIC_recompute(ELASTIC_level_des *lev) { |
673 | giacomo | 93 | |
676 | giacomo | 94 | PID i; |
95 | |||
96 | for (i=0; i<MAX_PROC; i++) { |
||
97 | if (lev->elist[i].flags & ELASTIC_PRESENT) |
||
98 | lev->elist[i].period = lev->elist[i].Tmax; |
||
99 | } |
||
100 | |||
673 | giacomo | 101 | return 0; |
102 | |||
103 | } |
||
104 | |||
676 | giacomo | 105 | static int ELASTIC_check_guarantie(ELASTIC_level_des *lev) { |
673 | giacomo | 106 | |
107 | return 0; |
||
108 | |||
109 | } |
||
110 | |||
671 | giacomo | 111 | static void ELASTIC_activation(ELASTIC_level_des *lev, |
112 | PID p, |
||
113 | struct timespec *acttime) |
||
114 | { |
||
115 | JOB_TASK_MODEL job; |
||
674 | giacomo | 116 | |
117 | /* Job deadline */ |
||
118 | TIMESPEC_ASSIGN(&(lev->elist[p].dline),acttime); |
||
119 | ADDUSEC2TIMESPEC(lev->elist[p].period,&(lev->elist[p].dline)); |
||
120 | |||
121 | /* Job insertion */ |
||
122 | job_task_default_model(job, lev->elist[p].dline); |
||
671 | giacomo | 123 | level_table[ lev->scheduling_level ]-> |
124 | private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job); |
||
125 | |||
674 | giacomo | 126 | } |
671 | giacomo | 127 | |
674 | giacomo | 128 | static void ELASTIC_timer_act(void *arg) { |
129 | |||
130 | PID p = (PID)(arg); |
||
131 | ELASTIC_level_des *lev; |
||
132 | struct timespec acttime; |
||
133 | |||
134 | kern_gettime(&acttime); |
||
135 | |||
136 | lev = (ELASTIC_level_des *)level_table[proc_table[p].task_level]; |
||
137 | |||
138 | ELASTIC_activation(lev, p, &acttime); |
||
671 | giacomo | 139 | } |
140 | |||
141 | /* The on-line guarantee is enabled only if the appropriate flag is set... */ |
||
142 | static int ELASTIC_public_guarantee(LEVEL l, bandwidth_t *freebandwidth) |
||
143 | { |
||
144 | ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]); |
||
145 | |||
673 | giacomo | 146 | return 0; |
147 | |||
671 | giacomo | 148 | } |
149 | |||
150 | static int ELASTIC_public_create(LEVEL l, PID p, TASK_MODEL *m) |
||
151 | { |
||
152 | ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]); |
||
153 | ELASTIC_TASK_MODEL *elastic; |
||
154 | |||
155 | if (m->pclass != ELASTIC_PCLASS) return -1; |
||
156 | if (m->level != 0 && m->level != l) return -1; |
||
157 | elastic = (ELASTIC_TASK_MODEL *)m; |
||
158 | |||
673 | giacomo | 159 | if (elastic->wcet == 0) return -1; |
160 | if (elastic->Tmin > elastic->Tmax) return -1; |
||
161 | if (elastic->Tmax == 0) return -1; |
||
162 | |||
163 | lev->elist[p].flags |= ELASTIC_PRESENT; |
||
164 | |||
165 | NULL_TIMESPEC(&(lev->elist[p].dline)); |
||
166 | lev->elist[p].Tmin = elastic->Tmin; |
||
167 | lev->elist[p].Tmax = elastic->Tmax; |
||
168 | lev->elist[p].wcet = elastic->wcet; |
||
169 | lev->elist[p].kelastic = elastic->kelastic; |
||
170 | lev->elist[p].beta = elastic->beta; |
||
171 | |||
172 | if (lev->flags & ELASTIC_ENABLE_GUARANTEE) |
||
676 | giacomo | 173 | if (ELASTIC_check_guarantie(lev) != 0) { |
673 | giacomo | 174 | lev->elist[p].flags = ELASTIC_EMPTY_SLOT; |
175 | return -1; |
||
176 | } |
||
177 | |||
676 | giacomo | 178 | ELASTIC_recompute(lev); |
673 | giacomo | 179 | |
180 | if (lev->elist[p].period == 0) { |
||
181 | lev->elist[p].flags = ELASTIC_EMPTY_SLOT; |
||
182 | return -1; |
||
183 | } |
||
184 | |||
674 | giacomo | 185 | proc_table[p].avail_time = elastic->wcet; |
673 | giacomo | 186 | proc_table[p].wcet = elastic->wcet; |
674 | giacomo | 187 | proc_table[p].control |= CONTROL_CAP; |
673 | giacomo | 188 | |
189 | if (elastic->arrivals == SAVE_ARRIVALS) |
||
676 | giacomo | 190 | lev->elist[p].arrivals |= ELASTIC_SAVE_ARRIVALS; |
673 | giacomo | 191 | |
671 | giacomo | 192 | return 0; /* OK, also if the task cannot be guaranteed... */ |
193 | |||
194 | } |
||
195 | |||
196 | static void ELASTIC_public_detach(LEVEL l, PID p) |
||
197 | { |
||
198 | ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]); |
||
199 | |||
200 | } |
||
201 | |||
202 | static int ELASTIC_public_eligible(LEVEL l, PID p) |
||
203 | { |
||
204 | ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]); |
||
205 | |||
206 | return 0; |
||
207 | |||
208 | } |
||
209 | |||
210 | static void ELASTIC_public_dispatch(LEVEL l, PID p, int nostop) |
||
211 | { |
||
212 | ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]); |
||
674 | giacomo | 213 | |
671 | giacomo | 214 | level_table[ lev->scheduling_level ]-> |
215 | private_dispatch(lev->scheduling_level,p,nostop); |
||
674 | giacomo | 216 | |
671 | giacomo | 217 | } |
218 | |||
219 | static void ELASTIC_public_epilogue(LEVEL l, PID p) |
||
220 | { |
||
221 | ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]); |
||
222 | |||
674 | giacomo | 223 | /* check if the wcet is finished... */ |
224 | if (proc_table[p].avail_time <= 0) { |
||
225 | |||
226 | TRACER_LOGEVENT(FTrace_EVT_task_wcet_violation,(unsigned short int)proc_table[p].context,0); |
||
227 | kern_raise(XWCET_VIOLATION,p); |
||
228 | |||
229 | } |
||
230 | |||
231 | level_table[ lev->scheduling_level ]-> |
||
232 | private_epilogue(lev->scheduling_level,p); |
||
233 | |||
671 | giacomo | 234 | } |
235 | |||
236 | static void ELASTIC_public_activate(LEVEL l, PID p, struct timespec *t) |
||
237 | { |
||
238 | ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]); |
||
239 | |||
674 | giacomo | 240 | #ifdef ELASTIC_DEBUG |
241 | printk("(ELASTIC:Act:%d)", p); |
||
242 | #endif |
||
243 | |||
244 | /* check if we are not in the SLEEP state */ |
||
245 | if (proc_table[p].status != SLEEP) { |
||
246 | |||
676 | giacomo | 247 | if (lev->elist[p].arrivals & ELASTIC_SAVE_ARRIVALS) { |
674 | giacomo | 248 | |
249 | /* skip the sporadic job, but increase a counter */ |
||
250 | #ifdef ELASTIC_DEBUG |
||
251 | printk("(ELASTIC:SaveAct:%d)", p); |
||
252 | #endif |
||
253 | |||
254 | lev->elist[p].nact++; |
||
255 | |||
256 | } |
||
257 | |||
258 | return; |
||
259 | |||
260 | } |
||
261 | |||
262 | ELASTIC_activation(lev,p,t); |
||
263 | |||
264 | /* Next activation */ |
||
265 | kern_event_post(&(lev->elist[p].dline), ELASTIC_timer_act, (void *)(p)); |
||
266 | |||
671 | giacomo | 267 | } |
268 | |||
269 | static void ELASTIC_public_unblock(LEVEL l, PID p) |
||
270 | { |
||
271 | ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]); |
||
272 | struct timespec acttime; |
||
273 | |||
274 | kern_gettime(&acttime); |
||
275 | |||
276 | ELASTIC_activation(lev,p,&acttime); |
||
277 | |||
278 | } |
||
279 | |||
280 | static void ELASTIC_public_block(LEVEL l, PID p) |
||
281 | { |
||
282 | ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]); |
||
283 | |||
284 | level_table[ lev->scheduling_level ]-> |
||
285 | private_extract(lev->scheduling_level,p); |
||
286 | |||
287 | } |
||
288 | |||
289 | static int ELASTIC_public_message(LEVEL l, PID p, void *m) |
||
290 | { |
||
291 | ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]); |
||
676 | giacomo | 292 | struct timespec acttime; |
671 | giacomo | 293 | |
294 | switch((long)(m)) { |
||
295 | |||
296 | case (long)(NULL): |
||
297 | |||
676 | giacomo | 298 | level_table[ lev->scheduling_level ]-> |
299 | private_extract(lev->scheduling_level,p); |
||
300 | |||
301 | if (lev->elist[p].nact == 0) { |
||
302 | |||
303 | lev->elist[p].nact--; |
||
304 | |||
305 | kern_gettime(&acttime); |
||
306 | |||
307 | ELASTIC_activation(lev,p,&acttime); |
||
308 | |||
309 | } |
||
310 | |||
671 | giacomo | 311 | jet_update_endcycle(); /* Update the Jet data... */ |
312 | TRACER_LOGEVENT(FTrace_EVT_task_end_cycle,(unsigned short int)proc_table[p].context,(unsigned int)l); |
||
313 | |||
314 | break; |
||
315 | |||
316 | case 1: |
||
317 | |||
676 | giacomo | 318 | level_table[ lev->scheduling_level ]-> |
319 | private_extract(lev->scheduling_level,p); |
||
320 | |||
321 | proc_table[p].status = SLEEP; |
||
322 | |||
671 | giacomo | 323 | TRACER_LOGEVENT(FTrace_EVT_task_disable,(unsigned short int)proc_table[p].context,(unsigned int)l); |
324 | |||
325 | break; |
||
326 | |||
327 | } |
||
328 | |||
329 | return 0; |
||
330 | |||
331 | } |
||
332 | |||
333 | static void ELASTIC_public_end(LEVEL l, PID p) |
||
334 | { |
||
335 | ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]); |
||
336 | |||
337 | level_table[ lev->scheduling_level ]-> |
||
338 | private_extract(lev->scheduling_level,p); |
||
339 | |||
340 | } |
||
341 | |||
342 | /*+ Registration function +*/ |
||
343 | LEVEL ELASTIC_register_level(int flags, LEVEL master) |
||
344 | { |
||
345 | LEVEL l; /* the level that we register */ |
||
346 | ELASTIC_level_des *lev; /* for readableness only */ |
||
347 | PID i; |
||
348 | |||
349 | printk("ELASTIC_register_level\n"); |
||
350 | |||
351 | /* request an entry in the level_table */ |
||
352 | l = level_alloc_descriptor(sizeof(ELASTIC_level_des)); |
||
353 | |||
354 | lev = (ELASTIC_level_des *)level_table[l]; |
||
355 | |||
356 | /* fill the standard descriptor */ |
||
357 | if (flags & ELASTIC_ENABLE_GUARANTEE) |
||
358 | lev->l.public_guarantee = ELASTIC_public_guarantee; |
||
359 | else |
||
360 | lev->l.public_guarantee = NULL; |
||
361 | lev->l.public_create = ELASTIC_public_create; |
||
362 | lev->l.public_detach = ELASTIC_public_detach; |
||
363 | lev->l.public_end = ELASTIC_public_end; |
||
364 | lev->l.public_eligible = ELASTIC_public_eligible; |
||
365 | lev->l.public_dispatch = ELASTIC_public_dispatch; |
||
366 | lev->l.public_epilogue = ELASTIC_public_epilogue; |
||
367 | lev->l.public_activate = ELASTIC_public_activate; |
||
368 | lev->l.public_unblock = ELASTIC_public_unblock; |
||
369 | lev->l.public_block = ELASTIC_public_block; |
||
370 | lev->l.public_message = ELASTIC_public_message; |
||
371 | |||
372 | lev->elist = malloc(MAX_PROC * sizeof(ELASTIC_task_descr)); |
||
373 | if (lev->elist == NULL) { |
||
374 | printk("ELASTIC: Error allocating elastic task decriptor table\n"); |
||
375 | sys_end(); |
||
376 | } |
||
377 | |||
676 | giacomo | 378 | /* fill the ELASTIC task descriptor part */ |
671 | giacomo | 379 | for (i=0; i<MAX_PROC; i++) { |
380 | NULL_TIMESPEC(&(lev->elist[i].dline)); |
||
381 | lev->elist[i].Tmin = 0; |
||
382 | lev->elist[i].Tmax = 0; |
||
383 | lev->elist[i].period = 0; |
||
384 | lev->elist[i].wcet = 0; |
||
676 | giacomo | 385 | lev->elist[i].Up = 0; |
671 | giacomo | 386 | lev->elist[i].kelastic = 0; |
387 | lev->elist[i].beta = 0; |
||
388 | lev->elist[i].nact = 0; |
||
676 | giacomo | 389 | lev->elist[i].arrivals = SKIP_ARRIVALS; |
671 | giacomo | 390 | lev->elist[i].flags = ELASTIC_EMPTY_SLOT; |
391 | } |
||
392 | |||
393 | lev->U = 0; |
||
394 | |||
395 | lev->scheduling_level = master; |
||
396 | |||
397 | lev->current_level = l; |
||
398 | |||
399 | lev->flags = flags; |
||
400 | |||
401 | return l; |
||
402 | } |
||
403 |