libgcov: support overloaded malloc
gcc/ChangeLog: * gcov-io.h (GCOV_PREALLOCATED_KVP): New. libgcc/ChangeLog: * libgcov-driver.c: Add __gcov_kvp_pool and __gcov_kvp_pool_index variables. * libgcov.h (allocate_gcov_kvp): New. (gcov_topn_add_value): Use it. gcc/testsuite/ChangeLog: * gcc.dg/tree-prof/indir-call-prof-malloc.c: New test.
This commit is contained in:
parent
072a8b8fb6
commit
bc2b1a232b
@ -292,6 +292,9 @@ GCOV_COUNTERS
|
||||
/* Maximum number of tracked TOP N value profiles. */
|
||||
#define GCOV_TOPN_MAXIMUM_TRACKED_VALUES 32
|
||||
|
||||
/* Number of pre-allocated gcov_kvp structures. */
|
||||
#define GCOV_PREALLOCATED_KVP 16
|
||||
|
||||
/* Convert a counter index to a tag. */
|
||||
#define GCOV_TAG_FOR_COUNTER(COUNT) \
|
||||
(GCOV_TAG_COUNTER_BASE + ((gcov_unsigned_t)(COUNT) << 17))
|
||||
|
49
gcc/testsuite/gcc.dg/tree-prof/indir-call-prof-malloc.c
Normal file
49
gcc/testsuite/gcc.dg/tree-prof/indir-call-prof-malloc.c
Normal file
@ -0,0 +1,49 @@
|
||||
/* { dg-options "-O2 -ldl" } */
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
int global;
|
||||
int global2;
|
||||
|
||||
void report1 (size_t size)
|
||||
{
|
||||
global++;
|
||||
}
|
||||
|
||||
void report2 (size_t size)
|
||||
{
|
||||
global2++;
|
||||
}
|
||||
|
||||
typedef void (*tp) (size_t);
|
||||
static tp fns[] = {report1, report2};
|
||||
|
||||
void* malloc(size_t size)
|
||||
{
|
||||
static void* (*real_malloc)(size_t) = NULL;
|
||||
if (!real_malloc)
|
||||
real_malloc = dlsym(RTLD_NEXT, "malloc");
|
||||
|
||||
void *p = real_malloc (size);
|
||||
fns[size % 2] (size);
|
||||
// fprintf(stderr, "malloc(%d) = %p\n", size, p);
|
||||
return p;
|
||||
}
|
||||
|
||||
void *calloc (size_t n, size_t size)
|
||||
{
|
||||
void *ptr = malloc (n * size);
|
||||
__builtin_memset (ptr, 0, n * size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *ptr;
|
||||
|
||||
int main()
|
||||
{
|
||||
ptr = malloc (16);
|
||||
return 0;
|
||||
}
|
@ -588,6 +588,12 @@ struct gcov_root __gcov_root;
|
||||
struct gcov_master __gcov_master =
|
||||
{GCOV_VERSION, 0};
|
||||
|
||||
/* Pool of pre-allocated gcov_kvp strutures. */
|
||||
struct gcov_kvp __gcov_kvp_pool[GCOV_PREALLOCATED_KVP];
|
||||
|
||||
/* Index to first free gcov_kvp in the pool. */
|
||||
unsigned __gcov_kvp_pool_index;
|
||||
|
||||
void
|
||||
__gcov_exit (void)
|
||||
{
|
||||
|
@ -250,6 +250,8 @@ struct indirect_call_tuple
|
||||
|
||||
/* Exactly one of these will be active in the process. */
|
||||
extern struct gcov_master __gcov_master;
|
||||
extern struct gcov_kvp __gcov_kvp_pool[GCOV_PREALLOCATED_KVP];
|
||||
extern unsigned __gcov_kvp_pool_index;
|
||||
|
||||
/* Dump a set of gcov objects. */
|
||||
extern void __gcov_dump_one (struct gcov_root *) ATTRIBUTE_HIDDEN;
|
||||
@ -402,6 +404,47 @@ gcov_counter_add (gcov_type *counter, gcov_type value,
|
||||
*counter += value;
|
||||
}
|
||||
|
||||
/* Allocate gcov_kvp from heap. If we are recursively called, then allocate
|
||||
it from a list of pre-allocated pool. */
|
||||
|
||||
static inline struct gcov_kvp *
|
||||
allocate_gcov_kvp (void)
|
||||
{
|
||||
struct gcov_kvp *new_node = NULL;
|
||||
|
||||
static
|
||||
#if defined(HAVE_CC_TLS)
|
||||
__thread
|
||||
#endif
|
||||
volatile unsigned in_recursion ATTRIBUTE_UNUSED = 0;
|
||||
|
||||
#if !defined(IN_GCOV_TOOL) && !defined(L_gcov_merge_topn)
|
||||
if (__builtin_expect (in_recursion, 0))
|
||||
{
|
||||
unsigned index;
|
||||
#if GCOV_SUPPORTS_ATOMIC
|
||||
index
|
||||
= __atomic_fetch_add (&__gcov_kvp_pool_index, 1, __ATOMIC_RELAXED);
|
||||
#else
|
||||
index = __gcov_kvp_pool_index++;
|
||||
#endif
|
||||
if (index < GCOV_PREALLOCATED_KVP)
|
||||
new_node = &__gcov_kvp_pool[index];
|
||||
else
|
||||
/* Do not crash in the situation. */
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
in_recursion = 1;
|
||||
new_node = (struct gcov_kvp *)xcalloc (1, sizeof (struct gcov_kvp));
|
||||
in_recursion = 0;
|
||||
}
|
||||
|
||||
return new_node;
|
||||
}
|
||||
|
||||
/* Add key value pair VALUE:COUNT to a top N COUNTERS. When INCREMENT_TOTAL
|
||||
is true, add COUNT to total of the TOP counter. If USE_ATOMIC is true,
|
||||
do it in atomic way. */
|
||||
@ -443,8 +486,10 @@ gcov_topn_add_value (gcov_type *counters, gcov_type value, gcov_type count,
|
||||
}
|
||||
else
|
||||
{
|
||||
struct gcov_kvp *new_node
|
||||
= (struct gcov_kvp *)xcalloc (1, sizeof (struct gcov_kvp));
|
||||
struct gcov_kvp *new_node = allocate_gcov_kvp ();
|
||||
if (new_node == NULL)
|
||||
return;
|
||||
|
||||
new_node->value = value;
|
||||
new_node->count = count;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user