2 * Copyright © 2006 Joonas Pihlaja
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.
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
25 #include "cairo-error-private.h"
26 #include "cairo-freelist-private.h"
29 _cairo_freelist_init (cairo_freelist_t
*freelist
, unsigned nodesize
)
31 memset (freelist
, 0, sizeof (cairo_freelist_t
));
32 freelist
->nodesize
= nodesize
;
36 _cairo_freelist_fini (cairo_freelist_t
*freelist
)
38 cairo_freelist_node_t
*node
= freelist
->first_free_node
;
40 cairo_freelist_node_t
*next
;
42 VG (VALGRIND_MAKE_MEM_DEFINED (node
, sizeof (node
->next
)));
51 _cairo_freelist_alloc (cairo_freelist_t
*freelist
)
53 if (freelist
->first_free_node
) {
54 cairo_freelist_node_t
*node
;
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
));
64 return malloc (freelist
->nodesize
);
68 _cairo_freelist_calloc (cairo_freelist_t
*freelist
)
70 void *node
= _cairo_freelist_alloc (freelist
);
72 memset (node
, 0, freelist
->nodesize
);
77 _cairo_freelist_free (cairo_freelist_t
*freelist
, void *voidnode
)
79 cairo_freelist_node_t
*node
= voidnode
;
81 node
->next
= freelist
->first_free_node
;
82 freelist
->first_free_node
= node
;
83 VG (VALGRIND_MAKE_MEM_NOACCESS (node
, freelist
->nodesize
));
88 _cairo_freepool_init (cairo_freepool_t
*freepool
, unsigned nodesize
)
90 freepool
->first_free_node
= NULL
;
91 freepool
->pools
= &freepool
->embedded_pool
;
92 freepool
->freepools
= NULL
;
93 freepool
->nodesize
= nodesize
;
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
;
100 VG (VALGRIND_MAKE_MEM_NOACCESS (freepool
->embedded_data
, sizeof (freepool
->embedded_data
)));
104 _cairo_freepool_fini (cairo_freepool_t
*freepool
)
106 cairo_freelist_pool_t
*pool
;
108 pool
= freepool
->pools
;
109 while (pool
!= &freepool
->embedded_pool
) {
110 cairo_freelist_pool_t
*next
= pool
->next
;
115 pool
= freepool
->freepools
;
116 while (pool
!= NULL
) {
117 cairo_freelist_pool_t
*next
= pool
->next
;
122 VG (VALGRIND_MAKE_MEM_NOACCESS (freepool
, sizeof (freepool
)));
126 _cairo_freepool_alloc_from_new_pool (cairo_freepool_t
*freepool
)
128 cairo_freelist_pool_t
*pool
;
131 if (freepool
->freepools
!= NULL
) {
132 pool
= freepool
->freepools
;
133 freepool
->freepools
= pool
->next
;
135 poolsize
= pool
->size
;
137 if (freepool
->pools
!= &freepool
->embedded_pool
)
138 poolsize
= 2 * freepool
->pools
->size
;
140 poolsize
= (128 * freepool
->nodesize
+ 8191) & -8192;
142 pool
= malloc (sizeof (cairo_freelist_pool_t
) + poolsize
);
143 if (unlikely (pool
== NULL
))
146 pool
->size
= poolsize
;
149 pool
->next
= freepool
->pools
;
150 freepool
->pools
= pool
;
152 pool
->rem
= poolsize
- freepool
->nodesize
;
153 pool
->data
= (uint8_t *) (pool
+ 1) + freepool
->nodesize
;
155 VG (VALGRIND_MAKE_MEM_NOACCESS (pool
->data
, pool
->rem
));
161 _cairo_freepool_alloc_array (cairo_freepool_t
*freepool
,
167 for (i
= 0; i
< count
; i
++) {
168 cairo_freelist_node_t
*node
;
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
));
176 node
= _cairo_freepool_alloc_from_pool (freepool
);
177 if (unlikely (node
== NULL
))
184 return CAIRO_STATUS_SUCCESS
;
188 _cairo_freepool_free (freepool
, array
[i
]);
190 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);