Subversion Repositories shark

Rev

Rev 5 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 1
/*
2
 * Project: S.Ha.R.K.
3
 *
4
 * Coordinators:
5
 *   Giorgio Buttazzo    <giorgio@sssup.it>
6
 *   Paolo Gai           <pj@gandalf.sssup.it>
7
 *
8
 * Authors     :
9
 *   Paolo Gai           <pj@gandalf.sssup.it>
10
 *   Massimiliano Giorgi <massy@gandalf.sssup.it>
11
 *   Luca Abeni          <luca@gandalf.sssup.it>
12
 *   (see the web pages for full authors list)
13
 *
14
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
15
 *
16
 * http://www.sssup.it
17
 * http://retis.sssup.it
18
 * http://shark.sssup.it
19
 */
20
 
21
/*
22
 * Copyright (C) 1999 Massimiliano Giorgi
23
 *
24
 * This program is free software; you can redistribute it and/or modify
25
 * it under the terms of the GNU General Public License as published by
26
 * the Free Software Foundation; either version 2 of the License, or
27
 * (at your option) any later version.
28
 *
29
 * This program is distributed in the hope that it will be useful,
30
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32
 * GNU General Public License for more details.
33
 *
34
 * You should have received a copy of the GNU General Public License
35
 * along with this program; if not, write to the Free Software
36
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
37
 *
38
 */
39
 
40
/*
38 pj 41
 * CVS :        $Id: trace.c,v 1.3 2003-01-07 17:07:51 pj Exp $
2 pj 42
 *
43
 * File:        $File$
38 pj 44
 * Revision:    $Revision: 1.3 $
45
 * Last update: $Date: 2003-01-07 17:07:51 $
2 pj 46
 */
47
 
48
#include <ll/sys/types.h>
49
#include <ll/stdlib.h>
50
#include <ll/string.h>
51
 
52
#include <kernel/func.h>
53
#include <kernel/trace.h>
54
 
55
#include <trace/types.h>
56
#include <trace/trace.h>
57
#include <trace/queues.h>
58
 
59
#include <bits/limits.h>
60
 
5 pj 61
/* maximum number of different queues where we want to log our events */
2 pj 62
#define TRC_MAXQUEUES 5
63
 
64
/*
65
 *
66
 */
67
 
5 pj 68
/* this is the base path that is used as a prologue for all the
69
filenames that are passed to the tracer */
2 pj 70
static char basepath[PATH_MAX];
71
 
5 pj 72
/* used to create the name for a tracer file */
2 pj 73
void trc_create_name(char *basename, int uniq, char *pathname)
74
{
75
  if (uniq) sprintf(pathname,"%s/%s%i",basepath,basename,uniq);
76
  else      sprintf(pathname,"%s/%s",basepath,basename);
77
}
78
 
79
/*
80
 *
81
 */
82
 
5 pj 83
/* the flag used to discriminate if an event have to be traced or not */
2 pj 84
#define FLAG_NOTRACE 0x01
85
 
86
typedef struct TAGtrc_evtinfo_t {
5 pj 87
  trc_queue_t *queue;  /* the queue responsible for the logging of an event */
88
  unsigned    flags;   /* if = FLAG_NOTRACE the event must not be logged */
2 pj 89
} trc_evtinfo_t;
90
 
91
/* -- */
92
 
5 pj 93
/* one entry for each event; this array says for each event the queue to use
94
and if it must be logged */
2 pj 95
trc_evtinfo_t eventstable[TRC_NUMEVENTS];
96
 
5 pj 97
/* For each kind of queue (see include/tracer/queues.h) there is a set of
98
pointers to the functions that a queue should implement */
2 pj 99
int (*createqueue[TRC_QUEUETYPESNUMBER])(trc_queue_t *, void *);
100
int (*activatequeue[TRC_QUEUETYPESNUMBER])(void *,int);
101
int (*terminatequeue[TRC_QUEUETYPESNUMBER])(void *);
102
 
5 pj 103
/* for each queue registered in the system,
104
   the functions used to get/post an event
105
   The elements of this table are initialized with calls to createqueue[type]()
106
   (see include/trace/queues.h) */
2 pj 107
trc_queue_t queuetable[TRC_MAXQUEUES];
5 pj 108
 
109
/* initialized as a dummy queue, the default value of all the queues */
2 pj 110
trc_queue_t queuesink;
5 pj 111
 
112
/* number of registered queues in the system */
2 pj 113
int numqueues;
114
 
115
/* -- */
116
 
5 pj 117
/* The Dummy queue */
118
 
2 pj 119
static trc_event_t *dummy_get(void *foo)
120
{  
121
  return NULL;
122
}
123
 
124
static int dummy_post(void *foo)
125
{
126
  return 0;
127
}
128
 
129
static int dummy_createqueue(trc_queue_t *queue, void *unused)
130
{
131
  queue->get=dummy_get;
132
  queue->post=dummy_post;
133
  queue->data=NULL;
134
  return 0;
135
}
136
 
137
static int dummy_terminatequeue(void *unused)
138
{
139
  return 0;
140
}
141
 
142
static int dummy_activatequeue(void *unused, int unused2)
143
{
144
  return 0;
145
}
146
 
147
/* -- */
148
 
5 pj 149
/* this function simply register the functions that are used to
150
   handle a queue */
2 pj 151
int trc_register_queuetype(int queuetype,
152
                           int(*creat)(trc_queue_t *, void *),
153
                           int(*activate)(void *,int),
154
                           int(*term)(void *))
155
{
156
  if (queuetype<0||queuetype>=TRC_QUEUETYPESNUMBER) return -1;
157
  createqueue[queuetype]=creat;
158
  activatequeue[queuetype]=activate;
159
  terminatequeue[queuetype]=term;
160
  return 0;
161
}
162
 
5 pj 163
/* this function register a queue in the system.
164
   It uses the type to access to the queue handling functions registered
165
   with the previous function (trc_register_queuetype)
166
   numqueue is incremented!
167
   */
2 pj 168
int trc_create_queue(int queuetype, void *args)
169
{
170
  int res;
171
 
172
  if (createqueue[queuetype]==dummy_createqueue) return -1;
173
  if (numqueues==TRC_MAXQUEUES) return -1;
174
  res=createqueue[queuetype](&queuetable[numqueues],args);
175
  if (res) return -1;
176
  queuetable[numqueues].type=queuetype;
177
  numqueues++;
178
  return numqueues-1;
179
}
180
 
181
/* -- */
182
 
183
static void (*old_logevent)(int event, void *ptr)=NULL;
184
static void internal_trc_logevent(int, void *ptr);
185
 
186
static void trc_end(void *unused)
187
{
188
  int i;
189
 
190
  printk(KERN_INFO "tracer shutdown...");
191
 
192
  /* suspend event logging */
193
  trc_suspend();
194
 
195
  /* for safety: send all events to the sink queue */
196
  for (i=0;i<TRC_NUMEVENTS;i++) {
197
    eventstable[i].queue=&queuesink;
198
    eventstable[i].flags|=FLAG_NOTRACE;
199
  }
200
 
201
  /* terminate all queues */
202
  for (i=0;i<numqueues;i++)
203
    terminatequeue[queuetable[i].type](queuetable[i].data);
204
}
205
 
206
static int internal_trc_resume(void);
207
static int internal_trc_suspend(void);
208
 
209
int TRC_init_phase1(TRC_PARMS *parms)
210
{
211
  int i;
212
 
213
  printk(KERN_INFO "initializing tracer...");
214
 
5 pj 215
  /* all the queues are initialized to the dummy queue (sink!) */
2 pj 216
  for (i=0;i<TRC_QUEUETYPESNUMBER;i++) {
217
    createqueue[i]=dummy_createqueue;
218
    terminatequeue[i]=dummy_terminatequeue;
219
  }
5 pj 220
 
221
  /* the sink queue is initialized */
2 pj 222
  dummy_createqueue(&queuesink,NULL);
5 pj 223
 
224
  /* no queues registered yet */
2 pj 225
  numqueues=0;
226
 
5 pj 227
  /* all the events are initialized to put to the sink queue */
2 pj 228
  for (i=0;i<TRC_NUMEVENTS;i++) {
229
    eventstable[i].queue=&queuesink;
230
    eventstable[i].flags=FLAG_NOTRACE;
231
  }
232
 
5 pj 233
  /* this will end the tracer at shutdown */
2 pj 234
  i=sys_atrunlevel(trc_end,NULL,RUNLEVEL_SHUTDOWN);
235
 
5 pj 236
  /* initialize the parameters if not initialized */
2 pj 237
  {
238
    TRC_PARMS m;
239
    trc_default_parms(m);
240
    if (parms==NULL) parms=&m;
241
 
242
    strncpy(basepath,parms->path,sizeof(basepath));
243
    basepath[sizeof(basepath)-1]='\0';
244
  }
245
 
246
  trc_suspend=internal_trc_suspend;
247
  trc_resume=internal_trc_resume;
248
 
5 pj 249
  /* start the tracer */
2 pj 250
  trc_resume();
251
  return 0;
252
}
253
 
5 pj 254
/* this function simply activates all the registered queues.
255
   This is usually called into the init() tasks!!! */
2 pj 256
int TRC_init_phase2(void)
257
{
258
  int i;
259
  for (i=0;i<numqueues;i++)
260
    activatequeue[queuetable[i].type](queuetable[i].data,i+1);
261
  return 0;
262
}
263
 
5 pj 264
/* saves the current logevent function and set it as
265
   the internal_trc_logevent */
2 pj 266
static int internal_trc_resume(void)
267
{
268
  SYS_FLAGS f;
269
  int ret=-1;
270
  f=kern_fsave();
271
  if (old_logevent==NULL) {  
272
    old_logevent=trc_logevent;
273
    trc_logevent=internal_trc_logevent;
274
    ret=0;
275
  }
276
  kern_frestore(f);
277
  return ret;
278
}
279
 
5 pj 280
/* restores the saved logevent function (initially, the logevent function is
281
   a dummy function) */
2 pj 282
static int internal_trc_suspend(void)
283
{
284
  SYS_FLAGS f;
285
  int ret=-1;
286
  f=kern_fsave();
287
  if (old_logevent!=NULL) {    
288
    trc_logevent=old_logevent;
289
    old_logevent=NULL;
290
    ret=0;
291
  }
292
  kern_frestore(f);
293
  return 0;
294
}
295
 
296
static void internal_trc_logevent(int event, void *ptr)
297
{
298
  trc_event_t   *evt;
299
  trc_queue_t   *queue;
300
  SYS_FLAGS f;
301
 
5 pj 302
  /* disables interrupts (this function can be called also into a task */
2 pj 303
  f=kern_fsave();
304
 
5 pj 305
  /* check if the event has to be logged */
2 pj 306
  if (eventstable[event].flags&FLAG_NOTRACE) {
307
    kern_frestore(f);
308
    return;
309
  }
310
  queue=eventstable[event].queue;
311
 
5 pj 312
  /* gets a free event descriptor, fills it and post it */
2 pj 313
  evt=queue->get(queue->data);
314
  if (evt!=NULL) {
315
    evt->event=event;
38 pj 316
    evt->time=kern_gettime(NULL);
2 pj 317
    memcpy(&evt->x,ptr,sizeof(trc_allevents_t));
318
    queue->post(queue->data);
319
  }
320
 
321
  kern_frestore(f);
322
}
323
 
324
/*
325
 *
326
 *
327
 *
328
 */
329
 
5 pj 330
/* these set of functions can be used to trace or not single event and classes.
331
   They make use of the classtable structure, that is used to discriminate
332
   the indexes occupied by every class */
333
 
2 pj 334
int classtable[TRC_NUMCLASSES+1]={
335
  TRC_F_TRACER,
336
  TRC_F_SYSTEM,
337
  TRC_F_USER,
338
  TRC_F_LL,
339
  TRC_F_SEM,
340
  TRC_F_LAST
341
};
342
 
343
#define checkevent(x)   if ((x)<0||(x)>=TRC_NUMEVENTS) return -1
344
#define checkqueue(x)   if ((x)<0||(x)>=numqueues) return -1
345
#define checkclass(x)   if ((x)<0||(x)>=TRC_NUMCLASSES) return -1
346
 
347
int trc_assign_event_to_queue(int event, int queue)
348
{
349
  checkevent(event);
350
  checkqueue(queue);
351
  eventstable[event].queue=&queuetable[queue];
352
  return 0;
353
}
354
 
355
int trc_assign_class_to_queue(int class, int queue)
356
{
357
  int i;
358
  checkqueue(queue);
359
  checkclass(class);
360
  for (i=classtable[class];i<classtable[class+1];i++)
361
    eventstable[i].queue=&queuetable[queue];
362
  return 0;
363
}
364
 
365
int trc_notrace_event(int event)
366
{
367
  checkevent(event);
368
  eventstable[event].flags|=FLAG_NOTRACE;
369
  return 0;
370
}
371
 
372
int trc_trace_event(int event)
373
{
374
  checkevent(event);
375
  eventstable[event].flags&=~FLAG_NOTRACE;
376
  return 0;
377
}
378
 
379
int trc_notrace_class(int class)
380
{
381
  int i;
382
  checkclass(class);
383
  for (i=classtable[class];i<classtable[class+1];i++)
384
    eventstable[i].flags|=FLAG_NOTRACE;
385
  return 0;
386
}
387
 
388
int trc_trace_class(int class)
389
{
390
  int i;
391
  checkclass(class);
392
  for (i=classtable[class];i<classtable[class+1];i++)
393
    eventstable[i].flags&=~FLAG_NOTRACE;
394
  return 0;
395
}
396
 
397
 
398
/* -- */
399
 
400
int TRC_init_phase1_standard(void)
401
{
402
  int qf,qc;
403
  int res;
5 pj 404
 
405
  /* initialize the trace */  
2 pj 406
  res=TRC_init_phase1(NULL);
407
  if (res) return res;
408
 
5 pj 409
  /* register two kinds of queues, fixed and circular */
2 pj 410
  res=trc_register_circular_queue();
411
  if (res) return res;
412
  res=trc_register_fixed_queue();
413
  if (res) return res;
414
 
5 pj 415
  /* creates two queues:
416
      a circular queue for the system events,
417
      a fixed queue
418
      */
2 pj 419
  qc=trc_create_queue(TRC_CIRCULAR_QUEUE,NULL);
420
  qf=trc_create_queue(TRC_FIXED_QUEUE,NULL);
421
  if (qc==-1||qf==-1) return -97;
422
 
5 pj 423
  /* We want to trace all the system events */
2 pj 424
  res=trc_trace_class(TRC_CLASS_SYSTEM);
425
  if (res) return res;
5 pj 426
  /* All the system events must be traced into the circular queue */
2 pj 427
  res=trc_assign_class_to_queue(TRC_CLASS_SYSTEM,qc);
428
  if (res) return res;
429
 
430
  return 0;
431
}
432
 
433
int TRC_init_phase2_standard(void)
434
{
435
  return TRC_init_phase2();
436
}
437
 
438