1a4bd5210SJason Evans #define JEMALLOC_RTREE_C_ 2a4bd5210SJason Evans #include "jemalloc/internal/jemalloc_internal.h" 3a4bd5210SJason Evans 4a4bd5210SJason Evans rtree_t * 5*f921d10fSJason Evans rtree_new(unsigned bits, rtree_alloc_t *alloc, rtree_dalloc_t *dalloc) 6a4bd5210SJason Evans { 7a4bd5210SJason Evans rtree_t *ret; 8*f921d10fSJason Evans unsigned bits_per_level, bits_in_leaf, height, i; 9*f921d10fSJason Evans 10*f921d10fSJason Evans assert(bits > 0 && bits <= (sizeof(uintptr_t) << 3)); 11a4bd5210SJason Evans 12a4bd5210SJason Evans bits_per_level = ffs(pow2_ceil((RTREE_NODESIZE / sizeof(void *)))) - 1; 13*f921d10fSJason Evans bits_in_leaf = ffs(pow2_ceil((RTREE_NODESIZE / sizeof(uint8_t)))) - 1; 14*f921d10fSJason Evans if (bits > bits_in_leaf) { 15*f921d10fSJason Evans height = 1 + (bits - bits_in_leaf) / bits_per_level; 16*f921d10fSJason Evans if ((height-1) * bits_per_level + bits_in_leaf != bits) 17a4bd5210SJason Evans height++; 18*f921d10fSJason Evans } else { 19*f921d10fSJason Evans height = 1; 20*f921d10fSJason Evans } 21*f921d10fSJason Evans assert((height-1) * bits_per_level + bits_in_leaf >= bits); 22a4bd5210SJason Evans 23*f921d10fSJason Evans ret = (rtree_t*)alloc(offsetof(rtree_t, level2bits) + 24a4bd5210SJason Evans (sizeof(unsigned) * height)); 25a4bd5210SJason Evans if (ret == NULL) 26a4bd5210SJason Evans return (NULL); 27a4bd5210SJason Evans memset(ret, 0, offsetof(rtree_t, level2bits) + (sizeof(unsigned) * 28a4bd5210SJason Evans height)); 29a4bd5210SJason Evans 30*f921d10fSJason Evans ret->alloc = alloc; 31*f921d10fSJason Evans ret->dalloc = dalloc; 32a4bd5210SJason Evans if (malloc_mutex_init(&ret->mutex)) { 33*f921d10fSJason Evans if (dalloc != NULL) 34*f921d10fSJason Evans dalloc(ret); 35a4bd5210SJason Evans return (NULL); 36a4bd5210SJason Evans } 37a4bd5210SJason Evans ret->height = height; 38*f921d10fSJason Evans if (height > 1) { 39*f921d10fSJason Evans if ((height-1) * bits_per_level + bits_in_leaf > bits) { 40*f921d10fSJason Evans ret->level2bits[0] = (bits - bits_in_leaf) % 41*f921d10fSJason Evans bits_per_level; 42*f921d10fSJason Evans } else 43a4bd5210SJason Evans ret->level2bits[0] = bits_per_level; 44*f921d10fSJason Evans for (i = 1; i < height-1; i++) 45a4bd5210SJason Evans ret->level2bits[i] = bits_per_level; 46*f921d10fSJason Evans ret->level2bits[height-1] = bits_in_leaf; 47*f921d10fSJason Evans } else 48*f921d10fSJason Evans ret->level2bits[0] = bits; 49a4bd5210SJason Evans 50*f921d10fSJason Evans ret->root = (void**)alloc(sizeof(void *) << ret->level2bits[0]); 51a4bd5210SJason Evans if (ret->root == NULL) { 52*f921d10fSJason Evans if (dalloc != NULL) 53*f921d10fSJason Evans dalloc(ret); 54a4bd5210SJason Evans return (NULL); 55a4bd5210SJason Evans } 56a4bd5210SJason Evans memset(ret->root, 0, sizeof(void *) << ret->level2bits[0]); 57a4bd5210SJason Evans 58a4bd5210SJason Evans return (ret); 59a4bd5210SJason Evans } 6082872ac0SJason Evans 61*f921d10fSJason Evans static void 62*f921d10fSJason Evans rtree_delete_subtree(rtree_t *rtree, void **node, unsigned level) 63*f921d10fSJason Evans { 64*f921d10fSJason Evans 65*f921d10fSJason Evans if (level < rtree->height - 1) { 66*f921d10fSJason Evans size_t nchildren, i; 67*f921d10fSJason Evans 68*f921d10fSJason Evans nchildren = ZU(1) << rtree->level2bits[level]; 69*f921d10fSJason Evans for (i = 0; i < nchildren; i++) { 70*f921d10fSJason Evans void **child = (void **)node[i]; 71*f921d10fSJason Evans if (child != NULL) 72*f921d10fSJason Evans rtree_delete_subtree(rtree, child, level + 1); 73*f921d10fSJason Evans } 74*f921d10fSJason Evans } 75*f921d10fSJason Evans rtree->dalloc(node); 76*f921d10fSJason Evans } 77*f921d10fSJason Evans 78*f921d10fSJason Evans void 79*f921d10fSJason Evans rtree_delete(rtree_t *rtree) 80*f921d10fSJason Evans { 81*f921d10fSJason Evans 82*f921d10fSJason Evans rtree_delete_subtree(rtree, rtree->root, 0); 83*f921d10fSJason Evans rtree->dalloc(rtree); 84*f921d10fSJason Evans } 85*f921d10fSJason Evans 8682872ac0SJason Evans void 8782872ac0SJason Evans rtree_prefork(rtree_t *rtree) 8882872ac0SJason Evans { 8982872ac0SJason Evans 9082872ac0SJason Evans malloc_mutex_prefork(&rtree->mutex); 9182872ac0SJason Evans } 9282872ac0SJason Evans 9382872ac0SJason Evans void 9482872ac0SJason Evans rtree_postfork_parent(rtree_t *rtree) 9582872ac0SJason Evans { 9682872ac0SJason Evans 9782872ac0SJason Evans malloc_mutex_postfork_parent(&rtree->mutex); 9882872ac0SJason Evans } 9982872ac0SJason Evans 10082872ac0SJason Evans void 10182872ac0SJason Evans rtree_postfork_child(rtree_t *rtree) 10282872ac0SJason Evans { 10382872ac0SJason Evans 10482872ac0SJason Evans malloc_mutex_postfork_child(&rtree->mutex); 10582872ac0SJason Evans } 106