Blame |
Last modification |
View Log
| RSS feed
/*
* Project: HARTIK (HA-rd R-eal TI-me K-ernel)
*
* Coordinators: Giorgio Buttazzo <giorgio@sssup.it>
* Gerardo Lamastra <gerardo@sssup.it>
*
* Authors : Massimiliano Giorgi <massy@hartik.sssup.it>
* (see authors.txt for full list of hartik's authors)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://hartik.sssup.it
*/
/*
* Copyright (C) 2000 Massimiliano Giorgi
*
* 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
*
*/
/*
* CVS : $Id: trace.c,v 1.1.1.1 2002-03-29 14:12:53 pj Exp $
*
* File: $File$
* Revision: $Revision: 1.1.1.1 $
* Last update: $Date: 2002-03-29 14:12:53 $
*/
#include <ll/sys/types.h>
#include <kernel/assert.h>
#include <kernel/func.h>
#include <kernel/log.h>
#include <kernel/trace.h>
#include <modules/trace.h>
#include <modules/traceevt.h>
#include <modules/tracestr.h>
/* Well...
* TRC_init2() and tracer() must be called when the system is up,
* so they can call functions of the unistd.h
*/
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
/* -- */
/*+ number of event per blocks +*/
#define TRC_BLOCKSIZE 1024
/*+ numbers of tables can grow until this is raggiunto +*/
#define TRC_MAXNUMTABLES 48
/* -- */
#define DEBUG_INIT KERN_DEBUG
//#undef DEBUGINIT
#ifdef DEBUG_INIT
#define printk0(fmt,args...) printk(DEBUG_INIT fmt,##args)
#else
#define printk0(fmt,args...)
#endif
/* -- */
static __inline__
void *allocmemory
(long size
)
{
SYS_FLAGS f
;
void *ptr
;
f
=kern_fsave
();
ptr
=kern_alloc
(size
+sizeof(long));
kern_frestore
(f
);
if (ptr
!=NULL
) {
*((long*)ptr
)=size
;
return (char *)ptr
+sizeof(long);
}
return ptr
;
}
static __inline__
void freememory
(void *ptr
)
{
SYS_FLAGS f
;
long size
;
size
=*(long*)((char *)ptr
-sizeof(long));
f
=kern_fsave
();
kern_free
(ptr
-sizeof(long),size
+sizeof(long));
kern_frestore
(f
);
}
/* -- */
typedef struct TAGtrc_events
{
struct TAGtrc_events
*next
;
trc_event_t event
[TRC_BLOCKSIZE
] __attribute__
((packed
));
} trc_events
;
static int counter
;
static int hoops
;
static trc_events
*acttable
,*writable
;
static int actindex
,wriindex
;
static int handle
=-1;
static int numtables
;
static TASK tracer
(void *dummy
)
{
int index
,n
,res
;
res
=0;
for (;;) {
while (counter
>0) {
kern_cli
();
if (acttable
!=writable
) {
kern_sti
();
n
=TRC_BLOCKSIZE
-wriindex
;
res
=write
(handle
,writable
->event
+wriindex
,n
*sizeof(trc_event_t
));
writable
=writable
->next
;
wriindex
=0;
} else {
index
=actindex
;
kern_sti
();
n
=index
-wriindex
;
assertk
(n
>0);
res
=write
(handle
,writable
->event
+wriindex
,n
*sizeof(trc_event_t
));
wriindex
=index
;
}
if (res
!=n
*sizeof(trc_event_t
)) {
res
=-1;
break;
}
counter
-=n
;
assertk
(counter
>=0);
}
/* errors trap */
if (res
==-1) {
SYS_FLAGS f
;
f
=kern_fsave
();
printk
(KERN_ERR
"tracer task write error!");
kern_frestore
(f
);
for (;;) task_endcycle
();
}
task_endcycle
();
}
}
static TRACE_PARMS defparms
=BASE_TRACE
;
static TRACE_PARMS
*myparms
=&defparms
;
static void internal_trc_logevent
(PID pid
, int event
, void *ptr
, int size
);
int TRC_init_phase1
(TRACE_PARMS
*inparms
)
{
trc_events
*nexttable
;
printk0
("tracer init: START phase1");
acttable
=allocmemory
(sizeof(trc_events
));
if (acttable
==NULL
) goto ERROR
;
printk0
("tracer init: first table created");
nexttable
=allocmemory
(sizeof(trc_events
));
if (nexttable
==NULL
) {
freememory
(acttable
);
acttable
=NULL
;
goto ERROR
;
}
printk0
("tracer init: second table created");
acttable
->next
=nexttable
;
nexttable
->next
=acttable
;
actindex
=0;
writable
=acttable
;
wriindex
=0;
counter
=0;
hoops
=0;
numtables
=2;
printk0
("tracer init: internal variables initialized");
if (inparms
!=NULL
) myparms
=inparms
;
trc_resume
();
printk0
("tracer init: END phase 1 (tracer started)");
return 0;
ERROR
:
printk
(KERN_ERR
"tracer initialization fails!");
return -1;
}
static void TRC_end
(void *dummy
);
int TRC_init_phase2
(void)
{
trc_event_t event
;
SOFT_TASK_MODEL model
;
int res
;
PID pid
;
printk0
("tracer init: START phase 2");
/* for safety */
if (acttable
==NULL
) return -1;
printk0
("tracer init: safety test passed");
handle
=open
(myparms
->filename
,O_CREAT
|O_TRUNC
|O_WRONLY
);
if (handle
==-1) goto ERROR
;
printk0
("tracer init: file opened");
event.
size=sizeof(trc_event_t
);
event.
what=TRC_INITLOG
;
event.
x.
id=TRC_INITID
;
//cprintf("size=====%li\n",sizeof(trc_event_t));
res
=write
(handle
,&event
,sizeof(trc_event_t
));
if (res
!=sizeof(trc_event_t
)) goto ERROR
;
printk0
("tracer init: write");
soft_task_default_model
(model
);
soft_task_def_system
(model
);
soft_task_def_notrace
(model
);
soft_task_def_periodic
(model
);
soft_task_def_period
(model
,myparms
->period
);
soft_task_def_met
(model
,myparms
->slice
);
soft_task_def_wcet
(model
,myparms
->slice
);
pid
=task_create
("sysTracer",tracer
,&model
,NULL
);
if (pid
==-1) goto ERROR
;
task_activate
(pid
);
printk0
("tracer init: tracer task created and activated");
//sys_atexit(TRC_end,(void*)handle,BEFORE_EXIT);
printk0
("tracer init: END phase 2");
printk
(KERN_NOTICE
"tracer started!");
return 0;
ERROR
:
kern_cli
();
freememory
(acttable
->next
);
freememory
(acttable
);
acttable
=NULL
;
kern_sti
();
if (handle
!=-1) close
(handle
);
printk
(KERN_ERR
"tracer initialization fails (%s)!",strerror(errno
));
return -1;
}
static void (*old_logevent
)(PID pid
, int event
, void *ptr
, int size
)=NULL
;
int trc_resume
(void)
{
SYS_FLAGS f
;
int ret
=-1;
f
=kern_fsave
();
if (acttable
!=NULL
&&old_logevent
==NULL
) {
old_logevent
=trc_logevent
;
trc_logevent
=internal_trc_logevent
;
ret
=0;
}
kern_frestore
(f
);
return ret
;
}
int trc_suspend
(void)
{
SYS_FLAGS f
;
int ret
=-1;
f
=kern_fsave
();
if (acttable
!=NULL
&&old_logevent
!=NULL
) {
trc_logevent
=old_logevent
;
old_logevent
=NULL
;
ret
=0;
}
kern_frestore
(f
);
return 0;
}
static void TRC_end
(void *dummy
)
{
printk
(KERN_INFO
"shuting down tracer...");
trc_suspend
();
if (counter
>0) {
/* wait a bit for flushing events queue */
int x
=30;
while (counter
>0) {
cprintf
("<%li>",(long)counter
);
task_delay
(100000); // 100msec
if (x
--==0) break;
}
}
close
(handle
);
printk
(KERN_DEBUG
"tracer hoops: %5i",hoops
);
printk
(KERN_DEBUG
"tracer numtables: %5i",numtables
);
}
static trc_event_t
*getrecord
(void)
{
trc_events
*newtable
;
trc_event_t
*event
;
event
=&acttable
->event
[actindex
];
actindex
++;
if (actindex
==TRC_BLOCKSIZE
) {
actindex
=0;
if (acttable
->next
==writable
) {
if (numtables
==TRC_MAXNUMTABLES
) {
hoops
++;
actindex
=TRC_BLOCKSIZE
-1;
return NULL
;
}
newtable
=allocmemory
(sizeof(trc_events
));
if (newtable
==NULL
) {
hoops
++;
actindex
=TRC_BLOCKSIZE
-1;
return NULL
;
}
newtable
->next
=acttable
->next
;
acttable
->next
=newtable
;
acttable
=newtable
;
numtables
++;
}
else acttable
=acttable
->next
;
}
return event
;
}
static void internal_trc_logevent
(int event
, PID pid
, void *ptr
, int size
)
{
SYS_FLAGS f
;
trc_event_t
*evt
;
if (acttable
==NULL
) return;
f
=kern_fsave
();
evt
=getrecord
();
if (evt
!=NULL
) {
evt
->size
=sizeof(trc_event_t
);
evt
->what
=event
;
if ((event
&0xff00)==(TRC_USR_EVENTS
<<8)) {
evt
->x.
user.
when=ll_gettime
(TIME_EXACT
,NULL
);
evt
->x.
user.
who=(pid
==TRC_NOPID
?exec_shadow
:pid
);
if (ptr
!=NULL
) memcpy(&evt
->x.
user.
info,ptr
,TRC_MAXUSERINFO
);
} else
switch (event
) {
case TRC_TASKNAME
:
evt
->x.
tskname.
who=pid
;
memcpy(&evt
->x.
tskname.
name,ptr
,TRC_MAXNAMESIZE
);
break;
case TRC_SCHEDULE
:
evt
->x.
sched.
when=ll_gettime
(TIME_EXACT
,NULL
);
memcpy(&evt
->x.
sched.
info,ptr
,sizeof(trc_schedule_t
));
break;
default:
evt
->x.
norm.
when=ll_gettime
(TIME_EXACT
,NULL
);
evt
->x.
norm.
who=pid
;
break;
}
counter
++;
}
kern_frestore
(f
);
return;
}