Add hooking functionality
This allows us to hook chosen functions and do interesting things there (in particular: reentrancy checking).
This commit is contained in:
committed by
David Goldblatt
parent
36bd90b962
commit
0a0fcd3e6a
@@ -1,10 +1,42 @@
|
||||
#include "test/jemalloc_test.h"
|
||||
|
||||
/* Test status state. */
|
||||
|
||||
static unsigned test_count = 0;
|
||||
static test_status_t test_counts[test_status_count] = {0, 0, 0};
|
||||
static test_status_t test_status = test_status_pass;
|
||||
static const char * test_name = "";
|
||||
|
||||
/* Reentrancy testing helpers. */
|
||||
|
||||
#define NUM_REENTRANT_ALLOCS 20
|
||||
static bool reentrant = false;
|
||||
static bool hook_ran = false;
|
||||
static void *to_free[NUM_REENTRANT_ALLOCS];
|
||||
|
||||
static void
|
||||
reentrancy_hook() {
|
||||
hook_ran = true;
|
||||
hooks_libc_hook = NULL;
|
||||
|
||||
void *to_free_local[NUM_REENTRANT_ALLOCS];
|
||||
size_t alloc_size = 1;
|
||||
for (int i = 0; i < NUM_REENTRANT_ALLOCS; i++) {
|
||||
to_free[i] = malloc(alloc_size);
|
||||
to_free_local[i] = malloc(alloc_size);
|
||||
alloc_size *= 2;
|
||||
}
|
||||
for (int i = 0; i < NUM_REENTRANT_ALLOCS; i++) {
|
||||
free(to_free_local[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Actual test infrastructure. */
|
||||
bool
|
||||
test_is_reentrant() {
|
||||
return reentrant;
|
||||
}
|
||||
|
||||
JEMALLOC_FORMAT_PRINTF(1, 2)
|
||||
void
|
||||
test_skip(const char *format, ...) {
|
||||
@@ -49,11 +81,13 @@ p_test_init(const char *name) {
|
||||
void
|
||||
p_test_fini(void) {
|
||||
test_counts[test_status]++;
|
||||
malloc_printf("%s: %s\n", test_name, test_status_string(test_status));
|
||||
malloc_printf("%s: %s (%s)\n", test_name,
|
||||
test_status_string(test_status),
|
||||
reentrant ? "reentrant" : "non-reentrant");
|
||||
}
|
||||
|
||||
static test_status_t
|
||||
p_test_impl(bool do_malloc_init, test_t *t, va_list ap) {
|
||||
p_test_impl(bool do_malloc_init, bool do_reentrant, test_t *t, va_list ap) {
|
||||
test_status_t ret;
|
||||
|
||||
if (do_malloc_init) {
|
||||
@@ -71,10 +105,27 @@ p_test_impl(bool do_malloc_init, test_t *t, va_list ap) {
|
||||
|
||||
ret = test_status_pass;
|
||||
for (; t != NULL; t = va_arg(ap, test_t *)) {
|
||||
/* Non-reentrant run. */
|
||||
reentrant = false;
|
||||
t();
|
||||
if (test_status > ret) {
|
||||
ret = test_status;
|
||||
}
|
||||
/* Reentrant run. */
|
||||
if (do_reentrant) {
|
||||
reentrant = true;
|
||||
hooks_libc_hook = &reentrancy_hook;
|
||||
t();
|
||||
if (test_status > ret) {
|
||||
ret = test_status;
|
||||
}
|
||||
if (hook_ran) {
|
||||
hook_ran = false;
|
||||
for (int i = 0; i < NUM_REENTRANT_ALLOCS; i++) {
|
||||
free(to_free[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
malloc_printf("--- %s: %u/%u, %s: %u/%u, %s: %u/%u ---\n",
|
||||
@@ -95,7 +146,20 @@ p_test(test_t *t, ...) {
|
||||
|
||||
ret = test_status_pass;
|
||||
va_start(ap, t);
|
||||
ret = p_test_impl(true, t, ap);
|
||||
ret = p_test_impl(true, true, t, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
test_status_t
|
||||
p_test_no_reentrancy(test_t *t, ...) {
|
||||
test_status_t ret;
|
||||
va_list ap;
|
||||
|
||||
ret = test_status_pass;
|
||||
va_start(ap, t);
|
||||
ret = p_test_impl(true, false, t, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
@@ -108,7 +172,11 @@ p_test_no_malloc_init(test_t *t, ...) {
|
||||
|
||||
ret = test_status_pass;
|
||||
va_start(ap, t);
|
||||
ret = p_test_impl(false, t, ap);
|
||||
/*
|
||||
* We also omit reentrancy from bootstrapping tests, since we don't
|
||||
* (yet) care about general reentrancy during bootstrapping.
|
||||
*/
|
||||
ret = p_test_impl(false, false, t, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
|
Reference in New Issue
Block a user