/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; |