Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1670 | pj | 1 | #include <ctype.h> |
2 | #include "hlpdemo.h" |
||
3 | |||
4 | extern taskconf_list_t *taskconf; |
||
5 | extern mutex_list_t *mutexes; |
||
6 | |||
7 | typedef enum { TT_TASK = 0, |
||
8 | TT_EVERY = 1, |
||
9 | TT_RUNS = 2, |
||
10 | TT_LOCKS = 3, |
||
11 | TT_UNLOCKS = 4, |
||
12 | TT_ID, |
||
13 | TT_INT, |
||
14 | TT_INVALID = -1 } keyword_t; |
||
15 | |||
16 | /* multitype value management */ |
||
17 | typedef struct value_struct { |
||
18 | int type; /* -1 invalid, 0 int, 1 string, 2 token, 3 eof */ |
||
19 | int intval; |
||
20 | char *strval; |
||
21 | keyword_t keyword; |
||
22 | } value_t; |
||
23 | |||
24 | value_t *invalid_value (int type) |
||
25 | { |
||
26 | value_t *new; |
||
27 | new = (value_t *) kern_alloc(sizeof(value_t)); |
||
28 | new->type = type; |
||
29 | new->intval = -1; |
||
30 | new->strval = NULL; |
||
31 | new->keyword = TT_INVALID; |
||
32 | return new; |
||
33 | } |
||
34 | |||
35 | char *strdup(char *str) |
||
36 | { |
||
37 | char *ret; |
||
38 | |||
39 | ret = (char *)kern_alloc((strlen(str) + 1) * sizeof(char)); |
||
40 | strncpy(ret, str, strlen(str)); |
||
41 | ret[strlen(str)] = '\0'; |
||
42 | |||
43 | return ret; |
||
44 | } |
||
45 | |||
46 | value_t *keyword_value (char *token) |
||
47 | { |
||
48 | int i; |
||
49 | value_t *new = NULL; |
||
50 | char *type_assoc[] = { "task", |
||
51 | "every", |
||
52 | "runs", |
||
53 | "locks", |
||
54 | "unlocks", |
||
55 | NULL}; |
||
56 | for (i=0; type_assoc[i] != NULL ; i++) |
||
57 | { |
||
58 | if (strcmp(token, type_assoc[i]) == 0) |
||
59 | { |
||
60 | new = (value_t *)kern_alloc(sizeof(value_t)); |
||
61 | new->type = 2; |
||
62 | new->intval = -1; |
||
63 | new->strval = strdup(token); |
||
64 | new->keyword = (keyword_t)i; |
||
65 | } |
||
66 | } |
||
67 | return new; |
||
68 | } |
||
69 | |||
70 | value_t *int_value (int n) |
||
71 | { |
||
72 | value_t *new; |
||
73 | new = (value_t *) kern_alloc(sizeof(value_t)); |
||
74 | new->type = 0; |
||
75 | new->intval = n; |
||
76 | new->strval = NULL; |
||
77 | new->keyword = TT_INT; |
||
78 | return new; |
||
79 | } |
||
80 | |||
81 | value_t *str_value (char *str) |
||
82 | { |
||
83 | value_t *new; |
||
84 | new = (value_t *) kern_alloc(sizeof(value_t)); |
||
85 | new->type = 1; |
||
86 | new->intval = -1; |
||
87 | new->strval = strdup(str); |
||
88 | new->keyword = TT_ID; |
||
89 | return new; |
||
90 | } |
||
91 | |||
92 | void dprint(char *str) |
||
93 | { |
||
94 | #ifdef DEBUG |
||
95 | if (str) |
||
96 | cprintf("%s\n", str); |
||
97 | #endif |
||
98 | } |
||
99 | |||
100 | void dprint_value(value_t *val) |
||
101 | { |
||
102 | #ifdef DEBUG |
||
103 | switch (val->type) { |
||
104 | case 0: |
||
105 | cprintf("Value is an integer: %d\n", val->intval); |
||
106 | break; |
||
107 | case 1: |
||
108 | cprintf("Value is a string: '%s'\n", val->strval); |
||
109 | break; |
||
110 | case 2: |
||
111 | cprintf("Value is a keyword: %d\n", (int)val->keyword); |
||
112 | break; |
||
113 | case 3: |
||
114 | cprintf("Value is an eof terminator\n"); |
||
115 | break; |
||
116 | } |
||
117 | #endif |
||
118 | } |
||
119 | |||
120 | int intlen(int val) |
||
121 | { |
||
122 | int ret = 1; |
||
123 | |||
124 | while ( (val = val / 10) >= 1) ret++; |
||
125 | |||
126 | return ret; |
||
127 | } |
||
128 | |||
129 | /* |
||
130 | @desc Tokenizza uno stream, riconoscendo interi, identificatori e |
||
131 | token del linguaggio. Ad ogni chiamata restituisce il prossimo |
||
132 | token. |
||
133 | @return il prossimo token come multitype value (esistono i value di errore) |
||
134 | */ |
||
135 | value_t *get_token_from_str (char *stream, unsigned int size) |
||
136 | { |
||
137 | int c, intval; |
||
138 | static int pos = 0; |
||
139 | |||
140 | /* Ignore white space, get first nonwhite character. */ |
||
141 | while ((c = stream[pos++]) == ' ' || c == '\t' || c == '\n'); |
||
142 | |||
143 | if (c == EOF || c == '\0' || pos == size - 1) |
||
144 | return invalid_value(3); |
||
145 | |||
146 | /* Char starts a number => parse the number. */ |
||
147 | if (c == '.' || isdigit (c)) |
||
148 | { |
||
149 | pos--; |
||
150 | sscanf (&stream[pos], "%d", &intval); |
||
151 | pos += intlen(intval); |
||
152 | return int_value(intval); |
||
153 | } |
||
154 | |||
155 | /* Char starts an identifier => read the name. */ |
||
156 | if (isalpha (c)) |
||
157 | { |
||
158 | value_t *keyword_val; |
||
159 | static char *symbuf = 0; |
||
160 | static int length = 0; |
||
161 | int i; |
||
162 | |||
163 | /* Initially make the buffer long enough |
||
164 | for a 40-character symbol name. */ |
||
165 | if (length == 0) |
||
166 | length = 40, symbuf = (char *)kern_alloc (length + 1); |
||
167 | |||
168 | i = 0; |
||
169 | do |
||
170 | { |
||
171 | /* If buffer is full, make it bigger. */ |
||
172 | if (i == length) |
||
173 | { |
||
174 | length *= 2; |
||
175 | symbuf = (char *) realloc (symbuf, length + 1); |
||
176 | } |
||
177 | /* Add this character to the buffer. */ |
||
178 | symbuf[i++] = c; |
||
179 | /* Get another character. */ |
||
180 | c = stream[pos++]; |
||
181 | } |
||
182 | while (isalnum (c)); |
||
183 | |||
184 | pos--; |
||
185 | symbuf[i] = '\0'; |
||
186 | |||
187 | keyword_val = keyword_value(symbuf); |
||
188 | |||
189 | if (keyword_val->type == 2) |
||
190 | { |
||
191 | dprint("found a keyword"); |
||
192 | return keyword_val; |
||
193 | } |
||
194 | else |
||
195 | { |
||
196 | dprint("found an identifier"); |
||
197 | return str_value(symbuf); |
||
198 | } |
||
199 | } |
||
200 | |||
201 | /* Any other character is a token by itself. */ |
||
202 | #ifdef DEBUG |
||
203 | cprintf("Invalid Token: '%c'\n", c); |
||
204 | #endif |
||
205 | return invalid_value(-1); |
||
206 | } |
||
207 | |||
208 | |||
209 | /* |
||
210 | @desc Ricerca un mutex di un dato nome in una mutex_list_t |
||
211 | @return il mutex trovato o NULL in caso di mutex non trovato |
||
212 | */ |
||
213 | mutex_list_t *in_mutex_list(char *needle, mutex_list_t *list) |
||
214 | { |
||
215 | while (list) |
||
216 | { |
||
217 | if (!strcmp(needle, list->name)) |
||
218 | break; |
||
219 | list = list->next; |
||
220 | } |
||
221 | |||
222 | return list; |
||
223 | } |
||
224 | |||
225 | /* @return Calcola il wcet sommando tutte le azioni di load */ |
||
226 | DWORD calc_wcet(taskconf_list_t *task) |
||
227 | { |
||
228 | action_list_t *scan = task->actionlist; |
||
229 | DWORD wcet = 0; |
||
230 | |||
231 | while(scan) |
||
232 | { |
||
233 | wcet += (scan->type == LOAD ? scan->time : 0); |
||
234 | scan = scan->next; |
||
235 | } |
||
236 | |||
237 | return wcet; |
||
238 | } |
||
239 | |||
240 | /* |
||
241 | @desc Legge la configurazione dal buffer esterno myfilebuf |
||
242 | Riempie la struttura dati esterna taskconf |
||
243 | @return 0 ok |
||
244 | -1 errore nel parsing |
||
245 | */ |
||
246 | int read_conf(char *stream, unsigned int size) |
||
247 | { |
||
248 | value_t *tmpval, *curval = get_token_from_str(stream, size); |
||
249 | taskconf_list_t *tcnew, *tccur = taskconf; |
||
250 | action_list_t *acnew, *accur = NULL; |
||
251 | mutex_list_t *mutnew, *mutcur = NULL; |
||
252 | TIME seme; |
||
253 | |||
254 | dprint(stream); |
||
255 | |||
256 | while (curval->type != 3) /* until eof */ |
||
257 | { |
||
258 | switch (curval->keyword) |
||
259 | { |
||
260 | case TT_TASK: /* create new task */ |
||
261 | tmpval = get_token_from_str(stream, size); /* get the name */ |
||
262 | |||
263 | if (tmpval->type != 1) { |
||
264 | dprint("No name after task"); |
||
265 | return -1; |
||
266 | } |
||
267 | |||
268 | /* alloc mem and set default data */ |
||
269 | tcnew = (taskconf_list_t *)kern_alloc((sizeof(taskconf_list_t))); |
||
270 | tcnew->name = strdup(tmpval->strval); |
||
271 | tcnew->period = -1; |
||
272 | tcnew->wcet = 0; |
||
273 | tcnew->next = NULL; |
||
274 | tcnew->mutexlist = NULL; |
||
275 | tcnew->actionlist = NULL; |
||
276 | |||
277 | /* reset current mutex and current action */ |
||
278 | mutcur = NULL; |
||
279 | accur = NULL; |
||
280 | |||
281 | /* fill the first taskconf */ |
||
282 | if (taskconf == NULL) |
||
283 | taskconf = tcnew; |
||
284 | |||
285 | if (tccur != NULL) |
||
286 | tccur->next = tcnew; |
||
287 | |||
288 | tccur = tcnew; |
||
289 | |||
290 | break; |
||
291 | |||
292 | case TT_EVERY: |
||
293 | tmpval = get_token_from_str(stream, size); |
||
294 | if (tmpval->type != 0) { |
||
295 | dprint("No period after every"); |
||
296 | return -1; |
||
297 | } |
||
298 | tccur->period = tmpval->intval; |
||
299 | break; |
||
300 | |||
301 | case TT_RUNS: |
||
302 | /* making new action */ |
||
303 | tmpval = get_token_from_str(stream, size); |
||
304 | if (tmpval->type != 0) { |
||
305 | dprint("No period after runs"); |
||
306 | return -1; |
||
307 | } |
||
308 | |||
309 | acnew = (action_list_t *)kern_alloc((sizeof(action_list_t))); |
||
310 | acnew->type = LOAD; |
||
311 | acnew->time = tmpval->intval; |
||
312 | acnew->next = NULL; |
||
313 | acnew->mutex = NULL; |
||
314 | |||
315 | if (tccur->actionlist == NULL) |
||
316 | tccur->actionlist = acnew; |
||
317 | else |
||
318 | accur->next = acnew; |
||
319 | |||
320 | accur = acnew; |
||
321 | |||
322 | /* calculate wcet for the former task */ |
||
323 | if (tccur != NULL) |
||
324 | { |
||
325 | /* calc the wcet */ |
||
326 | tccur->wcet = calc_wcet(tccur); |
||
327 | } |
||
328 | |||
329 | break; |
||
330 | |||
331 | case TT_LOCKS: |
||
332 | |||
333 | tmpval = get_token_from_str(stream, size); |
||
334 | |||
335 | if (tmpval->type != 1) |
||
336 | return -1; |
||
337 | |||
338 | acnew = (action_list_t *)kern_alloc(sizeof(action_list_t)); |
||
339 | acnew->type = LOCK; |
||
340 | acnew->time = -1; |
||
341 | acnew->next = NULL; |
||
342 | |||
343 | /* create new mutex if does not exist*/ |
||
344 | if ( !(mutnew = in_mutex_list(tmpval->strval, mutexes))) |
||
345 | { |
||
346 | mutnew = (mutex_list_t *)kern_alloc(sizeof(mutex_list_t)); |
||
347 | mutnew->name = strdup(tmpval->strval); |
||
348 | |||
349 | seme = sys_gettime(NULL); |
||
350 | srand(seme); |
||
351 | mutnew->color = rgb16(rand() % 255, |
||
352 | rand() % 255, |
||
353 | rand() % 255); |
||
354 | mutnew->next = NULL; |
||
355 | |||
356 | /* adding to mutexes */ |
||
357 | if (mutexes == NULL) |
||
358 | mutexes = mutnew; |
||
359 | else |
||
360 | mutexes->next = mutnew; |
||
361 | } |
||
362 | acnew->mutex = mutnew; |
||
363 | |||
364 | /* add mutex to the list of tasks using it */ |
||
365 | if (tccur->mutexlist == NULL) |
||
366 | { |
||
367 | tccur->mutexlist = mutnew; |
||
368 | } |
||
369 | else |
||
370 | { |
||
371 | if (in_mutex_list(tmpval->strval, tccur->mutexlist)) |
||
372 | mutcur->next = mutnew; |
||
373 | } |
||
374 | |||
375 | mutcur = mutnew; |
||
376 | |||
377 | /* updating action list */ |
||
378 | if (tccur->actionlist == NULL) |
||
379 | tccur->actionlist = acnew; |
||
380 | else |
||
381 | accur->next = acnew; |
||
382 | |||
383 | accur = acnew; |
||
384 | break; |
||
385 | |||
386 | case TT_UNLOCKS: |
||
387 | |||
388 | tmpval = get_token_from_str(stream, size); |
||
389 | if (tmpval->type != 1) |
||
390 | return -1; |
||
391 | |||
392 | acnew = (action_list_t *)kern_alloc((sizeof(action_list_t))); |
||
393 | acnew->type = UNLOCK; |
||
394 | acnew->time = -1; |
||
395 | acnew->next = NULL; |
||
396 | |||
397 | if ( (mutnew = in_mutex_list(tmpval->strval, tccur->mutexlist)) == NULL) |
||
398 | { |
||
399 | #ifdef DEBUG |
||
400 | cprintf("Mutex %s unlocked but never locked\n", tmpval->strval); |
||
401 | #endif |
||
402 | return -1; |
||
403 | } |
||
404 | |||
405 | acnew->mutex = mutnew; |
||
406 | |||
407 | if (tccur->actionlist == NULL) |
||
408 | tccur->actionlist = acnew; |
||
409 | else |
||
410 | accur->next = acnew; |
||
411 | |||
412 | accur = acnew; |
||
413 | break; |
||
414 | |||
415 | case TT_ID: |
||
416 | dprint_value(curval); |
||
417 | break; |
||
418 | |||
419 | case TT_INT: |
||
420 | dprint_value(curval); |
||
421 | break; |
||
422 | |||
423 | case TT_INVALID: |
||
424 | break; |
||
425 | } |
||
426 | curval = get_token_from_str(stream, size); |
||
427 | } |
||
428 | return 0; |
||
429 | } |
||
430 | |||
431 | void print_taskconf(taskconf_list_t *tc) |
||
432 | { |
||
433 | action_list_t *action; |
||
434 | mutex_list_t *mutex; |
||
435 | |||
436 | if (tc == NULL) |
||
437 | return; |
||
438 | |||
439 | cprintf("Task: %s, period %ld, wcet %ld\n", tc->name, tc->period, tc->wcet); |
||
440 | cprintf("Actions:\n"); |
||
441 | |||
442 | action = tc->actionlist; |
||
443 | |||
444 | while (action) |
||
445 | { |
||
446 | cprintf("---Type %d, time %d, mutex %s\n", action->type, action->time, (action->mutex == NULL ? "" : action->mutex->name)); |
||
447 | action = action->next; |
||
448 | } |
||
449 | |||
450 | cprintf("Mutex used:\n"); |
||
451 | mutex = tc->mutexlist; |
||
452 | |||
453 | while (mutex) |
||
454 | { |
||
455 | cprintf("---Name %s, Color %d\n", mutex->name, mutex->color); |
||
456 | mutex = mutex->next; |
||
457 | } |
||
458 | |||
459 | print_taskconf(tc->next); |
||
460 | } |