"Fossies" - the Fresh Open Source Software Archive 
Member "FunctionCheck-3.2.0/src/libfc/fc_com.c" (26 May 2012, 10204 Bytes) of package /linux/privat/old/FunctionCheck-3.2.0.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /*
2 * FunctionCheck profiler
3 * (C) Copyright 2000-2012 Yannick Perret
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 /** fc_com.h: manage coms between profiled program and the manager **/
21
22 #include <errno.h>
23 #include <stdio.h>
24 #include "fc_com.h"
25 #include "fc_time.h"
26 #include "fc_global.h"
27 #include "fc_tools.h"
28 #include "fc_fifo.h"
29
30 #ifndef FC_NO_THREAD
31 #include <pthread.h>
32 #endif /* FC_NOTHREAD */
33
34 /** flag to indicate if the lib is compiled with threads **/
35 #ifndef FC_NO_THREAD
36 int fc_allow_thread_hard=1;
37 #else
38 int fc_allow_thread_hard=0;
39 #endif
40
41 /** sizes for each type **/
42 unsigned int fc_type_sizes[FC_TYPE_MAX] =
43 {
44 sizeof (FC_CEnter),
45 sizeof (FC_CExit),
46 sizeof (FC_CMalloc),
47 sizeof (FC_CFree),
48 sizeof (FC_CMemalign),
49 sizeof (FC_CRealloc),
50 sizeof (FC_CQuit),
51 sizeof (FC_CDlopen),
52 sizeof (FC_CDlclose),
53 sizeof (FC_CDlsym),
54 sizeof (FC_CParent),
55 sizeof (FC_CFork),
56 sizeof (FC_CThread),
57 sizeof (FC_CTime)
58 };
59
60 /* maximum element size of fc_type_sizes[] */
61 static unsigned int fc_max_tsize = 0;
62
63 /* FIFO for the com */
64 static FC_FIFO fc_com_fifo = FC_FIFO_NDEF;
65
66 /* mode */
67 int fc_used_mode=0;
68
69 /* current ID for SINGLE mode */
70 static int fc_single_id = 0;
71
72 /** internal data for messages **/
73 static unsigned char fc_buffer_total[512];
74 /* buffer for messages */
75 static unsigned char *fc_buffer_write = NULL;
76 /* offset to write the pid */
77 static unsigned char *fc_buffer_opid = NULL;
78 /* offset to write the tid */
79 static unsigned char *fc_buffer_otid = NULL;
80 /* offset to write the data */
81 static unsigned char *fc_buffer_odata = NULL;
82
83 /* impossible to code as inline due to containing #ifdef.
84 Easier to code too as a function instead of inline. */
85 static inline void build_fc_com(void** com, unsigned int *curid, unsigned int type)
86 {
87 unsigned char *buffer;
88
89 if (fc_buffer_opid != NULL)
90 {
91 *curid = getpid();
92 }
93 else
94 {
95 /* else if needed the tid */
96 if (fc_buffer_otid != NULL)
97 {
98 #ifdef FC_NO_THREAD
99 *curid = getpid();
100 #else
101 *curid = (unsigned int) pthread_self();
102 #endif
103 }
104 }
105
106 buffer = fc_fifo_write_single(fc_com_fifo, /* sizeof(int) for id + fc_max_tsize + sizeof(char) for type */ fc_max_tsize, *curid);
107 if (buffer == 0)
108 {
109 fc_message("failed to write to fifo buffer, full already.");
110 *com = 0;
111 return;
112 }
113
114 buffer[0] = (char) type;
115 buffer++;
116
117 if (fc_buffer_opid != NULL)
118 {
119 *((unsigned int*) buffer) = *curid;
120 buffer += sizeof (int);
121 }
122 else
123 {
124 if (fc_buffer_otid != NULL)
125 {
126 *((unsigned int*) buffer) = *curid;
127 buffer += sizeof (int);
128 }
129 }
130
131 *com = (void*)buffer;
132
133 return;
134 }
135
136 #define DECLARE_FC_COM(struct_) \
137 unsigned int curid = fc_single_id; \
138 struct_* com;
139
140 #define BUILD_FC_COM(type) build_fc_com((void**)&com, &curid, type); \
141 if (com == 0) \
142 return;
143
144 #define SEND_FC_COM() fc_fifo_write_single_done(fc_com_fifo, curid);
145
146 /* functions */
147 void fc_com_enter(void *f, void *s)
148 {
149 DECLARE_FC_COM(FC_CEnter);
150
151 BUILD_FC_COM(FC_TYPE_ENTER);
152
153 com->to = f;
154 com->from = s;
155 fc_gettimeofday(&(com->time));
156
157 SEND_FC_COM();
158 }
159
160 void fc_com_exit(void *f, void *s)
161 {
162 DECLARE_FC_COM(FC_CExit);
163
164 BUILD_FC_COM(FC_TYPE_EXIT);
165
166 com->to = f;
167 com->from = s;
168 fc_gettimeofday(&(com->time));
169
170 SEND_FC_COM();
171 }
172
173 void fc_com_malloc(void *ptr, unsigned int size, void *where)
174 {
175 DECLARE_FC_COM(FC_CMalloc);
176
177 BUILD_FC_COM(FC_TYPE_MALLOC);
178
179 com->ptr = ptr;
180 com->where = where;
181 com->size = size;
182
183 SEND_FC_COM();
184 }
185
186 void fc_com_free(void *ptr, void *where)
187 {
188 DECLARE_FC_COM(FC_CFree);
189
190 BUILD_FC_COM(FC_TYPE_FREE);
191
192 com->ptr = ptr;
193 com->where = where;
194
195 SEND_FC_COM();
196 }
197
198 void fc_com_realloc(void *ptr, void *inc, unsigned int size, void *where)
199 {
200 DECLARE_FC_COM(FC_CRealloc);
201
202 BUILD_FC_COM(FC_TYPE_REALLOC);
203
204 com->ptr = ptr;
205 com->old = inc;
206 com->size = size;
207 com->where = where;
208
209 SEND_FC_COM();
210 }
211
212 void fc_com_memalign(void *ptr, unsigned int align, unsigned int size, void *where)
213 {
214 DECLARE_FC_COM(FC_CMemalign);
215
216 BUILD_FC_COM(FC_TYPE_MEMALIGN);
217
218 com->ptr = ptr;
219 com->align = align;
220 com->size = size;
221 com->where = where;
222
223 SEND_FC_COM();
224 }
225
226 void fc_com_dlopen(void *ptr, const char *filename, int flag)
227 {
228 DECLARE_FC_COM(FC_CDlopen);
229
230 BUILD_FC_COM(FC_TYPE_DLOPEN);
231
232 com->handle = ptr;
233 com->flag = flag;
234 sprintf(com->name, "%31s", filename);
235
236 SEND_FC_COM();
237 }
238
239 void fc_com_dlclose(void *handle)
240 {
241 DECLARE_FC_COM(FC_CDlclose);
242
243 BUILD_FC_COM(FC_TYPE_DLCLOSE);
244
245 com->handle = handle;
246
247 SEND_FC_COM();
248 }
249
250 void fc_com_dlsym(void *ptr, void *handle, char *symbol)
251 {
252 DECLARE_FC_COM(FC_CDlsym);
253
254 BUILD_FC_COM(FC_TYPE_DLSYM);
255
256 com->handle = handle;
257 com->fnc = ptr;
258 sprintf(com->name, "%31s", symbol);
259
260 SEND_FC_COM();
261 }
262
263 void fc_com_fork(int pid)
264 {
265 DECLARE_FC_COM(FC_CFork);
266
267 BUILD_FC_COM(FC_TYPE_FORK);
268
269 com->child = pid;
270 fc_gettimeofday(&(com->time));
271
272 SEND_FC_COM();
273 }
274
275 void fc_com_thread(int tid)
276 {
277 DECLARE_FC_COM(FC_CThread);
278
279 BUILD_FC_COM(FC_TYPE_THREAD);
280
281 com->thread = tid;
282 fc_gettimeofday(&(com->time));
283
284 SEND_FC_COM();
285 }
286
287 void fc_com_parent(int pid)
288 {
289 DECLARE_FC_COM(FC_CParent);
290
291 BUILD_FC_COM(FC_TYPE_PARENT);
292
293 com->parent = pid;
294
295 SEND_FC_COM();
296 }
297
298 void fc_com_quit(void)
299 {
300 DECLARE_FC_COM(FC_CQuit);
301
302 BUILD_FC_COM(FC_TYPE_QUIT);
303
304 fc_gettimeofday(&(com->time));
305
306 SEND_FC_COM();
307 }
308
309 /* init the communication process and start the manager */
310 int fc_com_init(int mode, int buffer_size, unsigned int *shmid)
311 {
312 int i;
313
314 fc_debug("entering fc_com_init");
315
316 /* set the pointers */
317 fc_used_mode = mode;
318 if (mode == FC_MODE_SINGLE)
319 {
320 fc_buffer_write = fc_buffer_total;
321 fc_buffer_opid = NULL;
322 fc_buffer_otid = NULL;
323 fc_buffer_odata = &(fc_buffer_total[1]);
324 }
325 else
326 if (mode == FC_MODE_FORK)
327 {
328 fc_buffer_write = fc_buffer_total;
329 fc_buffer_opid = &(fc_buffer_total[1]);
330 fc_buffer_otid = NULL;
331 fc_buffer_odata = &(fc_buffer_total[1 + sizeof (int) ]);
332 }
333 else
334 if (mode == FC_MODE_THREAD)
335 {
336 fc_buffer_write = fc_buffer_total;
337 fc_buffer_opid = NULL;
338 fc_buffer_otid = &(fc_buffer_total[1]);
339 fc_buffer_odata = &(fc_buffer_total[1 + sizeof (int) ]);
340 }
341 else
342 {
343 fc_message("invalid mode for communication initialisation (%d).");
344 return (0);
345 }
346
347 /* compute the largest element size */
348 for (i = 0; i <= FC_TYPE_MAX; i++)
349 {
350 fc_max_tsize = (fc_type_sizes[i] > fc_max_tsize) ? fc_type_sizes[i] : fc_max_tsize;
351 }
352
353 fc_max_tsize += (sizeof(char) /*type*/ + sizeof(int) /*pid/tid*/);
354
355 /* create the FIFO */
356 fc_com_fifo = fc_fifo_create(buffer_size, fc_max_tsize, shmid, mode == FC_MODE_SINGLE ? 1 : 0);
357 if (fc_com_fifo == FC_FIFO_NDEF)
358 {/* error */
359 fc_message("error while opening fifo");
360 return (0);
361 }
362
363 fc_debug("FIFO '%d' mapped at %p", shmid, (void*) fc_com_fifo);
364
365 /* single-mode PID */
366 fc_single_id = (int) getpid();
367
368 /* ok */
369 return (1);
370 }
371
372 int fc_com_start_manager(unsigned int shmid)
373 {
374 int i, ret;
375 char *args[64];
376 char temp[1024];
377
378 /* args for the manager */
379 for (i = 0; i < 64; i++)
380 {
381 args[i] = NULL;
382 }
383
384 args[0] = strdup("fcmanager"); /* to change */
385 sprintf(temp, "%d", shmid);
386 args[1] = strdup(temp);
387
388 fc_debug("args [%s] [%s]", args[0], args[1]);
389
390 /* fork */
391 fc_debug("starting manager");
392 if ((ret = fork()) == 0)
393 {/* the child */
394 /* start the manager */
395 fc_debug("CHILD SIDE: -> execvp");
396 execvp(args[0], args);
397
398 fc_message("error: unable to start profile manager.");
399 fc_message_fatal(FC_ERR_EXEC, "unable to continute treatments.");
400 }
401
402 fc_debug("fork -> %d", ret);
403 if (ret < 0)
404 {
405 fc_message("error: unable to fork.");
406 fc_message_fatal(FC_ERR_FORK, "unable to continute treatments.");
407 }
408
409 return ret;
410 }
411
412 /* stop the communication process */
413 int fc_com_fini(unsigned int shmid)
414 {
415 /* close the com */
416 fc_fifo_close(fc_com_fifo, shmid, 0 /* don't delete shm, fcmanager still processing */);
417
418 /* nothing to do */
419 return(1);
420 }
421
422 /* send an init message */
423 int fc_com_write_init(FC_INIT *init)
424 {
425 fc_debug("writing FC_INIT structure");
426 if (fc_used_mode == FC_MODE_SINGLE)
427 {
428 init->first_pid = getpid();
429 }
430 else
431 if (fc_used_mode == FC_MODE_FORK)
432 {
433 init->first_pid = getpid();
434 }
435 else
436 if (fc_used_mode == FC_MODE_THREAD)
437 {
438 #ifndef FC_NO_THREAD
439 init->first_pid = pthread_self();
440 #else
441 init->first_pid = getpid();
442 #endif
443 }
444 else
445 {
446 fc_message("invalid mode for communication initialisation (%d).");
447 return 0;
448 }
449
450 fc_fifo_write_init(fc_com_fifo, init, sizeof(FC_INIT), fc_single_id);
451
452 return 1;
453 }
454
455 /* send an dynamic-lib message */
456 int fc_com_write_lib(FC_LDYN *ldyn)
457 {
458 fc_fifo_write_ldyn(fc_com_fifo, ldyn, sizeof (FC_LDYN), fc_single_id);
459
460 return 1;
461 }