Blame |
Last modification |
View Log
| RSS feed
#include <ctype.h>
#include "hlpdemo.h"
extern taskconf_list_t
*taskconf
;
extern mutex_list_t
*mutexes
;
typedef enum { TT_TASK
= 0,
TT_EVERY
= 1,
TT_RUNS
= 2,
TT_LOCKS
= 3,
TT_UNLOCKS
= 4,
TT_ID
,
TT_INT
,
TT_INVALID
= -1 } keyword_t
;
/* multitype value management */
typedef struct value_struct
{
int type
; /* -1 invalid, 0 int, 1 string, 2 token, 3 eof */
int intval
;
char *strval
;
keyword_t keyword
;
} value_t
;
value_t
*invalid_value
(int type
)
{
value_t
*new
;
new
= (value_t
*) kern_alloc
(sizeof(value_t
));
new
->type
= type
;
new
->intval
= -1;
new
->strval
= NULL
;
new
->keyword
= TT_INVALID
;
return new
;
}
char *strdup
(char *str
)
{
char *ret
;
ret
= (char *)kern_alloc
((strlen(str
) + 1) * sizeof(char));
strncpy(ret
, str
, strlen(str
));
ret
[strlen(str
)] = '\0';
return ret
;
}
value_t
*keyword_value
(char *token
)
{
int i
;
value_t
*new
= NULL
;
char *type_assoc
[] = { "task",
"every",
"runs",
"locks",
"unlocks",
NULL
};
for (i
=0; type_assoc
[i
] != NULL
; i
++)
{
if (strcmp(token
, type_assoc
[i
]) == 0)
{
new
= (value_t
*)kern_alloc
(sizeof(value_t
));
new
->type
= 2;
new
->intval
= -1;
new
->strval
= strdup
(token
);
new
->keyword
= (keyword_t
)i
;
}
}
return new
;
}
value_t
*int_value
(int n
)
{
value_t
*new
;
new
= (value_t
*) kern_alloc
(sizeof(value_t
));
new
->type
= 0;
new
->intval
= n
;
new
->strval
= NULL
;
new
->keyword
= TT_INT
;
return new
;
}
value_t
*str_value
(char *str
)
{
value_t
*new
;
new
= (value_t
*) kern_alloc
(sizeof(value_t
));
new
->type
= 1;
new
->intval
= -1;
new
->strval
= strdup
(str
);
new
->keyword
= TT_ID
;
return new
;
}
void dprint
(char *str
)
{
#ifdef DEBUG
if (str
)
cprintf
("%s\n", str
);
#endif
}
void dprint_value
(value_t
*val
)
{
#ifdef DEBUG
switch (val
->type
) {
case 0:
cprintf
("Value is an integer: %d\n", val
->intval
);
break;
case 1:
cprintf
("Value is a string: '%s'\n", val
->strval
);
break;
case 2:
cprintf
("Value is a keyword: %d\n", (int)val
->keyword
);
break;
case 3:
cprintf
("Value is an eof terminator\n");
break;
}
#endif
}
int intlen
(int val
)
{
int ret
= 1;
while ( (val
= val
/ 10) >= 1) ret
++;
return ret
;
}
/*
@desc Tokenizza uno stream, riconoscendo interi, identificatori e
token del linguaggio. Ad ogni chiamata restituisce il prossimo
token.
@return il prossimo token come multitype value (esistono i value di errore)
*/
value_t
*get_token_from_str
(char *stream
, unsigned int size
)
{
int c
, intval
;
static int pos
= 0;
/* Ignore white space, get first nonwhite character. */
while ((c
= stream
[pos
++]) == ' ' || c
== '\t' || c
== '\n');
if (c
== EOF
|| c
== '\0' || pos
== size
- 1)
return invalid_value
(3);
/* Char starts a number => parse the number. */
if (c
== '.' || isdigit (c
))
{
pos
--;
sscanf (&stream
[pos
], "%d", &intval
);
pos
+= intlen
(intval
);
return int_value
(intval
);
}
/* Char starts an identifier => read the name. */
if (isalpha (c
))
{
value_t
*keyword_val
;
static char *symbuf
= 0;
static int length
= 0;
int i
;
/* Initially make the buffer long enough
for a 40-character symbol name. */
if (length
== 0)
length
= 40, symbuf
= (char *)kern_alloc
(length
+ 1);
i
= 0;
do
{
/* If buffer is full, make it bigger. */
if (i
== length
)
{
length
*= 2;
symbuf
= (char *) realloc (symbuf
, length
+ 1);
}
/* Add this character to the buffer. */
symbuf
[i
++] = c
;
/* Get another character. */
c
= stream
[pos
++];
}
while (isalnum (c
));
pos
--;
symbuf
[i
] = '\0';
keyword_val
= keyword_value
(symbuf
);
if (keyword_val
->type
== 2)
{
dprint
("found a keyword");
return keyword_val
;
}
else
{
dprint
("found an identifier");
return str_value
(symbuf
);
}
}
/* Any other character is a token by itself. */
#ifdef DEBUG
cprintf
("Invalid Token: '%c'\n", c
);
#endif
return invalid_value
(-1);
}
/*
@desc Ricerca un mutex di un dato nome in una mutex_list_t
@return il mutex trovato o NULL in caso di mutex non trovato
*/
mutex_list_t
*in_mutex_list
(char *needle
, mutex_list_t
*list
)
{
while (list
)
{
if (!strcmp(needle
, list
->name
))
break;
list
= list
->next
;
}
return list
;
}
/* @return Calcola il wcet sommando tutte le azioni di load */
DWORD calc_wcet
(taskconf_list_t
*task
)
{
action_list_t
*scan
= task
->actionlist
;
DWORD wcet
= 0;
while(scan
)
{
wcet
+= (scan
->type
== LOAD
? scan
->time : 0);
scan
= scan
->next
;
}
return wcet
;
}
/*
@desc Legge la configurazione dal buffer esterno myfilebuf
Riempie la struttura dati esterna taskconf
@return 0 ok
-1 errore nel parsing
*/
int read_conf
(char *stream
, unsigned int size
)
{
value_t
*tmpval
, *curval
= get_token_from_str
(stream
, size
);
taskconf_list_t
*tcnew
, *tccur
= taskconf
;
action_list_t
*acnew
, *accur
= NULL
;
mutex_list_t
*mutnew
, *mutcur
= NULL
;
TIME seme
;
dprint
(stream
);
while (curval
->type
!= 3) /* until eof */
{
switch (curval
->keyword
)
{
case TT_TASK
: /* create new task */
tmpval
= get_token_from_str
(stream
, size
); /* get the name */
if (tmpval
->type
!= 1) {
dprint
("No name after task");
return -1;
}
/* alloc mem and set default data */
tcnew
= (taskconf_list_t
*)kern_alloc
((sizeof(taskconf_list_t
)));
tcnew
->name
= strdup
(tmpval
->strval
);
tcnew
->period
= -1;
tcnew
->wcet
= 0;
tcnew
->next
= NULL
;
tcnew
->mutexlist
= NULL
;
tcnew
->actionlist
= NULL
;
/* reset current mutex and current action */
mutcur
= NULL
;
accur
= NULL
;
/* fill the first taskconf */
if (taskconf
== NULL
)
taskconf
= tcnew
;
if (tccur
!= NULL
)
tccur
->next
= tcnew
;
tccur
= tcnew
;
break;
case TT_EVERY
:
tmpval
= get_token_from_str
(stream
, size
);
if (tmpval
->type
!= 0) {
dprint
("No period after every");
return -1;
}
tccur
->period
= tmpval
->intval
;
break;
case TT_RUNS
:
/* making new action */
tmpval
= get_token_from_str
(stream
, size
);
if (tmpval
->type
!= 0) {
dprint
("No period after runs");
return -1;
}
acnew
= (action_list_t
*)kern_alloc
((sizeof(action_list_t
)));
acnew
->type
= LOAD
;
acnew
->time = tmpval
->intval
;
acnew
->next
= NULL
;
acnew
->mutex
= NULL
;
if (tccur
->actionlist
== NULL
)
tccur
->actionlist
= acnew
;
else
accur
->next
= acnew
;
accur
= acnew
;
/* calculate wcet for the former task */
if (tccur
!= NULL
)
{
/* calc the wcet */
tccur
->wcet
= calc_wcet
(tccur
);
}
break;
case TT_LOCKS
:
tmpval
= get_token_from_str
(stream
, size
);
if (tmpval
->type
!= 1)
return -1;
acnew
= (action_list_t
*)kern_alloc
(sizeof(action_list_t
));
acnew
->type
= LOCK
;
acnew
->time = -1;
acnew
->next
= NULL
;
/* create new mutex if does not exist*/
if ( !(mutnew
= in_mutex_list
(tmpval
->strval
, mutexes
)))
{
mutnew
= (mutex_list_t
*)kern_alloc
(sizeof(mutex_list_t
));
mutnew
->name
= strdup
(tmpval
->strval
);
seme
= sys_gettime
(NULL
);
srand(seme
);
mutnew
->color
= rgb16
(rand() % 255,
rand() % 255,
rand() % 255);
mutnew
->next
= NULL
;
/* adding to mutexes */
if (mutexes
== NULL
)
mutexes
= mutnew
;
else
mutexes
->next
= mutnew
;
}
acnew
->mutex
= mutnew
;
/* add mutex to the list of tasks using it */
if (tccur
->mutexlist
== NULL
)
{
tccur
->mutexlist
= mutnew
;
}
else
{
if (in_mutex_list
(tmpval
->strval
, tccur
->mutexlist
))
mutcur
->next
= mutnew
;
}
mutcur
= mutnew
;
/* updating action list */
if (tccur
->actionlist
== NULL
)
tccur
->actionlist
= acnew
;
else
accur
->next
= acnew
;
accur
= acnew
;
break;
case TT_UNLOCKS
:
tmpval
= get_token_from_str
(stream
, size
);
if (tmpval
->type
!= 1)
return -1;
acnew
= (action_list_t
*)kern_alloc
((sizeof(action_list_t
)));
acnew
->type
= UNLOCK
;
acnew
->time = -1;
acnew
->next
= NULL
;
if ( (mutnew
= in_mutex_list
(tmpval
->strval
, tccur
->mutexlist
)) == NULL
)
{
#ifdef DEBUG
cprintf
("Mutex %s unlocked but never locked\n", tmpval
->strval
);
#endif
return -1;
}
acnew
->mutex
= mutnew
;
if (tccur
->actionlist
== NULL
)
tccur
->actionlist
= acnew
;
else
accur
->next
= acnew
;
accur
= acnew
;
break;
case TT_ID
:
dprint_value
(curval
);
break;
case TT_INT
:
dprint_value
(curval
);
break;
case TT_INVALID
:
break;
}
curval
= get_token_from_str
(stream
, size
);
}
return 0;
}
void print_taskconf
(taskconf_list_t
*tc
)
{
action_list_t
*action
;
mutex_list_t
*mutex
;
if (tc
== NULL
)
return;
cprintf
("Task: %s, period %ld, wcet %ld\n", tc
->name
, tc
->period
, tc
->wcet
);
cprintf
("Actions:\n");
action
= tc
->actionlist
;
while (action
)
{
cprintf
("---Type %d, time %d, mutex %s\n", action
->type
, action
->time, (action
->mutex
== NULL
? "" : action
->mutex
->name
));
action
= action
->next
;
}
cprintf
("Mutex used:\n");
mutex
= tc
->mutexlist
;
while (mutex
)
{
cprintf
("---Name %s, Color %d\n", mutex
->name
, mutex
->color
);
mutex
= mutex
->next
;
}
print_taskconf
(tc
->next
);
}