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