forked from KolibriOS/kolibrios
192 lines
5.1 KiB
C
192 lines
5.1 KiB
C
|
/*
|
||
|
* 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);
|
||
|
}
|