#define JEMALLOC_RTREE_C_ #include "jemalloc/internal/jemalloc_internal.h" rtree_t * rtree_new(unsigned bits, rtree_alloc_t *alloc, rtree_dalloc_t *dalloc) { rtree_t *ret; unsigned bits_per_level, bits_in_leaf, height, i; assert(bits > 0 && bits <= (sizeof(uintptr_t) << 3)); bits_per_level = jemalloc_ffs(pow2_ceil((RTREE_NODESIZE / sizeof(void *)))) - 1; bits_in_leaf = jemalloc_ffs(pow2_ceil((RTREE_NODESIZE / sizeof(uint8_t)))) - 1; if (bits > bits_in_leaf) { height = 1 + (bits - bits_in_leaf) / bits_per_level; if ((height-1) * bits_per_level + bits_in_leaf != bits) height++; } else { height = 1; } assert((height-1) * bits_per_level + bits_in_leaf >= bits); ret = (rtree_t*)alloc(offsetof(rtree_t, level2bits) + (sizeof(unsigned) * height)); if (ret == NULL) return (NULL); memset(ret, 0, offsetof(rtree_t, level2bits) + (sizeof(unsigned) * height)); ret->alloc = alloc; ret->dalloc = dalloc; if (malloc_mutex_init(&ret->mutex)) { if (dalloc != NULL) dalloc(ret); return (NULL); } ret->height = height; if (height > 1) { if ((height-1) * bits_per_level + bits_in_leaf > bits) { ret->level2bits[0] = (bits - bits_in_leaf) % bits_per_level; } else ret->level2bits[0] = bits_per_level; for (i = 1; i < height-1; i++) ret->level2bits[i] = bits_per_level; ret->level2bits[height-1] = bits_in_leaf; } else ret->level2bits[0] = bits; ret->root = (void**)alloc(sizeof(void *) << ret->level2bits[0]); if (ret->root == NULL) { if (dalloc != NULL) dalloc(ret); return (NULL); } memset(ret->root, 0, sizeof(void *) << ret->level2bits[0]); return (ret); } static void rtree_delete_subtree(rtree_t *rtree, void **node, unsigned level) { if (level < rtree->height - 1) { size_t nchildren, i; nchildren = ZU(1) << rtree->level2bits[level]; for (i = 0; i < nchildren; i++) { void **child = (void **)node[i]; if (child != NULL) rtree_delete_subtree(rtree, child, level + 1); } } rtree->dalloc(node); } void rtree_delete(rtree_t *rtree) { rtree_delete_subtree(rtree, rtree->root, 0); rtree->dalloc(rtree); } void rtree_prefork(rtree_t *rtree) { malloc_mutex_prefork(&rtree->mutex); } void rtree_postfork_parent(rtree_t *rtree) { malloc_mutex_postfork_parent(&rtree->mutex); } void rtree_postfork_child(rtree_t *rtree) { malloc_mutex_postfork_child(&rtree->mutex); }