+ if (stack) {
+ if (!sh) {
+ sh = ch_malloc(sizeof(struct slab_heap));
+ sh->sh_base = ch_malloc(size);
+#ifdef NO_THREADS
+ slheap = sh;
+#else
+ ldap_pvt_thread_pool_setkey(ctx, (void *)slap_sl_mem_init,
+ (void *)sh, slap_sl_mem_destroy, NULL, NULL);
+#endif
+ } else if ( size > (char *)sh->sh_end - (char *)sh->sh_base ) {
+ void *newptr;
+
+ newptr = ch_realloc( sh->sh_base, size );
+ if ( newptr == NULL ) return NULL;
+ sh->sh_base = newptr;
+ }
+ sh->sh_last = sh->sh_base;
+ sh->sh_end = (char *) sh->sh_base + size;
+ sh->sh_stack = stack;
+ return sh;
+ } else {
+ size_shift = size - 1;
+ do {
+ order_end++;
+ } while (size_shift >>= 1);
+
+ pad_shift = pad - 1;
+ do {
+ order_start++;
+ } while (pad_shift >>= 1);
+
+ order = order_end - order_start + 1;
+
+ if (!sh) {
+ sh = (struct slab_heap *) ch_malloc(sizeof(struct slab_heap));
+ sh->sh_base = ch_malloc(size);
+#ifdef NO_THREADS
+ slheap = sh;
+#else
+ ldap_pvt_thread_pool_setkey(ctx, (void *)slap_sl_mem_init,
+ (void *)sh, slap_sl_mem_destroy, NULL, NULL);
+#endif
+ } else {
+ for (i = 0; i <= sh->sh_maxorder - order_start; i++) {
+ so = LDAP_LIST_FIRST(&sh->sh_free[i]);
+ while (so) {
+ struct slab_object *so_tmp = so;
+ so = LDAP_LIST_NEXT(so, so_link);
+ LDAP_LIST_INSERT_HEAD(&sh->sh_sopool, so_tmp, so_link);
+ }
+ ch_free(sh->sh_map[i]);
+ }
+ ch_free(sh->sh_free);
+ ch_free(sh->sh_map);
+
+ so = LDAP_LIST_FIRST(&sh->sh_sopool);
+ while (so) {
+ struct slab_object *so_tmp = so;
+ so = LDAP_LIST_NEXT(so, so_link);
+ if (!so_tmp->so_blockhead) {
+ LDAP_LIST_REMOVE(so_tmp, so_link);
+ }
+ }
+ so = LDAP_LIST_FIRST(&sh->sh_sopool);
+ while (so) {
+ struct slab_object *so_tmp = so;
+ so = LDAP_LIST_NEXT(so, so_link);
+ ch_free(so_tmp);
+ }
+
+ if (size > (char *)sh->sh_end - (char *)sh->sh_base) {
+ void *newptr;
+
+ newptr = realloc( sh->sh_base, size );
+ if ( newptr == NULL ) return NULL;
+ sh->sh_base = newptr;
+ }
+ }
+ sh->sh_end = (char *)sh->sh_base + size;
+ sh->sh_maxorder = order_end;
+
+ sh->sh_free = (struct sh_freelist *)
+ ch_malloc(order * sizeof(struct sh_freelist));
+ for (i = 0; i < order; i++) {
+ LDAP_LIST_INIT(&sh->sh_free[i]);
+ }
+
+ LDAP_LIST_INIT(&sh->sh_sopool);
+
+ if (LDAP_LIST_EMPTY(&sh->sh_sopool)) {
+ slap_replenish_sopool(sh);
+ }
+ so = LDAP_LIST_FIRST(&sh->sh_sopool);
+ LDAP_LIST_REMOVE(so, so_link);
+ so->so_ptr = sh->sh_base;
+
+ LDAP_LIST_INSERT_HEAD(&sh->sh_free[order-1], so, so_link);
+
+ sh->sh_map = (unsigned char **)
+ ch_malloc(order * sizeof(unsigned char *));
+ for (i = 0; i < order; i++) {
+ int shiftamt = order_start + 1 + i;
+ int nummaps = size >> shiftamt;
+ assert(nummaps);
+ nummaps >>= 3;
+ if (!nummaps) nummaps = 1;
+ sh->sh_map[i] = (unsigned char *) ch_malloc(nummaps);
+ memset(sh->sh_map[i], 0, nummaps);
+ }
+ sh->sh_stack = stack;
+ return sh;