OSDN Git Service

Update README.md
[android-x86/hardware-intel-common-vaapi.git] / src / object_heap.c
1 /*
2  * Copyright (c) 2007 Intel Corporation. All Rights Reserved.
3  *
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:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the Software.
15  *
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.
23  */
24
25 #include "object_heap.h"
26
27 #include "assert.h"
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31
32 #define ASSERT  assert
33
34 #define LAST_FREE   -1
35 #define ALLOCATED   -2
36
37 /*
38  * Expands the heap
39  * Return 0 on success, -1 on error
40  */
41 static int object_heap_expand(object_heap_p heap)
42 {
43     int i;
44     void *new_heap_index;
45     int next_free;
46     int new_heap_size = heap->heap_size + heap->heap_increment;
47     int bucket_index = new_heap_size / heap->heap_increment - 1;
48
49     if (bucket_index >= heap->num_buckets) {
50         int new_num_buckets = heap->num_buckets + 8;
51         void **new_bucket;
52
53         new_bucket = realloc(heap->bucket, new_num_buckets * sizeof(void *));
54         if (NULL == new_bucket) {
55             return -1;
56         }
57
58         heap->num_buckets = new_num_buckets;
59         heap->bucket = new_bucket;
60     }
61
62     new_heap_index = (void *) malloc(heap->heap_increment * heap->object_size);
63     if (NULL == new_heap_index) {
64         return -1; /* Out of memory */
65     }
66
67     heap->bucket[bucket_index] = new_heap_index;
68     next_free = heap->next_free;
69     for (i = new_heap_size; i-- > heap->heap_size;) {
70         object_base_p obj = (object_base_p)(new_heap_index + (i - heap->heap_size) * heap->object_size);
71         obj->id = i + heap->id_offset;
72         obj->next_free = next_free;
73         next_free = i;
74     }
75     heap->next_free = next_free;
76     heap->heap_size = new_heap_size;
77     return 0; /* Success */
78 }
79
80 /*
81  * Return 0 on success, -1 on error
82  */
83 int object_heap_init(object_heap_p heap, int object_size, int id_offset)
84 {
85     heap->object_size = object_size;
86     heap->id_offset = id_offset & OBJECT_HEAP_OFFSET_MASK;
87     heap->heap_size = 0;
88     heap->heap_increment = 16;
89     heap->next_free = LAST_FREE;
90     heap->num_buckets = 0;
91     heap->bucket = NULL;
92
93     if (object_heap_expand(heap) == 0) {
94         ASSERT(heap->heap_size);
95         _i965InitMutex(&heap->mutex);
96         return 0;
97     } else {
98         ASSERT(!heap->heap_size);
99         ASSERT(!heap->bucket || !heap->bucket[0]);
100
101         free(heap->bucket);
102
103         return -1;
104     }
105 }
106
107 /*
108  * Allocates an object
109  * Returns the object ID on success, returns -1 on error
110  */
111 int object_heap_allocate(object_heap_p heap)
112 {
113     object_base_p obj;
114     int bucket_index, obj_index;
115
116     _i965LockMutex(&heap->mutex);
117     if (LAST_FREE == heap->next_free) {
118         if (-1 == object_heap_expand(heap)) {
119             _i965UnlockMutex(&heap->mutex);
120             return -1; /* Out of memory */
121         }
122     }
123     ASSERT(heap->next_free >= 0);
124
125     bucket_index = heap->next_free / heap->heap_increment;
126     obj_index = heap->next_free % heap->heap_increment;
127
128     obj = (object_base_p)(heap->bucket[bucket_index] + obj_index * heap->object_size);
129     heap->next_free = obj->next_free;
130     _i965UnlockMutex(&heap->mutex);
131
132     obj->next_free = ALLOCATED;
133     return obj->id;
134 }
135
136 /*
137  * Lookup an object by object ID
138  * Returns a pointer to the object on success, returns NULL on error
139  */
140 object_base_p object_heap_lookup(object_heap_p heap, int id)
141 {
142     object_base_p obj;
143     int bucket_index, obj_index;
144
145     _i965LockMutex(&heap->mutex);
146     if ((id < heap->id_offset) || (id > (heap->heap_size + heap->id_offset))) {
147         _i965UnlockMutex(&heap->mutex);
148         return NULL;
149     }
150     id &= OBJECT_HEAP_ID_MASK;
151     bucket_index = id / heap->heap_increment;
152     obj_index = id % heap->heap_increment;
153     obj = (object_base_p)(heap->bucket[bucket_index] + obj_index * heap->object_size);
154     _i965UnlockMutex(&heap->mutex);
155
156     /* Check if the object has in fact been allocated */
157     if (obj->next_free != ALLOCATED) {
158         return NULL;
159     }
160     return obj;
161 }
162
163 /*
164  * Iterate over all objects in the heap.
165  * Returns a pointer to the first object on the heap, returns NULL if heap is empty.
166  */
167 object_base_p object_heap_first(object_heap_p heap, object_heap_iterator *iter)
168 {
169     *iter = -1;
170     return object_heap_next(heap, iter);
171 }
172
173 /*
174  * Iterate over all objects in the heap.
175  * Returns a pointer to the next object on the heap, returns NULL if heap is empty.
176  */
177 object_base_p object_heap_next(object_heap_p heap, object_heap_iterator *iter)
178 {
179     object_base_p obj;
180     int i = *iter + 1;
181     int bucket_index, obj_index;
182
183     _i965LockMutex(&heap->mutex);
184     while (i < heap->heap_size) {
185         bucket_index = i / heap->heap_increment;
186         obj_index = i % heap->heap_increment;
187
188         obj = (object_base_p)(heap->bucket[bucket_index] + obj_index * heap->object_size);
189         if (obj->next_free == ALLOCATED) {
190             _i965UnlockMutex(&heap->mutex);
191             *iter = i;
192             return obj;
193         }
194         i++;
195     }
196     _i965UnlockMutex(&heap->mutex);
197     *iter = i;
198     return NULL;
199 }
200
201
202
203 /*
204  * Frees an object
205  */
206 void object_heap_free(object_heap_p heap, object_base_p obj)
207 {
208     /* Don't complain about NULL pointers */
209     if (NULL != obj) {
210         /* Check if the object has in fact been allocated */
211         ASSERT(obj->next_free == ALLOCATED);
212
213         _i965LockMutex(&heap->mutex);
214         obj->next_free = heap->next_free;
215         heap->next_free = obj->id & OBJECT_HEAP_ID_MASK;
216         _i965UnlockMutex(&heap->mutex);
217     }
218 }
219
220 /*
221  * Destroys a heap, the heap must be empty.
222  */
223 void object_heap_destroy(object_heap_p heap)
224 {
225     object_base_p obj;
226     int i;
227     int bucket_index, obj_index;
228
229     if (heap->heap_size) {
230         _i965DestroyMutex(&heap->mutex);
231
232         /* Check if heap is empty */
233         for (i = 0; i < heap->heap_size; i++) {
234             /* Check if object is not still allocated */
235             bucket_index = i / heap->heap_increment;
236             obj_index = i % heap->heap_increment;
237             obj = (object_base_p)(heap->bucket[bucket_index] + obj_index * heap->object_size);
238             ASSERT(obj->next_free != ALLOCATED);
239         }
240
241         for (i = 0; i < heap->heap_size / heap->heap_increment; i++) {
242             free(heap->bucket[i]);
243         }
244
245         free(heap->bucket);
246     }
247
248     heap->bucket = NULL;
249     heap->heap_size = 0;
250     heap->next_free = LAST_FREE;
251 }