Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6515 serge 1
/* Routines required for instrumenting a program.  */
2
/* Compile this one with gcc.  */
3
/* Copyright (C) 1989-2015 Free Software Foundation, Inc.
4
 
5
This file is part of GCC.
6
 
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.
11
 
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.
16
 
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.
20
 
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
.  */
25
 
26
#include "libgcov.h"
27
#include "gthr.h"
28
 
29
#if defined(inhibit_libc)
30
 
31
#ifdef L_gcov_flush
32
void __gcov_flush (void) {}
33
#endif
34
 
35
#ifdef L_gcov_reset
36
void __gcov_reset (void) {}
37
#endif
38
 
39
#ifdef L_gcov_dump
40
void __gcov_dump (void) {}
41
#endif
42
 
43
#else
44
 
45
/* Some functions we want to bind in this dynamic object, but have an
46
   overridable global alias.  Unfortunately not all targets support
47
   aliases, so we just have a forwarding function.  That'll be tail
48
   called, so the cost is a single jump instruction.*/
49
 
50
#define ALIAS_void_fn(src,dst) \
51
  void dst (void)	    \
52
  { src (); }
53
 
54
extern __gthread_mutex_t __gcov_flush_mx ATTRIBUTE_HIDDEN;
55
extern __gthread_mutex_t __gcov_flush_mx ATTRIBUTE_HIDDEN;
56
 
57
#ifdef L_gcov_flush
58
#ifdef __GTHREAD_MUTEX_INIT
59
__gthread_mutex_t __gcov_flush_mx = __GTHREAD_MUTEX_INIT;
60
#define init_mx_once()
61
#else
62
__gthread_mutex_t __gcov_flush_mx;
63
 
64
static void
65
init_mx (void)
66
{
67
  __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_flush_mx);
68
}
69
 
70
static void
71
init_mx_once (void)
72
{
73
  static __gthread_once_t once = __GTHREAD_ONCE_INIT;
74
  __gthread_once (&once, init_mx);
75
}
76
#endif
77
 
78
/* Called before fork or exec - write out profile information gathered so
79
   far and reset it to zero.  This avoids duplication or loss of the
80
   profile information gathered so far.  */
81
 
82
void
83
__gcov_flush (void)
84
{
85
  init_mx_once ();
86
  __gthread_mutex_lock (&__gcov_flush_mx);
87
 
88
  __gcov_dump_int ();
89
  __gcov_reset_int ();
90
 
91
  __gthread_mutex_unlock (&__gcov_flush_mx);
92
}
93
 
94
#endif /* L_gcov_flush */
95
 
96
#ifdef L_gcov_reset
97
 
98
/* Reset all counters to zero.  */
99
 
100
static void
101
gcov_clear (const struct gcov_info *list)
102
{
103
  const struct gcov_info *gi_ptr;
104
 
105
  for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
106
    {
107
      unsigned f_ix;
108
 
109
      for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
110
        {
111
          unsigned t_ix;
112
          const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
113
 
114
          if (!gfi_ptr || gfi_ptr->key != gi_ptr)
115
            continue;
116
          const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
117
          for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
118
            {
119
              if (!gi_ptr->merge[t_ix])
120
                continue;
121
 
122
              memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
123
              ci_ptr++;
124
            }
125
        }
126
    }
127
}
128
 
129
/* Function that can be called from application to reset counters to zero,
130
   in order to collect profile in region of interest.  */
131
 
132
void
133
__gcov_reset_int (void)
134
{
135
  struct gcov_root *root;
136
 
137
  /* If we're compatible with the master, iterate over everything,
138
     otherise just do us.  */
139
  for (root = __gcov_master.version == GCOV_VERSION
140
	 ? __gcov_master.root : &__gcov_root; root; root = root->next)
141
    {
142
      gcov_clear (root->list);
143
      root->dumped = 0;
144
    }
145
}
146
 
147
ALIAS_void_fn (__gcov_reset_int, __gcov_reset);
148
 
149
#endif /* L_gcov_reset */
150
 
151
#ifdef L_gcov_dump
152
/* Function that can be called from application to write profile collected
153
   so far, in order to collect profile in region of interest.  */
154
 
155
void
156
__gcov_dump_int (void)
157
{
158
  struct gcov_root *root;
159
 
160
  /* If we're compatible with the master, iterate over everything,
161
     otherise just do us.  */
162
  for (root = __gcov_master.version == GCOV_VERSION
163
	 ? __gcov_master.root : &__gcov_root; root; root = root->next)
164
    __gcov_dump_one (root);
165
}
166
 
167
ALIAS_void_fn (__gcov_dump_int, __gcov_dump);
168
 
169
#endif /* L_gcov_dump */
170
 
171
#ifdef L_gcov_fork
172
/* A wrapper for the fork function.  Flushes the accumulated profiling data, so
173
   that they are not counted twice.  */
174
 
175
pid_t
176
__gcov_fork (void)
177
{
178
  pid_t pid;
179
  __gcov_flush ();
180
  pid = fork ();
181
  if (pid == 0)
182
    __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_flush_mx);
183
  return pid;
184
}
185
#endif
186
 
187
#ifdef L_gcov_execl
188
/* A wrapper for the execl function.  Flushes the accumulated
189
   profiling data, so that they are not lost.  */
190
 
191
int
192
__gcov_execl (const char *path, char *arg, ...)
193
{
194
  va_list ap, aq;
195
  unsigned i, length;
196
  char **args;
197
 
198
  __gcov_flush ();
199
 
200
  va_start (ap, arg);
201
  va_copy (aq, ap);
202
 
203
  length = 2;
204
  while (va_arg (ap, char *))
205
    length++;
206
  va_end (ap);
207
 
208
  args = (char **) alloca (length * sizeof (void *));
209
  args[0] = arg;
210
  for (i = 1; i < length; i++)
211
    args[i] = va_arg (aq, char *);
212
  va_end (aq);
213
 
214
  return execv (path, args);
215
}
216
#endif
217
 
218
#ifdef L_gcov_execlp
219
/* A wrapper for the execlp function.  Flushes the accumulated
220
   profiling data, so that they are not lost.  */
221
 
222
int
223
__gcov_execlp (const char *path, char *arg, ...)
224
{
225
  va_list ap, aq;
226
  unsigned i, length;
227
  char **args;
228
 
229
  __gcov_flush ();
230
 
231
  va_start (ap, arg);
232
  va_copy (aq, ap);
233
 
234
  length = 2;
235
  while (va_arg (ap, char *))
236
    length++;
237
  va_end (ap);
238
 
239
  args = (char **) alloca (length * sizeof (void *));
240
  args[0] = arg;
241
  for (i = 1; i < length; i++)
242
    args[i] = va_arg (aq, char *);
243
  va_end (aq);
244
 
245
  return execvp (path, args);
246
}
247
#endif
248
 
249
#ifdef L_gcov_execle
250
/* A wrapper for the execle function.  Flushes the accumulated
251
   profiling data, so that they are not lost.  */
252
 
253
int
254
__gcov_execle (const char *path, char *arg, ...)
255
{
256
  va_list ap, aq;
257
  unsigned i, length;
258
  char **args;
259
  char **envp;
260
 
261
  __gcov_flush ();
262
 
263
  va_start (ap, arg);
264
  va_copy (aq, ap);
265
 
266
  length = 2;
267
  while (va_arg (ap, char *))
268
    length++;
269
  va_end (ap);
270
 
271
  args = (char **) alloca (length * sizeof (void *));
272
  args[0] = arg;
273
  for (i = 1; i < length; i++)
274
    args[i] = va_arg (aq, char *);
275
  envp = va_arg (aq, char **);
276
  va_end (aq);
277
 
278
  return execve (path, args, envp);
279
}
280
#endif
281
 
282
#ifdef L_gcov_execv
283
/* A wrapper for the execv function.  Flushes the accumulated
284
   profiling data, so that they are not lost.  */
285
 
286
int
287
__gcov_execv (const char *path, char *const argv[])
288
{
289
  __gcov_flush ();
290
  return execv (path, argv);
291
}
292
#endif
293
 
294
#ifdef L_gcov_execvp
295
/* A wrapper for the execvp function.  Flushes the accumulated
296
   profiling data, so that they are not lost.  */
297
 
298
int
299
__gcov_execvp (const char *path, char *const argv[])
300
{
301
  __gcov_flush ();
302
  return execvp (path, argv);
303
}
304
#endif
305
 
306
#ifdef L_gcov_execve
307
/* A wrapper for the execve function.  Flushes the accumulated
308
   profiling data, so that they are not lost.  */
309
 
310
int
311
__gcov_execve (const char *path, char *const argv[], char *const envp[])
312
{
313
  __gcov_flush ();
314
  return execve (path, argv, envp);
315
}
316
#endif
317
#endif /* inhibit_libc */