Implement __gcov_dump_all for shared libs
[official-gcc.git] / gcc-4_9 / libgcc / libgcov-interface.c
bloba3effa41137f3047f658b4f5914008994465a009
1 /* Routines required for instrumenting a program. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1989-2014 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 #include "libgcov.h"
27 #include "gthr.h"
29 #if defined(inhibit_libc)
31 #ifdef L_gcov_flush
32 void __gcov_flush (void) {}
33 #endif
35 #ifdef L_gcov_reset
36 void __gcov_reset (void) {}
37 #endif
39 #ifdef L_gcov_dump
40 void __gcov_dump (void) {}
41 #endif
43 #else
45 extern void gcov_clear (void) ATTRIBUTE_HIDDEN;
46 extern void gcov_exit (void) ATTRIBUTE_HIDDEN;
47 extern void set_gcov_dump_complete (void) ATTRIBUTE_HIDDEN;
48 extern void reset_gcov_dump_complete (void) ATTRIBUTE_HIDDEN;
50 #ifdef L_gcov_flush
52 #ifdef __GTHREAD_MUTEX_INIT
53 ATTRIBUTE_HIDDEN __gthread_mutex_t __gcov_flush_mx = __GTHREAD_MUTEX_INIT;
54 #define init_mx_once()
55 #else
56 __gthread_mutex_t __gcov_flush_mx ATTRIBUTE_HIDDEN;
58 static void
59 init_mx (void)
61 __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_flush_mx);
63 static void
64 init_mx_once (void)
66 static __gthread_once_t once = __GTHREAD_ONCE_INIT;
67 __gthread_once (&once, init_mx);
69 #endif
71 /* Called before fork or exec - write out profile information gathered so
72 far and reset it to zero. This avoids duplication or loss of the
73 profile information gathered so far. */
75 void
76 __gcov_flush (void)
78 init_mx_once ();
79 __gthread_mutex_lock (&__gcov_flush_mx);
81 gcov_exit ();
82 gcov_clear ();
84 __gthread_mutex_unlock (&__gcov_flush_mx);
87 #endif /* L_gcov_flush */
89 #ifdef L_gcov_reset
91 /* Function that can be called from application to reset counters to zero,
92 in order to collect profile in region of interest. */
94 void
95 __gcov_reset (void)
97 gcov_clear ();
98 /* Re-enable dumping to support collecting profile in multiple regions
99 of interest. */
100 reset_gcov_dump_complete ();
103 #endif /* L_gcov_reset */
105 #ifdef L_gcov_dump
107 /* Function that can be called from application to write profile collected
108 so far, in order to collect profile in region of interest. */
110 void
111 __gcov_dump (void)
113 gcov_exit ();
114 /* Prevent profile from being dumped a second time on application exit. */
115 set_gcov_dump_complete ();
118 /* Emitted in coverage.c. */
119 extern gcov_unsigned_t __gcov_test_coverage;
121 unsigned int __gcov_profiling_for_test_coverage (void);
123 /* Function that can be called from application to distinguish binaries
124 instrumented for coverage from those instrumented for profile
125 optimization (e.g. -fprofile-generate). */
127 unsigned int __gcov_profiling_for_test_coverage (void)
129 return __gcov_test_coverage;
132 typedef void (*gcov_dumper_type) (void);
133 struct dumper_entry
135 gcov_dumper_type dumper;
136 struct dumper_entry *next_dumper;
139 static struct dumper_entry this_dumper = {&__gcov_dump, 0};
141 /* global dumper list with default visibilty. */
142 struct dumper_entry *__gcov_dumper_list;
144 #ifdef __GTHREAD_MUTEX_INIT
145 __gthread_mutex_t __gcov_dump_mx = __GTHREAD_MUTEX_INIT;
146 #define init_mx_once()
147 #else
148 __gthread_mutex_t __gcov_dump_mx;
150 static void
151 init_mx (void)
153 __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_dump_mx);
155 static void
156 init_mx_once (void)
158 static __gthread_once_t once = __GTHREAD_ONCE_INIT;
159 __gthread_once (&once, init_mx);
161 #endif
163 /* Register the library private __gcov_dump method
164 to the global list. */
166 __attribute__((constructor))
167 static void
168 register_dumper (void)
170 init_mx_once ();
171 __gthread_mutex_lock (&__gcov_dump_mx);
172 this_dumper.next_dumper = __gcov_dumper_list;
173 __gcov_dumper_list = &this_dumper;
174 __gthread_mutex_unlock (&__gcov_dump_mx);
177 __attribute__((destructor))
178 static void
179 unregister_dumper (void)
181 struct dumper_entry *dumper;
182 struct dumper_entry *prev_dumper = 0;
184 init_mx_once ();
185 __gthread_mutex_lock (&__gcov_dump_mx);
186 dumper = __gcov_dumper_list;
188 while (dumper)
190 if (dumper->dumper == &__gcov_dump)
192 if (prev_dumper)
193 prev_dumper->next_dumper = dumper->next_dumper;
194 else
195 __gcov_dumper_list = dumper->next_dumper;
196 break;
198 prev_dumper = dumper;
199 dumper = dumper->next_dumper;
201 __gthread_mutex_unlock (&__gcov_dump_mx);
204 /* Public interface to dump profile data for all shared libraries
205 via registered dumpers from the libraries. This interface
206 has default visibility (unlike gcov_dump which has hidden
207 visbility. */
209 void
210 __gcov_dump_all (void)
212 struct dumper_entry *dumper;
214 init_mx_once ();
215 __gthread_mutex_lock (&__gcov_dump_mx);
217 dumper = __gcov_dumper_list;
218 while (dumper)
220 dumper->dumper ();
221 dumper = dumper->next_dumper;
223 __gthread_mutex_unlock (&__gcov_dump_mx);
226 #endif /* L_gcov_dump */
228 #ifdef L_gcov_sampling
230 /* Emitted in coverage.c. */
232 /* Sampling period. */
233 extern gcov_unsigned_t __gcov_sampling_period;
234 extern gcov_unsigned_t __gcov_has_sampling;
235 void __gcov_set_sampling_period (unsigned int period);
236 unsigned int __gcov_sampling_enabled ();
237 /* Per thread sample counter. */
238 __thread gcov_unsigned_t __gcov_sample_counter = 0;
240 /* Set sampling period to PERIOD. */
242 void __gcov_set_sampling_period (unsigned int period)
244 gcc_assert (__gcov_has_sampling);
245 __gcov_sampling_period = period;
248 unsigned int __gcov_sampling_enabled ()
250 return __gcov_has_sampling;
253 #endif
255 #ifdef L_gcov_prefix
257 /* Profile directory prefix specified to -fprofile-generate=. */
258 extern char * __gcov_profile_prefix;
260 char *__gcov_get_profile_prefix ()
262 return __gcov_profile_prefix;
265 #endif
268 #ifdef L_gcov_fork
269 /* A wrapper for the fork function. Flushes the accumulated profiling data, so
270 that they are not counted twice. */
272 pid_t
273 __gcov_fork (void)
275 pid_t pid;
276 extern __gthread_mutex_t __gcov_flush_mx;
277 __gcov_flush ();
278 pid = fork ();
279 if (pid == 0)
280 __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_flush_mx);
281 return pid;
283 #endif
285 #ifdef L_gcov_execl
286 /* A wrapper for the execl function. Flushes the accumulated profiling data, so
287 that they are not lost. */
290 __gcov_execl (const char *path, char *arg, ...)
292 va_list ap, aq;
293 unsigned i, length;
294 char **args;
296 __gcov_flush ();
298 va_start (ap, arg);
299 va_copy (aq, ap);
301 length = 2;
302 while (va_arg (ap, char *))
303 length++;
304 va_end (ap);
306 args = (char **) alloca (length * sizeof (void *));
307 args[0] = arg;
308 for (i = 1; i < length; i++)
309 args[i] = va_arg (aq, char *);
310 va_end (aq);
312 return execv (path, args);
314 #endif
316 #ifdef L_gcov_execlp
317 /* A wrapper for the execlp function. Flushes the accumulated profiling data, so
318 that they are not lost. */
321 __gcov_execlp (const char *path, char *arg, ...)
323 va_list ap, aq;
324 unsigned i, length;
325 char **args;
327 __gcov_flush ();
329 va_start (ap, arg);
330 va_copy (aq, ap);
332 length = 2;
333 while (va_arg (ap, char *))
334 length++;
335 va_end (ap);
337 args = (char **) alloca (length * sizeof (void *));
338 args[0] = arg;
339 for (i = 1; i < length; i++)
340 args[i] = va_arg (aq, char *);
341 va_end (aq);
343 return execvp (path, args);
345 #endif
347 #ifdef L_gcov_execle
348 /* A wrapper for the execle function. Flushes the accumulated profiling data, so
349 that they are not lost. */
352 __gcov_execle (const char *path, char *arg, ...)
354 va_list ap, aq;
355 unsigned i, length;
356 char **args;
357 char **envp;
359 __gcov_flush ();
361 va_start (ap, arg);
362 va_copy (aq, ap);
364 length = 2;
365 while (va_arg (ap, char *))
366 length++;
367 va_end (ap);
369 args = (char **) alloca (length * sizeof (void *));
370 args[0] = arg;
371 for (i = 1; i < length; i++)
372 args[i] = va_arg (aq, char *);
373 envp = va_arg (aq, char **);
374 va_end (aq);
376 return execve (path, args, envp);
378 #endif
380 #ifdef L_gcov_execv
381 /* A wrapper for the execv function. Flushes the accumulated profiling data, so
382 that they are not lost. */
385 __gcov_execv (const char *path, char *const argv[])
387 __gcov_flush ();
388 return execv (path, argv);
390 #endif
392 #ifdef L_gcov_execvp
393 /* A wrapper for the execvp function. Flushes the accumulated profiling data, so
394 that they are not lost. */
397 __gcov_execvp (const char *path, char *const argv[])
399 __gcov_flush ();
400 return execvp (path, argv);
402 #endif
404 #ifdef L_gcov_execve
405 /* A wrapper for the execve function. Flushes the accumulated profiling data, so
406 that they are not lost. */
409 __gcov_execve (const char *path, char *const argv[], char *const envp[])
411 __gcov_flush ();
412 return execve (path, argv, envp);
414 #endif
415 #endif /* inhibit_libc */