1/* $NetBSD: sl_malloc.c,v 1.1.1.3 2010/12/12 15:22:45 adam Exp $ */ 2 3/* sl_malloc.c - malloc routines using a per-thread slab */ 4/* OpenLDAP: pkg/ldap/servers/slapd/sl_malloc.c,v 1.39.2.13 2010/04/19 20:58:45 quanah Exp */ 5/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2003-2010 The OpenLDAP Foundation. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted only as authorized by the OpenLDAP 12 * Public License. 13 * 14 * A copy of this license is available in the file LICENSE in the 15 * top-level directory of the distribution or, alternatively, at 16 * <http://www.OpenLDAP.org/license.html>. 17 */ 18 19#include "portable.h" 20 21#include <stdio.h> 22#include <ac/string.h> 23 24#include "slap.h" 25 26static struct slab_object * slap_replenish_sopool(struct slab_heap* sh); 27#ifdef SLAPD_UNUSED 28static void print_slheap(int level, void *ctx); 29#endif 30 31void 32slap_sl_mem_destroy( 33 void *key, 34 void *data 35) 36{ 37 struct slab_heap *sh = data; 38 int pad = 2*sizeof(int)-1, pad_shift; 39 int order_start = -1, i; 40 struct slab_object *so; 41 42 if (sh->sh_stack) { 43 ber_memfree_x(sh->sh_base, NULL); 44 ber_memfree_x(sh, NULL); 45 } else { 46 pad_shift = pad - 1; 47 do { 48 order_start++; 49 } while (pad_shift >>= 1); 50 51 for (i = 0; i <= sh->sh_maxorder - order_start; i++) { 52 so = LDAP_LIST_FIRST(&sh->sh_free[i]); 53 while (so) { 54 struct slab_object *so_tmp = so; 55 so = LDAP_LIST_NEXT(so, so_link); 56 LDAP_LIST_INSERT_HEAD(&sh->sh_sopool, so_tmp, so_link); 57 } 58 ch_free(sh->sh_map[i]); 59 } 60 ch_free(sh->sh_free); 61 ch_free(sh->sh_map); 62 63 so = LDAP_LIST_FIRST(&sh->sh_sopool); 64 while (so) { 65 struct slab_object *so_tmp = so; 66 so = LDAP_LIST_NEXT(so, so_link); 67 if (!so_tmp->so_blockhead) { 68 LDAP_LIST_REMOVE(so_tmp, so_link); 69 } 70 } 71 so = LDAP_LIST_FIRST(&sh->sh_sopool); 72 while (so) { 73 struct slab_object *so_tmp = so; 74 so = LDAP_LIST_NEXT(so, so_link); 75 ch_free(so_tmp); 76 } 77 ber_memfree_x(sh->sh_base, NULL); 78 ber_memfree_x(sh, NULL); 79 } 80} 81 82BerMemoryFunctions slap_sl_mfuncs = 83 { slap_sl_malloc, slap_sl_calloc, slap_sl_realloc, slap_sl_free }; 84 85void 86slap_sl_mem_init() 87{ 88 ber_set_option( NULL, LBER_OPT_MEMORY_FNS, &slap_sl_mfuncs ); 89} 90 91#ifdef NO_THREADS 92static struct slab_heap *slheap; 93#endif 94 95/* This allocator always returns memory aligned on a 2-int boundary. 96 * 97 * The stack-based allocator stores the size as a ber_len_t at both 98 * the head and tail of the allocated block. When freeing a block, the 99 * tail length is ORed with 1 to mark it as free. Freed space can only 100 * be reclaimed from the tail forward. If the tail block is never freed, 101 * nothing else will be reclaimed until the slab is reset... 102 */ 103void * 104slap_sl_mem_create( 105 ber_len_t size, 106 int stack, 107 void *ctx, 108 int new 109) 110{ 111 struct slab_heap *sh; 112 ber_len_t size_shift; 113 int pad = 2*sizeof(int)-1, pad_shift; 114 int order = -1, order_start = -1, order_end = -1; 115 int i; 116 struct slab_object *so; 117 118#ifdef NO_THREADS 119 sh = slheap; 120#else 121 void *sh_tmp = NULL; 122 ldap_pvt_thread_pool_getkey( 123 ctx, (void *)slap_sl_mem_init, &sh_tmp, NULL ); 124 sh = sh_tmp; 125#endif 126 127 if ( sh && !new ) 128 return sh; 129 130 /* round up to doubleword boundary */ 131 size += pad; 132 size &= ~pad; 133 134 if (stack) { 135 if (!sh) { 136 sh = ch_malloc(sizeof(struct slab_heap)); 137 sh->sh_base = ch_malloc(size); 138#ifdef NO_THREADS 139 slheap = sh; 140#else 141 ldap_pvt_thread_pool_setkey(ctx, (void *)slap_sl_mem_init, 142 (void *)sh, slap_sl_mem_destroy, NULL, NULL); 143#endif 144 } else if ( size > (char *)sh->sh_end - (char *)sh->sh_base ) { 145 void *newptr; 146 147 newptr = ch_realloc( sh->sh_base, size ); 148 if ( newptr == NULL ) return NULL; 149 sh->sh_base = newptr; 150 } 151 /* insert dummy len */ 152 { 153 ber_len_t *i = sh->sh_base; 154 *i++ = 0; 155 sh->sh_last = i; 156 } 157 sh->sh_end = (char *) sh->sh_base + size; 158 sh->sh_stack = stack; 159 return sh; 160 } else { 161 size_shift = size - 1; 162 do { 163 order_end++; 164 } while (size_shift >>= 1); 165 166 pad_shift = pad - 1; 167 do { 168 order_start++; 169 } while (pad_shift >>= 1); 170 171 order = order_end - order_start + 1; 172 173 if (!sh) { 174 sh = (struct slab_heap *) ch_malloc(sizeof(struct slab_heap)); 175 sh->sh_base = ch_malloc(size); 176#ifdef NO_THREADS 177 slheap = sh; 178#else 179 ldap_pvt_thread_pool_setkey(ctx, (void *)slap_sl_mem_init, 180 (void *)sh, slap_sl_mem_destroy, NULL, NULL); 181#endif 182 } else { 183 for (i = 0; i <= sh->sh_maxorder - order_start; i++) { 184 so = LDAP_LIST_FIRST(&sh->sh_free[i]); 185 while (so) { 186 struct slab_object *so_tmp = so; 187 so = LDAP_LIST_NEXT(so, so_link); 188 LDAP_LIST_INSERT_HEAD(&sh->sh_sopool, so_tmp, so_link); 189 } 190 ch_free(sh->sh_map[i]); 191 } 192 ch_free(sh->sh_free); 193 ch_free(sh->sh_map); 194 195 so = LDAP_LIST_FIRST(&sh->sh_sopool); 196 while (so) { 197 struct slab_object *so_tmp = so; 198 so = LDAP_LIST_NEXT(so, so_link); 199 if (!so_tmp->so_blockhead) { 200 LDAP_LIST_REMOVE(so_tmp, so_link); 201 } 202 } 203 so = LDAP_LIST_FIRST(&sh->sh_sopool); 204 while (so) { 205 struct slab_object *so_tmp = so; 206 so = LDAP_LIST_NEXT(so, so_link); 207 ch_free(so_tmp); 208 } 209 210 if (size > (char *)sh->sh_end - (char *)sh->sh_base) { 211 void *newptr; 212 213 newptr = ch_realloc( sh->sh_base, size ); 214 if ( newptr == NULL ) return NULL; 215 sh->sh_base = newptr; 216 } 217 } 218 sh->sh_end = (char *)sh->sh_base + size; 219 sh->sh_maxorder = order_end; 220 221 sh->sh_free = (struct sh_freelist *) 222 ch_malloc(order * sizeof(struct sh_freelist)); 223 for (i = 0; i < order; i++) { 224 LDAP_LIST_INIT(&sh->sh_free[i]); 225 } 226 227 LDAP_LIST_INIT(&sh->sh_sopool); 228 229 if (LDAP_LIST_EMPTY(&sh->sh_sopool)) { 230 slap_replenish_sopool(sh); 231 } 232 so = LDAP_LIST_FIRST(&sh->sh_sopool); 233 LDAP_LIST_REMOVE(so, so_link); 234 so->so_ptr = sh->sh_base; 235 236 LDAP_LIST_INSERT_HEAD(&sh->sh_free[order-1], so, so_link); 237 238 sh->sh_map = (unsigned char **) 239 ch_malloc(order * sizeof(unsigned char *)); 240 for (i = 0; i < order; i++) { 241 int shiftamt = order_start + 1 + i; 242 int nummaps = size >> shiftamt; 243 assert(nummaps); 244 nummaps >>= 3; 245 if (!nummaps) nummaps = 1; 246 sh->sh_map[i] = (unsigned char *) ch_malloc(nummaps); 247 memset(sh->sh_map[i], 0, nummaps); 248 } 249 sh->sh_stack = stack; 250 return sh; 251 } 252} 253 254void 255slap_sl_mem_detach( 256 void *ctx, 257 void *memctx 258) 259{ 260#ifdef NO_THREADS 261 slheap = NULL; 262#else 263 /* separate from context */ 264 ldap_pvt_thread_pool_setkey( ctx, (void *)slap_sl_mem_init, 265 NULL, 0, NULL, NULL ); 266#endif 267} 268 269void * 270slap_sl_malloc( 271 ber_len_t size, 272 void *ctx 273) 274{ 275 struct slab_heap *sh = ctx; 276 int pad = 2*sizeof(int)-1, pad_shift; 277 ber_len_t *ptr, *newptr; 278 279#ifdef SLAP_NO_SL_MALLOC 280 newptr = ber_memalloc_x( size, NULL ); 281 if ( newptr ) return newptr; 282 assert( 0 ); 283 exit( EXIT_FAILURE ); 284#endif 285 286 /* ber_set_option calls us like this */ 287 if (!ctx) { 288 newptr = ber_memalloc_x( size, NULL ); 289 if ( newptr ) return newptr; 290 assert( 0 ); 291 exit( EXIT_FAILURE ); 292 } 293 294 /* round up to doubleword boundary, plus space for len at head and tail */ 295 size += 2*sizeof(ber_len_t) + pad; 296 size &= ~pad; 297 298 if (sh->sh_stack) { 299 if ((char *)sh->sh_last + size >= (char *)sh->sh_end) { 300 Debug(LDAP_DEBUG_TRACE, 301 "slap_sl_malloc of %lu bytes failed, using ch_malloc\n", 302 (long)size, 0, 0); 303 return ch_malloc(size); 304 } 305 newptr = sh->sh_last; 306 sh->sh_last = (char *) sh->sh_last + size; 307 size -= sizeof(ber_len_t); 308 *newptr++ = size; 309 *(ber_len_t *)((char *)sh->sh_last - sizeof(ber_len_t)) = size; 310 return( (void *)newptr ); 311 } else { 312 struct slab_object *so_new, *so_left, *so_right; 313 ber_len_t size_shift; 314 int order = -1, order_start = -1; 315 unsigned long diff; 316 int i, j; 317 318 size_shift = size - 1; 319 do { 320 order++; 321 } while (size_shift >>= 1); 322 323 pad_shift = pad - 1; 324 do { 325 order_start++; 326 } while (pad_shift >>= 1); 327 328 for (i = order; i <= sh->sh_maxorder && 329 LDAP_LIST_EMPTY(&sh->sh_free[i-order_start]); i++); 330 331 if (i == order) { 332 so_new = LDAP_LIST_FIRST(&sh->sh_free[i-order_start]); 333 LDAP_LIST_REMOVE(so_new, so_link); 334 ptr = so_new->so_ptr; 335 diff = (unsigned long)((char*)ptr - 336 (char*)sh->sh_base) >> (order + 1); 337 sh->sh_map[order-order_start][diff>>3] |= (1 << (diff & 0x7)); 338 *ptr++ = size - sizeof(ber_len_t); 339 LDAP_LIST_INSERT_HEAD(&sh->sh_sopool, so_new, so_link); 340 return((void*)ptr); 341 } else if (i <= sh->sh_maxorder) { 342 for (j = i; j > order; j--) { 343 so_left = LDAP_LIST_FIRST(&sh->sh_free[j-order_start]); 344 LDAP_LIST_REMOVE(so_left, so_link); 345 if (LDAP_LIST_EMPTY(&sh->sh_sopool)) { 346 slap_replenish_sopool(sh); 347 } 348 so_right = LDAP_LIST_FIRST(&sh->sh_sopool); 349 LDAP_LIST_REMOVE(so_right, so_link); 350 so_right->so_ptr = (void *)((char *)so_left->so_ptr + (1 << j)); 351 if (j == order + 1) { 352 ptr = so_left->so_ptr; 353 diff = (unsigned long)((char*)ptr - 354 (char*)sh->sh_base) >> (order+1); 355 sh->sh_map[order-order_start][diff>>3] |= 356 (1 << (diff & 0x7)); 357 *ptr++ = size - sizeof(ber_len_t); 358 LDAP_LIST_INSERT_HEAD( 359 &sh->sh_free[j-1-order_start], so_right, so_link); 360 LDAP_LIST_INSERT_HEAD(&sh->sh_sopool, so_left, so_link); 361 return((void*)ptr); 362 } else { 363 LDAP_LIST_INSERT_HEAD( 364 &sh->sh_free[j-1-order_start], so_right, so_link); 365 LDAP_LIST_INSERT_HEAD( 366 &sh->sh_free[j-1-order_start], so_left, so_link); 367 } 368 } 369 } else { 370 Debug( LDAP_DEBUG_TRACE, 371 "sl_malloc %lu: ch_malloc\n", 372 (long)size, 0, 0); 373 return (void*)ch_malloc(size); 374 } 375 } 376 377 /* FIXME: missing return; guessing... */ 378 return NULL; 379} 380 381void * 382slap_sl_calloc( ber_len_t n, ber_len_t size, void *ctx ) 383{ 384 void *newptr; 385 386 newptr = slap_sl_malloc( n*size, ctx ); 387 if ( newptr ) { 388 memset( newptr, 0, n*size ); 389 } 390 return newptr; 391} 392 393void * 394slap_sl_realloc(void *ptr, ber_len_t size, void *ctx) 395{ 396 struct slab_heap *sh = ctx; 397 int pad = 2*sizeof(int) -1; 398 ber_len_t *p = (ber_len_t *)ptr, *newptr; 399 400 if (ptr == NULL) 401 return slap_sl_malloc(size, ctx); 402 403#ifdef SLAP_NO_SL_MALLOC 404 newptr = ber_memrealloc_x( ptr, size, NULL ); 405 if ( newptr ) return newptr; 406 assert( 0 ); 407 exit( EXIT_FAILURE ); 408#endif 409 410 /* Not our memory? */ 411 if (!sh || ptr < sh->sh_base || ptr >= sh->sh_end) { 412 /* duplicate of realloc behavior, oh well */ 413 newptr = ber_memrealloc_x(ptr, size, NULL); 414 if (newptr) { 415 return newptr; 416 } 417 Debug(LDAP_DEBUG_ANY, "ch_realloc of %lu bytes failed\n", 418 (long) size, 0, 0); 419 assert(0); 420 exit( EXIT_FAILURE ); 421 } 422 423 if (size == 0) { 424 slap_sl_free(ptr, ctx); 425 return NULL; 426 } 427 428 if (sh->sh_stack) { 429 /* round up to doubleword boundary */ 430 size += pad + sizeof( ber_len_t ); 431 size &= ~pad; 432 433 p--; 434 435 /* Never shrink blocks */ 436 if (size <= p[0]) { 437 newptr = ptr; 438 439 /* If reallocing the last block, we can grow it */ 440 } else if ((char *)ptr + p[0] == sh->sh_last && 441 (char *)ptr + size < (char *)sh->sh_end ) { 442 newptr = ptr; 443 sh->sh_last = (char *)ptr + size; 444 p[0] = size; 445 p[size/sizeof(ber_len_t)] = size; 446 447 /* Nowhere to grow, need to alloc and copy */ 448 } else { 449 newptr = slap_sl_malloc(size-sizeof(ber_len_t), ctx); 450 AC_MEMCPY(newptr, ptr, p[0]-sizeof(ber_len_t)); 451 /* mark old region as free */ 452 p[p[0]/sizeof(ber_len_t)] |= 1; 453 } 454 return newptr; 455 } else { 456 void *newptr2; 457 458 newptr2 = slap_sl_malloc(size, ctx); 459 if (size < p[-1]) { 460 AC_MEMCPY(newptr2, ptr, size); 461 } else { 462 AC_MEMCPY(newptr2, ptr, p[-1]); 463 } 464 slap_sl_free(ptr, ctx); 465 return newptr2; 466 } 467} 468 469void 470slap_sl_free(void *ptr, void *ctx) 471{ 472 struct slab_heap *sh = ctx; 473 ber_len_t size; 474 ber_len_t *p = (ber_len_t *)ptr, *tmpp; 475 476 if (!ptr) 477 return; 478 479#ifdef SLAP_NO_SL_MALLOC 480 ber_memfree_x( ptr, NULL ); 481 return; 482#endif 483 484 if (!sh || ptr < sh->sh_base || ptr >= sh->sh_end) { 485 ber_memfree_x(ptr, NULL); 486 } else if (sh->sh_stack) { 487 tmpp = (ber_len_t *)((char *)ptr + p[-1]); 488 /* mark it free */ 489 tmpp[-1] |= 1; 490 /* reclaim free space off tail */ 491 while ( tmpp == sh->sh_last ) { 492 if ( tmpp[-1] & 1 ) { 493 size = tmpp[-1] ^ 1; 494 ptr = (char *)tmpp - size; 495 p = (ber_len_t *)ptr; 496 p--; 497 sh->sh_last = p; 498 tmpp = sh->sh_last; 499 } else { 500 break; 501 } 502 } 503 } else { 504 int size_shift, order_size; 505 int pad = 2*sizeof(int)-1, pad_shift; 506 int order_start = -1, order = -1; 507 struct slab_object *so; 508 unsigned long diff; 509 int i, inserted = 0; 510 511 size = *(--p); 512 size_shift = size + sizeof(ber_len_t) - 1; 513 do { 514 order++; 515 } while (size_shift >>= 1); 516 517 pad_shift = pad - 1; 518 do { 519 order_start++; 520 } while (pad_shift >>= 1); 521 522 for (i = order, tmpp = p; i <= sh->sh_maxorder; i++) { 523 order_size = 1 << (i+1); 524 diff = (unsigned long)((char*)tmpp - (char*)sh->sh_base) >> (i+1); 525 sh->sh_map[i-order_start][diff>>3] &= (~(1 << (diff & 0x7))); 526 if (diff == ((diff>>1)<<1)) { 527 if (!(sh->sh_map[i-order_start][(diff+1)>>3] & 528 (1<<((diff+1)&0x7)))) { 529 so = LDAP_LIST_FIRST(&sh->sh_free[i-order_start]); 530 while (so) { 531 if ((char*)so->so_ptr == (char*)tmpp) { 532 LDAP_LIST_REMOVE( so, so_link ); 533 } else if ((char*)so->so_ptr == 534 (char*)tmpp + order_size) { 535 LDAP_LIST_REMOVE(so, so_link); 536 break; 537 } 538 so = LDAP_LIST_NEXT(so, so_link); 539 } 540 if (so) { 541 if (i < sh->sh_maxorder) { 542 inserted = 1; 543 so->so_ptr = tmpp; 544 LDAP_LIST_INSERT_HEAD(&sh->sh_free[i-order_start+1], 545 so, so_link); 546 } 547 continue; 548 } else { 549 if (LDAP_LIST_EMPTY(&sh->sh_sopool)) { 550 slap_replenish_sopool(sh); 551 } 552 so = LDAP_LIST_FIRST(&sh->sh_sopool); 553 LDAP_LIST_REMOVE(so, so_link); 554 so->so_ptr = tmpp; 555 LDAP_LIST_INSERT_HEAD(&sh->sh_free[i-order_start], 556 so, so_link); 557 break; 558 559 Debug(LDAP_DEBUG_TRACE, "slap_sl_free: " 560 "free object not found while bit is clear.\n", 561 0, 0, 0); 562 assert(so != NULL); 563 564 } 565 } else { 566 if (!inserted) { 567 if (LDAP_LIST_EMPTY(&sh->sh_sopool)) { 568 slap_replenish_sopool(sh); 569 } 570 so = LDAP_LIST_FIRST(&sh->sh_sopool); 571 LDAP_LIST_REMOVE(so, so_link); 572 so->so_ptr = tmpp; 573 LDAP_LIST_INSERT_HEAD(&sh->sh_free[i-order_start], 574 so, so_link); 575 } 576 break; 577 } 578 } else { 579 if (!(sh->sh_map[i-order_start][(diff-1)>>3] & 580 (1<<((diff-1)&0x7)))) { 581 so = LDAP_LIST_FIRST(&sh->sh_free[i-order_start]); 582 while (so) { 583 if ((char*)so->so_ptr == (char*)tmpp) { 584 LDAP_LIST_REMOVE(so, so_link); 585 } else if ((char*)tmpp == (char *)so->so_ptr + order_size) { 586 LDAP_LIST_REMOVE(so, so_link); 587 tmpp = so->so_ptr; 588 break; 589 } 590 so = LDAP_LIST_NEXT(so, so_link); 591 } 592 if (so) { 593 if (i < sh->sh_maxorder) { 594 inserted = 1; 595 LDAP_LIST_INSERT_HEAD(&sh->sh_free[i-order_start+1], so, so_link); 596 continue; 597 } 598 } else { 599 if (LDAP_LIST_EMPTY(&sh->sh_sopool)) { 600 slap_replenish_sopool(sh); 601 } 602 so = LDAP_LIST_FIRST(&sh->sh_sopool); 603 LDAP_LIST_REMOVE(so, so_link); 604 so->so_ptr = tmpp; 605 LDAP_LIST_INSERT_HEAD(&sh->sh_free[i-order_start], 606 so, so_link); 607 break; 608 609 Debug(LDAP_DEBUG_TRACE, "slap_sl_free: " 610 "free object not found while bit is clear.\n", 611 0, 0, 0 ); 612 assert(so != NULL); 613 614 } 615 } else { 616 if ( !inserted ) { 617 if (LDAP_LIST_EMPTY(&sh->sh_sopool)) { 618 slap_replenish_sopool(sh); 619 } 620 so = LDAP_LIST_FIRST(&sh->sh_sopool); 621 LDAP_LIST_REMOVE(so, so_link); 622 so->so_ptr = tmpp; 623 LDAP_LIST_INSERT_HEAD(&sh->sh_free[i-order_start], 624 so, so_link); 625 } 626 break; 627 } 628 } 629 } 630 } 631} 632 633void * 634slap_sl_context( void *ptr ) 635{ 636 struct slab_heap *sh; 637 void *ctx, *sh_tmp; 638 639 if ( slapMode & SLAP_TOOL_MODE ) return NULL; 640 641#ifdef NO_THREADS 642 sh = slheap; 643#else 644 ctx = ldap_pvt_thread_pool_context(); 645 646 sh_tmp = NULL; 647 ldap_pvt_thread_pool_getkey( 648 ctx, (void *)slap_sl_mem_init, &sh_tmp, NULL); 649 sh = sh_tmp; 650#endif 651 652 if (sh && ptr >= sh->sh_base && ptr <= sh->sh_end) { 653 return sh; 654 } 655 return NULL; 656} 657 658static struct slab_object * 659slap_replenish_sopool( 660 struct slab_heap* sh 661) 662{ 663 struct slab_object *so_block; 664 int i; 665 666 so_block = (struct slab_object *)ch_malloc( 667 SLAP_SLAB_SOBLOCK * sizeof(struct slab_object)); 668 669 if ( so_block == NULL ) { 670 return NULL; 671 } 672 673 so_block[0].so_blockhead = 1; 674 LDAP_LIST_INSERT_HEAD(&sh->sh_sopool, &so_block[0], so_link); 675 for (i = 1; i < SLAP_SLAB_SOBLOCK; i++) { 676 so_block[i].so_blockhead = 0; 677 LDAP_LIST_INSERT_HEAD(&sh->sh_sopool, &so_block[i], so_link ); 678 } 679 680 return so_block; 681} 682 683#ifdef SLAPD_UNUSED 684static void 685print_slheap(int level, void *ctx) 686{ 687 struct slab_heap *sh = ctx; 688 int order_start = -1; 689 int pad = 2*sizeof(int)-1, pad_shift; 690 struct slab_object *so; 691 int i, j, once = 0; 692 693 if (!ctx) { 694 Debug(level, "NULL memctx\n", 0, 0, 0); 695 return; 696 } 697 698 pad_shift = pad - 1; 699 do { 700 order_start++; 701 } while (pad_shift >>= 1); 702 703 Debug(level, "sh->sh_maxorder=%d\n", sh->sh_maxorder, 0, 0); 704 705 for (i = order_start; i <= sh->sh_maxorder; i++) { 706 once = 0; 707 Debug(level, "order=%d\n", i, 0, 0); 708 for (j = 0; j < (1<<(sh->sh_maxorder-i))/8; j++) { 709 Debug(level, "%02x ", sh->sh_map[i-order_start][j], 0, 0); 710 once = 1; 711 } 712 if (!once) { 713 Debug(level, "%02x ", sh->sh_map[i-order_start][0], 0, 0); 714 } 715 Debug(level, "\n", 0, 0, 0); 716 Debug(level, "free list:\n", 0, 0, 0); 717 so = LDAP_LIST_FIRST(&sh->sh_free[i-order_start]); 718 while (so) { 719 Debug(level, "%lx\n", (unsigned long) so->so_ptr, 0, 0); 720 so = LDAP_LIST_NEXT(so, so_link); 721 } 722 } 723} 724#endif 725