Subversion Repositories shark

Rev

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

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