Subversion Repositories shark

Rev

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

Rev Author Line No. Line
2 pj 1
/*
2
 * Project: HARTIK (HA-rd R-eal TI-me K-ernel)
3
 *
4
 * Coordinators: Giorgio Buttazzo <giorgio@sssup.it>
5
 *               Gerardo Lamastra <gerardo@sssup.it>
6
 *
7
 * Authors     : Massimiliano Giorgi <massy@hartik.sssup.it>
8
 * (see authors.txt for full list of hartik's authors)
9
 *
10
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
11
 *
12
 * http://www.sssup.it
13
 * http://retis.sssup.it
14
 * http://hartik.sssup.it
15
 */
16
 
17
/*
18
 * Copyright (C) 2000 Massimiliano Giorgi
19
 *
20
 * This program is free software; you can redistribute it and/or modify
21
 * it under the terms of the GNU General Public License as published by
22
 * the Free Software Foundation; either version 2 of the License, or
23
 * (at your option) any later version.
24
 *
25
 * This program is distributed in the hope that it will be useful,
26
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28
 * GNU General Public License for more details.
29
 *
30
 * You should have received a copy of the GNU General Public License
31
 * along with this program; if not, write to the Free Software
32
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
33
 *
34
 */
35
 
36
/*
37
 * CVS :        $Id: trace.c,v 1.1.1.1 2002-03-29 14:12:53 pj Exp $
38
 *
39
 * File:        $File$
40
 * Revision:    $Revision: 1.1.1.1 $
41
 * Last update: $Date: 2002-03-29 14:12:53 $
42
 */
43
 
44
#include <ll/sys/types.h>
45
#include <kernel/assert.h>
46
#include <kernel/func.h>
47
#include <kernel/log.h>
48
 
49
#include <kernel/trace.h>
50
#include <modules/trace.h>
51
#include <modules/traceevt.h>
52
#include <modules/tracestr.h>
53
 
54
/* Well...
55
 * TRC_init2() and tracer() must be called when the system is up,
56
 * so they can call functions of the unistd.h
57
 */
58
#include <fcntl.h>
59
#include <unistd.h>
60
#include <errno.h>
61
#include <string.h>
62
 
63
/* -- */
64
 
65
/*+ number of event per blocks +*/
66
#define TRC_BLOCKSIZE     1024 
67
 
68
/*+ numbers of tables can grow until this is raggiunto +*/
69
#define TRC_MAXNUMTABLES    48
70
 
71
/* -- */
72
 
73
#define DEBUG_INIT KERN_DEBUG
74
//#undef DEBUGINIT
75
 
76
#ifdef DEBUG_INIT
77
#define printk0(fmt,args...) printk(DEBUG_INIT fmt,##args)
78
#else
79
#define printk0(fmt,args...)
80
#endif
81
 
82
 
83
/* -- */
84
 
85
static __inline__ void *allocmemory(long size)
86
{
87
  SYS_FLAGS f;
88
  void *ptr;
89
  f=kern_fsave();
90
  ptr=kern_alloc(size+sizeof(long));
91
  kern_frestore(f);
92
  if (ptr!=NULL) {
93
    *((long*)ptr)=size;
94
    return (char *)ptr+sizeof(long);
95
  }
96
  return ptr;
97
}
98
 
99
static __inline__ void freememory(void *ptr)
100
{
101
  SYS_FLAGS f;
102
  long size;
103
  size=*(long*)((char *)ptr-sizeof(long));
104
  f=kern_fsave();
105
  kern_free(ptr-sizeof(long),size+sizeof(long));
106
  kern_frestore(f);
107
}
108
 
109
/* -- */
110
 
111
typedef struct TAGtrc_events {
112
  struct TAGtrc_events *next;
113
  trc_event_t event[TRC_BLOCKSIZE] __attribute__((packed));
114
} trc_events;
115
 
116
static int counter;
117
static int hoops;
118
static trc_events *acttable,*writable;
119
static int actindex,wriindex;
120
static int handle=-1;
121
 
122
static int numtables;
123
 
124
static TASK tracer(void *dummy)
125
{
126
  int index,n,res;
127
  res=0;
128
  for (;;) {
129
    while (counter>0) {
130
      kern_cli();
131
      if (acttable!=writable) {
132
        kern_sti();
133
        n=TRC_BLOCKSIZE-wriindex;
134
        res=write(handle,writable->event+wriindex,n*sizeof(trc_event_t));
135
        writable=writable->next;
136
        wriindex=0;
137
      } else {
138
        index=actindex;
139
        kern_sti();
140
        n=index-wriindex;
141
        assertk(n>0);
142
        res=write(handle,writable->event+wriindex,n*sizeof(trc_event_t));
143
        wriindex=index;
144
      }
145
      if (res!=n*sizeof(trc_event_t)) {
146
        res=-1;
147
        break;
148
      }
149
      counter-=n;
150
      assertk(counter>=0);
151
    }
152
    /* errors trap */
153
    if (res==-1) {
154
      SYS_FLAGS f;
155
      f=kern_fsave();
156
      printk(KERN_ERR "tracer task write error!");
157
      kern_frestore(f);
158
      for (;;) task_endcycle();
159
    }
160
    task_endcycle();
161
  }
162
}
163
 
164
static TRACE_PARMS defparms=BASE_TRACE;
165
static TRACE_PARMS *myparms=&defparms;
166
 
167
static void internal_trc_logevent(PID pid, int event, void *ptr, int size);
168
 
169
int TRC_init_phase1(TRACE_PARMS *inparms)
170
{
171
  trc_events *nexttable;
172
 
173
  printk0("tracer init: START phase1");
174
 
175
  acttable=allocmemory(sizeof(trc_events));
176
  if (acttable==NULL) goto ERROR;
177
  printk0("tracer init: first table created");
178
  nexttable=allocmemory(sizeof(trc_events));
179
  if (nexttable==NULL) {
180
    freememory(acttable);
181
    acttable=NULL;
182
    goto ERROR;
183
  }
184
  printk0("tracer init: second table created");
185
 
186
  acttable->next=nexttable;
187
  nexttable->next=acttable;
188
  actindex=0;
189
  writable=acttable;
190
  wriindex=0;
191
  counter=0;
192
  hoops=0;
193
  numtables=2;
194
  printk0("tracer init: internal variables initialized");
195
 
196
  if (inparms!=NULL) myparms=inparms;
197
 
198
  trc_resume();
199
  printk0("tracer init: END phase 1 (tracer started)");
200
  return 0;
201
 
202
ERROR:
203
  printk(KERN_ERR "tracer initialization fails!");
204
  return -1;
205
}
206
 
207
static void TRC_end(void *dummy);
208
 
209
int TRC_init_phase2(void)
210
{
211
  trc_event_t event;
212
  SOFT_TASK_MODEL model;
213
  int res;
214
  PID pid;
215
 
216
  printk0("tracer init: START phase 2");
217
 
218
  /* for safety */
219
  if (acttable==NULL) return -1;
220
  printk0("tracer init: safety test passed");
221
 
222
  handle=open(myparms->filename,O_CREAT|O_TRUNC|O_WRONLY);  
223
  if (handle==-1) goto ERROR;
224
  printk0("tracer init: file opened");
225
 
226
  event.size=sizeof(trc_event_t);
227
  event.what=TRC_INITLOG;
228
  event.x.id=TRC_INITID;
229
 
230
  //cprintf("size=====%li\n",sizeof(trc_event_t));
231
 
232
  res=write(handle,&event,sizeof(trc_event_t));
233
  if (res!=sizeof(trc_event_t)) goto ERROR;
234
  printk0("tracer init: write");
235
 
236
  soft_task_default_model(model);
237
  soft_task_def_system(model);
238
  soft_task_def_notrace(model);
239
  soft_task_def_periodic(model);
240
  soft_task_def_period(model,myparms->period);
241
  soft_task_def_met(model,myparms->slice);
242
  soft_task_def_wcet(model,myparms->slice);
243
 
244
  pid=task_create("sysTracer",tracer,&model,NULL);
245
  if (pid==-1) goto ERROR;
246
  task_activate(pid);
247
  printk0("tracer init: tracer task created and activated");
248
 
249
  //sys_atexit(TRC_end,(void*)handle,BEFORE_EXIT);
250
  printk0("tracer init: END phase 2");
251
  printk (KERN_NOTICE "tracer started!");
252
  return 0;
253
 
254
ERROR:
255
  kern_cli();
256
  freememory(acttable->next);
257
  freememory(acttable);
258
  acttable=NULL;
259
  kern_sti();
260
  if (handle!=-1) close(handle);
261
  printk(KERN_ERR "tracer initialization fails (%s)!",strerror(errno));
262
  return -1;
263
}
264
 
265
static void (*old_logevent)(PID pid, int event, void *ptr, int size)=NULL;
266
 
267
int trc_resume(void)
268
{
269
  SYS_FLAGS f;
270
  int ret=-1;
271
  f=kern_fsave();
272
  if (acttable!=NULL&&old_logevent==NULL) {  
273
    old_logevent=trc_logevent;
274
    trc_logevent=internal_trc_logevent;
275
    ret=0;
276
  }
277
  kern_frestore(f);
278
  return ret;
279
}
280
 
281
int trc_suspend(void)
282
{
283
  SYS_FLAGS f;
284
  int ret=-1;
285
  f=kern_fsave();
286
  if (acttable!=NULL&&old_logevent!=NULL) {    
287
    trc_logevent=old_logevent;
288
    old_logevent=NULL;
289
    ret=0;
290
  }
291
  kern_frestore(f);
292
  return 0;
293
}
294
 
295
static void TRC_end(void *dummy)
296
{
297
  printk(KERN_INFO "shuting down tracer...");
298
 
299
  trc_suspend();
300
  if (counter>0) {
301
    /* wait a bit for flushing events queue */
302
    int x=30;
303
    while (counter>0) {
304
      cprintf("<%li>",(long)counter);
305
      task_delay(100000); // 100msec
306
      if (x--==0) break;
307
    }
308
  }
309
  close(handle);
310
 
311
  printk(KERN_DEBUG "tracer hoops:     %5i",hoops);
312
  printk(KERN_DEBUG "tracer numtables: %5i",numtables);  
313
}
314
 
315
static trc_event_t *getrecord(void)
316
{
317
  trc_events  *newtable;
318
  trc_event_t *event;
319
  event=&acttable->event[actindex];
320
  actindex++;
321
  if (actindex==TRC_BLOCKSIZE) {
322
    actindex=0;    
323
    if (acttable->next==writable) {
324
      if (numtables==TRC_MAXNUMTABLES) {
325
        hoops++;
326
        actindex=TRC_BLOCKSIZE-1;
327
        return NULL;
328
      }
329
      newtable=allocmemory(sizeof(trc_events));
330
      if (newtable==NULL) {
331
        hoops++;
332
        actindex=TRC_BLOCKSIZE-1;
333
        return NULL;
334
      }
335
      newtable->next=acttable->next;
336
      acttable->next=newtable;
337
      acttable=newtable;
338
      numtables++;
339
    }
340
    else acttable=acttable->next;    
341
  }
342
  return event;
343
}
344
 
345
static void internal_trc_logevent(int event, PID pid, void *ptr, int size)
346
{
347
  SYS_FLAGS f;
348
  trc_event_t *evt;
349
 
350
  if (acttable==NULL) return;
351
 
352
  f=kern_fsave();
353
  evt=getrecord();  
354
  if (evt!=NULL) {
355
 
356
    evt->size=sizeof(trc_event_t);
357
    evt->what=event;
358
    if ((event&0xff00)==(TRC_USR_EVENTS<<8)) {
359
          evt->x.user.when=ll_gettime(TIME_EXACT,NULL);
360
          evt->x.user.who=(pid==TRC_NOPID?exec_shadow:pid);
361
          if (ptr!=NULL) memcpy(&evt->x.user.info,ptr,TRC_MAXUSERINFO);  
362
    } else
363
      switch (event) {
364
        case TRC_TASKNAME:
365
          evt->x.tskname.who=pid;
366
          memcpy(&evt->x.tskname.name,ptr,TRC_MAXNAMESIZE);
367
          break;
368
        case TRC_SCHEDULE:
369
          evt->x.sched.when=ll_gettime(TIME_EXACT,NULL);
370
          memcpy(&evt->x.sched.info,ptr,sizeof(trc_schedule_t));
371
          break;
372
        default:
373
          evt->x.norm.when=ll_gettime(TIME_EXACT,NULL);
374
          evt->x.norm.who=pid;
375
          break;
376
      }
377
 
378
    counter++;
379
  }
380
  kern_frestore(f);
381
 
382
  return;
383
}