diff options
Diffstat (limited to 'src/pk.h')
| -rw-r--r-- | src/pk.h | 348 |
1 files changed, 295 insertions, 53 deletions
@@ -1,7 +1,7 @@ #ifndef PK_SINGLE_HEADER_FILE_H #define PK_SINGLE_HEADER_FILE_H /******************************************************************************* -* PK Single-Header-Library V0.7.0 +* PK Single-Header-Library V0.9.0 * * Author: Jonathan Bradley * Copyright: © 2024-2025 Jonathan Bradley @@ -291,7 +291,7 @@ * *******************************************************************************/ -#define PK_VERSION "0.7.0" +#define PK_VERSION "0.9.0" #ifdef PK_IMPL_ALL # ifndef PK_IMPL_MEM_TYPES @@ -912,6 +912,9 @@ pk_mem_bucket_create(const char* description, int64_t sz, enum PK_MEMBUCKET_FLAG // [000-127] pk_membucket // [128-191] 64 bytes of data LOL // [192-511] 20 pk_memblocks (20 is worst-case, start 16, 4 per 64 bytes) + if ((sz % 64) > 0) { + sz += 64 - (sz % 64); + } assert(sz >= 512 && "[pkmem.h] bucket too small to track allocation data"); struct pk_membucket* bkt = (struct pk_membucket*)aligned_alloc(64, sz); if (bkt == NULL) return NULL; @@ -1767,6 +1770,37 @@ pk_ev_unregister_cb(pk_ev_mgr_id_T evmgr, pk_ev_id_T evid, pk_ev_cb_id_T cbid) } #endif /* PK_IMPL_EV */ +#ifndef PK_PKITER_H +#define PK_PKITER_H + +union pk_iter_id { + struct pk_iter_bkt_handle { + unsigned int b : 24; + unsigned int i : 8; + } bkt; + struct pk_iter_arr_idx { + unsigned int i : 32; + } arr; +}; + +struct pk_iter { + void *data; + union pk_iter_id id; +}; + +#if defined (__cplusplus) +template <typename T> +struct pk_iter_t : public pk_iter { + operator T*() { + return reinterpret_cast<T*>(this->data); + } + T* operator->() { + return reinterpret_cast<T*>(this->data); + } +}; +#endif + +#endif /* PK_PKITER_H */ #ifndef PK_PKARR_H #define PK_PKARR_H @@ -1793,6 +1827,10 @@ void pk_arr_remove_at(struct pk_arr *arr, uint32_t index); void pk_arr_clone(struct pk_arr *lhs, struct pk_arr *rhs); void pk_arr_swap(struct pk_arr *lhs, struct pk_arr *rhs); uint32_t pk_arr_find_first_index(struct pk_arr *arr, void *user_data, pk_arr_item_compare *fn); +bool pk_arr_iter_begin(struct pk_arr *arr, struct pk_iter *it); +bool pk_arr_iter_end(struct pk_arr *arr, struct pk_iter *it); +bool pk_arr_iter_increment(struct pk_arr *arr, struct pk_iter *it); +bool pk_arr_iter_decrement(struct pk_arr *arr, struct pk_iter *it); #if defined(__cplusplus) template<typename T> @@ -2061,6 +2099,48 @@ pk_arr_find_first_index(struct pk_arr *arr, void *user_data, pk_arr_item_compare return -1; } +bool +pk_arr_iter_begin(struct pk_arr *arr, struct pk_iter *it) { + it->data = nullptr; + it->id.arr.i = 0; + if (arr->data != nullptr && arr->data != CAFE_BABE(void)) { + it->data = arr->data; + return true; + } + return false; +} + +bool pk_arr_iter_end(struct pk_arr *arr, struct pk_iter *it) { + it->data = nullptr; + it->id.arr.i = 0; + if (arr->data != nullptr && arr->data != CAFE_BABE(void)) { + it->id.arr.i = arr->next - 1; + it->data = (void *)((char*)arr->data + (arr->stride * it->id.arr.i)); + return true; + } + return false; +} + +bool +pk_arr_iter_increment(struct pk_arr *arr, struct pk_iter *it) { + if (it->id.arr.i + 1 >= arr->next) { + return false; + } + it->id.arr.i += 1; + it->data = (void *)((char*)arr->data + (arr->stride * it->id.arr.i)); + return true; +} + +bool +pk_arr_iter_decrement(struct pk_arr *arr, struct pk_iter *it) { + if (it->id.arr.i == 0) { + return false; + } + it->id.arr.i -= 1; + it->data = (void *)((char*)arr->data + (arr->stride * it->id.arr.i)); + return true; +} + #endif /* PK_IMPL_ARR */ #ifndef PK_PK_STN_H #define PK_PK_STN_H @@ -2674,6 +2754,7 @@ enum PK_BKT_ARR_HANDLE_VALIDATION pk_bkt_arr_handle_validate(struct pk_bkt_arr * void pk_bkt_arr_init(struct pk_bkt_arr *bkt_arr, unsigned long stride, unsigned long alignment, struct pk_bkt_arr_handle limits, struct pk_membucket *bkt_buckets, struct pk_membucket *bkt_data); void pk_bkt_arr_clear(struct pk_bkt_arr *bkt_arr); +void pk_bkt_arr_reserve(struct pk_bkt_arr *bkt_arr, size_t count); struct pk_bkt_arr_handle pk_bkt_arr_find_first_handle(struct pk_bkt_arr *bkt_arr, pk_bkt_arr_compare_fn fn, void *user_data, const void *user_obj_data); void pk_bkt_arr_iterate(struct pk_bkt_arr *bkt_arr, pk_bkt_arr_iterate_fn fn, void *user_data); void pk_bkt_arr_teardown(struct pk_bkt_arr *bkt_arr); @@ -2682,13 +2763,17 @@ void pk_bkt_arr_free_handle(struct pk_bkt_arr *bkt_arr, struct pk_bkt_arr_handle int pk_bkt_arr_handle_compare(struct pk_bkt_arr_handle lhs, struct pk_bkt_arr_handle rhs); struct pk_bkt_arr_handle pk_bkt_arr_handle_increment(struct pk_bkt_arr *arr, struct pk_bkt_arr_handle h); struct pk_bkt_arr_handle pk_bkt_arr_handle_decrement(struct pk_bkt_arr *arr, struct pk_bkt_arr_handle h); +bool pk_bkt_arr_iter_begin(struct pk_bkt_arr *arr, struct pk_iter *it); +bool pk_bkt_arr_iter_end(struct pk_bkt_arr *arr, struct pk_iter *it); +bool pk_bkt_arr_iter_increment(struct pk_bkt_arr *arr, struct pk_iter *it); +bool pk_bkt_arr_iter_decrement(struct pk_bkt_arr *arr, struct pk_iter *it); #if defined (__cplusplus) #include <assert.h> template<typename T> struct pk_bkt_arr_t : public pk_bkt_arr { pk_bkt_arr_t(); - pk_bkt_arr_t(struct pk_bkt_arr_handle limits, struct pk_membucket *bkt_buckets = nullptr, struct pk_membucket *bkt_data = nullptr); + pk_bkt_arr_t(struct pk_bkt_arr_handle limits, struct pk_membucket *bkt_buckets, struct pk_membucket *bkt_data); ~pk_bkt_arr_t(); T &operator[](struct pk_bkt_arr_handle); using FN_Iter = pk_tmpln_1<void, T*, void*>; @@ -2710,7 +2795,7 @@ T &pk_bkt_arr_t<T>::operator[](struct pk_bkt_arr_handle handle) { assert(this->bucketed_data != nullptr); assert(handle.b <= this->limits.b); assert(handle.i <= this->limits.i); - assert(handle.b != this->head_r.b || handle.i < this->head_r.i); + assert(handle.b != this->head_r.b || handle.i <= this->head_r.i); T** two_star_programmer = reinterpret_cast<T**>(this->bucketed_data); return two_star_programmer[handle.b][handle.i]; } @@ -2728,9 +2813,10 @@ enum PK_BKT_ARR_HANDLE_VALIDATION pk_bkt_arr_handle_validate(struct pk_bkt_arr * if (handle.b >= bkt_arr->reserved_buckets || handle.b >= bkt_arr->limits.b) { ret |= PK_BKT_ARR_HANDLE_VALIDATION_BUCKET_INDEX_TOO_HIGH; } - if (handle.b == bkt_arr->reserved_buckets-1 && handle.i > bkt_arr->head_r.i) { + if (handle.i >= bkt_arr->limits.i) { ret |= PK_BKT_ARR_HANDLE_VALIDATION_ITEM_INDEX_TOO_HIGH; - } else if (handle.b < bkt_arr->reserved_buckets-1 && handle.i > bkt_arr->limits.i) { + } + if (handle.b == bkt_arr->head_r.b && handle.i > bkt_arr->head_r.i) { ret |= PK_BKT_ARR_HANDLE_VALIDATION_ITEM_INDEX_TOO_HIGH; } return (enum PK_BKT_ARR_HANDLE_VALIDATION)ret; @@ -2740,6 +2826,8 @@ void pk_bkt_arr_init(struct pk_bkt_arr *bkt_arr, unsigned long stride, unsigned { assert(limits.b <= PK_BKT_ARR_HANDLE_B_MAX); assert(limits.i <= PK_BKT_ARR_HANDLE_I_MAX); + assert(bkt_buckets != nullptr); + assert(bkt_data != nullptr); assert(bkt_arr != nullptr); memset(bkt_arr, 0, sizeof(struct pk_bkt_arr)); bkt_arr->bkt_buckets = bkt_buckets; @@ -2752,10 +2840,10 @@ void pk_bkt_arr_init(struct pk_bkt_arr *bkt_arr, unsigned long stride, unsigned bkt_arr->reserved_buckets = 1; bkt_arr->stride = stride; bkt_arr->alignment = alignment; - bkt_arr->idx_unused = (unsigned long long *)pk_new(sizeof(unsigned long long), alignof(unsigned long long), bkt_buckets); + bkt_arr->idx_unused = (unsigned long long *)pk_new_bkt(sizeof(unsigned long long), alignof(unsigned long long), bkt_buckets); bkt_arr->idx_unused[0] = PK_BKT_ARR_ALL_UNUSED_VAL; - bkt_arr->bucketed_data = (void **)pk_new(sizeof(void *), alignof(void *), bkt_buckets); - bkt_arr->bucketed_data[0] = pk_new(stride * limits.i, alignment, bkt_data); + bkt_arr->bucketed_data = (void **)pk_new_bkt(sizeof(void *), alignof(void *), bkt_buckets); + bkt_arr->bucketed_data[0] = pk_new_bkt(stride * limits.i, alignment, bkt_data); } void pk_bkt_arr_clear(struct pk_bkt_arr *bkt_arr) { @@ -2769,6 +2857,26 @@ void pk_bkt_arr_clear(struct pk_bkt_arr *bkt_arr) { } } +void pk_bkt_arr_reserve(struct pk_bkt_arr *bkt_arr, size_t count) { + size_t bucket_count = count / bkt_arr->limits.i; + if (bkt_arr->reserved_buckets >= bucket_count) return; + unsigned long long *new_idx_unused = (unsigned long long *)pk_new_bkt(sizeof(unsigned long long) * bucket_count, alignof(uint64_t), bkt_arr->bkt_buckets); + void **new_bucketed_data = (void **)pk_new_bkt(sizeof(void *) * bucket_count, alignof(void *), bkt_arr->bkt_buckets); + if (bkt_arr->reserved_buckets > 0) { + memcpy(new_idx_unused, bkt_arr->idx_unused, sizeof(unsigned long long) * bkt_arr->reserved_buckets); + memcpy(new_bucketed_data, bkt_arr->bucketed_data, sizeof(void *) * bkt_arr->reserved_buckets); + pk_delete_bkt(bkt_arr->bucketed_data, sizeof(void *) * bkt_arr->reserved_buckets, bkt_arr->bkt_buckets); + pk_delete_bkt(bkt_arr->idx_unused, sizeof(unsigned long long) * bkt_arr->reserved_buckets, bkt_arr->bkt_buckets); + } + for (size_t i = bkt_arr->reserved_buckets; i < bucket_count; ++i) { + new_idx_unused[i] = PK_BKT_ARR_ALL_UNUSED_VAL; + new_bucketed_data[i] = pk_new_bkt(bkt_arr->stride * bkt_arr->limits.i, bkt_arr->alignment, bkt_arr->bkt_data); + } + bkt_arr->idx_unused = new_idx_unused; + bkt_arr->bucketed_data = new_bucketed_data; + bkt_arr->reserved_buckets = bucket_count; +} + struct pk_bkt_arr_handle pk_bkt_arr_find_first_handle(struct pk_bkt_arr *bkt_arr, pk_bkt_arr_compare_fn fn, void *user_data, const void *user_obj_data) { assert(bkt_arr != NULL); assert(fn != NULL); @@ -2799,7 +2907,7 @@ void pk_bkt_arr_iterate(struct pk_bkt_arr *bkt_arr, pk_bkt_arr_iterate_fn fn, vo unsigned int b, i, ii; for (b = 0; b < bkt_arr->reserved_buckets; ++b) { char *arr = ((char**)(bkt_arr->bucketed_data))[b]; - ii = b == bkt_arr->reserved_buckets-1 ? bkt_arr->head_r.i : bkt_arr->limits.i; + ii = b == bkt_arr->head_r.b ? bkt_arr->head_r.i : bkt_arr->limits.i; for (i = 0; i < ii; ++i) { if (PK_HAS_FLAG(bkt_arr->idx_unused[b], 1ull << i)) { continue; @@ -2815,10 +2923,10 @@ void pk_bkt_arr_teardown(struct pk_bkt_arr *bkt_arr) size_t sz = bkt_arr->limits.i * bkt_arr->stride; if (bkt_arr->idx_unused == nullptr && bkt_arr->bucketed_data == nullptr) return; for (b = bkt_arr->reserved_buckets - 1; b > -1; --b) { - pk_delete(bkt_arr->bucketed_data[b], sz, bkt_arr->bkt_data); + pk_delete_bkt(bkt_arr->bucketed_data[b], sz, bkt_arr->bkt_data); } - pk_delete((void *)bkt_arr->idx_unused, sizeof(unsigned long long) * (bkt_arr->reserved_buckets), bkt_arr->bkt_buckets); - pk_delete((void *)bkt_arr->bucketed_data, sizeof(void *) * (bkt_arr->reserved_buckets), bkt_arr->bkt_buckets); + pk_delete_bkt((void *)bkt_arr->idx_unused, sizeof(unsigned long long) * (bkt_arr->reserved_buckets), bkt_arr->bkt_buckets); + pk_delete_bkt((void *)bkt_arr->bucketed_data, sizeof(void *) * (bkt_arr->reserved_buckets), bkt_arr->bkt_buckets); memset(bkt_arr, 0, sizeof(struct pk_bkt_arr)); bkt_arr->bkt_buckets = NULL; bkt_arr->bkt_data = NULL; @@ -2857,18 +2965,18 @@ struct pk_bkt_arr_handle pk_bkt_arr_new_handle(struct pk_bkt_arr *bkt_arr) if (bkt_arr->head_r.b == bkt_arr->reserved_buckets && bkt_arr->head_r.i == 0) { bkt_arr->reserved_buckets += 1; - unsigned long long *new_idx_unused = (unsigned long long *)pk_new(sizeof(unsigned long long) * bkt_arr->reserved_buckets, alignof(unsigned long long), bkt_arr->bkt_buckets); - void **new_data_ptrs = (void **)pk_new(sizeof(void *) * bkt_arr->reserved_buckets, alignof(void *), bkt_arr->bkt_buckets); + unsigned long long *new_idx_unused = (unsigned long long *)pk_new_bkt(sizeof(unsigned long long) * bkt_arr->reserved_buckets, alignof(unsigned long long), bkt_arr->bkt_buckets); + void **new_data_ptrs = (void **)pk_new_bkt(sizeof(void *) * bkt_arr->reserved_buckets, alignof(void *), bkt_arr->bkt_buckets); for (b = 0; b < bkt_arr->reserved_buckets - 1; ++b) { new_idx_unused[b] = bkt_arr->idx_unused[b]; new_data_ptrs[b] = bkt_arr->bucketed_data[b]; } new_idx_unused[bkt_arr->reserved_buckets - 1] = PK_BKT_ARR_ALL_UNUSED_VAL; - new_data_ptrs[bkt_arr->reserved_buckets - 1] = pk_new(bkt_arr->stride * bkt_arr->limits.i, bkt_arr->alignment, bkt_arr->bkt_data); + new_data_ptrs[bkt_arr->reserved_buckets - 1] = pk_new_bkt(bkt_arr->stride * bkt_arr->limits.i, bkt_arr->alignment, bkt_arr->bkt_data); - pk_delete((void *)bkt_arr->idx_unused, sizeof(unsigned long long) * (bkt_arr->reserved_buckets - 1), bkt_arr->bkt_buckets); - pk_delete((void *)bkt_arr->bucketed_data, sizeof(void *) * (bkt_arr->reserved_buckets - 1), bkt_arr->bkt_buckets); + pk_delete_bkt((void *)bkt_arr->idx_unused, sizeof(unsigned long long) * (bkt_arr->reserved_buckets - 1), bkt_arr->bkt_buckets); + pk_delete_bkt((void *)bkt_arr->bucketed_data, sizeof(void *) * (bkt_arr->reserved_buckets - 1), bkt_arr->bkt_buckets); bkt_arr->idx_unused = new_idx_unused; bkt_arr->bucketed_data = new_data_ptrs; } @@ -2926,12 +3034,80 @@ struct pk_bkt_arr_handle pk_bkt_arr_handle_decrement(struct pk_bkt_arr *arr, str return h; } +bool pk_bkt_arr_iter_begin(struct pk_bkt_arr *arr, struct pk_iter *it) { + it->data = nullptr; + it->id.bkt.b = 0; + it->id.bkt.i = 0; + if ((arr->idx_unused[it->id.bkt.b] & (1ull << it->id.bkt.i)) != 0) return false; + it->data = arr->bucketed_data[0]; + return true; +} + +bool pk_bkt_arr_iter_end(struct pk_bkt_arr *arr, struct pk_iter *it) { + it->data = nullptr; + it->id.bkt.b = 0; + it->id.bkt.i = 0; + if (arr->head_r.b == 0 && arr->head_r.i == 0) return false; + do { + struct pk_bkt_arr_handle handle = arr->head_r; + for (;;) { + if ((arr->idx_unused[handle.b] & (1ull << handle.i)) == 0) break; + if (handle.b == 0 && handle.i == 0) return false; + handle = pk_bkt_arr_handle_decrement(arr, handle); + } + it->id.bkt.b = handle.b; + it->id.bkt.i = handle.i; + break; + } while (true); + if (arr->bucketed_data != nullptr && arr->bucketed_data[it->id.bkt.b] != nullptr) { + it->data = (char*)(arr->bucketed_data[it->id.bkt.b]) + (arr->stride * it->id.bkt.i); + return true; + } + return false; +} + +bool pk_bkt_arr_iter_increment(struct pk_bkt_arr *arr, struct pk_iter *it) { + struct pk_bkt_arr_handle handle = { + .b = it->id.bkt.b, + .i = it->id.bkt.i, + }; + if (it->id.bkt.b == arr->limits.b-1 && it->id.bkt.i == arr->limits.i-1) return false; + for (;;) { + handle = pk_bkt_arr_handle_increment(arr, handle); + if (handle.b >= arr->reserved_buckets) return false; + if ((arr->idx_unused[handle.b] & (1ull << handle.i)) == 0) break; + } + it->id.bkt.b = handle.b; + it->id.bkt.i = handle.i; + if ((arr->idx_unused[it->id.bkt.b] & (1ull << it->id.bkt.i)) != 0) return false; + it->data = (char*)(arr->bucketed_data[it->id.bkt.b]) + (arr->stride * it->id.bkt.i); + return true; +} + +bool pk_bkt_arr_iter_decrement(struct pk_bkt_arr *arr, struct pk_iter *it) { + struct pk_bkt_arr_handle handle = { + .b = it->id.bkt.b, + .i = it->id.bkt.i, + }; + for (;;) { + handle = pk_bkt_arr_handle_decrement(arr, handle); + if ((arr->idx_unused[handle.b] & (1ull << handle.i)) == 0) break; + if (handle.b == 0 && handle.i == 0) break; + } + if (it->id.bkt.b == handle.b && it->id.bkt.i == handle.i) return false; + it->id.bkt.b = handle.b; + it->id.bkt.i = handle.i; + if ((arr->idx_unused[it->id.bkt.b] & (1ull << it->id.bkt.i)) != 0) return false; + it->data = ((char*)(arr->bucketed_data[it->id.bkt.b])) + (arr->stride * it->id.bkt.i); + return true; +} + #endif /* PK_IMPL_BKTARR */ #ifndef PK_PKFUNCINSTR_H #define PK_PKFUNCINSTR_H -#define PK_FUNCINSTR_CHILDREN_INCREMENT_COUNT 8 +#include <stdio.h> struct pk_funcinstr; struct pk_funcinstr { @@ -2945,6 +3121,7 @@ struct pk_funcinstr { }; void pk_funcinstr_init(); +void pk_funcinstr_set_ouputs(FILE *out, FILE *err); void pk_funcinstr_teardown(); #if defined(__cplusplus) @@ -2955,6 +3132,17 @@ extern "C" { // clang #elif defined(__GNUC__) || defined(__GNUG__) +#ifndef __USE_GNU + #define __USE_GNU +#endif +#if defined(__cplusplus) +#include <cxxabi.h> +#endif +#include <dlfcn.h> +#include <link.h> +#include <string.h> + + void __cyg_profile_func_enter(void* this_fn, void* call_site); void __cyg_profile_func_exit(void* this_fn, void* call_site); @@ -2974,16 +3162,13 @@ void __cyg_profile_func_exit(void* this_fn, void* call_site); #include <threads.h> #include <string.h> -// TODO 2025-06-02 JCB -// There's some speed improvements that can be made here by growing faster. -// OR use some type of bucket -// - might be a good chance to isolate some of the pkmem logic - -#define PK_FUNCINSTR_BKT_START_COUNT 4 -#define PK_FUNCINSTR_BKT_GROW_AMOUNT 4 -#define PK_FUNCINSTR_BKT_DATA_COUNT 255 +#define PK_FUNCINSTR_CHILDREN_START_COUNT 8 +#define PK_FUNCINSTR_CHILDREN_GROW_RATIO 2.0 +#define PK_FUNCINSTR_BKT_START_COUNT 64 +#define PK_FUNCINSTR_BKT_GROW_RATIO 2.0 +#define PK_FUNCINSTR_BKT_DATA_COUNT 0xFFFF struct pk_funcinstr_bkt { - uint8_t used_count; + uint16_t used_count; uint8_t guard_enter; uint8_t guard_exit; struct timespec reset_time; @@ -2991,6 +3176,8 @@ struct pk_funcinstr_bkt { }; struct pk_funcinstr_mstr { mtx_t mtx; + FILE *out; + FILE *err; struct timespec reset_time; struct pk_funcinstr_bkt **buckets; size_t r_buckets; @@ -3004,19 +3191,72 @@ static struct pk_funcinstr_mstr thrd_mstr; __attribute__((no_instrument_function)) void pk_funcinstr_init() { + assert(thrd_mstr.out == NULL); + assert(thrd_mstr.err == NULL); assert(thrd_mstr.reset_time.tv_sec == 0); assert(thrd_mstr.reset_time.tv_nsec == 0); assert(thrd_mstr.buckets == NULL); assert(thrd_mstr.r_buckets == 0); assert(thrd_mstr.n_buckets == 0); mtx_init(&thrd_mstr.mtx, mtx_plain); + thrd_mstr.out = stdout; + thrd_mstr.err = stderr; thrd_mstr.r_buckets = PK_FUNCINSTR_BKT_START_COUNT; thrd_mstr.buckets = (struct pk_funcinstr_bkt**)aligned_alloc(alignof(struct pk_funcinstr_bkt *), (sizeof(struct pk_funcinstr_bkt *) * PK_FUNCINSTR_BKT_START_COUNT)); - memset(thrd_mstr.buckets, 0, (sizeof(struct pk_funcinstr_bkt *) * PK_FUNCINSTR_BKT_START_COUNT)); clock_gettime(PK_TMR_CLOCK, &thrd_mstr.reset_time); } __attribute__((no_instrument_function)) +void pk_funcinstr_set_ouputs(FILE *out, FILE *err) { + thrd_mstr.out = out; + thrd_mstr.err = err; +} + +__attribute__((no_instrument_function)) +void pk_funcinstr_write(FILE *f) { + int64_t i, k, s; + struct pk_funcinstr_bkt *bkt = nullptr; + struct pk_funcinstr *instr = nullptr; + struct pk_tmr fake_tmr; + Dl_info info; + mtx_lock(&thrd_mstr.mtx); + fake_tmr.b = thrd_mstr.reset_time; + fprintf(f, "["); + for (i = 0; i < (int64_t)thrd_mstr.n_buckets; ++i) { + bkt = thrd_mstr.buckets[i]; + for (k = 0; k < (int64_t)bkt->used_count; ++k) { + instr = &bkt->data[k]; + for (s = 0; s < 2; ++s) { + if (i == 0 && k == 0 && s == 0) { + fprintf(f, "{"); + } else { + fprintf(f, ",{"); + } + if (dladdr(instr->fn, &info) != 0) { + fprintf(f, "\"name\": \"%s\",", info.dli_sname); + } else { + fprintf(f, "\"name\": \"unknown\","); + } + fprintf(f, "\"cat\": \"%s\",", "funcinstr"); + if (s == 0) { + fake_tmr.e = instr->tmr.b; + fprintf(f, "\"ph\": \"%c\",", 'B'); + } else { + fake_tmr.e = instr->tmr.e; + fprintf(f, "\"ph\": \"%c\",", 'E'); + } + fprintf(f, "\"ts\": %lli,", pk_tmr_duration_u64_nano(fake_tmr)); + fprintf(f, "\"pid\": %i,", 69); + fprintf(f, "\"tid\": %ld", thrd_current()); + fprintf(f, "}"); + } + } + } + fprintf(f, "]"); + mtx_unlock(&thrd_mstr.mtx); +} + +__attribute__((no_instrument_function)) void pk_funcinstr_teardown() { int64_t i, k; mtx_lock(&thrd_mstr.mtx); @@ -3027,6 +3267,8 @@ void pk_funcinstr_teardown() { } } free(thrd_mstr.buckets); + thrd_mstr.out = NULL; + thrd_mstr.err = NULL; thrd_mstr.reset_time.tv_sec = 0; thrd_mstr.reset_time.tv_nsec = 0; thrd_mstr.buckets = NULL; @@ -3041,16 +3283,6 @@ void pk_funcinstr_teardown() { // Come up with pk macros since XRay requires attributes to instrument? #elif defined(__GNUC__) || defined(__GNUG__) -#ifndef __USE_GNU - #define __USE_GNU -#endif -#if defined(__cplusplus) -#include <cxxabi.h> -#endif -#include <dlfcn.h> -#include <link.h> -#include <string.h> - __attribute__((no_instrument_function)) bool pk_funcinstr_detect_not_initialized() { if (thrd_mstr.buckets == NULL) return true; @@ -3076,10 +3308,9 @@ void pk_funcinstr_detect_and_handle_reset() { if (should_reset) { if (thrd_mstr.n_buckets == thrd_mstr.r_buckets) { mtx_lock(&thrd_mstr.mtx); - thrd_mstr.r_buckets += PK_FUNCINSTR_BKT_GROW_AMOUNT; + thrd_mstr.r_buckets *= PK_FUNCINSTR_BKT_GROW_RATIO; struct pk_funcinstr_bkt **buckets = (struct pk_funcinstr_bkt**)aligned_alloc(alignof(void *), sizeof(void *) * thrd_mstr.r_buckets); memcpy(buckets, thrd_mstr.buckets, sizeof(void *) * (thrd_mstr.n_buckets)); - memset((char*)buckets + (sizeof(void *) * (thrd_mstr.n_buckets)), 0, (sizeof(void *) * thrd_mstr.r_buckets) - sizeof(void *) * (thrd_mstr.n_buckets)); free(thrd_mstr.buckets); thrd_mstr.buckets = buckets; mtx_unlock(&thrd_mstr.mtx); @@ -3113,11 +3344,11 @@ __attribute__((no_instrument_function)) struct pk_funcinstr *pk_funcinstr_create_funcinstr(void *this_fn) { struct pk_funcinstr *funcinstr = &pk_funcinstr_thrd_bkt->data[pk_funcinstr_thrd_bkt->used_count]; pk_funcinstr_thrd_bkt->used_count++; - pk_tmr_start(funcinstr->tmr); funcinstr->fn = this_fn; + pk_tmr_start(funcinstr->tmr); funcinstr->parent = pk_funcinstr_thrd_instr; - funcinstr->children = NULL; funcinstr->first_child = NULL; + funcinstr->children = NULL; funcinstr->n_children = 0; funcinstr->r_children = 0; @@ -3127,9 +3358,12 @@ struct pk_funcinstr *pk_funcinstr_create_funcinstr(void *this_fn) { pk_funcinstr_thrd_instr->first_child = funcinstr; } else { if (pk_funcinstr_thrd_instr->n_children == pk_funcinstr_thrd_instr->r_children) { - pk_funcinstr_thrd_instr->r_children += PK_FUNCINSTR_CHILDREN_INCREMENT_COUNT; + if (pk_funcinstr_thrd_instr->r_children == 0) { + pk_funcinstr_thrd_instr->r_children = PK_FUNCINSTR_CHILDREN_START_COUNT; + } else { + pk_funcinstr_thrd_instr->r_children *= PK_FUNCINSTR_CHILDREN_GROW_RATIO; + } struct pk_funcinstr **children = (struct pk_funcinstr **)aligned_alloc(alignof(void *), sizeof(void *) * pk_funcinstr_thrd_instr->r_children); - memset((char*)children + (sizeof(void *) * (pk_funcinstr_thrd_instr->n_children)), 0, (sizeof(void *) * pk_funcinstr_thrd_instr->r_children) - sizeof(void *) * (pk_funcinstr_thrd_instr->n_children)); if (pk_funcinstr_thrd_instr->children != NULL) { memcpy(children, pk_funcinstr_thrd_instr->children, sizeof(void *) * pk_funcinstr_thrd_instr->n_children); free(pk_funcinstr_thrd_instr->children); @@ -3169,7 +3403,9 @@ void __cyg_profile_func_exit(void* this_fn, void* call_site) { if (pk_funcinstr_thrd_instr == NULL) return; // exit called before enter? pk_funcinstr_thrd_bkt->guard_exit++; +#ifdef PK_FUNCINSTR_PRINT Dl_info info; +#endif /* PK_FUNCINSTR_PRINT */ if (this_fn != pk_funcinstr_thrd_instr->fn) { int64_t i = (int64_t)pk_funcinstr_thrd_bkt->used_count - 1; @@ -3187,26 +3423,31 @@ void __cyg_profile_func_exit(void* this_fn, void* call_site) { struct pk_tmr tmr = pk_funcinstr_thrd_instr->tmr; pk_funcinstr_thrd_instr = pk_funcinstr_create_funcinstr(this_fn); pk_funcinstr_thrd_instr->tmr = tmr; - fprintf(stdout, "[pkfuncinstr] func mismatch; Parent func? Duration not accurate."); +#ifdef PK_FUNCINSTR_PRINT + fprintf(thrd_mstr.out, "[pkfuncinstr] func mismatch; Parent func? Duration not accurate."); +#endif /* PK_FUNCINSTR_PRINT */ } else { - fprintf(stderr, "[pkfuncinstr] func mismatch. Last: '"); +#ifdef PK_FUNCINSTR_PRINT + fprintf(thrd_mstr.err, "[pkfuncinstr] func mismatch. Last: '"); if (dladdr(pk_funcinstr_thrd_instr->fn, &info) != 0) { - fprintf(stderr, "%s", info.dli_sname); + fprintf(thrd_mstr.err, "%s", info.dli_sname); } else { - fprintf(stderr, "(unknown)"); + fprintf(thrd_mstr.err, "(unknown)"); } - fprintf(stderr, "'. Current: '"); + fprintf(thrd_mstr.err, "'. Current: '"); if (dladdr(this_fn, &info) != 0) { - fprintf(stderr, "%s'.\n", info.dli_sname); + fprintf(thrd_mstr.err, "%s'.\n", info.dli_sname); } else { - fprintf(stderr, "(unknown)'.\n"); + fprintf(thrd_mstr.err, "(unknown)'.\n"); } +#endif /* PK_FUNCINSTR_PRINT */ pk_funcinstr_thrd_bkt->guard_exit=0; return; } } pk_tmr_stop(pk_funcinstr_thrd_instr->tmr); +#ifdef PK_FUNCINSTR_PRINT if (dladdr(this_fn, &info) != 0) { int depth = 0; // TODO track depth in a better way @@ -3221,7 +3462,7 @@ void __cyg_profile_func_exit(void* this_fn, void* call_site) { demangled = abi::__cxa_demangle(info.dli_sname, NULL, NULL, NULL); #endif } - fprintf(stdout, "[pkfuncinstr] %p %*s %s took %.6f ms\n" + fprintf(thrd_mstr.out, "[pkfuncinstr] %p %*s %s took %.6f ms\n" ,this_fn ,depth, "" ,demangled != NULL ? demangled : info.dli_sname != NULL ? info.dli_sname : "???" @@ -3229,6 +3470,7 @@ void __cyg_profile_func_exit(void* this_fn, void* call_site) { ); if (demangled != NULL) free(demangled); } +#endif /* PK_FUNCINSTR_PRINT */ pk_funcinstr_thrd_bkt->guard_exit=0; pk_funcinstr_thrd_instr = pk_funcinstr_thrd_instr->parent; } |
