Subversion Repositories shark

Compare Revisions

Ignore whitespace Rev 354 → Rev 353

/shark/trunk/kernel/modules/trace.c
0,0 → 1,438
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* Massimiliano Giorgi <massy@gandalf.sssup.it>
* Luca Abeni <luca@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
*/
 
/*
* Copyright (C) 1999 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.3 2003-01-07 17:07:51 pj Exp $
*
* File: $File$
* Revision: $Revision: 1.3 $
* Last update: $Date: 2003-01-07 17:07:51 $
*/
 
#include <ll/sys/types.h>
#include <ll/stdlib.h>
#include <ll/string.h>
 
#include <kernel/func.h>
#include <kernel/trace.h>
 
#include <trace/types.h>
#include <trace/trace.h>
#include <trace/queues.h>
 
#include <bits/limits.h>
 
/* maximum number of different queues where we want to log our events */
#define TRC_MAXQUEUES 5
 
/*
*
*/
 
/* this is the base path that is used as a prologue for all the
filenames that are passed to the tracer */
static char basepath[PATH_MAX];
 
/* used to create the name for a tracer file */
void trc_create_name(char *basename, int uniq, char *pathname)
{
if (uniq) sprintf(pathname,"%s/%s%i",basepath,basename,uniq);
else sprintf(pathname,"%s/%s",basepath,basename);
}
 
/*
*
*/
 
/* the flag used to discriminate if an event have to be traced or not */
#define FLAG_NOTRACE 0x01
 
typedef struct TAGtrc_evtinfo_t {
trc_queue_t *queue; /* the queue responsible for the logging of an event */
unsigned flags; /* if = FLAG_NOTRACE the event must not be logged */
} trc_evtinfo_t;
 
/* -- */
 
/* one entry for each event; this array says for each event the queue to use
and if it must be logged */
trc_evtinfo_t eventstable[TRC_NUMEVENTS];
 
/* For each kind of queue (see include/tracer/queues.h) there is a set of
pointers to the functions that a queue should implement */
int (*createqueue[TRC_QUEUETYPESNUMBER])(trc_queue_t *, void *);
int (*activatequeue[TRC_QUEUETYPESNUMBER])(void *,int);
int (*terminatequeue[TRC_QUEUETYPESNUMBER])(void *);
 
/* for each queue registered in the system,
the functions used to get/post an event
The elements of this table are initialized with calls to createqueue[type]()
(see include/trace/queues.h) */
trc_queue_t queuetable[TRC_MAXQUEUES];
 
/* initialized as a dummy queue, the default value of all the queues */
trc_queue_t queuesink;
 
/* number of registered queues in the system */
int numqueues;
 
/* -- */
 
/* The Dummy queue */
 
static trc_event_t *dummy_get(void *foo)
{
return NULL;
}
 
static int dummy_post(void *foo)
{
return 0;
}
 
static int dummy_createqueue(trc_queue_t *queue, void *unused)
{
queue->get=dummy_get;
queue->post=dummy_post;
queue->data=NULL;
return 0;
}
 
static int dummy_terminatequeue(void *unused)
{
return 0;
}
 
static int dummy_activatequeue(void *unused, int unused2)
{
return 0;
}
 
/* -- */
 
/* this function simply register the functions that are used to
handle a queue */
int trc_register_queuetype(int queuetype,
int(*creat)(trc_queue_t *, void *),
int(*activate)(void *,int),
int(*term)(void *))
{
if (queuetype<0||queuetype>=TRC_QUEUETYPESNUMBER) return -1;
createqueue[queuetype]=creat;
activatequeue[queuetype]=activate;
terminatequeue[queuetype]=term;
return 0;
}
 
/* this function register a queue in the system.
It uses the type to access to the queue handling functions registered
with the previous function (trc_register_queuetype)
numqueue is incremented!
*/
int trc_create_queue(int queuetype, void *args)
{
int res;
 
if (createqueue[queuetype]==dummy_createqueue) return -1;
if (numqueues==TRC_MAXQUEUES) return -1;
res=createqueue[queuetype](&queuetable[numqueues],args);
if (res) return -1;
queuetable[numqueues].type=queuetype;
numqueues++;
return numqueues-1;
}
 
/* -- */
 
static void (*old_logevent)(int event, void *ptr)=NULL;
static void internal_trc_logevent(int, void *ptr);
 
static void trc_end(void *unused)
{
int i;
printk(KERN_INFO "tracer shutdown...");
/* suspend event logging */
trc_suspend();
 
/* for safety: send all events to the sink queue */
for (i=0;i<TRC_NUMEVENTS;i++) {
eventstable[i].queue=&queuesink;
eventstable[i].flags|=FLAG_NOTRACE;
}
/* terminate all queues */
for (i=0;i<numqueues;i++)
terminatequeue[queuetable[i].type](queuetable[i].data);
}
 
static int internal_trc_resume(void);
static int internal_trc_suspend(void);
 
int TRC_init_phase1(TRC_PARMS *parms)
{
int i;
printk(KERN_INFO "initializing tracer...");
/* all the queues are initialized to the dummy queue (sink!) */
for (i=0;i<TRC_QUEUETYPESNUMBER;i++) {
createqueue[i]=dummy_createqueue;
terminatequeue[i]=dummy_terminatequeue;
}
/* the sink queue is initialized */
dummy_createqueue(&queuesink,NULL);
/* no queues registered yet */
numqueues=0;
/* all the events are initialized to put to the sink queue */
for (i=0;i<TRC_NUMEVENTS;i++) {
eventstable[i].queue=&queuesink;
eventstable[i].flags=FLAG_NOTRACE;
}
/* this will end the tracer at shutdown */
i=sys_atrunlevel(trc_end,NULL,RUNLEVEL_SHUTDOWN);
 
/* initialize the parameters if not initialized */
{
TRC_PARMS m;
trc_default_parms(m);
if (parms==NULL) parms=&m;
 
strncpy(basepath,parms->path,sizeof(basepath));
basepath[sizeof(basepath)-1]='\0';
}
 
trc_suspend=internal_trc_suspend;
trc_resume=internal_trc_resume;
/* start the tracer */
trc_resume();
return 0;
}
 
/* this function simply activates all the registered queues.
This is usually called into the init() tasks!!! */
int TRC_init_phase2(void)
{
int i;
for (i=0;i<numqueues;i++)
activatequeue[queuetable[i].type](queuetable[i].data,i+1);
return 0;
}
 
/* saves the current logevent function and set it as
the internal_trc_logevent */
static int internal_trc_resume(void)
{
SYS_FLAGS f;
int ret=-1;
f=kern_fsave();
if (old_logevent==NULL) {
old_logevent=trc_logevent;
trc_logevent=internal_trc_logevent;
ret=0;
}
kern_frestore(f);
return ret;
}
 
/* restores the saved logevent function (initially, the logevent function is
a dummy function) */
static int internal_trc_suspend(void)
{
SYS_FLAGS f;
int ret=-1;
f=kern_fsave();
if (old_logevent!=NULL) {
trc_logevent=old_logevent;
old_logevent=NULL;
ret=0;
}
kern_frestore(f);
return 0;
}
 
static void internal_trc_logevent(int event, void *ptr)
{
trc_event_t *evt;
trc_queue_t *queue;
SYS_FLAGS f;
 
/* disables interrupts (this function can be called also into a task */
f=kern_fsave();
 
/* check if the event has to be logged */
if (eventstable[event].flags&FLAG_NOTRACE) {
kern_frestore(f);
return;
}
queue=eventstable[event].queue;
/* gets a free event descriptor, fills it and post it */
evt=queue->get(queue->data);
if (evt!=NULL) {
evt->event=event;
evt->time=kern_gettime(NULL);
memcpy(&evt->x,ptr,sizeof(trc_allevents_t));
queue->post(queue->data);
}
kern_frestore(f);
}
 
/*
*
*
*
*/
 
/* these set of functions can be used to trace or not single event and classes.
They make use of the classtable structure, that is used to discriminate
the indexes occupied by every class */
 
int classtable[TRC_NUMCLASSES+1]={
TRC_F_TRACER,
TRC_F_SYSTEM,
TRC_F_USER,
TRC_F_LL,
TRC_F_SEM,
TRC_F_LAST
};
 
#define checkevent(x) if ((x)<0||(x)>=TRC_NUMEVENTS) return -1
#define checkqueue(x) if ((x)<0||(x)>=numqueues) return -1
#define checkclass(x) if ((x)<0||(x)>=TRC_NUMCLASSES) return -1
 
int trc_assign_event_to_queue(int event, int queue)
{
checkevent(event);
checkqueue(queue);
eventstable[event].queue=&queuetable[queue];
return 0;
}
 
int trc_assign_class_to_queue(int class, int queue)
{
int i;
checkqueue(queue);
checkclass(class);
for (i=classtable[class];i<classtable[class+1];i++)
eventstable[i].queue=&queuetable[queue];
return 0;
}
 
int trc_notrace_event(int event)
{
checkevent(event);
eventstable[event].flags|=FLAG_NOTRACE;
return 0;
}
 
int trc_trace_event(int event)
{
checkevent(event);
eventstable[event].flags&=~FLAG_NOTRACE;
return 0;
}
 
int trc_notrace_class(int class)
{
int i;
checkclass(class);
for (i=classtable[class];i<classtable[class+1];i++)
eventstable[i].flags|=FLAG_NOTRACE;
return 0;
}
 
int trc_trace_class(int class)
{
int i;
checkclass(class);
for (i=classtable[class];i<classtable[class+1];i++)
eventstable[i].flags&=~FLAG_NOTRACE;
return 0;
}
 
 
/* -- */
 
int TRC_init_phase1_standard(void)
{
int qf,qc;
int res;
 
/* initialize the trace */
res=TRC_init_phase1(NULL);
if (res) return res;
 
/* register two kinds of queues, fixed and circular */
res=trc_register_circular_queue();
if (res) return res;
res=trc_register_fixed_queue();
if (res) return res;
 
/* creates two queues:
a circular queue for the system events,
a fixed queue
*/
qc=trc_create_queue(TRC_CIRCULAR_QUEUE,NULL);
qf=trc_create_queue(TRC_FIXED_QUEUE,NULL);
if (qc==-1||qf==-1) return -97;
 
/* We want to trace all the system events */
res=trc_trace_class(TRC_CLASS_SYSTEM);
if (res) return res;
/* All the system events must be traced into the circular queue */
res=trc_assign_class_to_queue(TRC_CLASS_SYSTEM,qc);
if (res) return res;
 
return 0;
}
 
int TRC_init_phase2_standard(void)
{
return TRC_init_phase2();
}
 
 
/shark/trunk/kernel/modules/trcfixed.c
0,0 → 1,171
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Massimiliano Giorgi <massy@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
*/
 
#include <ll/sys/types.h>
#include <ll/stdlib.h>
 
#include <kernel/func.h>
#include <kernel/mem.h>
#include <kernel/log.h>
 
#include <trace/types.h>
#include <trace/trace.h>
#include <trace/queues.h>
 
#include <fs/fs.h>
 
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
 
/* this file implement a fixed queue, that is simply an array that
is filled with the events until it is full. After that, all the other
events are discarded. */
 
 
 
 
typedef struct TAGfixed_queue_t {
int size;
int index;
char *filename;
int uniq;
trc_event_t table[0];
/* Yes, 0!... the elements are allocated
in a dirty way into the kern_alloc into fixed_create */
} fixed_queue_t;
 
/* This function simply return an event to fill (only if the fixed table
is not yet full) */
static trc_event_t *fixed_get(fixed_queue_t *queue)
{
if (queue->index>=queue->size) return NULL;
return &queue->table[queue->index++];
}
 
/* since get returns the correct event address,
the post function does nothing... */
static int fixed_post(fixed_queue_t *queue)
{
return 0;
}
 
static TRC_FIXED_PARMS defaultargs;
static int once=0;
 
static int fixed_create(trc_queue_t *queue, TRC_FIXED_PARMS *args)
{
fixed_queue_t *ptr;
 
/* initialize the default arguments for the fixed queue */
if (!once) {
/* well... this func is called when the system is not running! */
once=1;
trc_fixed_default_parms(defaultargs);
}
if (args==NULL) args=&defaultargs;
/* allocate the fixed queue data structure plus the array of events */
ptr=(fixed_queue_t*)kern_alloc(sizeof(fixed_queue_t)+
sizeof(trc_event_t)*(args->size+1));
if (ptr==NULL) return -1;
 
/* set the current queue pointers and data */
queue->get=(trc_event_t*(*)(void*))fixed_get;
queue->post=(int(*)(void*))fixed_post;
queue->data=ptr;
 
ptr->size=args->size;
ptr->index=0;
ptr->filename=args->filename;
return 0;
}
 
static TASK fixed_shutdown(fixed_queue_t *queue)
{
char pathname[PATH_MAX];
int h;
printk(KERN_DEBUG "<fixed queuesize:%i>",queue->index);
 
if (queue->filename==NULL) trc_create_name("fix",queue->uniq,pathname);
else trc_create_name(queue->filename,0,pathname);
 
h=open("/TEMP/FIX1",O_CREAT|O_TRUNC|O_WRONLY);
if (h!=-1) {
write(h,queue->table,queue->index*sizeof(trc_event_t));
close(h);
printk(KERN_NOTICE "tracer file %s created!",pathname);
} else {
printk(KERN_NOTICE "tracer file %s not created!",pathname);
}
resume_fs_shutdown();
return NULL;
}
 
static int fixed_activate(fixed_queue_t *queue, int uniq)
{
queue->uniq=uniq;
return 0;
}
 
static int fixed_terminate(fixed_queue_t *queue)
{
SOFT_TASK_MODEL model;
PID pid;
 
suspend_fs_shutdown();
//nrt_task_default_model(model);
//nrt_task_def_system(model);
//nrt_task_def_arg(model,queue);
 
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,50000);
soft_task_def_met(model,10000);
soft_task_def_wcet(model,10000);
soft_task_def_arg(model,queue);
pid=task_create("ShutTrcFix",fixed_shutdown,&model,NULL);
if (pid==-1) {
printk(KERN_ERR "can't start tracer shutdown task (fixed)");
return -1;
} else
task_activate(pid);
 
return 0;
}
 
int trc_register_fixed_queue(void)
{
int res;
res=trc_register_queuetype(TRC_FIXED_QUEUE,
(int(*)(trc_queue_t*,void*))fixed_create,
(int(*)(void*,int))fixed_activate,
(int(*)(void*))fixed_terminate
);
if (res!=0) printk(KERN_WARNING "can't register tracer fixed queue");
return res;
}
/shark/trunk/kernel/modules/trcudp.c
0,0 → 1,261
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* Massimiliano Giorgi <massy@gandalf.sssup.it>
* Luca Abeni <luca@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
*/
 
/*
* Copyright (C) 2002 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
*
* CVS : $Id: trcudp.c,v 1.3 2002-10-28 10:11:38 pj Exp $
*/
 
#include <ll/sys/types.h>
#include <ll/stdlib.h>
 
#include <kernel/func.h>
#include <kernel/mem.h>
#include <kernel/log.h>
 
#include <trace/types.h>
#include <trace/trace.h>
#include <trace/queues.h>
 
//#define DEBUG_TRCUDP
 
#define TRCUDP_MAXEVENTS (1500/sizeof(trc_event_t))
//#define TRCUDP_MAXEVENTS 10
 
/* Well... this file is very similar to trccirc.c! */
 
typedef struct TAGtrcudp_queue_t {
/*+ size of the queue +*/
int size;
/*+ index of the next insertion into the queue +*/
int index;
/*+ index of the next item to write (if online_tracer activated) +*/
int windex;
/*+ number of events lost (if online_tracer activated) +*/
long hoops;
/*+ local and remote IP numbers +*/
UDP_ADDR local, remote;
/*+ unique number that identify the queue +*/
int uniq;
/*+ =1 when the system shuts down +*/
int mustgodown;
TASK_MODEL *m;
/*+ dummy, needed for creating a valid packet (dirty trick ;-) +*/
short int dummy;
/*+ events table +*/
trc_event_t table[0];
} trcudp_queue_t;
 
static TASK online_tracer(trcudp_queue_t *queue)
{
int s; /* the socket */
int newwindex; /* new write index after sending the packet */
int n; /* number of packets to send */
short int *pkt;
 
 
s = udp_bind(&queue->local, NULL);
for (;;) {
if (queue->index<queue->windex) {
if (queue->windex+TRCUDP_MAXEVENTS < queue->size) {
newwindex = queue->windex+TRCUDP_MAXEVENTS;
n = TRCUDP_MAXEVENTS;
} else {
newwindex = 0;
n = queue->size-queue->windex;
}
} else {
if (queue->windex+TRCUDP_MAXEVENTS < queue->index) {
newwindex = queue->windex+TRCUDP_MAXEVENTS;
n = TRCUDP_MAXEVENTS;
} else {
newwindex = queue->index;
n = queue->index-queue->windex;
}
}
if (n) {
/* set the number of events into the UDP packet. It works
because the event entry before windex is always empty, or
because we use the dummy field into the struct */
pkt = ((short int *)(queue->table+queue->windex))-1;
*pkt = (short int)n;
udp_sendto(s,(char *)pkt,
n*sizeof(trc_event_t)+2,&queue->remote);
#ifdef DEBUG_TRCUDP
printk(KERN_DEBUG "UDP: SEND %d events,"
" index %d windex %d new %d!!!\n",n,
queue->index, queue->windex, newwindex);
#endif
queue->windex = newwindex;
}
if (queue->mustgodown) {
if (queue->windex == queue->index)
break;
}
else
task_endcycle();
}
 
return NULL;
}
 
 
static trc_event_t *trcudp_get(trcudp_queue_t *queue)
{
if (queue->mustgodown)
return NULL;
 
if (queue->index==queue->size-1) {
if (queue->windex==0) {
queue->hoops++;
return NULL;
}
queue->index=0;
return &queue->table[queue->size-1];
}
if (queue->index+1==queue->windex) {
queue->hoops++;
return NULL;
}
return &queue->table[queue->index++];
}
 
static int trcudp_post(trcudp_queue_t *queue)
{
return 0;
}
 
static void trcudp_shutdown(trcudp_queue_t *queue);
 
static int trcudp_create(trc_queue_t *p, TRC_UDP_PARMS *args)
{
trcudp_queue_t *queue;
 
if (args==NULL) {
printk(KERN_ERR "trcudp_create: you must specify a non-NULL parameter!");
return -1;
}
queue=(trcudp_queue_t*)kern_alloc(sizeof(trcudp_queue_t)+
sizeof(trc_event_t)*args->size);
if (queue==NULL) {
printk(KERN_ERR "trcudp_create: error during memory allocation!");
return -1;
}
 
p->get=(trc_event_t*(*)(void*))trcudp_get;
p->post=(int(*)(void*))trcudp_post;
p->data=queue;
queue->size=args->size;
queue->windex=queue->index=0;
queue->hoops=0;
queue->local=args->local;
queue->remote=args->remote;
/* uniq initialized in trcudp_activate */
queue->mustgodown=0;
queue->m = args->model;
/* dummy unused */
/* AFTER exit because in that way we can hope to be back in text mode... */
sys_atrunlevel((void (*)(void *))trcudp_shutdown, (void *)queue, RUNLEVEL_AFTER_EXIT);
return 0;
}
 
static int trcudp_activate(trcudp_queue_t *queue, int uniq)
{
SOFT_TASK_MODEL model;
TASK_MODEL *m;
PID pid;
 
 
queue->uniq=uniq;
 
if (!queue->m) {
soft_task_default_model(model);
soft_task_def_system(model);
/* soft_task_def_notrace(model); Should we trace the tracer? */
soft_task_def_periodic(model);
soft_task_def_period(model,250000);
soft_task_def_met(model,10000);
soft_task_def_wcet(model,10000);
/* soft_task_def_nokill(model); NOOOOOOO!!!! */
soft_task_def_arg(model,queue);
m = (TASK_MODEL *)&model;
}
else {
m = queue->m;
task_def_arg(*m,queue);
}
 
pid=task_create("trcUDP",online_tracer,m,NULL);
if (pid==-1) {
printk(KERN_ERR "can't start tracer online trcudp trace task");
} else
task_activate(pid);
 
return 0;
}
 
static int trcudp_terminate(trcudp_queue_t *queue)
{
queue->mustgodown = 1;
 
return 0;
}
 
static void trcudp_shutdown(trcudp_queue_t *queue)
{
printk(KERN_NOTICE "tracer: %li events lost into UDP queue %d",
queue->hoops, queue->uniq);
}
 
int trc_register_udp_queue(void)
{
int res;
res=trc_register_queuetype(TRC_UDP_QUEUE,
(int(*)(trc_queue_t*,void*))trcudp_create,
(int(*)(void*,int))trcudp_activate,
(int(*)(void*))trcudp_terminate
);
if (res!=0) printk(KERN_WARNING "can't register tracer trcudp queue");
return res;
}
/shark/trunk/kernel/modules/trcdfix.c
0,0 → 1,152
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Massimiliano Giorgi <massy@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
*/
 
#include <ll/sys/types.h>
#include <ll/stdlib.h>
 
#include <kernel/func.h>
#include <kernel/mem.h>
#include <kernel/log.h>
 
#include <trace/types.h>
#include <trace/trace.h>
#include <trace/queues.h>
 
#include <ll/i386/x-dos.h>
 
/* this file implement a fixed queue, that is simply an array that
is filled with the events until it is full. After that, all the other
events are discarded. It uses the DOSFS Filesystem to write all the data
 
This file is derived from the trcfixed.c file; I used a different file
because including trcfixed.c in the executable would have implied the
linking of all the filesystem...
*/
 
 
 
 
typedef struct TAGfixed_queue_t {
int size;
int index;
char *filename;
int uniq;
trc_event_t table[0];
/* Yes, 0!... the elements are allocated
in a dirty way into the kern_alloc into fixed_create */
} dosfs_fixed_queue_t;
 
/* This function simply return an event to fill (only if the fixed table
is not yet full) */
static trc_event_t *dosfs_fixed_get(dosfs_fixed_queue_t *queue)
{
if (queue->index>=queue->size) return NULL;
return &queue->table[queue->index++];
}
 
/* since get returns the correct event address,
the post function does nothing... */
static int dosfs_fixed_post(dosfs_fixed_queue_t *queue)
{
return 0;
}
 
static TRC_FIXED_PARMS defaultargs;
static int once=0;
 
static void dosfs_fixed_flush(void *arg);
 
static int dosfs_fixed_create(trc_queue_t *queue, TRC_FIXED_PARMS *args)
{
dosfs_fixed_queue_t *ptr;
 
/* initialize the default arguments for the fixed queue */
if (!once) {
/* well... this func is called when the system is not running! */
once=1;
trc_fixed_default_parms(defaultargs);
}
if (args==NULL) args=&defaultargs;
/* allocate the fixed queue data structure plus the array of events */
ptr=(dosfs_fixed_queue_t*)kern_alloc(sizeof(dosfs_fixed_queue_t)+
sizeof(trc_event_t)*(args->size+1));
if (ptr==NULL) return -1;
 
/* set the current queue pointers and data */
queue->get=(trc_event_t*(*)(void*))dosfs_fixed_get;
queue->post=(int(*)(void*))dosfs_fixed_post;
queue->data=ptr;
 
ptr->size=args->size;
ptr->index=0;
ptr->filename=args->filename;
 
/* prepare for shutdown ;-) */
sys_atrunlevel(dosfs_fixed_flush, (void *)ptr, RUNLEVEL_AFTER_EXIT);
 
return 0;
}
 
static void dosfs_fixed_flush(void *arg)
{
DOS_FILE *f;
dosfs_fixed_queue_t *queue = (dosfs_fixed_queue_t *)arg;
char pathname[100]; /* it should be PATH_MAX, but we do not use the
filesystem, so the symbol is not defined */
 
if (queue->filename==NULL) trc_create_name("fix",queue->uniq,pathname);
else trc_create_name(queue->filename,0,pathname);
 
printk(KERN_DEBUG "tracer flush index= %d pathname=%s\n",
queue->index, pathname);
 
f = DOS_fopen(pathname,"w");
 
DOS_fwrite(queue->table,1,queue->index*sizeof(trc_event_t),f);
 
DOS_fclose(f);
 
}
 
static int dosfs_fixed_activate(dosfs_fixed_queue_t *queue, int uniq)
{
queue->uniq=uniq;
return 0;
}
 
static int dosfs_fixed_terminate(dosfs_fixed_queue_t *queue)
{
return 0;
}
 
int trc_register_dosfs_fixed_queue(void)
{
int res;
res=trc_register_queuetype(TRC_DOSFS_FIXED_QUEUE,
(int(*)(trc_queue_t*,void*))dosfs_fixed_create,
(int(*)(void*,int))dosfs_fixed_activate,
(int(*)(void*))dosfs_fixed_terminate
);
if (res!=0) printk(KERN_WARNING "can't register tracer DOSFS fixed queue");
return res;
}
/shark/trunk/kernel/modules/trccirc.c
0,0 → 1,393
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* Massimiliano Giorgi <massy@gandalf.sssup.it>
* Luca Abeni <luca@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
*/
 
/*
* 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: trccirc.c,v 1.1.1.1 2002-03-29 14:12:52 pj Exp $
*
* File: $File$
* Revision: $Revision: 1.1.1.1 $
* Last update: $Date: 2002-03-29 14:12:52 $
*/
 
#include <ll/sys/types.h>
#include <ll/stdlib.h>
 
#include <kernel/func.h>
#include <kernel/mem.h>
#include <kernel/log.h>
 
#include <trace/types.h>
#include <trace/trace.h>
#include <trace/queues.h>
 
#include <fs/fs.h>
 
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
 
/* Well... this file is very similar to trcfixed.c! */
 
typedef struct TAGcircular_queue_t {
/*+ size of the queue +*/
int size;
/*+ index of the next insertion into the queue +*/
int index;
/*+ index of the next item to write (if online_tracer activated) +*/
int windex;
/*+ number of events lost (if online_tracer activated) +*/
long hoops;
/*+ filename of the trace file +*/
char *filename;
/*+ flags from flags field of the initialization struct +*/
int flags;
/*+ some internal models have needed of extra parameters +*/
void *dummy;
/*+ unique number that identify the queue +*/
int uniq;
/*+ events table +*/
trc_event_t table[0];
} circular_queue_t;
 
static int mustgodown=0;
 
static TASK online_tracer(circular_queue_t *queue)
{
char pathname[PATH_MAX];
int handle;
int index;
 
if (queue->filename==NULL) trc_create_name("cir",queue->uniq,pathname);
else trc_create_name(queue->filename,0,pathname);
 
if (wait_for_fs_initialization()) {
printk(KERN_NOTICE "tracer online task not running");
goto BADEND;
}
handle=open(pathname,O_CREAT|O_TRUNC|O_WRONLY);
if (handle==-1) {
printk(KERN_NOTICE "tracer file %s not created!",pathname);
goto BADEND;
}
for (;;) {
while (queue->index!=queue->windex) {
index=queue->index;
if (index<queue->windex) {
write(handle,
queue->table+queue->windex,
(queue->size-queue->windex)*sizeof(trc_event_t)
);
queue->windex=0;
continue;
}
write(handle,
queue->table+queue->windex,
(index-queue->windex)*sizeof(trc_event_t)
);
queue->windex=index;
}
if (mustgodown) break;
task_endcycle();
}
close(handle);
printk(KERN_NOTICE "tracer file %s created!",pathname);
 
if (queue->hoops)
printk(KERN_NOTICE "tracer: %li event lost into %s",queue->hoops,pathname);
 
resume_fs_shutdown();
return NULL;
 
BADEND:
resume_fs_shutdown();
/*Why this? for a little bug on the task_makefree() routine */
for (;;) {
if (mustgodown) break;
task_endcycle();
}
return NULL;
}
 
static trc_event_t *circular_get2(circular_queue_t *queue)
{
if (queue->index==queue->size-1) {
if (queue->windex==0) {
queue->hoops++;
return NULL;
}
queue->index=0;
return &queue->table[queue->size-1];
}
if (queue->index+1==queue->windex) {
queue->hoops++;
return NULL;
}
return &queue->table[queue->index++];
}
 
static trc_event_t *circular_get1(circular_queue_t *queue)
{
if (queue->index==queue->size-1) {
queue->index=0;
return &queue->table[queue->size-1];
}
return &queue->table[queue->index++];
}
 
static int circular_post(circular_queue_t *queue)
{
return 0;
}
 
struct create_args {
long period;
long slice;
circular_queue_t *queue;
};
 
 
/* to remove!!! */
/*
static void circular_create_postponed(void *foo)
{
struct create_args *ptr=(struct create_args *)foo;
SOFT_TASK_MODEL model;
PID pid;
 
printk(KERN_DEBUG "postponed create: START");
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,ptr->period);
soft_task_def_met(model,ptr->slice);
soft_task_def_wcet(model,ptr->slice);
soft_task_def_arg(model,ptr->queue);
 
printk(KERN_DEBUG "postponed create: A");
kern_free(foo,sizeof(struct create_args));
 
printk(KERN_DEBUG "postponed create: B");
pid=task_create("trcCirc",online_tracer,&model,NULL);
if (pid==-1) {
printk(KERN_ERR "can't start tracer online circular trace task");
} else {
printk(KERN_DEBUG "postponed create: C1");
task_activate(pid);
printk(KERN_DEBUG "postponed create: C2");
suspend_fs_shutdown();
printk(KERN_DEBUG "postponed create: C3");
}
 
printk(KERN_DEBUG "postponed create: END");
}
*/
 
static int circular_create(trc_queue_t *queue, TRC_CIRCULAR_PARMS *args)
{
TRC_CIRCULAR_PARMS defaultargs;
circular_queue_t *ptr;
 
if (args==NULL) {
trc_circular_default_parms(defaultargs);
args=&defaultargs;
}
ptr=(circular_queue_t*)kern_alloc(sizeof(circular_queue_t)+
sizeof(trc_event_t)*args->size);
if (ptr==NULL) return -1;
 
queue->get=(trc_event_t*(*)(void*))circular_get1;
queue->post=(int(*)(void*))circular_post;
queue->data=ptr;
ptr->size=args->size;
ptr->windex=ptr->index=0;
ptr->hoops=0;
ptr->filename=args->filename;
ptr->flags=args->flags;
ptr->dummy=NULL;
if (args->flags&TRC_CIRCULAR_ONLINETASK) {
struct create_args *p;
p=kern_alloc(sizeof(struct create_args));
if (p==NULL) {
printk(KERN_ERR "can't create tracer online circular trace task");
return -1;
}
queue->get=(trc_event_t*(*)(void*))circular_get2;
ptr->dummy=p;
p->period=args->period;
p->slice=args->slice;
p->queue=ptr;
//sys_atrunlevel(circular_create_postponed,(void*)p,RUNLEVEL_INIT);
}
return 0;
}
 
static int circular_activate(circular_queue_t *queue, int uniq)
{
queue->uniq=uniq;
 
if (queue->flags&TRC_CIRCULAR_ONLINETASK) {
struct create_args *ptr=(struct create_args *)queue->dummy;
SOFT_TASK_MODEL model;
PID pid;
 
printk(KERN_DEBUG "postponed create: START");
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,ptr->period);
soft_task_def_met(model,ptr->slice);
soft_task_def_wcet(model,ptr->slice);
soft_task_def_arg(model,ptr->queue);
 
printk(KERN_DEBUG "postponed create: A");
kern_free(queue->dummy,sizeof(struct create_args));
 
printk(KERN_DEBUG "postponed create: B");
pid=task_create("trcCirc",online_tracer,&model,NULL);
if (pid==-1) {
printk(KERN_ERR "can't start tracer online circular trace task");
} else {
printk(KERN_DEBUG "postponed create: C1");
suspend_fs_shutdown();
printk(KERN_DEBUG "postponed create: C2");
task_activate(pid);
printk(KERN_DEBUG "postponed create: C3");
}
 
printk(KERN_DEBUG "postponed create: END");
}
return 0;
}
 
static TASK circular_shutdown(circular_queue_t *queue)
{
char pathname[PATH_MAX];
int h;
if (queue->filename==NULL) trc_create_name("cir",queue->uniq,pathname);
else trc_create_name(queue->filename,0,pathname);
h=open(pathname,O_CREAT|O_TRUNC|O_WRONLY);
if (h!=-1) {
if (queue->index!=queue->size-1)
write(h,
queue->table+queue->index+1,
(queue->size-queue->index-1)*sizeof(trc_event_t)
);
write(h,
queue->table,
queue->index*sizeof(trc_event_t)
);
close(h);
printk(KERN_NOTICE "tracer file %s created!",pathname);
} else
printk(KERN_NOTICE "tracer file %s NOT created!",pathname);
resume_fs_shutdown();
return NULL;
}
 
static int circular_terminate(circular_queue_t *queue)
{
SOFT_TASK_MODEL model;
PID pid;
 
mustgodown=1;
if (queue->flags&TRC_CIRCULAR_ONLINETASK) return 0;
 
suspend_fs_shutdown();
//nrt_task_default_model(model);
//nrt_task_def_system(model);
//nrt_task_def_arg(model,queue);
 
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,50000);
soft_task_def_met(model,10000);
soft_task_def_wcet(model,10000);
soft_task_def_arg(model,queue);
pid=task_create("ShutTrcCir",circular_shutdown,&model,NULL);
if (pid==-1) {
printk(KERN_ERR "can't start tracer shutdown task (circular)");
return -1;
} else
task_activate(pid);
 
return 0;
}
 
int trc_register_circular_queue(void)
{
int res;
res=trc_register_queuetype(TRC_CIRCULAR_QUEUE,
(int(*)(trc_queue_t*,void*))circular_create,
(int(*)(void*,int))circular_activate,
(int(*)(void*))circular_terminate
);
if (res!=0) printk(KERN_WARNING "can't register tracer circular queue");
return res;
}
/shark/trunk/kernel/modules/trcdummy.c
0,0 → 1,66
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Massimiliano Giorgi <massy@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
*/
 
#include <ll/sys/types.h>
#include <ll/stdlib.h>
 
#include <kernel/log.h>
 
#include <trace/types.h>
#include <trace/trace.h>
#include <trace/queues.h>
 
static trc_event_t *dummy_queue_get(void *unused)
{
static trc_event_t event;
return &event;
}
 
static int dummy_queue_post(void *unused)
{
return 0;
}
 
static int create_dummy_queue(trc_queue_t *queue, void *unused)
{
queue->get=dummy_queue_get;
queue->post=dummy_queue_post;
queue->data=NULL;
return 0;
}
 
static int terminate_dummy_queue(void *unused)
{
return 0;
}
 
static int activate_dummy_queue(void *unused, int unused2)
{
return 0;
}
 
int trc_register_dummy_queue(void)
{
int res;
res=trc_register_queuetype(TRC_DUMMY_QUEUE,
create_dummy_queue,
activate_dummy_queue,
terminate_dummy_queue);
if (res!=0) printk(KERN_WARNING "can't register tracer dummy queue");
return res;
}
/shark/trunk/kernel/trace.c
0,0 → 1,66
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Massimiliano Giorgi <massy@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
*/
 
/*
* 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:52 pj Exp $
*
* File: $File$
* Revision: $Revision: 1.1.1.1 $
* Last update: $Date: 2002-03-29 14:12:52 $
*/
 
#include <ll/sys/types.h>
 
#include <kernel/types.h>
#include <kernel/trace.h>
#include <kernel/var.h>
 
static void dummy_logevent(int event, void *ptr)
{
return;
}
 
void (*trc_logevent)
(int event, void *ptr)=dummy_logevent;
static int dummy_suspendresume(void)
{
return 0;
}
 
int (*trc_suspend)(void)=dummy_suspendresume;
int (*trc_resume)(void)=dummy_suspendresume;