Ticket #686: ngx_palloc.c

File ngx_palloc.c, 8.0 KB (added by Deming Sun, 12 years ago)
Line 
1
2/*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
6
7
8#include <ngx_config.h>
9#include <ngx_core.h>
10
11
12static void *ngx_palloc_block(ngx_pool_t *pool, size_t size);
13static void *ngx_palloc_large(ngx_pool_t *pool, size_t size);
14
15
16ngx_pool_t *
17ngx_create_pool(size_t size, ngx_log_t *log)
18{
19 ngx_pool_t *p;
20
21 p = ngx_memalign(NGX_POOL_ALIGNMENT, size, log);
22 if (p == NULL) {
23 return NULL;
24 }
25
26 p->d.last = (u_char *) p + sizeof(ngx_pool_t);
27 p->d.end = (u_char *) p + size;
28 p->d.next = NULL;
29 p->d.failed = 0;
30
31 size = size - sizeof(ngx_pool_t);
32 p->max = (size < NGX_MAX_ALLOC_FROM_POOL) ? size : NGX_MAX_ALLOC_FROM_POOL;
33
34 p->current = p;
35 p->chain = NULL;
36 p->large = NULL;
37 p->cleanup = NULL;
38 p->log = log;
39
40 return p;
41}
42
43
44void
45ngx_destroy_pool(ngx_pool_t *pool)
46{
47 ngx_pool_t *p, *n;
48 ngx_pool_large_t *l;
49 ngx_pool_cleanup_t *c;
50
51 for (c = pool->cleanup; c; c = c->next) {
52 if (c->handler) {
53 ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
54 "run cleanup: %p", c);
55 c->handler(c->data);
56 }
57 }
58
59 for (l = pool->large; l; l = l->next) {
60
61 ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, "free: %p", l->alloc);
62
63 if (l->alloc) {
64 ngx_free(l->alloc);
65 }
66 }
67
68#if (NGX_DEBUG)
69
70 /*
71 * we could allocate the pool->log from this pool
72 * so we cannot use this log while free()ing the pool
73 */
74
75 for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) {
76 ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
77 "free: %p, unused: %uz", p, p->d.end - p->d.last);
78
79 if (n == NULL) {
80 break;
81 }
82 }
83
84#endif
85
86 for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) {
87 ngx_free(p);
88
89 if (n == NULL) {
90 break;
91 }
92 }
93}
94
95
96void
97ngx_reset_pool(ngx_pool_t *pool)
98{
99 ngx_pool_t *p;
100 ngx_pool_large_t *l;
101
102 for (l = pool->large; l; l = l->next) {
103 if (l->alloc) {
104 ngx_free(l->alloc);
105 }
106 }
107
108 for (p = pool; p; p = p->d.next) {
109 p->d.last = (u_char *) p + sizeof(ngx_pool_t);
110 p->d.failed = 0;
111 }
112
113 pool->current = pool;
114 pool->chain = NULL;
115 pool->large = NULL;
116}
117
118
119void *
120ngx_palloc(ngx_pool_t *pool, size_t size)
121{
122 u_char *m;
123 ngx_pool_t *p;
124
125 if (size <= pool->max) {
126
127 p = pool->current;
128
129 do {
130 m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT);
131
132 if ((size_t) (p->d.end - m) >= size && p->d.end > m) {
133 p->d.last = m + size;
134
135 return m;
136 }
137
138 p = p->d.next;
139
140 } while (p);
141
142 return ngx_palloc_block(pool, size);
143 }
144
145 return ngx_palloc_large(pool, size);
146}
147
148
149void *
150ngx_pnalloc(ngx_pool_t *pool, size_t size)
151{
152 u_char *m;
153 ngx_pool_t *p;
154
155 if (size <= pool->max) {
156
157 p = pool->current;
158
159 do {
160 m = p->d.last;
161
162 if ((size_t) (p->d.end - m) >= size) {
163 p->d.last = m + size;
164
165 return m;
166 }
167
168 p = p->d.next;
169
170 } while (p);
171
172 return ngx_palloc_block(pool, size);
173 }
174
175 return ngx_palloc_large(pool, size);
176}
177
178
179static void *
180ngx_palloc_block(ngx_pool_t *pool, size_t size)
181{
182 u_char *m;
183 size_t psize;
184 ngx_pool_t *p, *new;
185
186 psize = (size_t) (pool->d.end - (u_char *) pool);
187
188 m = ngx_memalign(NGX_POOL_ALIGNMENT, psize, pool->log);
189 if (m == NULL) {
190 return NULL;
191 }
192
193 new = (ngx_pool_t *) m;
194
195 new->d.end = m + psize;
196 new->d.next = NULL;
197 new->d.failed = 0;
198
199 m += sizeof(ngx_pool_data_t);
200 m = ngx_align_ptr(m, NGX_ALIGNMENT);
201 new->d.last = m + size;
202
203 for (p = pool->current; p->d.next; p = p->d.next) {
204 if (p->d.failed++ > 4) {
205 pool->current = p->d.next;
206 }
207 }
208
209 p->d.next = new;
210
211 return m;
212}
213
214
215static void *
216ngx_palloc_large(ngx_pool_t *pool, size_t size)
217{
218 void *p;
219 ngx_uint_t n;
220 ngx_pool_large_t *large;
221
222 p = ngx_alloc(size, pool->log);
223 if (p == NULL) {
224 return NULL;
225 }
226
227 n = 0;
228
229 for (large = pool->large; large; large = large->next) {
230 if (large->alloc == NULL) {
231 large->alloc = p;
232 return p;
233 }
234
235 if (n++ > 3) {
236 break;
237 }
238 }
239
240 large = ngx_palloc(pool, sizeof(ngx_pool_large_t));
241 if (large == NULL) {
242 ngx_free(p);
243 return NULL;
244 }
245
246 large->alloc = p;
247 large->next = pool->large;
248 pool->large = large;
249
250 return p;
251}
252
253
254void *
255ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment)
256{
257 void *p;
258 ngx_pool_large_t *large;
259
260 p = ngx_memalign(alignment, size, pool->log);
261 if (p == NULL) {
262 return NULL;
263 }
264
265 large = ngx_palloc(pool, sizeof(ngx_pool_large_t));
266 if (large == NULL) {
267 ngx_free(p);
268 return NULL;
269 }
270
271 large->alloc = p;
272 large->next = pool->large;
273 pool->large = large;
274
275 return p;
276}
277
278
279ngx_int_t
280ngx_pfree(ngx_pool_t *pool, void *p)
281{
282 ngx_pool_large_t *l;
283
284 for (l = pool->large; l; l = l->next) {
285 if (p == l->alloc) {
286 ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
287 "free: %p", l->alloc);
288 ngx_free(l->alloc);
289 l->alloc = NULL;
290
291 return NGX_OK;
292 }
293 }
294
295 return NGX_DECLINED;
296}
297
298
299void *
300ngx_pcalloc(ngx_pool_t *pool, size_t size)
301{
302 void *p;
303
304 p = ngx_palloc(pool, size);
305 if (p) {
306 ngx_memzero(p, size);
307 }
308
309 return p;
310}
311
312
313ngx_pool_cleanup_t *
314ngx_pool_cleanup_add(ngx_pool_t *p, size_t size)
315{
316 ngx_pool_cleanup_t *c;
317
318 c = ngx_palloc(p, sizeof(ngx_pool_cleanup_t));
319 if (c == NULL) {
320 return NULL;
321 }
322
323 if (size) {
324 c->data = ngx_palloc(p, size);
325 if (c->data == NULL) {
326 return NULL;
327 }
328
329 } else {
330 c->data = NULL;
331 }
332
333 c->handler = NULL;
334 c->next = p->cleanup;
335
336 p->cleanup = c;
337
338 ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, p->log, 0, "add cleanup: %p", c);
339
340 return c;
341}
342
343
344void
345ngx_pool_run_cleanup_file(ngx_pool_t *p, ngx_fd_t fd)
346{
347 ngx_pool_cleanup_t *c;
348 ngx_pool_cleanup_file_t *cf;
349
350 for (c = p->cleanup; c; c = c->next) {
351 if (c->handler == ngx_pool_cleanup_file) {
352
353 cf = c->data;
354
355 if (cf->fd == fd) {
356 c->handler(cf);
357 c->handler = NULL;
358 return;
359 }
360 }
361 }
362}
363
364
365void
366ngx_pool_cleanup_file(void *data)
367{
368 ngx_pool_cleanup_file_t *c = data;
369
370 ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, c->log, 0, "file cleanup: fd:%d",
371 c->fd);
372
373 if (ngx_close_file(c->fd) == NGX_FILE_ERROR) {
374 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
375 ngx_close_file_n " \"%s\" failed", c->name);
376 }
377}
378
379
380void
381ngx_pool_delete_file(void *data)
382{
383 ngx_pool_cleanup_file_t *c = data;
384
385 ngx_err_t err;
386
387 ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, c->log, 0, "file cleanup: fd:%d %s",
388 c->fd, c->name);
389
390 if (ngx_delete_file(c->name) == NGX_FILE_ERROR) {
391 err = ngx_errno;
392
393 if (err != NGX_ENOENT) {
394 ngx_log_error(NGX_LOG_CRIT, c->log, err,
395 ngx_delete_file_n " \"%s\" failed", c->name);
396 }
397 }
398
399 if (ngx_close_file(c->fd) == NGX_FILE_ERROR) {
400 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
401 ngx_close_file_n " \"%s\" failed", c->name);
402 }
403}
404
405
406#if 0
407
408static void *
409ngx_get_cached_block(size_t size)
410{
411 void *p;
412 ngx_cached_block_slot_t *slot;
413
414 if (ngx_cycle->cache == NULL) {
415 return NULL;
416 }
417
418 slot = &ngx_cycle->cache[(size + ngx_pagesize - 1) / ngx_pagesize];
419
420 slot->tries++;
421
422 if (slot->number) {
423 p = slot->block;
424 slot->block = slot->block->next;
425 slot->number--;
426 return p;
427 }
428
429 return NULL;
430}
431
432#endif