Rev 3 | Rev 25 | Go to most recent revision | 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 : |
||
10 | pj | 9 | * Paolo Gai <pj@gandalf.sssup.it> |
2 | pj | 10 | * Massimiliano Giorgi <massy@gandalf.sssup.it> |
10 | pj | 11 | * Luca Abeni <luca@gandalf.sssup.it> |
2 | pj | 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 | |||
10 | pj | 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.2 2002-10-28 07:54:52 pj Exp $ |
||
39 | */ |
||
40 | |||
2 | pj | 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 <trace/types.h> |
||
49 | #include <trace/trace.h> |
||
50 | #include <trace/queues.h> |
||
51 | |||
10 | pj | 52 | //#define DEBUG_TRCUDP |
2 | pj | 53 | |
10 | pj | 54 | #define TRCUDP_MAXEVENTS (1500/sizeof(trc_event_t)) |
55 | //#define TRCUDP_MAXEVENTS 10 |
||
2 | pj | 56 | |
10 | pj | 57 | /* Well... this file is very similar to trccirc.c! */ |
2 | pj | 58 | |
10 | pj | 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) |
||
2 | pj | 82 | { |
10 | pj | 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; |
||
2 | pj | 135 | } |
136 | |||
10 | pj | 137 | |
138 | static trc_event_t *trcudp_get(trcudp_queue_t *queue) |
||
2 | pj | 139 | { |
10 | pj | 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 | { |
||
2 | pj | 160 | return 0; |
161 | } |
||
162 | |||
10 | pj | 163 | static void trcudp_shutdown(trcudp_queue_t *queue); |
164 | |||
165 | static int trcudp_create(trc_queue_t *p, TRC_UDP_PARMS *args) |
||
2 | pj | 166 | { |
10 | pj | 167 | trcudp_queue_t *queue; |
2 | pj | 168 | |
10 | pj | 169 | if (args==NULL) { |
170 | printk(KERN_ERR "trcudp_create: you must specify a non-NULL parameter!"); |
||
171 | return -1; |
||
172 | } |
||
2 | pj | 173 | |
10 | pj | 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 | } |
||
2 | pj | 180 | |
10 | pj | 181 | p->get=(trc_event_t*(*)(void*))trcudp_get; |
182 | p->post=(int(*)(void*))trcudp_post; |
||
183 | p->data=queue; |
||
2 | pj | 184 | |
10 | pj | 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 | |||
2 | pj | 198 | return 0; |
199 | } |
||
200 | |||
10 | pj | 201 | static int trcudp_activate(trcudp_queue_t *queue, int uniq) |
2 | pj | 202 | { |
10 | pj | 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 | |||
225 | pid=task_create("trcUDP",online_tracer,m,NULL); |
||
226 | if (pid==-1) { |
||
227 | printk(KERN_ERR "can't start tracer online trcudp trace task"); |
||
228 | } else |
||
229 | task_activate(pid); |
||
230 | |||
2 | pj | 231 | return 0; |
232 | } |
||
233 | |||
10 | pj | 234 | static int trcudp_terminate(trcudp_queue_t *queue) |
2 | pj | 235 | { |
10 | pj | 236 | queue->mustgodown = 1; |
237 | |||
2 | pj | 238 | return 0; |
239 | } |
||
240 | |||
10 | pj | 241 | static void trcudp_shutdown(trcudp_queue_t *queue) |
242 | { |
||
243 | printk(KERN_NOTICE "tracer: %li events lost into UDP queue %d", |
||
244 | queue->hoops, queue->uniq); |
||
245 | } |
||
246 | |||
2 | pj | 247 | int trc_register_udp_queue(void) |
248 | { |
||
249 | int res; |
||
250 | |||
251 | res=trc_register_queuetype(TRC_UDP_QUEUE, |
||
10 | pj | 252 | (int(*)(trc_queue_t*,void*))trcudp_create, |
253 | (int(*)(void*,int))trcudp_activate, |
||
254 | (int(*)(void*))trcudp_terminate |
||
255 | ); |
||
256 | |||
257 | if (res!=0) printk(KERN_WARNING "can't register tracer trcudp queue"); |
||
2 | pj | 258 | return res; |
259 | } |