2 * Copyright (c) 2007 Intel Corporation. All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sub license, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 #include "object_heap.h"
36 * Return 0 on success, -1 on error
39 object_heap_expand(object_heap_p heap)
44 int new_heap_size = heap->heap_size + heap->heap_increment;
45 int bucket_index = new_heap_size / heap->heap_increment - 1;
47 if (bucket_index >= heap->num_buckets) {
48 int new_num_buckets = heap->num_buckets + 8;
51 new_bucket = realloc(heap->bucket, new_num_buckets * sizeof(void *));
52 if (NULL == new_bucket) {
56 heap->num_buckets = new_num_buckets;
57 heap->bucket = new_bucket;
60 new_heap_index = (void *) malloc(heap->heap_increment * heap->object_size);
61 if (NULL == new_heap_index) {
62 return -1; /* Out of memory */
65 heap->bucket[bucket_index] = new_heap_index;
66 next_free = heap->next_free;
67 for (i = new_heap_size; i-- > heap->heap_size;) {
68 object_base_p obj = (object_base_p)(new_heap_index + (i - heap->heap_size) * heap->object_size);
69 obj->id = i + heap->id_offset;
70 obj->next_free = next_free;
73 heap->next_free = next_free;
74 heap->heap_size = new_heap_size;
75 return 0; /* Success */
79 * Return 0 on success, -1 on error
82 object_heap_init(object_heap_p heap, int object_size, int id_offset)
84 pthread_mutex_init(&heap->mutex, NULL);
85 heap->object_size = object_size;
86 heap->id_offset = id_offset & OBJECT_HEAP_OFFSET_MASK;
88 heap->heap_increment = 16;
89 heap->next_free = LAST_FREE;
90 heap->num_buckets = 0;
92 return object_heap_expand(heap);
97 * Returns the object ID on success, returns -1 on error
100 object_heap_allocate_unlocked(object_heap_p heap)
103 int bucket_index, obj_index;
105 if (LAST_FREE == heap->next_free) {
106 if (-1 == object_heap_expand(heap)) {
107 return -1; /* Out of memory */
110 ASSERT(heap->next_free >= 0);
112 bucket_index = heap->next_free / heap->heap_increment;
113 obj_index = heap->next_free % heap->heap_increment;
115 obj = (object_base_p)(heap->bucket[bucket_index] + obj_index * heap->object_size);
116 heap->next_free = obj->next_free;
117 obj->next_free = ALLOCATED;
122 object_heap_allocate(object_heap_p heap)
126 pthread_mutex_lock(&heap->mutex);
127 ret = object_heap_allocate_unlocked(heap);
128 pthread_mutex_unlock(&heap->mutex);
133 * Lookup an object by object ID
134 * Returns a pointer to the object on success, returns NULL on error
137 object_heap_lookup_unlocked(object_heap_p heap, int id)
140 int bucket_index, obj_index;
142 if ((id < heap->id_offset) || (id > (heap->heap_size + heap->id_offset))) {
145 id &= OBJECT_HEAP_ID_MASK;
146 bucket_index = id / heap->heap_increment;
147 obj_index = id % heap->heap_increment;
148 obj = (object_base_p)(heap->bucket[bucket_index] + obj_index * heap->object_size);
150 /* Check if the object has in fact been allocated */
151 if (obj->next_free != ALLOCATED) {
158 object_heap_lookup(object_heap_p heap, int id)
162 pthread_mutex_lock(&heap->mutex);
163 obj = object_heap_lookup_unlocked(heap, id);
164 pthread_mutex_unlock(&heap->mutex);
169 * Iterate over all objects in the heap.
170 * Returns a pointer to the first object on the heap, returns NULL if heap is empty.
173 object_heap_first(object_heap_p heap, object_heap_iterator *iter)
176 return object_heap_next(heap, iter);
180 * Iterate over all objects in the heap.
181 * Returns a pointer to the next object on the heap, returns NULL if heap is empty.
184 object_heap_next_unlocked(object_heap_p heap, object_heap_iterator *iter)
187 int bucket_index, obj_index;
190 while (i < heap->heap_size) {
191 bucket_index = i / heap->heap_increment;
192 obj_index = i % heap->heap_increment;
194 obj = (object_base_p)(heap->bucket[bucket_index] + obj_index * heap->object_size);
195 if (obj->next_free == ALLOCATED) {
206 object_heap_next(object_heap_p heap, object_heap_iterator *iter)
210 pthread_mutex_lock(&heap->mutex);
211 obj = object_heap_next_unlocked(heap, iter);
212 pthread_mutex_unlock(&heap->mutex);
220 object_heap_free_unlocked(object_heap_p heap, object_base_p obj)
222 /* Check if the object has in fact been allocated */
223 ASSERT(obj->next_free == ALLOCATED);
225 obj->next_free = heap->next_free;
226 heap->next_free = obj->id & OBJECT_HEAP_ID_MASK;
230 object_heap_free(object_heap_p heap, object_base_p obj)
234 pthread_mutex_lock(&heap->mutex);
235 object_heap_free_unlocked(heap, obj);
236 pthread_mutex_unlock(&heap->mutex);
240 * Destroys a heap, the heap must be empty.
243 object_heap_destroy(object_heap_p heap)
246 int bucket_index, obj_index, i;
248 /* Check if heap is empty */
249 for (i = 0; i < heap->heap_size; i++) {
250 /* Check if object is not still allocated */
251 bucket_index = i / heap->heap_increment;
252 obj_index = i % heap->heap_increment;
253 obj = (object_base_p)(heap->bucket[bucket_index] + obj_index * heap->object_size);
254 ASSERT(obj->next_free != ALLOCATED);
257 for (i = 0; i < heap->heap_size / heap->heap_increment; i++) {
258 free(heap->bucket[i]);
261 pthread_mutex_destroy(&heap->mutex);
266 heap->next_free = LAST_FREE;