aboutsummaryrefslogtreecommitdiff
path: root/libgcc
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2020-06-02 13:31:48 +0200
committerMartin Liska <mliska@suse.cz>2020-07-31 10:57:50 +0200
commitbc2b1a232b1825b421a1aaa21a0865b2d1e4e08c (patch)
treeca7bba49f12a55544ae9fa3ab9c44dfa5d9d0742 /libgcc
parent072a8b8fb6e861d8ac2db847bcc81dbcb1ef1b35 (diff)
downloadgcc-bc2b1a232b1825b421a1aaa21a0865b2d1e4e08c.zip
gcc-bc2b1a232b1825b421a1aaa21a0865b2d1e4e08c.tar.gz
gcc-bc2b1a232b1825b421a1aaa21a0865b2d1e4e08c.tar.bz2
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.
Diffstat (limited to 'libgcc')
-rw-r--r--libgcc/libgcov-driver.c6
-rw-r--r--libgcc/libgcov.h49
2 files changed, 53 insertions, 2 deletions
diff --git a/libgcc/libgcov-driver.c b/libgcc/libgcov-driver.c
index 2590593..5891426 100644
--- a/libgcc/libgcov-driver.c
+++ b/libgcc/libgcov-driver.c
@@ -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)
{
diff --git a/libgcc/libgcov.h b/libgcc/libgcov.h
index 81e1895..8be5beb 100644
--- a/libgcc/libgcov.h
+++ b/libgcc/libgcov.h
@@ -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;