Line data Source code
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 0 : _cairo_freelist_init (cairo_freelist_t *freelist, unsigned nodesize)
30 : {
31 0 : memset (freelist, 0, sizeof (cairo_freelist_t));
32 0 : freelist->nodesize = nodesize;
33 0 : }
34 :
35 : void
36 0 : _cairo_freelist_fini (cairo_freelist_t *freelist)
37 : {
38 0 : cairo_freelist_node_t *node = freelist->first_free_node;
39 0 : while (node) {
40 : cairo_freelist_node_t *next;
41 :
42 : VG (VALGRIND_MAKE_MEM_DEFINED (node, sizeof (node->next)));
43 0 : next = node->next;
44 :
45 0 : free (node);
46 0 : node = next;
47 : }
48 0 : }
49 :
50 : void *
51 0 : _cairo_freelist_alloc (cairo_freelist_t *freelist)
52 : {
53 0 : if (freelist->first_free_node) {
54 : cairo_freelist_node_t *node;
55 :
56 0 : node = freelist->first_free_node;
57 : VG (VALGRIND_MAKE_MEM_DEFINED (node, sizeof (node->next)));
58 0 : freelist->first_free_node = node->next;
59 : VG (VALGRIND_MAKE_MEM_UNDEFINED (node, freelist->nodesize));
60 :
61 0 : return node;
62 : }
63 :
64 0 : return malloc (freelist->nodesize);
65 : }
66 :
67 : void *
68 0 : _cairo_freelist_calloc (cairo_freelist_t *freelist)
69 : {
70 0 : void *node = _cairo_freelist_alloc (freelist);
71 0 : if (node)
72 0 : memset (node, 0, freelist->nodesize);
73 0 : return node;
74 : }
75 :
76 : void
77 0 : _cairo_freelist_free (cairo_freelist_t *freelist, void *voidnode)
78 : {
79 0 : cairo_freelist_node_t *node = voidnode;
80 0 : if (node) {
81 0 : node->next = freelist->first_free_node;
82 0 : freelist->first_free_node = node;
83 : VG (VALGRIND_MAKE_MEM_NOACCESS (node, freelist->nodesize));
84 : }
85 0 : }
86 :
87 : void
88 0 : _cairo_freepool_init (cairo_freepool_t *freepool, unsigned nodesize)
89 : {
90 0 : freepool->first_free_node = NULL;
91 0 : freepool->pools = &freepool->embedded_pool;
92 0 : freepool->freepools = NULL;
93 0 : freepool->nodesize = nodesize;
94 :
95 0 : freepool->embedded_pool.next = NULL;
96 0 : freepool->embedded_pool.size = sizeof (freepool->embedded_data);
97 0 : freepool->embedded_pool.rem = sizeof (freepool->embedded_data);
98 0 : freepool->embedded_pool.data = freepool->embedded_data;
99 :
100 : VG (VALGRIND_MAKE_MEM_NOACCESS (freepool->embedded_data, sizeof (freepool->embedded_data)));
101 0 : }
102 :
103 : void
104 0 : _cairo_freepool_fini (cairo_freepool_t *freepool)
105 : {
106 : cairo_freelist_pool_t *pool;
107 :
108 0 : pool = freepool->pools;
109 0 : while (pool != &freepool->embedded_pool) {
110 0 : cairo_freelist_pool_t *next = pool->next;
111 0 : free (pool);
112 0 : pool = next;
113 : }
114 :
115 0 : pool = freepool->freepools;
116 0 : while (pool != NULL) {
117 0 : cairo_freelist_pool_t *next = pool->next;
118 0 : free (pool);
119 0 : pool = next;
120 : }
121 :
122 : VG (VALGRIND_MAKE_MEM_NOACCESS (freepool, sizeof (freepool)));
123 0 : }
124 :
125 : void *
126 0 : _cairo_freepool_alloc_from_new_pool (cairo_freepool_t *freepool)
127 : {
128 : cairo_freelist_pool_t *pool;
129 : int poolsize;
130 :
131 0 : if (freepool->freepools != NULL) {
132 0 : pool = freepool->freepools;
133 0 : freepool->freepools = pool->next;
134 :
135 0 : poolsize = pool->size;
136 : } else {
137 0 : if (freepool->pools != &freepool->embedded_pool)
138 0 : poolsize = 2 * freepool->pools->size;
139 : else
140 0 : poolsize = (128 * freepool->nodesize + 8191) & -8192;
141 :
142 0 : pool = malloc (sizeof (cairo_freelist_pool_t) + poolsize);
143 0 : if (unlikely (pool == NULL))
144 0 : return pool;
145 :
146 0 : pool->size = poolsize;
147 : }
148 :
149 0 : pool->next = freepool->pools;
150 0 : freepool->pools = pool;
151 :
152 0 : pool->rem = poolsize - freepool->nodesize;
153 0 : pool->data = (uint8_t *) (pool + 1) + freepool->nodesize;
154 :
155 : VG (VALGRIND_MAKE_MEM_NOACCESS (pool->data, pool->rem));
156 :
157 0 : return pool + 1;
158 : }
159 :
160 : cairo_status_t
161 0 : _cairo_freepool_alloc_array (cairo_freepool_t *freepool,
162 : int count,
163 : void **array)
164 : {
165 : int i;
166 :
167 0 : for (i = 0; i < count; i++) {
168 : cairo_freelist_node_t *node;
169 :
170 0 : node = freepool->first_free_node;
171 0 : if (likely (node != NULL)) {
172 : VG (VALGRIND_MAKE_MEM_DEFINED (node, sizeof (node->next)));
173 0 : freepool->first_free_node = node->next;
174 : VG (VALGRIND_MAKE_MEM_UNDEFINED (node, freepool->nodesize));
175 : } else {
176 0 : node = _cairo_freepool_alloc_from_pool (freepool);
177 0 : if (unlikely (node == NULL))
178 0 : goto CLEANUP;
179 : }
180 :
181 0 : array[i] = node;
182 : }
183 :
184 0 : return CAIRO_STATUS_SUCCESS;
185 :
186 : CLEANUP:
187 0 : while (i--)
188 0 : _cairo_freepool_free (freepool, array[i]);
189 :
190 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
191 : }
|