+slap_sl_free(void *ptr, void *ctx)
+{
+ struct slab_heap *sh = ctx;
+ int size, size_shift, order_size;
+ int pad = 2*sizeof(int)-1, pad_shift;
+ ber_len_t *p = (ber_len_t *)ptr, *tmpp;
+ int order_start = -1, order = -1;
+ struct slab_object *so;
+ unsigned long diff;
+ int i, inserted = 0;
+
+ if (!ptr)
+ return;
+
+#ifdef SLAP_NO_SL_MALLOC
+ ber_memfree_x( ptr, NULL );
+ return;
+#endif
+
+ if (!sh || ptr < sh->sh_base || ptr >= sh->sh_end) {
+ ber_memfree_x(ptr, NULL);
+ } else if (sh->sh_stack && (char *)ptr + p[-1] == sh->sh_last) {
+ p--;
+ sh->sh_last = p;
+ } else if (!sh->sh_stack) {
+ size = *(--p);
+ size_shift = size + sizeof(ber_len_t) - 1;
+ do {
+ order++;
+ } while (size_shift >>= 1);
+
+ pad_shift = pad - 1;
+ do {
+ order_start++;
+ } while (pad_shift >>= 1);
+
+ for (i = order, tmpp = p; i <= sh->sh_maxorder; i++) {
+ order_size = 1 << (i+1);
+ diff = (unsigned long)((char*)tmpp - (char*)sh->sh_base) >> (i+1);
+ sh->sh_map[i-order_start][diff>>3] &= (~(1 << (diff & 0x7)));
+ if (diff == ((diff>>1)<<1)) {
+ if (!(sh->sh_map[i-order_start][(diff+1)>>3] &
+ (1<<((diff+1)&0x7)))) {
+ so = LDAP_LIST_FIRST(&sh->sh_free[i-order_start]);
+ while (so) {
+ if ((char*)so->so_ptr == (char*)tmpp) {
+ LDAP_LIST_REMOVE( so, so_link );
+ } else if ((char*)so->so_ptr ==
+ (char*)tmpp + order_size) {
+ LDAP_LIST_REMOVE(so, so_link);
+ break;
+ }
+ so = LDAP_LIST_NEXT(so, so_link);
+ }
+ if (so) {
+ if (i < sh->sh_maxorder) {
+ inserted = 1;
+ so->so_ptr = tmpp;
+ LDAP_LIST_INSERT_HEAD(&sh->sh_free[i-order_start+1],
+ so, so_link);
+ }
+ continue;
+ } else {
+ 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 = tmpp;
+ LDAP_LIST_INSERT_HEAD(&sh->sh_free[i-order_start],
+ so, so_link);
+ break;
+
+ Debug(LDAP_DEBUG_TRACE, "slap_sl_free: "
+ "free object not found while bit is clear.\n",
+ 0, 0, 0);
+ assert(so != NULL);
+
+ }
+ } else {
+ if (!inserted) {
+ 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 = tmpp;
+ LDAP_LIST_INSERT_HEAD(&sh->sh_free[i-order_start],
+ so, so_link);
+ }
+ break;
+ }
+ } else {
+ if (!(sh->sh_map[i-order_start][(diff-1)>>3] &
+ (1<<((diff-1)&0x7)))) {
+ so = LDAP_LIST_FIRST(&sh->sh_free[i-order_start]);
+ while (so) {
+ if ((char*)so->so_ptr == (char*)tmpp) {
+ LDAP_LIST_REMOVE(so, so_link);
+ } else if ((char*)tmpp == (char *)so->so_ptr + order_size) {
+ LDAP_LIST_REMOVE(so, so_link);
+ tmpp = so->so_ptr;
+ break;
+ }
+ so = LDAP_LIST_NEXT(so, so_link);
+ }
+ if (so) {
+ if (i < sh->sh_maxorder) {
+ inserted = 1;
+ LDAP_LIST_INSERT_HEAD(&sh->sh_free[i-order_start+1], so, so_link);
+ continue;
+ }
+ } else {
+ 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 = tmpp;
+ LDAP_LIST_INSERT_HEAD(&sh->sh_free[i-order_start],
+ so, so_link);
+ break;
+
+ Debug(LDAP_DEBUG_TRACE, "slap_sl_free: "
+ "free object not found while bit is clear.\n",
+ 0, 0, 0 );
+ assert(so != NULL);
+
+ }
+ } else {
+ if ( !inserted ) {
+ 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 = tmpp;
+ LDAP_LIST_INSERT_HEAD(&sh->sh_free[i-order_start],
+ so, so_link);
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
+void *
+slap_sl_context( void *ptr )