0,0 → 1,191 |
/* |
* Copyright © 2006 Joonas Pihlaja |
* |
* Permission to use, copy, modify, distribute, and sell this software and its |
* documentation for any purpose is hereby granted without fee, provided that |
* the above copyright notice appear in all copies and that both that copyright |
* notice and this permission notice appear in supporting documentation, and |
* that the name of the copyright holders not be used in advertising or |
* publicity pertaining to distribution of the software without specific, |
* written prior permission. The copyright holders make no representations |
* about the suitability of this software for any purpose. It is provided "as |
* is" without express or implied warranty. |
* |
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO |
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, |
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE |
* OF THIS SOFTWARE. |
*/ |
|
#include "cairoint.h" |
|
#include "cairo-error-private.h" |
#include "cairo-freelist-private.h" |
|
void |
_cairo_freelist_init (cairo_freelist_t *freelist, unsigned nodesize) |
{ |
memset (freelist, 0, sizeof (cairo_freelist_t)); |
freelist->nodesize = nodesize; |
} |
|
void |
_cairo_freelist_fini (cairo_freelist_t *freelist) |
{ |
cairo_freelist_node_t *node = freelist->first_free_node; |
while (node) { |
cairo_freelist_node_t *next; |
|
VG (VALGRIND_MAKE_MEM_DEFINED (node, sizeof (node->next))); |
next = node->next; |
|
free (node); |
node = next; |
} |
} |
|
void * |
_cairo_freelist_alloc (cairo_freelist_t *freelist) |
{ |
if (freelist->first_free_node) { |
cairo_freelist_node_t *node; |
|
node = freelist->first_free_node; |
VG (VALGRIND_MAKE_MEM_DEFINED (node, sizeof (node->next))); |
freelist->first_free_node = node->next; |
VG (VALGRIND_MAKE_MEM_UNDEFINED (node, freelist->nodesize)); |
|
return node; |
} |
|
return malloc (freelist->nodesize); |
} |
|
void * |
_cairo_freelist_calloc (cairo_freelist_t *freelist) |
{ |
void *node = _cairo_freelist_alloc (freelist); |
if (node) |
memset (node, 0, freelist->nodesize); |
return node; |
} |
|
void |
_cairo_freelist_free (cairo_freelist_t *freelist, void *voidnode) |
{ |
cairo_freelist_node_t *node = voidnode; |
if (node) { |
node->next = freelist->first_free_node; |
freelist->first_free_node = node; |
VG (VALGRIND_MAKE_MEM_NOACCESS (node, freelist->nodesize)); |
} |
} |
|
void |
_cairo_freepool_init (cairo_freepool_t *freepool, unsigned nodesize) |
{ |
freepool->first_free_node = NULL; |
freepool->pools = &freepool->embedded_pool; |
freepool->freepools = NULL; |
freepool->nodesize = nodesize; |
|
freepool->embedded_pool.next = NULL; |
freepool->embedded_pool.size = sizeof (freepool->embedded_data); |
freepool->embedded_pool.rem = sizeof (freepool->embedded_data); |
freepool->embedded_pool.data = freepool->embedded_data; |
|
VG (VALGRIND_MAKE_MEM_NOACCESS (freepool->embedded_data, sizeof (freepool->embedded_data))); |
} |
|
void |
_cairo_freepool_fini (cairo_freepool_t *freepool) |
{ |
cairo_freelist_pool_t *pool; |
|
pool = freepool->pools; |
while (pool != &freepool->embedded_pool) { |
cairo_freelist_pool_t *next = pool->next; |
free (pool); |
pool = next; |
} |
|
pool = freepool->freepools; |
while (pool != NULL) { |
cairo_freelist_pool_t *next = pool->next; |
free (pool); |
pool = next; |
} |
|
VG (VALGRIND_MAKE_MEM_NOACCESS (freepool, sizeof (freepool))); |
} |
|
void * |
_cairo_freepool_alloc_from_new_pool (cairo_freepool_t *freepool) |
{ |
cairo_freelist_pool_t *pool; |
int poolsize; |
|
if (freepool->freepools != NULL) { |
pool = freepool->freepools; |
freepool->freepools = pool->next; |
|
poolsize = pool->size; |
} else { |
if (freepool->pools != &freepool->embedded_pool) |
poolsize = 2 * freepool->pools->size; |
else |
poolsize = (128 * freepool->nodesize + 8191) & -8192; |
|
pool = malloc (sizeof (cairo_freelist_pool_t) + poolsize); |
if (unlikely (pool == NULL)) |
return pool; |
|
pool->size = poolsize; |
} |
|
pool->next = freepool->pools; |
freepool->pools = pool; |
|
pool->rem = poolsize - freepool->nodesize; |
pool->data = (uint8_t *) (pool + 1) + freepool->nodesize; |
|
VG (VALGRIND_MAKE_MEM_NOACCESS (pool->data, pool->rem)); |
|
return pool + 1; |
} |
|
cairo_status_t |
_cairo_freepool_alloc_array (cairo_freepool_t *freepool, |
int count, |
void **array) |
{ |
int i; |
|
for (i = 0; i < count; i++) { |
cairo_freelist_node_t *node; |
|
node = freepool->first_free_node; |
if (likely (node != NULL)) { |
VG (VALGRIND_MAKE_MEM_DEFINED (node, sizeof (node->next))); |
freepool->first_free_node = node->next; |
VG (VALGRIND_MAKE_MEM_UNDEFINED (node, freepool->nodesize)); |
} else { |
node = _cairo_freepool_alloc_from_pool (freepool); |
if (unlikely (node == NULL)) |
goto CLEANUP; |
} |
|
array[i] = node; |
} |
|
return CAIRO_STATUS_SUCCESS; |
|
CLEANUP: |
while (i--) |
_cairo_freepool_free (freepool, array[i]); |
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
} |