258
|
1
|
|
2 /*
|
|
3 * Copyright (C) Igor Sysoev
|
660
|
4 * Copyright (C) Nginx, Inc.
|
258
|
5 */
|
|
6
|
|
7 #include <ngx_config.h>
|
|
8 #include <ngx_core.h>
|
|
9
|
|
10
|
|
11 #define NGX_SLAB_PAGE_MASK 3
|
|
12 #define NGX_SLAB_PAGE 0
|
|
13 #define NGX_SLAB_BIG 1
|
|
14 #define NGX_SLAB_EXACT 2
|
|
15 #define NGX_SLAB_SMALL 3
|
|
16
|
|
17 #if (NGX_PTR_SIZE == 4)
|
|
18
|
|
19 #define NGX_SLAB_PAGE_FREE 0
|
|
20 #define NGX_SLAB_PAGE_BUSY 0xffffffff
|
|
21 #define NGX_SLAB_PAGE_START 0x80000000
|
|
22
|
|
23 #define NGX_SLAB_SHIFT_MASK 0x0000000f
|
|
24 #define NGX_SLAB_MAP_MASK 0xffff0000
|
|
25 #define NGX_SLAB_MAP_SHIFT 16
|
|
26
|
|
27 #define NGX_SLAB_BUSY 0xffffffff
|
|
28
|
|
29 #else /* (NGX_PTR_SIZE == 8) */
|
|
30
|
|
31 #define NGX_SLAB_PAGE_FREE 0
|
|
32 #define NGX_SLAB_PAGE_BUSY 0xffffffffffffffff
|
|
33 #define NGX_SLAB_PAGE_START 0x8000000000000000
|
|
34
|
|
35 #define NGX_SLAB_SHIFT_MASK 0x000000000000000f
|
|
36 #define NGX_SLAB_MAP_MASK 0xffffffff00000000
|
|
37 #define NGX_SLAB_MAP_SHIFT 32
|
|
38
|
|
39 #define NGX_SLAB_BUSY 0xffffffffffffffff
|
|
40
|
|
41 #endif
|
|
42
|
|
43
|
|
44 #if (NGX_DEBUG_MALLOC)
|
358
|
45
|
646
|
46 #define ngx_slab_junk(p, size) ngx_memset(p, 0xA5, size)
|
358
|
47
|
258
|
48 #else
|
358
|
49
|
646
|
50 #if (NGX_HAVE_DEBUG_MALLOC)
|
358
|
51
|
|
52 #define ngx_slab_junk(p, size) \
|
646
|
53 if (ngx_debug_malloc) ngx_memset(p, 0xA5, size)
|
358
|
54
|
|
55 #else
|
|
56
|
258
|
57 #define ngx_slab_junk(p, size)
|
358
|
58
|
|
59 #endif
|
|
60
|
258
|
61 #endif
|
|
62
|
|
63 static ngx_slab_page_t *ngx_slab_alloc_pages(ngx_slab_pool_t *pool,
|
|
64 ngx_uint_t pages);
|
|
65 static void ngx_slab_free_pages(ngx_slab_pool_t *pool, ngx_slab_page_t *page,
|
|
66 ngx_uint_t pages);
|
468
|
67 static void ngx_slab_error(ngx_slab_pool_t *pool, ngx_uint_t level,
|
|
68 char *text);
|
258
|
69
|
|
70
|
|
71 static ngx_uint_t ngx_slab_max_size;
|
|
72 static ngx_uint_t ngx_slab_exact_size;
|
|
73 static ngx_uint_t ngx_slab_exact_shift;
|
|
74
|
|
75
|
|
76 void
|
|
77 ngx_slab_init(ngx_slab_pool_t *pool)
|
|
78 {
|
|
79 u_char *p;
|
|
80 size_t size;
|
|
81 ngx_int_t m;
|
|
82 ngx_uint_t i, n, pages;
|
|
83 ngx_slab_page_t *slots;
|
|
84
|
|
85 /* STUB */
|
|
86 if (ngx_slab_max_size == 0) {
|
|
87 ngx_slab_max_size = ngx_pagesize / 2;
|
|
88 ngx_slab_exact_size = ngx_pagesize / (8 * sizeof(uintptr_t));
|
|
89 for (n = ngx_slab_exact_size; n >>= 1; ngx_slab_exact_shift++) {
|
|
90 /* void */
|
|
91 }
|
|
92 }
|
|
93 /**/
|
|
94
|
|
95 pool->min_size = 1 << pool->min_shift;
|
|
96
|
|
97 p = (u_char *) pool + sizeof(ngx_slab_pool_t);
|
|
98 size = pool->end - p;
|
|
99
|
|
100 ngx_slab_junk(p, size);
|
|
101
|
|
102 slots = (ngx_slab_page_t *) p;
|
|
103 n = ngx_pagesize_shift - pool->min_shift;
|
|
104
|
|
105 for (i = 0; i < n; i++) {
|
|
106 slots[i].slab = 0;
|
|
107 slots[i].next = &slots[i];
|
|
108 slots[i].prev = 0;
|
|
109 }
|
|
110
|
|
111 p += n * sizeof(ngx_slab_page_t);
|
|
112
|
348
|
113 pages = (ngx_uint_t) (size / (ngx_pagesize + sizeof(ngx_slab_page_t)));
|
258
|
114
|
|
115 ngx_memzero(p, pages * sizeof(ngx_slab_page_t));
|
|
116
|
|
117 pool->pages = (ngx_slab_page_t *) p;
|
|
118
|
|
119 pool->free.prev = 0;
|
|
120 pool->free.next = (ngx_slab_page_t *) p;
|
|
121
|
|
122 pool->pages->slab = pages;
|
|
123 pool->pages->next = &pool->free;
|
|
124 pool->pages->prev = (uintptr_t) &pool->free;
|
|
125
|
|
126 pool->start = (u_char *)
|
274
|
127 ngx_align_ptr((uintptr_t) p + pages * sizeof(ngx_slab_page_t),
|
258
|
128 ngx_pagesize);
|
|
129
|
|
130 m = pages - (pool->end - pool->start) / ngx_pagesize;
|
|
131 if (m > 0) {
|
|
132 pages -= m;
|
|
133 pool->pages->slab = pages;
|
|
134 }
|
|
135
|
468
|
136 pool->log_ctx = &pool->zero;
|
|
137 pool->zero = '\0';
|
258
|
138 }
|
|
139
|
|
140
|
|
141 void *
|
|
142 ngx_slab_alloc(ngx_slab_pool_t *pool, size_t size)
|
|
143 {
|
272
|
144 void *p;
|
|
145
|
|
146 ngx_shmtx_lock(&pool->mutex);
|
|
147
|
|
148 p = ngx_slab_alloc_locked(pool, size);
|
|
149
|
|
150 ngx_shmtx_unlock(&pool->mutex);
|
|
151
|
|
152 return p;
|
|
153 }
|
|
154
|
|
155
|
|
156 void *
|
|
157 ngx_slab_alloc_locked(ngx_slab_pool_t *pool, size_t size)
|
|
158 {
|
258
|
159 size_t s;
|
260
|
160 uintptr_t p, n, m, mask, *bitmap;
|
|
161 ngx_uint_t i, slot, shift, map;
|
258
|
162 ngx_slab_page_t *page, *prev, *slots;
|
|
163
|
272
|
164 if (size >= ngx_slab_max_size) {
|
258
|
165
|
272
|
166 ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0,
|
|
167 "slab alloc: %uz", size);
|
|
168
|
258
|
169 page = ngx_slab_alloc_pages(pool, (size + ngx_pagesize - 1)
|
|
170 >> ngx_pagesize_shift);
|
|
171 if (page) {
|
|
172 p = (page - pool->pages) << ngx_pagesize_shift;
|
|
173 p += (uintptr_t) pool->start;
|
|
174
|
|
175 } else {
|
|
176 p = 0;
|
|
177 }
|
|
178
|
|
179 goto done;
|
|
180 }
|
|
181
|
|
182 if (size > pool->min_size) {
|
|
183 shift = 1;
|
|
184 for (s = size - 1; s >>= 1; shift++) { /* void */ }
|
|
185 slot = shift - pool->min_shift;
|
|
186
|
|
187 } else {
|
|
188 size = pool->min_size;
|
|
189 shift = pool->min_shift;
|
|
190 slot = 0;
|
|
191 }
|
|
192
|
|
193 ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0,
|
|
194 "slab alloc: %uz slot: %ui", size, slot);
|
|
195
|
|
196 slots = (ngx_slab_page_t *) ((u_char *) pool + sizeof(ngx_slab_pool_t));
|
|
197 page = slots[slot].next;
|
|
198
|
|
199 if (page->next != page) {
|
|
200
|
272
|
201 if (shift < ngx_slab_exact_shift) {
|
258
|
202
|
|
203 do {
|
|
204 p = (page - pool->pages) << ngx_pagesize_shift;
|
|
205 bitmap = (uintptr_t *) (pool->start + p);
|
|
206
|
|
207 map = (1 << (ngx_pagesize_shift - shift))
|
|
208 / (sizeof(uintptr_t) * 8);
|
|
209
|
|
210 for (n = 0; n < map; n++) {
|
|
211
|
|
212 if (bitmap[n] != NGX_SLAB_BUSY) {
|
|
213
|
|
214 for (m = 1, i = 0; m; m <<= 1, i++) {
|
|
215 if ((bitmap[n] & m)) {
|
|
216 continue;
|
|
217 }
|
|
218
|
|
219 bitmap[n] |= m;
|
272
|
220
|
|
221 i = ((n * sizeof(uintptr_t) * 8) << shift)
|
|
222 + (i << shift);
|
258
|
223
|
|
224 if (bitmap[n] == NGX_SLAB_BUSY) {
|
|
225 for (n = n + 1; n < map; n++) {
|
|
226 if (bitmap[n] != NGX_SLAB_BUSY) {
|
|
227 p = (uintptr_t) bitmap + i;
|
|
228
|
|
229 goto done;
|
|
230 }
|
|
231 }
|
|
232
|
|
233 prev = (ngx_slab_page_t *)
|
|
234 (page->prev & ~NGX_SLAB_PAGE_MASK);
|
|
235 prev->next = page->next;
|
|
236 page->next->prev = page->prev;
|
|
237
|
|
238 page->next = NULL;
|
|
239 page->prev = NGX_SLAB_SMALL;
|
|
240 }
|
|
241
|
|
242 p = (uintptr_t) bitmap + i;
|
|
243
|
|
244 goto done;
|
|
245 }
|
|
246 }
|
|
247 }
|
|
248
|
|
249 page = page->next;
|
|
250
|
|
251 } while (page);
|
|
252
|
272
|
253 } else if (shift == ngx_slab_exact_shift) {
|
258
|
254
|
|
255 do {
|
|
256 if (page->slab != NGX_SLAB_BUSY) {
|
|
257
|
|
258 for (m = 1, i = 0; m; m <<= 1, i++) {
|
|
259 if ((page->slab & m)) {
|
|
260 continue;
|
|
261 }
|
|
262
|
|
263 page->slab |= m;
|
|
264
|
|
265 if (page->slab == NGX_SLAB_BUSY) {
|
|
266 prev = (ngx_slab_page_t *)
|
|
267 (page->prev & ~NGX_SLAB_PAGE_MASK);
|
|
268 prev->next = page->next;
|
|
269 page->next->prev = page->prev;
|
|
270
|
|
271 page->next = NULL;
|
|
272 page->prev = NGX_SLAB_EXACT;
|
|
273 }
|
|
274
|
|
275 p = (page - pool->pages) << ngx_pagesize_shift;
|
|
276 p += i << shift;
|
|
277 p += (uintptr_t) pool->start;
|
|
278
|
|
279 goto done;
|
|
280 }
|
|
281 }
|
|
282
|
|
283 page = page->next;
|
|
284
|
|
285 } while (page);
|
|
286
|
272
|
287 } else { /* shift > ngx_slab_exact_shift */
|
258
|
288
|
|
289 n = ngx_pagesize_shift - (page->slab & NGX_SLAB_SHIFT_MASK);
|
|
290 n = 1 << n;
|
274
|
291 n = ((uintptr_t) 1 << n) - 1;
|
258
|
292 mask = n << NGX_SLAB_MAP_SHIFT;
|
|
293
|
|
294 do {
|
|
295 if ((page->slab & NGX_SLAB_MAP_MASK) != mask) {
|
|
296
|
260
|
297 for (m = (uintptr_t) 1 << NGX_SLAB_MAP_SHIFT, i = 0;
|
258
|
298 m & mask;
|
|
299 m <<= 1, i++)
|
|
300 {
|
|
301 if ((page->slab & m)) {
|
|
302 continue;
|
|
303 }
|
|
304
|
|
305 page->slab |= m;
|
|
306
|
|
307 if ((page->slab & NGX_SLAB_MAP_MASK) == mask) {
|
|
308 prev = (ngx_slab_page_t *)
|
|
309 (page->prev & ~NGX_SLAB_PAGE_MASK);
|
|
310 prev->next = page->next;
|
|
311 page->next->prev = page->prev;
|
|
312
|
|
313 page->next = NULL;
|
|
314 page->prev = NGX_SLAB_BIG;
|
|
315 }
|
|
316
|
|
317 p = (page - pool->pages) << ngx_pagesize_shift;
|
|
318 p += i << shift;
|
|
319 p += (uintptr_t) pool->start;
|
|
320
|
|
321 goto done;
|
|
322 }
|
|
323 }
|
|
324
|
|
325 page = page->next;
|
|
326
|
|
327 } while (page);
|
|
328 }
|
|
329 }
|
|
330
|
|
331 page = ngx_slab_alloc_pages(pool, 1);
|
|
332
|
|
333 if (page) {
|
272
|
334 if (shift < ngx_slab_exact_shift) {
|
258
|
335 p = (page - pool->pages) << ngx_pagesize_shift;
|
|
336 bitmap = (uintptr_t *) (pool->start + p);
|
|
337
|
|
338 s = 1 << shift;
|
|
339 n = (1 << (ngx_pagesize_shift - shift)) / 8 / s;
|
|
340
|
|
341 if (n == 0) {
|
|
342 n = 1;
|
|
343 }
|
|
344
|
|
345 bitmap[0] = (2 << n) - 1;
|
|
346
|
|
347 map = (1 << (ngx_pagesize_shift - shift)) / (sizeof(uintptr_t) * 8);
|
|
348
|
|
349 for (i = 1; i < map; i++) {
|
|
350 bitmap[i] = 0;
|
|
351 }
|
|
352
|
|
353 page->slab = shift;
|
|
354 page->next = &slots[slot];
|
|
355 page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_SMALL;
|
|
356
|
|
357 slots[slot].next = page;
|
|
358
|
|
359 p = ((page - pool->pages) << ngx_pagesize_shift) + s * n;
|
|
360 p += (uintptr_t) pool->start;
|
|
361
|
|
362 goto done;
|
|
363
|
272
|
364 } else if (shift == ngx_slab_exact_shift) {
|
258
|
365
|
|
366 page->slab = 1;
|
|
367 page->next = &slots[slot];
|
|
368 page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_EXACT;
|
|
369
|
|
370 slots[slot].next = page;
|
|
371
|
|
372 p = (page - pool->pages) << ngx_pagesize_shift;
|
|
373 p += (uintptr_t) pool->start;
|
|
374
|
|
375 goto done;
|
|
376
|
272
|
377 } else { /* shift > ngx_slab_exact_shift */
|
258
|
378
|
260
|
379 page->slab = ((uintptr_t) 1 << NGX_SLAB_MAP_SHIFT) | shift;
|
258
|
380 page->next = &slots[slot];
|
|
381 page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_BIG;
|
|
382
|
|
383 slots[slot].next = page;
|
|
384
|
|
385 p = (page - pool->pages) << ngx_pagesize_shift;
|
|
386 p += (uintptr_t) pool->start;
|
|
387
|
|
388 goto done;
|
|
389 }
|
|
390 }
|
|
391
|
|
392 p = 0;
|
|
393
|
|
394 done:
|
|
395
|
|
396 ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0, "slab alloc: %p", p);
|
|
397
|
|
398 return (void *) p;
|
|
399 }
|
|
400
|
|
401
|
|
402 void
|
|
403 ngx_slab_free(ngx_slab_pool_t *pool, void *p)
|
|
404 {
|
272
|
405 ngx_shmtx_lock(&pool->mutex);
|
|
406
|
|
407 ngx_slab_free_locked(pool, p);
|
|
408
|
|
409 ngx_shmtx_unlock(&pool->mutex);
|
|
410 }
|
|
411
|
|
412
|
|
413 void
|
|
414 ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p)
|
|
415 {
|
258
|
416 size_t size;
|
274
|
417 uintptr_t slab, m, *bitmap;
|
|
418 ngx_uint_t n, type, slot, shift, map;
|
258
|
419 ngx_slab_page_t *slots, *page;
|
|
420
|
|
421 ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0, "slab free: %p", p);
|
|
422
|
|
423 if ((u_char *) p < pool->start || (u_char *) p > pool->end) {
|
468
|
424 ngx_slab_error(pool, NGX_LOG_ALERT, "ngx_slab_free(): outside of pool");
|
258
|
425 goto fail;
|
|
426 }
|
|
427
|
|
428 n = ((u_char *) p - pool->start) >> ngx_pagesize_shift;
|
|
429 page = &pool->pages[n];
|
|
430 slab = page->slab;
|
|
431 type = page->prev & NGX_SLAB_PAGE_MASK;
|
|
432
|
|
433 switch (type) {
|
|
434
|
|
435 case NGX_SLAB_SMALL:
|
|
436
|
|
437 shift = slab & NGX_SLAB_SHIFT_MASK;
|
|
438 size = 1 << shift;
|
|
439
|
|
440 if ((uintptr_t) p & (size - 1)) {
|
|
441 goto wrong_chunk;
|
|
442 }
|
|
443
|
|
444 n = ((uintptr_t) p & (ngx_pagesize - 1)) >> shift;
|
274
|
445 m = (uintptr_t) 1 << (n & (sizeof(uintptr_t) * 8 - 1));
|
258
|
446 n /= (sizeof(uintptr_t) * 8);
|
|
447 bitmap = (uintptr_t *) ((uintptr_t) p & ~(ngx_pagesize - 1));
|
|
448
|
|
449 if (bitmap[n] & m) {
|
|
450
|
|
451 if (page->next == NULL) {
|
|
452 slots = (ngx_slab_page_t *)
|
|
453 ((u_char *) pool + sizeof(ngx_slab_pool_t));
|
|
454 slot = shift - pool->min_shift;
|
|
455
|
|
456 page->next = slots[slot].next;
|
|
457 slots[slot].next = page;
|
|
458
|
|
459 page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_SMALL;
|
|
460 page->next->prev = (uintptr_t) page | NGX_SLAB_SMALL;
|
|
461 }
|
|
462
|
|
463 bitmap[n] &= ~m;
|
|
464
|
|
465 n = (1 << (ngx_pagesize_shift - shift)) / 8 / (1 << shift);
|
|
466
|
|
467 if (n == 0) {
|
|
468 n = 1;
|
|
469 }
|
|
470
|
274
|
471 if (bitmap[0] & ~(((uintptr_t) 1 << n) - 1)) {
|
258
|
472 goto done;
|
|
473 }
|
|
474
|
|
475 map = (1 << (ngx_pagesize_shift - shift)) / (sizeof(uintptr_t) * 8);
|
|
476
|
|
477 for (n = 1; n < map; n++) {
|
|
478 if (bitmap[n]) {
|
|
479 goto done;
|
|
480 }
|
|
481 }
|
|
482
|
|
483 ngx_slab_free_pages(pool, page, 1);
|
|
484
|
|
485 goto done;
|
|
486 }
|
|
487
|
|
488 goto chunk_already_free;
|
|
489
|
|
490 case NGX_SLAB_EXACT:
|
|
491
|
274
|
492 m = (uintptr_t) 1 <<
|
|
493 (((uintptr_t) p & (ngx_pagesize - 1)) >> ngx_slab_exact_shift);
|
258
|
494 size = ngx_slab_exact_size;
|
|
495
|
|
496 if ((uintptr_t) p & (size - 1)) {
|
|
497 goto wrong_chunk;
|
|
498 }
|
|
499
|
|
500 if (slab & m) {
|
|
501 if (slab == NGX_SLAB_BUSY) {
|
|
502 slots = (ngx_slab_page_t *)
|
|
503 ((u_char *) pool + sizeof(ngx_slab_pool_t));
|
|
504 slot = ngx_slab_exact_shift - pool->min_shift;
|
|
505
|
|
506 page->next = slots[slot].next;
|
|
507 slots[slot].next = page;
|
|
508
|
|
509 page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_EXACT;
|
|
510 page->next->prev = (uintptr_t) page | NGX_SLAB_EXACT;
|
|
511 }
|
|
512
|
|
513 page->slab &= ~m;
|
|
514
|
|
515 if (page->slab) {
|
|
516 goto done;
|
|
517 }
|
|
518
|
|
519 ngx_slab_free_pages(pool, page, 1);
|
|
520
|
|
521 goto done;
|
|
522 }
|
|
523
|
|
524 goto chunk_already_free;
|
|
525
|
|
526 case NGX_SLAB_BIG:
|
|
527
|
|
528 shift = slab & NGX_SLAB_SHIFT_MASK;
|
|
529 size = 1 << shift;
|
|
530
|
|
531 if ((uintptr_t) p & (size - 1)) {
|
|
532 goto wrong_chunk;
|
|
533 }
|
|
534
|
274
|
535 m = (uintptr_t) 1 << ((((uintptr_t) p & (ngx_pagesize - 1)) >> shift)
|
|
536 + NGX_SLAB_MAP_SHIFT);
|
258
|
537
|
|
538 if (slab & m) {
|
|
539
|
|
540 if (page->next == NULL) {
|
|
541 slots = (ngx_slab_page_t *)
|
|
542 ((u_char *) pool + sizeof(ngx_slab_pool_t));
|
|
543 slot = shift - pool->min_shift;
|
|
544
|
|
545 page->next = slots[slot].next;
|
|
546 slots[slot].next = page;
|
|
547
|
|
548 page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_BIG;
|
|
549 page->next->prev = (uintptr_t) page | NGX_SLAB_BIG;
|
|
550 }
|
|
551
|
|
552 page->slab &= ~m;
|
|
553
|
|
554 if (page->slab & NGX_SLAB_MAP_MASK) {
|
|
555 goto done;
|
|
556 }
|
|
557
|
|
558 ngx_slab_free_pages(pool, page, 1);
|
|
559
|
|
560 goto done;
|
|
561 }
|
|
562
|
|
563 goto chunk_already_free;
|
|
564
|
|
565 case NGX_SLAB_PAGE:
|
|
566
|
|
567 if ((uintptr_t) p & (ngx_pagesize - 1)) {
|
|
568 goto wrong_chunk;
|
|
569 }
|
|
570
|
|
571 if (slab == NGX_SLAB_PAGE_FREE) {
|
468
|
572 ngx_slab_error(pool, NGX_LOG_ALERT,
|
|
573 "ngx_slab_free(): page is already free");
|
258
|
574 goto fail;
|
|
575 }
|
|
576
|
|
577 if (slab == NGX_SLAB_PAGE_BUSY) {
|
468
|
578 ngx_slab_error(pool, NGX_LOG_ALERT,
|
|
579 "ngx_slab_free(): pointer to wrong page");
|
258
|
580 goto fail;
|
|
581 }
|
|
582
|
|
583 n = ((u_char *) p - pool->start) >> ngx_pagesize_shift;
|
|
584 size = slab & ~NGX_SLAB_PAGE_START;
|
|
585
|
|
586 ngx_slab_free_pages(pool, &pool->pages[n], size);
|
|
587
|
480
|
588 ngx_slab_junk(p, size << ngx_pagesize_shift);
|
258
|
589
|
480
|
590 return;
|
258
|
591 }
|
|
592
|
|
593 /* not reached */
|
|
594
|
|
595 return;
|
|
596
|
|
597 done:
|
|
598
|
|
599 ngx_slab_junk(p, size);
|
|
600
|
|
601 return;
|
|
602
|
|
603 wrong_chunk:
|
|
604
|
468
|
605 ngx_slab_error(pool, NGX_LOG_ALERT,
|
|
606 "ngx_slab_free(): pointer to wrong chunk");
|
258
|
607
|
|
608 goto fail;
|
|
609
|
|
610 chunk_already_free:
|
|
611
|
468
|
612 ngx_slab_error(pool, NGX_LOG_ALERT,
|
|
613 "ngx_slab_free(): chunk is already free");
|
258
|
614
|
|
615 fail:
|
|
616
|
|
617 return;
|
|
618 }
|
|
619
|
|
620
|
|
621 static ngx_slab_page_t *
|
|
622 ngx_slab_alloc_pages(ngx_slab_pool_t *pool, ngx_uint_t pages)
|
|
623 {
|
|
624 ngx_slab_page_t *page, *p;
|
|
625
|
|
626 for (page = pool->free.next; page != &pool->free; page = page->next) {
|
|
627
|
|
628 if (page->slab >= pages) {
|
|
629
|
|
630 if (page->slab > pages) {
|
|
631 page[pages].slab = page->slab - pages;
|
|
632 page[pages].next = page->next;
|
|
633 page[pages].prev = page->prev;
|
|
634
|
|
635 p = (ngx_slab_page_t *) page->prev;
|
|
636 p->next = &page[pages];
|
|
637 page->next->prev = (uintptr_t) &page[pages];
|
|
638
|
|
639 } else {
|
|
640 p = (ngx_slab_page_t *) page->prev;
|
|
641 p->next = page->next;
|
|
642 page->next->prev = page->prev;
|
|
643 }
|
|
644
|
|
645 page->slab = pages | NGX_SLAB_PAGE_START;
|
|
646 page->next = NULL;
|
|
647 page->prev = NGX_SLAB_PAGE;
|
|
648
|
|
649 if (--pages == 0) {
|
|
650 return page;
|
|
651 }
|
|
652
|
|
653 for (p = page + 1; pages; pages--) {
|
|
654 p->slab = NGX_SLAB_PAGE_BUSY;
|
|
655 p->next = NULL;
|
|
656 p->prev = NGX_SLAB_PAGE;
|
|
657 p++;
|
|
658 }
|
|
659
|
|
660 return page;
|
|
661 }
|
|
662 }
|
|
663
|
468
|
664 ngx_slab_error(pool, NGX_LOG_CRIT, "ngx_slab_alloc() failed: no memory");
|
272
|
665
|
258
|
666 return NULL;
|
|
667 }
|
|
668
|
|
669
|
|
670 static void
|
|
671 ngx_slab_free_pages(ngx_slab_pool_t *pool, ngx_slab_page_t *page,
|
|
672 ngx_uint_t pages)
|
|
673 {
|
|
674 ngx_slab_page_t *prev;
|
|
675
|
|
676 page->slab = pages--;
|
|
677
|
|
678 if (pages) {
|
|
679 ngx_memzero(&page[1], pages * sizeof(ngx_slab_page_t));
|
|
680 }
|
|
681
|
272
|
682 if (page->next) {
|
|
683 prev = (ngx_slab_page_t *) (page->prev & ~NGX_SLAB_PAGE_MASK);
|
|
684 prev->next = page->next;
|
|
685 page->next->prev = page->prev;
|
|
686 }
|
258
|
687
|
272
|
688 page->prev = (uintptr_t) &pool->free;
|
258
|
689 page->next = pool->free.next;
|
272
|
690
|
|
691 page->next->prev = (uintptr_t) page;
|
|
692
|
258
|
693 pool->free.next = page;
|
|
694 }
|
468
|
695
|
|
696
|
|
697 static void
|
|
698 ngx_slab_error(ngx_slab_pool_t *pool, ngx_uint_t level, char *text)
|
|
699 {
|
|
700 ngx_log_error(level, ngx_cycle->log, 0, "%s%s", text, pool->log_ctx);
|
|
701 }
|