src/core/ngx_palloc.c - nginx-1.7.10

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>


  7. static void *ngx_palloc_block(ngx_pool_t *pool, size_t size);
  8. static void *ngx_palloc_large(ngx_pool_t *pool, size_t size);


  9. ngx_pool_t *
  10. ngx_create_pool(size_t size, ngx_log_t *log)
  11. {
  12.     ngx_pool_t  *p;

  13.     p = ngx_memalign(NGX_POOL_ALIGNMENT, size, log);
  14.     if (p == NULL) {
  15.         return NULL;
  16.     }

  17.     p->d.last = (u_char *) p + sizeof(ngx_pool_t);
  18.     p->d.end = (u_char *) p + size;
  19.     p->d.next = NULL;
  20.     p->d.failed = 0;

  21.     size = size - sizeof(ngx_pool_t);
  22.     p->max = (size < NGX_MAX_ALLOC_FROM_POOL) ? size : NGX_MAX_ALLOC_FROM_POOL;

  23.     p->current = p;
  24.     p->chain = NULL;
  25.     p->large = NULL;
  26.     p->cleanup = NULL;
  27.     p->log = log;

  28.     return p;
  29. }


  30. void
  31. ngx_destroy_pool(ngx_pool_t *pool)
  32. {
  33.     ngx_pool_t          *p, *n;
  34.     ngx_pool_large_t    *l;
  35.     ngx_pool_cleanup_t  *c;

  36.     for (c = pool->cleanup; c; c = c->next) {
  37.         if (c->handler) {
  38.             ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
  39.                            "run cleanup: %p", c);
  40.             c->handler(c->data);
  41.         }
  42.     }

  43.     for (l = pool->large; l; l = l->next) {

  44.         ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, "free: %p", l->alloc);

  45.         if (l->alloc) {
  46.             ngx_free(l->alloc);
  47.         }
  48.     }

  49. #if (NGX_DEBUG)

  50.     /*
  51.      * we could allocate the pool->log from this pool
  52.      * so we cannot use this log while free()ing the pool
  53.      */

  54.     for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) {
  55.         ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
  56.                        "free: %p, unused: %uz", p, p->d.end - p->d.last);

  57.         if (n == NULL) {
  58.             break;
  59.         }
  60.     }

  61. #endif

  62.     for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) {
  63.         ngx_free(p);

  64.         if (n == NULL) {
  65.             break;
  66.         }
  67.     }
  68. }


  69. void
  70. ngx_reset_pool(ngx_pool_t *pool)
  71. {
  72.     ngx_pool_t        *p;
  73.     ngx_pool_large_t  *l;

  74.     for (l = pool->large; l; l = l->next) {
  75.         if (l->alloc) {
  76.             ngx_free(l->alloc);
  77.         }
  78.     }

  79.     for (p = pool; p; p = p->d.next) {
  80.         p->d.last = (u_char *) p + sizeof(ngx_pool_t);
  81.         p->d.failed = 0;
  82.     }

  83.     pool->current = pool;
  84.     pool->chain = NULL;
  85.     pool->large = NULL;
  86. }


  87. void *
  88. ngx_palloc(ngx_pool_t *pool, size_t size)
  89. {
  90.     u_char      *m;
  91.     ngx_pool_t  *p;

  92.     if (size <= pool->max) {

  93.         p = pool->current;

  94.         do {
  95.             m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT);

  96.             if ((size_t) (p->d.end - m) >= size) {
  97.                 p->d.last = m + size;

  98.                 return m;
  99.             }

  100.             p = p->d.next;

  101.         } while (p);

  102.         return ngx_palloc_block(pool, size);
  103.     }

  104.     return ngx_palloc_large(pool, size);
  105. }


  106. void *
  107. ngx_pnalloc(ngx_pool_t *pool, size_t size)
  108. {
  109.     u_char      *m;
  110.     ngx_pool_t  *p;

  111.     if (size <= pool->max) {

  112.         p = pool->current;

  113.         do {
  114.             m = p->d.last;

  115.             if ((size_t) (p->d.end - m) >= size) {
  116.                 p->d.last = m + size;

  117.                 return m;
  118.             }

  119.             p = p->d.next;

  120.         } while (p);

  121.         return ngx_palloc_block(pool, size);
  122.     }

  123.     return ngx_palloc_large(pool, size);
  124. }


  125. static void *
  126. ngx_palloc_block(ngx_pool_t *pool, size_t size)
  127. {
  128.     u_char      *m;
  129.     size_t       psize;
  130.     ngx_pool_t  *p, *new;

  131.     psize = (size_t) (pool->d.end - (u_char *) pool);

  132.     m = ngx_memalign(NGX_POOL_ALIGNMENT, psize, pool->log);
  133.     if (m == NULL) {
  134.         return NULL;
  135.     }

  136.     new = (ngx_pool_t *) m;

  137.     new->d.end = m + psize;
  138.     new->d.next = NULL;
  139.     new->d.failed = 0;

  140.     m += sizeof(ngx_pool_data_t);
  141.     m = ngx_align_ptr(m, NGX_ALIGNMENT);
  142.     new->d.last = m + size;

  143.     for (p = pool->current; p->d.next; p = p->d.next) {
  144.         if (p->d.failed++ > 4) {
  145.             pool->current = p->d.next;
  146.         }
  147.     }

  148.     p->d.next = new;

  149.     return m;
  150. }


  151. static void *
  152. ngx_palloc_large(ngx_pool_t *pool, size_t size)
  153. {
  154.     void              *p;
  155.     ngx_uint_t         n;
  156.     ngx_pool_large_t  *large;

  157.     p = ngx_alloc(size, pool->log);
  158.     if (p == NULL) {
  159.         return NULL;
  160.     }

  161.     n = 0;

  162.     for (large = pool->large; large; large = large->next) {
  163.         if (large->alloc == NULL) {
  164.             large->alloc = p;
  165.             return p;
  166.         }

  167.         if (n++ > 3) {
  168.             break;
  169.         }
  170.     }

  171.     large = ngx_palloc(pool, sizeof(ngx_pool_large_t));
  172.     if (large == NULL) {
  173.         ngx_free(p);
  174.         return NULL;
  175.     }

  176.     large->alloc = p;
  177.     large->next = pool->large;
  178.     pool->large = large;

  179.     return p;
  180. }


  181. void *
  182. ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment)
  183. {
  184.     void              *p;
  185.     ngx_pool_large_t  *large;

  186.     p = ngx_memalign(alignment, size, pool->log);
  187.     if (p == NULL) {
  188.         return NULL;
  189.     }

  190.     large = ngx_palloc(pool, sizeof(ngx_pool_large_t));
  191.     if (large == NULL) {
  192.         ngx_free(p);
  193.         return NULL;
  194.     }

  195.     large->alloc = p;
  196.     large->next = pool->large;
  197.     pool->large = large;

  198.     return p;
  199. }


  200. ngx_int_t
  201. ngx_pfree(ngx_pool_t *pool, void *p)
  202. {
  203.     ngx_pool_large_t  *l;

  204.     for (l = pool->large; l; l = l->next) {
  205.         if (p == l->alloc) {
  206.             ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
  207.                            "free: %p", l->alloc);
  208.             ngx_free(l->alloc);
  209.             l->alloc = NULL;

  210.             return NGX_OK;
  211.         }
  212.     }

  213.     return NGX_DECLINED;
  214. }


  215. void *
  216. ngx_pcalloc(ngx_pool_t *pool, size_t size)
  217. {
  218.     void *p;

  219.     p = ngx_palloc(pool, size);
  220.     if (p) {
  221.         ngx_memzero(p, size);
  222.     }

  223.     return p;
  224. }


  225. ngx_pool_cleanup_t *
  226. ngx_pool_cleanup_add(ngx_pool_t *p, size_t size)
  227. {
  228.     ngx_pool_cleanup_t  *c;

  229.     c = ngx_palloc(p, sizeof(ngx_pool_cleanup_t));
  230.     if (c == NULL) {
  231.         return NULL;
  232.     }

  233.     if (size) {
  234.         c->data = ngx_palloc(p, size);
  235.         if (c->data == NULL) {
  236.             return NULL;
  237.         }

  238.     } else {
  239.         c->data = NULL;
  240.     }

  241.     c->handler = NULL;
  242.     c->next = p->cleanup;

  243.     p->cleanup = c;

  244.     ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, p->log, 0, "add cleanup: %p", c);

  245.     return c;
  246. }


  247. void
  248. ngx_pool_run_cleanup_file(ngx_pool_t *p, ngx_fd_t fd)
  249. {
  250.     ngx_pool_cleanup_t       *c;
  251.     ngx_pool_cleanup_file_t  *cf;

  252.     for (c = p->cleanup; c; c = c->next) {
  253.         if (c->handler == ngx_pool_cleanup_file) {

  254.             cf = c->data;

  255.             if (cf->fd == fd) {
  256.                 c->handler(cf);
  257.                 c->handler = NULL;
  258.                 return;
  259.             }
  260.         }
  261.     }
  262. }


  263. void
  264. ngx_pool_cleanup_file(void *data)
  265. {
  266.     ngx_pool_cleanup_file_t  *c = data;

  267.     ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, c->log, 0, "file cleanup: fd:%d",
  268.                    c->fd);

  269.     if (ngx_close_file(c->fd) == NGX_FILE_ERROR) {
  270.         ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
  271.                       ngx_close_file_n " \"%s\" failed", c->name);
  272.     }
  273. }


  274. void
  275. ngx_pool_delete_file(void *data)
  276. {
  277.     ngx_pool_cleanup_file_t  *c = data;

  278.     ngx_err_t  err;

  279.     ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, c->log, 0, "file cleanup: fd:%d %s",
  280.                    c->fd, c->name);

  281.     if (ngx_delete_file(c->name) == NGX_FILE_ERROR) {
  282.         err = ngx_errno;

  283.         if (err != NGX_ENOENT) {
  284.             ngx_log_error(NGX_LOG_CRIT, c->log, err,
  285.                           ngx_delete_file_n " \"%s\" failed", c->name);
  286.         }
  287.     }

  288.     if (ngx_close_file(c->fd) == NGX_FILE_ERROR) {
  289.         ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
  290.                       ngx_close_file_n " \"%s\" failed", c->name);
  291.     }
  292. }


  293. #if 0

  294. static void *
  295. ngx_get_cached_block(size_t size)
  296. {
  297.     void                     *p;
  298.     ngx_cached_block_slot_t  *slot;

  299.     if (ngx_cycle->cache == NULL) {
  300.         return NULL;
  301.     }

  302.     slot = &ngx_cycle->cache[(size + ngx_pagesize - 1) / ngx_pagesize];

  303.     slot->tries++;

  304.     if (slot->number) {
  305.         p = slot->block;
  306.         slot->block = slot->block->next;
  307.         slot->number--;
  308.         return p;
  309.     }

  310.     return NULL;
  311. }

  312. #endif