sl_malloc.c 15.7 KB
Newer Older
1
2
/* sl_malloc.c - malloc routines using a per-thread slab */
/* $OpenLDAP$ */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
3
4
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
5
 * Copyright 2003-2006 The OpenLDAP Foundation.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
6
7
8
9
10
11
12
13
14
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
15
16
17
18
19
20
21
22
23
 */

#include "portable.h"

#include <stdio.h>
#include <ac/string.h>

#include "slap.h"

Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
24
static struct slab_object * slap_replenish_sopool(struct slab_heap* sh);
Pierangelo Masarati's avatar
Pierangelo Masarati committed
25
#ifdef SLAPD_UNUSED
26
static void print_slheap(int level, void *ctx);
Pierangelo Masarati's avatar
Pierangelo Masarati committed
27
#endif
28

29
void
30
slap_sl_mem_destroy(
31
32
33
34
35
	void *key,
	void *data
)
{
	struct slab_heap *sh = data;
36
37
38
	int pad = 2*sizeof(int)-1, pad_shift;
	int order_start = -1, i;
	struct slab_object *so;
39

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
	if (sh->sh_stack) {
		ber_memfree_x(sh->sh_base, NULL);
		ber_memfree_x(sh, NULL);
	} else {
		pad_shift = pad - 1;
		do {
			order_start++;
		} while (pad_shift >>= 1);

		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);
		}
		ber_memfree_x(sh->sh_base, NULL);
		ber_memfree_x(sh, NULL);
	}
78
79
}

80
81
BerMemoryFunctions slap_sl_mfuncs =
	{ slap_sl_malloc, slap_sl_calloc, slap_sl_realloc, slap_sl_free };
82
83

void
84
slap_sl_mem_init()
85
{
86
	ber_set_option( NULL, LBER_OPT_MEMORY_FNS, &slap_sl_mfuncs );
87
88
}

Howard Chu's avatar
Howard Chu committed
89
90
91
92
#ifdef NO_THREADS
static struct slab_heap *slheap;
#endif

Howard Chu's avatar
Howard Chu committed
93
void *
94
slap_sl_mem_create(
95
	ber_len_t size,
96
	int stack,
97
98
99
	void *ctx
)
{
100
	struct slab_heap *sh;
101
102
103
	ber_len_t size_shift;
	int pad = 2*sizeof(int)-1, pad_shift;
	int order = -1, order_start = -1, order_end = -1;
Howard Chu's avatar
Howard Chu committed
104
	int i;
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
105
	struct slab_object *so;
106

Howard Chu's avatar
Howard Chu committed
107
108
109
#ifdef NO_THREADS
	sh = slheap;
#else
110
	void *sh_tmp = NULL;
111
	ldap_pvt_thread_pool_getkey(
112
113
		ctx, (void *)slap_sl_mem_init, &sh_tmp, NULL );
	sh = sh_tmp;
Howard Chu's avatar
Howard Chu committed
114
#endif
115
116
117
118
119

	/* round up to doubleword boundary */
	size += pad;
	size &= ~pad;

120
121
122
123
124
125
126
127
128
129
130
	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);
#endif
		} else if ( size > (char *)sh->sh_end - (char *)sh->sh_base ) {
131
132
133
134
135
			void	*newptr;

			newptr = ch_realloc( sh->sh_base, size );
			if ( newptr == NULL ) return NULL;
			sh->sh_base = newptr;
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
		}
		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);
Howard Chu's avatar
Howard Chu committed
157
#ifdef NO_THREADS
158
			slheap = sh;
Howard Chu's avatar
Howard Chu committed
159
#else
160
161
			ldap_pvt_thread_pool_setkey(ctx, (void *)slap_sl_mem_init,
				(void *)sh, slap_sl_mem_destroy);
Howard Chu's avatar
Howard Chu committed
162
#endif
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
		} 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) {
192
193
194
195
196
				void	*newptr;

				newptr = realloc( sh->sh_base, size );
				if ( newptr == NULL ) return NULL;
				sh->sh_base = newptr;
197
198
199
200
201
202
203
204
205
206
207
208
209
210
			}
		}
		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)) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
211
			slap_replenish_sopool(sh);
212
		}
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
213
214
215
		so = LDAP_LIST_FIRST(&sh->sh_sopool);
		LDAP_LIST_REMOVE(so, so_link);
		so->so_ptr = sh->sh_base;
216
217
218
219

		LDAP_LIST_INSERT_HEAD(&sh->sh_free[order-1], so, so_link);

		sh->sh_map = (unsigned char **)
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
220
					ch_malloc(order * sizeof(unsigned char *));
221
		for (i = 0; i < order; i++) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
222
223
224
225
226
227
228
			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);
229
230
231
		}
		sh->sh_stack = stack;
		return sh;
232
233
234
	}
}

235
void
236
slap_sl_mem_detach(
237
238
239
240
	void *ctx,
	void *memctx
)
{
Howard Chu's avatar
Howard Chu committed
241
242
243
#ifdef NO_THREADS
	slheap = NULL;
#else
Howard Chu's avatar
Howard Chu committed
244
	/* separate from context */
245
	ldap_pvt_thread_pool_setkey( ctx, (void *)slap_sl_mem_init, NULL, NULL );
Howard Chu's avatar
Howard Chu committed
246
#endif
247
248
}

249
void *
250
slap_sl_malloc(
251
252
253
254
    ber_len_t	size,
    void *ctx
)
{
Howard Chu's avatar
Howard Chu committed
255
	struct slab_heap *sh = ctx;
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
256
	ber_len_t size_shift;
257
258
	int pad = 2*sizeof(int)-1, pad_shift;
	int order = -1, order_start = -1;
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
259
	struct slab_object *so_new, *so_left, *so_right;
260
	ber_len_t *ptr, *newptr;
261
	unsigned long diff;
Howard Chu's avatar
Howard Chu committed
262
	int i, j;
263

264
265
266
267
#ifdef SLAP_NO_SL_MALLOC
	return ber_malloc_x( size, NULL );
#endif

268
	/* ber_set_option calls us like this */
269
270
	if (!ctx) return ber_memalloc_x(size, NULL);

271
	/* round up to doubleword boundary */
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
272
	size += sizeof(ber_len_t) + pad;
273
274
	size &= ~pad;

275
276
277
278
279
280
281
	if (sh->sh_stack) {
		if ((char *)sh->sh_last + size >= (char *)sh->sh_end) {
			Debug(LDAP_DEBUG_TRACE,
				"slap_sl_malloc of %lu bytes failed, using ch_malloc\n",
				(long)size, 0, 0);
			return ch_malloc(size);
		}
282
283
		newptr = sh->sh_last;
		*newptr++ = size - sizeof(ber_len_t);
284
		sh->sh_last = (char *) sh->sh_last + size;
285
		return( (void *)newptr );
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
	} else {
		size_shift = size - 1;
		do {
			order++;
		} while (size_shift >>= 1);

		pad_shift = pad - 1;
		do {
			order_start++;
		} while (pad_shift >>= 1);

		for (i = order; i <= sh->sh_maxorder &&
				LDAP_LIST_EMPTY(&sh->sh_free[i-order_start]); i++);

		if (i == order) {
			so_new = LDAP_LIST_FIRST(&sh->sh_free[i-order_start]);
			LDAP_LIST_REMOVE(so_new, so_link);
			ptr = so_new->so_ptr;
			diff = (unsigned long)((char*)ptr -
					(char*)sh->sh_base) >> (order + 1);
			sh->sh_map[order-order_start][diff>>3] |= (1 << (diff & 0x7));
			*ptr++ = size - sizeof(ber_len_t);
			LDAP_LIST_INSERT_HEAD(&sh->sh_sopool, so_new, so_link);
			return((void*)ptr);
		} else if (i <= sh->sh_maxorder) {
			for (j = i; j > order; j--) {
				so_left = LDAP_LIST_FIRST(&sh->sh_free[j-order_start]);
				LDAP_LIST_REMOVE(so_left, so_link);
				if (LDAP_LIST_EMPTY(&sh->sh_sopool)) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
315
					slap_replenish_sopool(sh);
316
				}
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
317
318
				so_right = LDAP_LIST_FIRST(&sh->sh_sopool);
				LDAP_LIST_REMOVE(so_right, so_link);
319
				so_right->so_ptr = (void *)((char *)so_left->so_ptr + (1 << j));
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
				if (j == order + 1) {
					ptr = so_left->so_ptr;
					diff = (unsigned long)((char*)ptr -
							(char*)sh->sh_base) >> (order+1);
					sh->sh_map[order-order_start][diff>>3] |=
							(1 << (diff & 0x7));
					*ptr++ = size - sizeof(ber_len_t);
					LDAP_LIST_INSERT_HEAD(
							&sh->sh_free[j-1-order_start], so_right, so_link);
					LDAP_LIST_INSERT_HEAD(&sh->sh_sopool, so_left, so_link);
					return((void*)ptr);
				} else {
					LDAP_LIST_INSERT_HEAD(
							&sh->sh_free[j-1-order_start], so_right, so_link);
					LDAP_LIST_INSERT_HEAD(
							&sh->sh_free[j-1-order_start], so_left, so_link);
				}
			}
		} else {
			Debug( LDAP_DEBUG_TRACE,
				"slap_sl_malloc of %lu bytes failed, using ch_malloc\n",
				(long)size, 0, 0);
			return (void*)ch_malloc(size);
		}
344
	}
345
346
347

	/* FIXME: missing return; guessing... */
	return NULL;
348
349
350
}

void *
351
slap_sl_calloc( ber_len_t n, ber_len_t size, void *ctx )
352
{
353
	void *newptr;
354

355
356
357
	newptr = slap_sl_malloc( n*size, ctx );
	if ( newptr ) {
		memset( newptr, 0, n*size );
358
	}
359
	return newptr;
360
361
362
}

void *
363
slap_sl_realloc(void *ptr, ber_len_t size, void *ctx)
364
{
Howard Chu's avatar
Howard Chu committed
365
	struct slab_heap *sh = ctx;
Howard Chu's avatar
Howard Chu committed
366
	int pad = 2*sizeof(int) -1;
367
	ber_len_t *p = (ber_len_t *)ptr, *newptr;
368

369
370
	if (ptr == NULL)
		return slap_sl_malloc(size, ctx);
371

372
373
374
375
#ifdef SLAP_NO_SL_MALLOC
	return ber_memrealloc_x( ptr, size, NULL );
#endif

Howard Chu's avatar
Howard Chu committed
376
	/* Not our memory? */
377
378
	if (!sh || ptr < sh->sh_base || ptr >= sh->sh_end) {
		/* duplicate of realloc behavior, oh well */
379
380
381
		newptr = ber_memrealloc_x(ptr, size, NULL);
		if (newptr) {
			return newptr;
382
		}
383
384
385
		Debug(LDAP_DEBUG_ANY, "ch_realloc of %lu bytes failed\n",
				(long) size, 0, 0);
		assert(0);
386
		exit( EXIT_FAILURE );
387
388
	}

389
390
	if (size == 0) {
		slap_sl_free(ptr, ctx);
391
392
		return NULL;
	}
393

394
	if (sh->sh_stack) {
395
396
397
398
		/* round up to doubleword boundary */
		size += pad + sizeof( ber_len_t );
		size &= ~pad;

399
400
		/* Never shrink blocks */
		if (size <= p[-1]) {
401
			newptr = p;
402
	
403
		/* If reallocing the last block, we can grow it */
Howard Chu's avatar
Howard Chu committed
404
405
		} else if ((char *)ptr + p[-1] == sh->sh_last &&
			(char *)ptr + size < (char *)sh->sh_end ) {
406
			newptr = p;
407
408
			sh->sh_last = (char *)sh->sh_last + size - p[-1];
			p[-1] = size;
409
	
410
411
		/* Nowhere to grow, need to alloc and copy */
		} else {
412
413
			newptr = slap_sl_malloc(size, ctx);
			AC_MEMCPY(newptr, ptr, p[-1]);
414
		}
415
		return newptr;
416
	} else {
417
418
419
		void *newptr2;

		newptr2 = slap_sl_malloc(size, ctx);
420
		if (size < p[-1]) {
421
			AC_MEMCPY(newptr2, ptr, size);
422
		} else {
423
			AC_MEMCPY(newptr2, ptr, p[-1]);
424
425
		}
		slap_sl_free(ptr, ctx);
426
		return newptr2;
427
428
429
430
	}
}

void
431
slap_sl_free(void *ptr, void *ctx)
432
{
Howard Chu's avatar
Howard Chu committed
433
	struct slab_heap *sh = ctx;
434
435
436
437
	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;
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
438
	struct slab_object *so;
439
	unsigned long diff;
Howard Chu's avatar
Howard Chu committed
440
	int i, inserted = 0;
441

Howard Chu's avatar
Cleanup    
Howard Chu committed
442
443
444
	if (!ptr)
		return;

445
446
447
448
449
#ifdef SLAP_NO_SL_MALLOC
	ber_memfree_x( ptr, NULL );
	return;
#endif

450
451
452
	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) {
453
		p--;
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
		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)) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
495
							slap_replenish_sopool(sh);
496
						}
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
497
498
499
						so = LDAP_LIST_FIRST(&sh->sh_sopool);
						LDAP_LIST_REMOVE(so, so_link);
						so->so_ptr = tmpp;
500
501
502
503
						LDAP_LIST_INSERT_HEAD(&sh->sh_free[i-order_start],
								so, so_link);
						break;

Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
504
						Debug(LDAP_DEBUG_TRACE, "slap_sl_free: "
505
506
							"free object not found while bit is clear.\n",
							0, 0, 0);
507
						assert(so != NULL);
508
509
510
511
512

					}
				} else {
					if (!inserted) {
						if (LDAP_LIST_EMPTY(&sh->sh_sopool)) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
513
							slap_replenish_sopool(sh);
514
						}
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
515
516
517
						so = LDAP_LIST_FIRST(&sh->sh_sopool);
						LDAP_LIST_REMOVE(so, so_link);
						so->so_ptr = tmpp;
518
519
520
521
522
523
524
525
526
527
528
529
						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);
530
						} else if ((char*)tmpp == (char *)so->so_ptr + order_size) {
531
532
533
534
535
536
537
538
539
540
541
542
543
544
							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)) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
545
							slap_replenish_sopool(sh);
546
						}
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
547
548
549
						so = LDAP_LIST_FIRST(&sh->sh_sopool);
						LDAP_LIST_REMOVE(so, so_link);
						so->so_ptr = tmpp;
550
551
552
553
						LDAP_LIST_INSERT_HEAD(&sh->sh_free[i-order_start],
								so, so_link);
						break;

Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
554
						Debug(LDAP_DEBUG_TRACE, "slap_sl_free: "
555
556
							"free object not found while bit is clear.\n",
							0, 0, 0 );
557
						assert(so != NULL);
558
559
560
561
562

					}
				} else {
					if ( !inserted ) {
						if (LDAP_LIST_EMPTY(&sh->sh_sopool)) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
563
							slap_replenish_sopool(sh);
564
						}
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
565
566
567
						so = LDAP_LIST_FIRST(&sh->sh_sopool);
						LDAP_LIST_REMOVE(so, so_link);
						so->so_ptr = tmpp;
568
569
570
571
572
573
574
						LDAP_LIST_INSERT_HEAD(&sh->sh_free[i-order_start],
								so, so_link);
					}
					break;
				}
			}
		}
575
576
	}
}
Howard Chu's avatar
Howard Chu committed
577

578
void *
579
slap_sl_context( void *ptr )
580
{
581
582
	struct slab_heap *sh;
	void *ctx, *sh_tmp;
583

584
585
	if ( slapMode & SLAP_TOOL_MODE ) return NULL;

Howard Chu's avatar
Howard Chu committed
586
587
588
#ifdef NO_THREADS
	sh = slheap;
#else
589
590
	ctx = ldap_pvt_thread_pool_context();

591
592
593
594
	sh_tmp = NULL;
	ldap_pvt_thread_pool_getkey(
		ctx, (void *)slap_sl_mem_init, &sh_tmp, NULL);
	sh = sh_tmp;
Howard Chu's avatar
Howard Chu committed
595
#endif
596

597
	if (sh && ptr >= sh->sh_base && ptr <= sh->sh_end) {
598
599
600
601
		return sh;
	}
	return NULL;
}
602

Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
static struct slab_object *
slap_replenish_sopool(
    struct slab_heap* sh
)
{
    struct slab_object *so_block;
    int i;

    so_block = (struct slab_object *)ch_malloc(
                    SLAP_SLAB_SOBLOCK * sizeof(struct slab_object));

    if ( so_block == NULL ) {
        return NULL;
    }

    so_block[0].so_blockhead = 1;
    LDAP_LIST_INSERT_HEAD(&sh->sh_sopool, &so_block[0], so_link);
    for (i = 1; i < SLAP_SLAB_SOBLOCK; i++) {
        so_block[i].so_blockhead = 0;
        LDAP_LIST_INSERT_HEAD(&sh->sh_sopool, &so_block[i], so_link );
    }

    return so_block;
}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
628
#ifdef SLAPD_UNUSED
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
static void
print_slheap(int level, void *ctx)
{
	struct slab_heap *sh = ctx;
	int order_start = -1;
	int pad = 2*sizeof(int)-1, pad_shift;
	struct slab_object *so;
	int i, j, once = 0;

	if (!ctx) {
		Debug(level, "NULL memctx\n", 0, 0, 0);
		return;
	}

	pad_shift = pad - 1;
	do {
		order_start++;
	} while (pad_shift >>= 1);

	Debug(level, "sh->sh_maxorder=%d\n", sh->sh_maxorder, 0, 0);

	for (i = order_start; i <= sh->sh_maxorder; i++) {
		once = 0;
		Debug(level, "order=%d\n", i, 0, 0);
		for (j = 0; j < (1<<(sh->sh_maxorder-i))/8; j++) {
			Debug(level, "%02x ", sh->sh_map[i-order_start][j], 0, 0);
			once = 1;
		}
		if (!once) {
			Debug(level, "%02x ", sh->sh_map[i-order_start][0], 0, 0);
		}
		Debug(level, "\n", 0, 0, 0);
		Debug(level, "free list:\n", 0, 0, 0);
		so = LDAP_LIST_FIRST(&sh->sh_free[i-order_start]);
		while (so) {
664
			Debug(level, "%lx\n", (unsigned long) so->so_ptr, 0, 0);
665
666
667
668
			so = LDAP_LIST_NEXT(so, so_link);
		}
	}
}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
669
#endif