Initialize Tizen 2.3
[framework/graphics/cairo.git] / src / cairo-freelist.c
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 }