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