Rev 352 | Go to most recent revision | 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 | * 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) 2000 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 | /* |
||
41 | * CVS : $Id: trccirc.c,v 1.1 2003-12-10 16:48:48 giacomo Exp $ |
||
42 | * |
||
43 | * File: $File$ |
||
44 | * Revision: $Revision: 1.1 $ |
||
45 | * Last update: $Date: 2003-12-10 16:48:48 $ |
||
46 | */ |
||
47 | |||
48 | #include <ll/sys/types.h> |
||
49 | #include <ll/stdlib.h> |
||
50 | |||
51 | #include <kernel/func.h> |
||
52 | #include <kernel/mem.h> |
||
53 | #include <kernel/log.h> |
||
54 | |||
55 | #include <types.h> |
||
56 | #include <trace.h> |
||
57 | #include <queues.h> |
||
58 | |||
59 | #include <fs/fs.h> |
||
60 | |||
61 | #include <unistd.h> |
||
62 | #include <fcntl.h> |
||
63 | #include <limits.h> |
||
64 | |||
65 | /* Well... this file is very similar to trcfixed.c! */ |
||
66 | |||
67 | typedef struct TAGcircular_queue_t { |
||
68 | /*+ size of the queue +*/ |
||
69 | int size; |
||
70 | /*+ index of the next insertion into the queue +*/ |
||
71 | int index; |
||
72 | /*+ index of the next item to write (if online_tracer activated) +*/ |
||
73 | int windex; |
||
74 | /*+ number of events lost (if online_tracer activated) +*/ |
||
75 | long hoops; |
||
76 | /*+ filename of the trace file +*/ |
||
77 | char *filename; |
||
78 | /*+ flags from flags field of the initialization struct +*/ |
||
79 | int flags; |
||
80 | /*+ some internal models have needed of extra parameters +*/ |
||
81 | void *dummy; |
||
82 | /*+ unique number that identify the queue +*/ |
||
83 | int uniq; |
||
84 | |||
85 | /*+ events table +*/ |
||
86 | trc_event_t table[0]; |
||
87 | } circular_queue_t; |
||
88 | |||
89 | static int mustgodown=0; |
||
90 | |||
91 | static TASK online_tracer(circular_queue_t *queue) |
||
92 | { |
||
93 | char pathname[PATH_MAX]; |
||
94 | int handle; |
||
95 | int index; |
||
96 | |||
97 | if (queue->filename==NULL) trc_create_name("cir",queue->uniq,pathname); |
||
98 | else trc_create_name(queue->filename,0,pathname); |
||
99 | |||
100 | if (wait_for_fs_initialization()) { |
||
101 | printk(KERN_NOTICE "tracer online task not running"); |
||
102 | goto BADEND; |
||
103 | } |
||
104 | |||
105 | handle=open(pathname,O_CREAT|O_TRUNC|O_WRONLY); |
||
106 | if (handle==-1) { |
||
107 | printk(KERN_NOTICE "tracer file %s not created!",pathname); |
||
108 | goto BADEND; |
||
109 | } |
||
110 | |||
111 | for (;;) { |
||
112 | while (queue->index!=queue->windex) { |
||
113 | index=queue->index; |
||
114 | if (index<queue->windex) { |
||
115 | write(handle, |
||
116 | queue->table+queue->windex, |
||
117 | (queue->size-queue->windex)*sizeof(trc_event_t) |
||
118 | ); |
||
119 | queue->windex=0; |
||
120 | continue; |
||
121 | } |
||
122 | write(handle, |
||
123 | queue->table+queue->windex, |
||
124 | (index-queue->windex)*sizeof(trc_event_t) |
||
125 | ); |
||
126 | queue->windex=index; |
||
127 | } |
||
128 | if (mustgodown) break; |
||
129 | |||
130 | task_endcycle(); |
||
131 | } |
||
132 | |||
133 | close(handle); |
||
134 | printk(KERN_NOTICE "tracer file %s created!",pathname); |
||
135 | |||
136 | if (queue->hoops) |
||
137 | printk(KERN_NOTICE "tracer: %li event lost into %s",queue->hoops,pathname); |
||
138 | |||
139 | resume_fs_shutdown(); |
||
140 | return NULL; |
||
141 | |||
142 | BADEND: |
||
143 | resume_fs_shutdown(); |
||
144 | |||
145 | /*Why this? for a little bug on the task_makefree() routine */ |
||
146 | for (;;) { |
||
147 | if (mustgodown) break; |
||
148 | task_endcycle(); |
||
149 | } |
||
150 | |||
151 | return NULL; |
||
152 | } |
||
153 | |||
154 | static trc_event_t *circular_get2(circular_queue_t *queue) |
||
155 | { |
||
156 | if (queue->index==queue->size-1) { |
||
157 | if (queue->windex==0) { |
||
158 | queue->hoops++; |
||
159 | return NULL; |
||
160 | } |
||
161 | queue->index=0; |
||
162 | return &queue->table[queue->size-1]; |
||
163 | } |
||
164 | if (queue->index+1==queue->windex) { |
||
165 | queue->hoops++; |
||
166 | return NULL; |
||
167 | } |
||
168 | return &queue->table[queue->index++]; |
||
169 | } |
||
170 | |||
171 | static trc_event_t *circular_get1(circular_queue_t *queue) |
||
172 | { |
||
173 | if (queue->index==queue->size-1) { |
||
174 | queue->index=0; |
||
175 | return &queue->table[queue->size-1]; |
||
176 | } |
||
177 | return &queue->table[queue->index++]; |
||
178 | } |
||
179 | |||
180 | static int circular_post(circular_queue_t *queue) |
||
181 | { |
||
182 | return 0; |
||
183 | } |
||
184 | |||
185 | struct create_args { |
||
186 | long period; |
||
187 | long slice; |
||
188 | circular_queue_t *queue; |
||
189 | }; |
||
190 | |||
191 | |||
192 | /* to remove!!! */ |
||
193 | /* |
||
194 | static void circular_create_postponed(void *foo) |
||
195 | { |
||
196 | struct create_args *ptr=(struct create_args *)foo; |
||
197 | SOFT_TASK_MODEL model; |
||
198 | PID pid; |
||
199 | |||
200 | printk(KERN_DEBUG "postponed create: START"); |
||
201 | |||
202 | soft_task_default_model(model); |
||
203 | soft_task_def_system(model); |
||
204 | soft_task_def_notrace(model); |
||
205 | soft_task_def_periodic(model); |
||
206 | soft_task_def_period(model,ptr->period); |
||
207 | soft_task_def_met(model,ptr->slice); |
||
208 | soft_task_def_wcet(model,ptr->slice); |
||
209 | soft_task_def_arg(model,ptr->queue); |
||
210 | |||
211 | printk(KERN_DEBUG "postponed create: A"); |
||
212 | |||
213 | kern_free(foo,sizeof(struct create_args)); |
||
214 | |||
215 | printk(KERN_DEBUG "postponed create: B"); |
||
216 | |||
217 | pid=task_create("trcCirc",online_tracer,&model,NULL); |
||
218 | if (pid==-1) { |
||
219 | printk(KERN_ERR "can't start tracer online circular trace task"); |
||
220 | } else { |
||
221 | printk(KERN_DEBUG "postponed create: C1"); |
||
222 | task_activate(pid); |
||
223 | printk(KERN_DEBUG "postponed create: C2"); |
||
224 | suspend_fs_shutdown(); |
||
225 | printk(KERN_DEBUG "postponed create: C3"); |
||
226 | } |
||
227 | |||
228 | printk(KERN_DEBUG "postponed create: END"); |
||
229 | } |
||
230 | */ |
||
231 | |||
232 | static int circular_create(trc_queue_t *queue, TRC_CIRCULAR_PARMS *args) |
||
233 | { |
||
234 | TRC_CIRCULAR_PARMS defaultargs; |
||
235 | circular_queue_t *ptr; |
||
236 | |||
237 | if (args==NULL) { |
||
238 | trc_circular_default_parms(defaultargs); |
||
239 | args=&defaultargs; |
||
240 | } |
||
241 | |||
242 | ptr=(circular_queue_t*)kern_alloc(sizeof(circular_queue_t)+ |
||
243 | sizeof(trc_event_t)*args->size); |
||
244 | if (ptr==NULL) return -1; |
||
245 | |||
246 | queue->get=(trc_event_t*(*)(void*))circular_get1; |
||
247 | queue->post=(int(*)(void*))circular_post; |
||
248 | queue->data=ptr; |
||
249 | |||
250 | ptr->size=args->size; |
||
251 | ptr->windex=ptr->index=0; |
||
252 | ptr->hoops=0; |
||
253 | ptr->filename=args->filename; |
||
254 | ptr->flags=args->flags; |
||
255 | ptr->dummy=NULL; |
||
256 | |||
257 | if (args->flags&TRC_CIRCULAR_ONLINETASK) { |
||
258 | struct create_args *p; |
||
259 | p=kern_alloc(sizeof(struct create_args)); |
||
260 | if (p==NULL) { |
||
261 | printk(KERN_ERR "can't create tracer online circular trace task"); |
||
262 | return -1; |
||
263 | } |
||
264 | queue->get=(trc_event_t*(*)(void*))circular_get2; |
||
265 | ptr->dummy=p; |
||
266 | |||
267 | p->period=args->period; |
||
268 | p->slice=args->slice; |
||
269 | p->queue=ptr; |
||
270 | //sys_atrunlevel(circular_create_postponed,(void*)p,RUNLEVEL_INIT); |
||
271 | } |
||
272 | |||
273 | return 0; |
||
274 | } |
||
275 | |||
276 | static int circular_activate(circular_queue_t *queue, int uniq) |
||
277 | { |
||
278 | queue->uniq=uniq; |
||
279 | |||
280 | if (queue->flags&TRC_CIRCULAR_ONLINETASK) { |
||
281 | |||
282 | struct create_args *ptr=(struct create_args *)queue->dummy; |
||
283 | SOFT_TASK_MODEL model; |
||
284 | PID pid; |
||
285 | |||
286 | printk(KERN_DEBUG "postponed create: START"); |
||
287 | |||
288 | soft_task_default_model(model); |
||
289 | soft_task_def_system(model); |
||
290 | soft_task_def_notrace(model); |
||
291 | soft_task_def_periodic(model); |
||
292 | soft_task_def_period(model,ptr->period); |
||
293 | soft_task_def_met(model,ptr->slice); |
||
294 | soft_task_def_wcet(model,ptr->slice); |
||
295 | soft_task_def_arg(model,ptr->queue); |
||
296 | |||
297 | printk(KERN_DEBUG "postponed create: A"); |
||
298 | |||
299 | kern_free(queue->dummy,sizeof(struct create_args)); |
||
300 | |||
301 | printk(KERN_DEBUG "postponed create: B"); |
||
302 | |||
303 | pid=task_create("trcCirc",online_tracer,&model,NULL); |
||
304 | if (pid==-1) { |
||
305 | printk(KERN_ERR "can't start tracer online circular trace task"); |
||
306 | } else { |
||
307 | printk(KERN_DEBUG "postponed create: C1"); |
||
308 | suspend_fs_shutdown(); |
||
309 | printk(KERN_DEBUG "postponed create: C2"); |
||
310 | task_activate(pid); |
||
311 | printk(KERN_DEBUG "postponed create: C3"); |
||
312 | } |
||
313 | |||
314 | printk(KERN_DEBUG "postponed create: END"); |
||
315 | } |
||
316 | |||
317 | return 0; |
||
318 | } |
||
319 | |||
320 | static TASK circular_shutdown(circular_queue_t *queue) |
||
321 | { |
||
322 | char pathname[PATH_MAX]; |
||
323 | int h; |
||
324 | |||
325 | if (queue->filename==NULL) trc_create_name("cir",queue->uniq,pathname); |
||
326 | else trc_create_name(queue->filename,0,pathname); |
||
327 | |||
328 | h=open(pathname,O_CREAT|O_TRUNC|O_WRONLY); |
||
329 | if (h!=-1) { |
||
330 | if (queue->index!=queue->size-1) |
||
331 | write(h, |
||
332 | queue->table+queue->index+1, |
||
333 | (queue->size-queue->index-1)*sizeof(trc_event_t) |
||
334 | ); |
||
335 | write(h, |
||
336 | queue->table, |
||
337 | queue->index*sizeof(trc_event_t) |
||
338 | ); |
||
339 | close(h); |
||
340 | printk(KERN_NOTICE "tracer file %s created!",pathname); |
||
341 | } else |
||
342 | printk(KERN_NOTICE "tracer file %s NOT created!",pathname); |
||
343 | |||
344 | resume_fs_shutdown(); |
||
345 | return NULL; |
||
346 | } |
||
347 | |||
348 | static int circular_terminate(circular_queue_t *queue) |
||
349 | { |
||
350 | SOFT_TASK_MODEL model; |
||
351 | PID pid; |
||
352 | |||
353 | mustgodown=1; |
||
354 | if (queue->flags&TRC_CIRCULAR_ONLINETASK) return 0; |
||
355 | |||
356 | suspend_fs_shutdown(); |
||
357 | |||
358 | //nrt_task_default_model(model); |
||
359 | //nrt_task_def_system(model); |
||
360 | //nrt_task_def_arg(model,queue); |
||
361 | |||
362 | soft_task_default_model(model); |
||
363 | soft_task_def_system(model); |
||
364 | soft_task_def_notrace(model); |
||
365 | soft_task_def_periodic(model); |
||
366 | soft_task_def_period(model,50000); |
||
367 | soft_task_def_met(model,10000); |
||
368 | soft_task_def_wcet(model,10000); |
||
369 | soft_task_def_arg(model,queue); |
||
370 | |||
371 | pid=task_create("ShutTrcCir",circular_shutdown,&model,NULL); |
||
372 | if (pid==-1) { |
||
373 | printk(KERN_ERR "can't start tracer shutdown task (circular)"); |
||
374 | return -1; |
||
375 | } else |
||
376 | task_activate(pid); |
||
377 | |||
378 | return 0; |
||
379 | } |
||
380 | |||
381 | int trc_register_circular_queue(void) |
||
382 | { |
||
383 | int res; |
||
384 | |||
385 | res=trc_register_queuetype(TRC_CIRCULAR_QUEUE, |
||
386 | (int(*)(trc_queue_t*,void*))circular_create, |
||
387 | (int(*)(void*,int))circular_activate, |
||
388 | (int(*)(void*))circular_terminate |
||
389 | ); |
||
390 | |||
391 | if (res!=0) printk(KERN_WARNING "can't register tracer circular queue"); |
||
392 | return res; |
||
393 | } |