Subversion Repositories shark

Rev

Go to most recent revision | Details | 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
 *   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) 2002 Paolo Gai
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
 * CVS :        $Id: trcudp.c,v 1.1 2003-12-10 16:48:48 giacomo Exp $
39
 */
40
 
41
#include <ll/sys/types.h>
42
#include <ll/stdlib.h>
43
 
44
#include <kernel/func.h>
45
#include <kernel/mem.h>
46
#include <kernel/log.h>
47
 
48
#include <types.h>
49
#include <trace.h>
50
#include <queues.h>
51
 
52
//#define DEBUG_TRCUDP
53
 
54
#define TRCUDP_MAXEVENTS (1500/sizeof(trc_event_t))
55
//#define TRCUDP_MAXEVENTS 10
56
 
57
/* Well... this file is very similar to trccirc.c! */
58
 
59
typedef struct TAGtrcudp_queue_t {
60
  /*+ size of the queue +*/
61
  int         size;
62
  /*+ index of the next insertion into the queue +*/
63
  int         index;
64
  /*+ index of the next item to write (if online_tracer activated) +*/
65
  int         windex;
66
  /*+ number of events lost (if online_tracer activated) +*/
67
  long        hoops;
68
  /*+ local and remote IP numbers +*/
69
  UDP_ADDR local, remote;
70
  /*+ unique number that identify the queue +*/
71
  int         uniq;
72
  /*+ =1 when the system shuts down +*/
73
  int mustgodown;
74
  TASK_MODEL *m;
75
  /*+ dummy, needed for creating a valid packet (dirty trick ;-) +*/
76
  short int   dummy;
77
  /*+ events table +*/
78
  trc_event_t table[0];  
79
} trcudp_queue_t;
80
 
81
static TASK online_tracer(trcudp_queue_t *queue)
82
{
83
  int s; /* the socket */
84
  int newwindex; /* new write index after sending the packet */
85
  int n; /* number of packets to send */
86
  short int *pkt;
87
 
88
 
89
  s = udp_bind(&queue->local, NULL);
90
 
91
  for (;;) {
92
    if (queue->index<queue->windex) {
93
      if (queue->windex+TRCUDP_MAXEVENTS < queue->size) {
94
        newwindex = queue->windex+TRCUDP_MAXEVENTS;
95
        n = TRCUDP_MAXEVENTS;
96
      } else {
97
        newwindex = 0;
98
        n = queue->size-queue->windex;
99
      }
100
    } else {
101
      if (queue->windex+TRCUDP_MAXEVENTS < queue->index) {
102
        newwindex = queue->windex+TRCUDP_MAXEVENTS;
103
        n = TRCUDP_MAXEVENTS;
104
      } else {
105
        newwindex = queue->index;
106
        n = queue->index-queue->windex;
107
      }
108
    }
109
 
110
    if (n) {
111
      /* set the number of events into the UDP packet.  It works
112
         because the event entry before windex is always empty, or
113
         because we use the dummy field into the struct */
114
      pkt = ((short int *)(queue->table+queue->windex))-1;
115
      *pkt = (short int)n;
116
      udp_sendto(s,(char *)pkt,
117
                 n*sizeof(trc_event_t)+2,&queue->remote);
118
#ifdef DEBUG_TRCUDP
119
      printk(KERN_DEBUG "UDP: SEND %d events,"
120
             " index %d windex %d new %d!!!\n",n,
121
             queue->index, queue->windex, newwindex);
122
#endif
123
      queue->windex = newwindex;
124
    }
125
 
126
    if (queue->mustgodown) {
127
      if (queue->windex == queue->index)
128
        break;
129
    }
130
    else
131
      task_endcycle();
132
  }
133
 
134
  return NULL;
135
}
136
 
137
 
138
static trc_event_t *trcudp_get(trcudp_queue_t *queue)
139
{
140
  if (queue->mustgodown)
141
    return NULL;
142
 
143
  if (queue->index==queue->size-1) {
144
    if (queue->windex==0) {
145
      queue->hoops++;
146
      return NULL;
147
    }
148
    queue->index=0;
149
    return &queue->table[queue->size-1];
150
  }  
151
  if (queue->index+1==queue->windex) {
152
    queue->hoops++;
153
    return NULL;
154
  }
155
  return &queue->table[queue->index++];
156
}
157
 
158
static int trcudp_post(trcudp_queue_t *queue)
159
{
160
  return 0;
161
}
162
 
163
static void trcudp_shutdown(trcudp_queue_t *queue);
164
 
165
static int trcudp_create(trc_queue_t *p, TRC_UDP_PARMS *args)
166
{
167
  trcudp_queue_t *queue;
168
 
169
  if (args==NULL) {
170
    printk(KERN_ERR "trcudp_create: you must specify a non-NULL parameter!");
171
    return -1;
172
  }
173
 
174
  queue=(trcudp_queue_t*)kern_alloc(sizeof(trcudp_queue_t)+
175
                                    sizeof(trc_event_t)*args->size);
176
  if (queue==NULL) {
177
    printk(KERN_ERR "trcudp_create: error during memory allocation!");
178
    return -1;
179
  }
180
 
181
  p->get=(trc_event_t*(*)(void*))trcudp_get;
182
  p->post=(int(*)(void*))trcudp_post;
183
  p->data=queue;
184
 
185
  queue->size=args->size;
186
  queue->windex=queue->index=0;
187
  queue->hoops=0;
188
  queue->local=args->local;
189
  queue->remote=args->remote;
190
  /* uniq initialized in trcudp_activate */
191
  queue->mustgodown=0;
192
  queue->m = args->model;
193
  /* dummy unused */
194
 
195
  /* AFTER exit because in that way we can hope to be back in text mode... */
196
  sys_atrunlevel((void (*)(void *))trcudp_shutdown, (void *)queue, RUNLEVEL_AFTER_EXIT);
197
 
198
  return 0;
199
}
200
 
201
static int trcudp_activate(trcudp_queue_t *queue, int uniq)
202
{
203
  SOFT_TASK_MODEL model;
204
  TASK_MODEL *m;
205
  PID pid;
206
 
207
 
208
  queue->uniq=uniq;
209
 
210
  if (!queue->m) {
211
    soft_task_default_model(model);
212
    soft_task_def_system(model);
213
    /* soft_task_def_notrace(model); Should we trace the tracer? */
214
    soft_task_def_periodic(model);
215
    soft_task_def_period(model,250000);
216
    soft_task_def_met(model,10000);
217
    soft_task_def_wcet(model,10000);
218
    /* soft_task_def_nokill(model); NOOOOOOO!!!! */
219
    soft_task_def_arg(model,queue);
220
    m = (TASK_MODEL *)&model;
221
  }
222
  else {
223
    m = queue->m;
224
    task_def_arg(*m,queue);
225
  }
226
 
227
  pid=task_create("trcUDP",online_tracer,m,NULL);
228
  if (pid==-1) {
229
    printk(KERN_ERR "can't start tracer online trcudp trace task");
230
  } else
231
    task_activate(pid);
232
 
233
  return 0;
234
}
235
 
236
static int trcudp_terminate(trcudp_queue_t *queue)
237
{
238
  queue->mustgodown = 1;
239
 
240
  return 0;
241
}
242
 
243
static void trcudp_shutdown(trcudp_queue_t *queue)
244
{
245
  printk(KERN_NOTICE "tracer: %li events lost into UDP queue %d",
246
         queue->hoops, queue->uniq);
247
}
248
 
249
int trc_register_udp_queue(void)
250
{
251
  int res;
252
 
253
  res=trc_register_queuetype(TRC_UDP_QUEUE,
254
                             (int(*)(trc_queue_t*,void*))trcudp_create,
255
                             (int(*)(void*,int))trcudp_activate,
256
                             (int(*)(void*))trcudp_terminate
257
                             );
258
 
259
  if (res!=0) printk(KERN_WARNING "can't register tracer trcudp queue");
260
  return res;
261
}