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>
* 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.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 <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>
#define TRC_MAXQUEUES 5
/*
*
*/
static char basepath
[PATH_MAX
];
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
);
}
/*
*
*/
#define FLAG_NOTRACE 0x01
typedef struct TAGtrc_evtinfo_t
{
trc_queue_t
*queue
;
unsigned flags
;
} trc_evtinfo_t
;
/* -- */
trc_evtinfo_t eventstable
[TRC_NUMEVENTS
];
int (*createqueue
[TRC_QUEUETYPESNUMBER
])(trc_queue_t
*, void *);
int (*activatequeue
[TRC_QUEUETYPESNUMBER
])(void *,int);
int (*terminatequeue
[TRC_QUEUETYPESNUMBER
])(void *);
trc_queue_t queuetable
[TRC_MAXQUEUES
];
trc_queue_t queuesink
;
int numqueues
;
/* -- */
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;
}
/* -- */
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;
}
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...");
for (i
=0;i
<TRC_QUEUETYPESNUMBER
;i
++) {
createqueue
[i
]=dummy_createqueue
;
terminatequeue
[i
]=dummy_terminatequeue
;
}
dummy_createqueue
(&queuesink
,NULL
);
numqueues
=0;
for (i
=0;i
<TRC_NUMEVENTS
;i
++) {
eventstable
[i
].
queue=&queuesink
;
eventstable
[i
].
flags=FLAG_NOTRACE
;
}
i
=sys_atrunlevel
(trc_end
,NULL
,RUNLEVEL_SHUTDOWN
);
{
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
;
trc_resume
();
return 0;
}
int TRC_init_phase2
(void)
{
int i
;
for (i
=0;i
<numqueues
;i
++)
activatequeue
[queuetable
[i
].
type](queuetable
[i
].
data,i
+1);
return 0;
}
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
;
}
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
;
f
=kern_fsave
();
if (eventstable
[event
].
flags&FLAG_NOTRACE
) {
kern_frestore
(f
);
return;
}
queue
=eventstable
[event
].
queue;
evt
=queue
->get
(queue
->data
);
if (evt
!=NULL
) {
evt
->event
=event
;
evt
->time=ll_gettime
(TIME_EXACT
,NULL
);
memcpy(&evt
->x
,ptr
,sizeof(trc_allevents_t
));
queue
->post
(queue
->data
);
}
kern_frestore
(f
);
}
/*
*
*
*
*/
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
;
res
=TRC_init_phase1
(NULL
);
if (res
) return res
;
res
=trc_register_circular_queue
();
if (res
) return res
;
res
=trc_register_fixed_queue
();
if (res
) return res
;
qc
=trc_create_queue
(TRC_CIRCULAR_QUEUE
,NULL
);
qf
=trc_create_queue
(TRC_FIXED_QUEUE
,NULL
);
if (qc
==-1||qf
==-1) return -97;
res
=trc_trace_class
(TRC_CLASS_SYSTEM
);
if (res
) return res
;
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
();
}