Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2006 Joonas Pihlaja
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided that
  6.  * the above copyright notice appear in all copies and that both that copyright
  7.  * notice and this permission notice appear in supporting documentation, and
  8.  * that the name of the copyright holders not be used in advertising or
  9.  * publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.  The copyright holders make no representations
  11.  * about the suitability of this software for any purpose.  It is provided "as
  12.  * is" without express or implied warranty.
  13.  *
  14.  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  16.  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  19.  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  20.  * OF THIS SOFTWARE.
  21.  */
  22.  
  23. #include "cairoint.h"
  24.  
  25. #include "cairo-error-private.h"
  26. #include "cairo-freelist-private.h"
  27.  
  28. void
  29. _cairo_freelist_init (cairo_freelist_t *freelist, unsigned nodesize)
  30. {
  31.     memset (freelist, 0, sizeof (cairo_freelist_t));
  32.     freelist->nodesize = nodesize;
  33. }
  34.  
  35. void
  36. _cairo_freelist_fini (cairo_freelist_t *freelist)
  37. {
  38.     cairo_freelist_node_t *node = freelist->first_free_node;
  39.     while (node) {
  40.         cairo_freelist_node_t *next;
  41.  
  42.         VG (VALGRIND_MAKE_MEM_DEFINED (node, sizeof (node->next)));
  43.         next = node->next;
  44.  
  45.         free (node);
  46.         node = next;
  47.     }
  48. }
  49.  
  50. void *
  51. _cairo_freelist_alloc (cairo_freelist_t *freelist)
  52. {
  53.     if (freelist->first_free_node) {
  54.         cairo_freelist_node_t *node;
  55.  
  56.         node = freelist->first_free_node;
  57.         VG (VALGRIND_MAKE_MEM_DEFINED (node, sizeof (node->next)));
  58.         freelist->first_free_node = node->next;
  59.         VG (VALGRIND_MAKE_MEM_UNDEFINED (node, freelist->nodesize));
  60.  
  61.         return node;
  62.     }
  63.  
  64.     return malloc (freelist->nodesize);
  65. }
  66.  
  67. void *
  68. _cairo_freelist_calloc (cairo_freelist_t *freelist)
  69. {
  70.     void *node = _cairo_freelist_alloc (freelist);
  71.     if (node)
  72.         memset (node, 0, freelist->nodesize);
  73.     return node;
  74. }
  75.  
  76. void
  77. _cairo_freelist_free (cairo_freelist_t *freelist, void *voidnode)
  78. {
  79.     cairo_freelist_node_t *node = voidnode;
  80.     if (node) {
  81.         node->next = freelist->first_free_node;
  82.         freelist->first_free_node = node;
  83.         VG (VALGRIND_MAKE_MEM_NOACCESS (node, freelist->nodesize));
  84.     }
  85. }
  86.  
  87. void
  88. _cairo_freepool_init (cairo_freepool_t *freepool, unsigned nodesize)
  89. {
  90.     freepool->first_free_node = NULL;
  91.     freepool->pools = &freepool->embedded_pool;
  92.     freepool->freepools = NULL;
  93.     freepool->nodesize = nodesize;
  94.  
  95.     freepool->embedded_pool.next = NULL;
  96.     freepool->embedded_pool.size = sizeof (freepool->embedded_data);
  97.     freepool->embedded_pool.rem = sizeof (freepool->embedded_data);
  98.     freepool->embedded_pool.data = freepool->embedded_data;
  99.  
  100.     VG (VALGRIND_MAKE_MEM_NOACCESS (freepool->embedded_data, sizeof (freepool->embedded_data)));
  101. }
  102.  
  103. void
  104. _cairo_freepool_fini (cairo_freepool_t *freepool)
  105. {
  106.     cairo_freelist_pool_t *pool;
  107.  
  108.     pool = freepool->pools;
  109.     while (pool != &freepool->embedded_pool) {
  110.         cairo_freelist_pool_t *next = pool->next;
  111.         free (pool);
  112.         pool = next;
  113.     }
  114.  
  115.     pool = freepool->freepools;
  116.     while (pool != NULL) {
  117.         cairo_freelist_pool_t *next = pool->next;
  118.         free (pool);
  119.         pool = next;
  120.     }
  121.  
  122.     VG (VALGRIND_MAKE_MEM_NOACCESS (freepool, sizeof (freepool)));
  123. }
  124.  
  125. void *
  126. _cairo_freepool_alloc_from_new_pool (cairo_freepool_t *freepool)
  127. {
  128.     cairo_freelist_pool_t *pool;
  129.     int poolsize;
  130.  
  131.     if (freepool->freepools != NULL) {
  132.         pool = freepool->freepools;
  133.         freepool->freepools = pool->next;
  134.  
  135.         poolsize = pool->size;
  136.     } else {
  137.         if (freepool->pools != &freepool->embedded_pool)
  138.             poolsize = 2 * freepool->pools->size;
  139.         else
  140.             poolsize = (128 * freepool->nodesize + 8191) & -8192;
  141.  
  142.         pool = malloc (sizeof (cairo_freelist_pool_t) + poolsize);
  143.         if (unlikely (pool == NULL))
  144.             return pool;
  145.  
  146.         pool->size = poolsize;
  147.     }
  148.  
  149.     pool->next = freepool->pools;
  150.     freepool->pools = pool;
  151.  
  152.     pool->rem = poolsize - freepool->nodesize;
  153.     pool->data = (uint8_t *) (pool + 1) + freepool->nodesize;
  154.  
  155.     VG (VALGRIND_MAKE_MEM_NOACCESS (pool->data, pool->rem));
  156.  
  157.     return pool + 1;
  158. }
  159.  
  160. cairo_status_t
  161. _cairo_freepool_alloc_array (cairo_freepool_t *freepool,
  162.                              int count,
  163.                              void **array)
  164. {
  165.     int i;
  166.  
  167.     for (i = 0; i < count; i++) {
  168.         cairo_freelist_node_t *node;
  169.  
  170.         node = freepool->first_free_node;
  171.         if (likely (node != NULL)) {
  172.             VG (VALGRIND_MAKE_MEM_DEFINED (node, sizeof (node->next)));
  173.             freepool->first_free_node = node->next;
  174.             VG (VALGRIND_MAKE_MEM_UNDEFINED (node, freepool->nodesize));
  175.         } else {
  176.             node = _cairo_freepool_alloc_from_pool (freepool);
  177.             if (unlikely (node == NULL))
  178.                 goto CLEANUP;
  179.         }
  180.  
  181.         array[i] = node;
  182.     }
  183.  
  184.     return CAIRO_STATUS_SUCCESS;
  185.  
  186.   CLEANUP:
  187.     while (i--)
  188.         _cairo_freepool_free (freepool, array[i]);
  189.  
  190.     return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  191. }
  192.