Blame |
Last modification |
View Log
| RSS feed
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
/**
------------
CVS : $Id: step2.c,v 1.1 2004-07-05 14:17:15 pj Exp $
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2004-07-05 14:17:15 $
------------
**/
/*
* Copyright (C) 2000 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "kernel/kern.h"
#include "string.h"
#include "ll/i386/x-dos.h"
#include "modules/rr.h"
#include "modules/dummy.h"
#include "modules/edf.h"
#include "modules/sem.h"
#include "modules/hartport.h"
#include "drivers/keyb.h"
#include "ctype.h"
#include "tune.h"
int ending
=0;
// Patterns
#define MAX_PATTERN 10000
int max_pattern
= 0;
TIME pattern_t
[MAX_PATTERN
];
TIME pattern_period
[MAX_PATTERN
];
TIME pattern_wcet
[MAX_PATTERN
];
TIME pattern_iter
[MAX_PATTERN
];
void record_pattern
(TIME t
, TIME period
, TIME wcet
)
{
pattern_t
[max_pattern
] = t
;
pattern_period
[max_pattern
] = period
;
pattern_wcet
[max_pattern
] = wcet
;
max_pattern
++;
}
#define WCET_SLACK 500
void tune_pattern
(void)
{
int i
,w
;
for (i
=0; i
<max_pattern
; i
++) {
w
= (pattern_wcet
[i
]*80)/100-WCET_SLACK
;
// if (w>pattern_wcet[i]-WCET_SLACK) w=pattern_wcet[i]-WCET_SLACK;
pattern_iter
[i
] = tune_CPU_speed
(w
);
}
}
// Shape modification
#define DEFAULT_SHIFT 1000000
#define MAX_SHAPE 1000
bandwidth_t shape
=0; // current shape threshold
int current_shape
= 0;
bandwidth_t shape_B
[MAX_SHAPE
];
TIME shape_T
[MAX_SHAPE
];
int max_shape
;
void shape_event
(void *arg
)
{
struct timespec t
;
shape
= shape_B
[current_shape
];
current_shape
++;
if (current_shape
== max_shape
)
ending
= 1;
NULL_TIMESPEC
(&t
);
ADDUSEC2TIMESPEC
((shape_T
[current_shape
]*1000000+DEFAULT_SHIFT
),&t
);
// cprintf("At Time=%10ld.%10ld T=%10d Shape=%10d\n",t.tv_sec,t.tv_nsec,
// shape_T[current_shape],shape_B[current_shape]);
kern_event_post
(&t
,shape_event
,NULL
);
}
void start_shape
(void)
{
struct timespec t
;
NULL_TIMESPEC
(&t
);
ADDUSEC2TIMESPEC
(DEFAULT_SHIFT
,&t
);
kern_cli
();
kern_event_post
(&t
,shape_event
,NULL
);
kern_sti
();
}
// Hard task
#define ASTER_LIM 80
void *hard_task
(void *arg
)
{
int j
, x
, y
;
char s
[2];
x
= 0;
y
= rand() % 6 + 3;
s
[0] = '*'; s
[1] = 0;
while (x
< ASTER_LIM
) {
for (j
=0; j
<50; j
++) {
s
[0] = '*' + rand() % 100;
puts_xy
(x
,y
,rand()%15+1,s
);
}
task_endcycle
();
puts_xy
(x
,y
,WHITE
," ");
x
++;
}
return (void *)0;
}
#define MAX_PERIOD 100
// Load creation
void *create_load
(void *arg
)
{
PID p
;
HARD_TASK_MODEL m
;
TIME period
= 0;
TIME wcet
= 0;
int x
; // adaptive bandwidth...
int counter
=0;
char buf
[100];
hard_task_default_model
(m
);
x
= MAX_PERIOD
/3;
place
(0,11);
// waiting for the start time :-)
while (sys_gettime
(NULL
)<DEFAULT_SHIFT
);
while (1) {
sprintf(buf
,"Shape: %5.3f Band: %5.3f period: %10ld wcet: %10ld Time: %d",
(double)shape
/(double)MAX_BANDWIDTH
,
(double)EDF_usedbandwidth
(0)/(double)MAX_BANDWIDTH
,
period
, wcet
, sys_gettime
(NULL
)/1000000);
puts_xy
(0,10,WHITE
,buf
);
period
= (x
+rand() % (MAX_PERIOD
-x
+1))*1000;
wcet
= rand()%1000 * (period
/1500);
if ((MAX_BANDWIDTH
/period
)*wcet
> shape
- EDF_usedbandwidth
(0))
wcet
= (shape
- EDF_usedbandwidth
(0))/period
;
if (wcet
< period
/40) wcet
=period
/40;
if (wcet
< 500) wcet
=500;
if (EDF_usedbandwidth
(0) + (MAX_BANDWIDTH
/period
)*wcet
< shape
) {
hard_task_def_mit
(m
, period
);
hard_task_def_wcet
(m
, wcet
);
p
= task_create
("hard_task",hard_task
,&m
,NULL
);
if (p
== -1) {
x
+= rand()%10-4;
}
else {
record_pattern
(sys_gettime
(NULL
),period
,wcet
);
cprintf
("%d ",++counter
);
task_activate
(p
);
x
*= 3;
x
/= 4;
}
if (x
<MAX_PERIOD
/3) x
= MAX_PERIOD
/3;
if (x
> MAX_PERIOD
) x
= MAX_PERIOD
;
}
if (ending
) return (void *)0;
}
}
// Read/Write part
#define FILEBUF_DIM 10000
/* This is the buffer used by read_myfile */
char myfilebuf
[FILEBUF_DIM
];
/* This is the number of bytes read by read_myfile */
int myfilebuf_length
;
/* the buffer b is scannedc to search for numbers
at the first non-number the function stops */
int geti
(char *b
, int *pos
, int maxpos
)
{
int res
= 0;
// skip first chars
while (!isdigit(b
[*pos
])) {
(*pos
)++;
if (*pos
== maxpos
) return -1; // Error!!!
}
// read the numbers
do {
res
= (res
* 10) + b
[*pos
] - '0';
(*pos
)++;
} while (isdigit(b
[*pos
]));
return res
;
}
void parse_shape
(void)
{
int curr_filepos
= 0;
int i
= 0;
// read the number of tasks into the data file
max_shape
= geti
(myfilebuf
, &curr_filepos
, myfilebuf_length
);
if (max_shape
== -1) {
cprintf
("Error parsing shape.dat file...\n");
sys_end
();
}
for (i
=0; i
<max_shape
; i
++) {
// read the seven datas
shape_T
[i
] = geti
(myfilebuf
, &curr_filepos
, myfilebuf_length
);
shape_B
[i
] = geti
(myfilebuf
, &curr_filepos
, myfilebuf_length
);
// check the last one for an error
if (shape_B
[i
] == -1) {
cprintf
("Error parsing shape %d...\n",i
);
sys_end
();
}
}
}
void read_shapes
(void)
{
char name
[]="shape.dat";
/* DOS file descriptor */
DOS_FILE
*f
;
/* Error code */
int err
;
/* open the DOS file for reading (you can specify only "r" or "w") */
f
= DOS_fopen
(name
,"r");
/* check for open errors */
if (!f
) {
/* error!! */
err
= DOS_error
();
/* note that if you call DOS_error() here, it return 0!!! */
cprintf
("Error %d opening %s...\n", err
, name
);
myfilebuf_length
= 0;
return;
}
/* read up to 1000 chars */
myfilebuf_length
= DOS_fread
(&myfilebuf
,1,FILEBUF_DIM
,f
);
/* check for errors */
err
= DOS_error
();
cprintf
("Read %d bytes from %s...\n", myfilebuf_length
, name
);
if (err
) {
cprintf
("Error %d reading %s...\n", err
, name
);
myfilebuf_length
= 0;
/* there is not return because I want to close the file! */
}
/* Close the file */
DOS_fclose
(f
);
}
/* This function write myfile.out (up to 30 chars) */
void write_hpattern
(void *arg
)
{
DOS_FILE
*f
; /* DOS file descriptor */
int err
=0; /* Error code */
int writtenbytes
= 0; /* number of files written */
char buf
[100];
int i
;
/* open the DOS file for writing (you can specify only "r" or "w") */
f
= DOS_fopen
("hpattern.dat","w");
/* check for open errors */
if (!f
) {
/* error!! */
err
= DOS_error
();
/* note that if you call DOS_error() here, it return 0!!! */
cprintf
("Error %d opening hpattern.dat...\n", err
);
return;
}
sprintf(buf
,"%d\r\n",max_pattern
);
writtenbytes
+= DOS_fwrite
(buf
,1,strlen(buf
),f
);
for (i
=0; i
<max_pattern
; i
++) {
sprintf(buf
,"%ld %ld %ld %ld\r\n", pattern_t
[i
], pattern_period
[i
],
pattern_wcet
[i
], pattern_iter
[i
]);
writtenbytes
+= DOS_fwrite
(buf
,1,strlen(buf
),f
);
/* check for errors */
err
= DOS_error
();
if (err
) break;
}
cprintf
("Written %d bytes into hpattern.dat...\n", writtenbytes
);
if (err
) {
cprintf
("Error %d writing hpattern.dat...\n", err
);
/* there is not return because I want to close the file! */
}
/* Close the file */
DOS_fclose
(f
);
}
/*+ sysyem tick in us +*/
#define TICK 0
/*+ RR tick in us +*/
#define RRTICK 10000
void read_myfile
(void);
TIME __kernel_register_levels__
(void *arg
)
{
struct multiboot_info
*mb
= (struct multiboot_info
*)arg
;
EDF_register_level
(EDF_ENABLE_ALL
);
RR_register_level
(RRTICK
, RR_MAIN_NO
, mb
);
RR_register_level
(RRTICK
, RR_MAIN_YES
, mb
);
dummy_register_level
();
SEM_register_module
();
read_shapes
();
return TICK
;
}
NRT_TASK_MODEL keyb_model
;
TASK __init__
(void *arg
)
{
NRT_TASK_MODEL nrt
;
KEYB_PARMS kparms
= BASE_KEYB
;
HARTPORT_init
();
nrt_task_default_model
(keyb_model
);
nrt_task_def_system
(keyb_model
);
nrt_task_def_nokill
(keyb_model
);
keyb_def_task
(kparms
,(TASK_MODEL
*)&keyb_model
);
KEYB_init
(&kparms
);
set_exchandler_grx
();
nrt_task_default_model
(nrt
);
srand(sys_gettime
(NULL
));
clear
();
sys_atrunlevel
(write_hpattern
, NULL
, RUNLEVEL_AFTER_EXIT
);
parse_shape
();
start_shape
();
task_activate
(task_create
("create_load",create_load
,&nrt
,NULL
));
cputs
("\nWaiting the end of the periodic tasks...\n");
while (task_counter
!= 1);
// the task create_load preempt __init__ until all is finished!
tune_pattern
();
return (void *)0;
}
// never called!!!
int main
()
{
return 0;
}