summaryrefslogtreecommitdiff
path: root/src/pk.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/pk.h')
-rw-r--r--src/pk.h348
1 files changed, 295 insertions, 53 deletions
diff --git a/src/pk.h b/src/pk.h
index 702cfa3..b293d77 100644
--- a/src/pk.h
+++ b/src/pk.h
@@ -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;
}