OSDN Git Service

Merge branch 'master' into vaapi-ext
[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     
48     new_heap_index = (void *) realloc( heap->heap_index, new_heap_size * heap->object_size );
49     if ( NULL == new_heap_index )
50     {
51         return -1; /* Out of memory */
52     }
53     heap->heap_index = new_heap_index;
54     next_free = heap->next_free;
55     for(i = new_heap_size; i-- > heap->heap_size; )
56     {
57         object_base_p obj = (object_base_p) (heap->heap_index + i * heap->object_size);
58         obj->id = i + heap->id_offset;
59         obj->next_free = next_free;
60         next_free = i;
61     }
62     heap->next_free = next_free;
63     heap->heap_size = new_heap_size;
64     return 0; /* Success */
65 }
66
67 /*
68  * Return 0 on success, -1 on error
69  */
70 int object_heap_init( object_heap_p heap, int object_size, int id_offset)
71 {
72     heap->object_size = object_size;
73     heap->id_offset = id_offset & OBJECT_HEAP_OFFSET_MASK;
74     heap->heap_size = 0;
75     heap->heap_increment = 16;
76     heap->heap_index = NULL;
77     heap->next_free = LAST_FREE;
78     _i965InitMutex(&heap->mutex);
79     return object_heap_expand(heap);
80 }
81
82 /*
83  * Allocates an object
84  * Returns the object ID on success, returns -1 on error
85  */
86 int object_heap_allocate( object_heap_p heap )
87 {
88     object_base_p obj;
89
90     _i965LockMutex(&heap->mutex);
91     if ( LAST_FREE == heap->next_free )
92     {
93         if( -1 == object_heap_expand( heap ) )
94         {
95             _i965UnlockMutex(&heap->mutex);
96             return -1; /* Out of memory */
97         }
98     }
99     ASSERT( heap->next_free >= 0 );
100     
101     obj = (object_base_p) (heap->heap_index + heap->next_free * heap->object_size);
102     heap->next_free = obj->next_free;
103     _i965UnlockMutex(&heap->mutex);
104     
105     obj->next_free = ALLOCATED;
106     return obj->id;
107 }
108
109 /*
110  * Lookup an object by object ID
111  * Returns a pointer to the object on success, returns NULL on error
112  */
113 object_base_p object_heap_lookup( object_heap_p heap, int id )
114 {
115     object_base_p obj;
116
117     _i965LockMutex(&heap->mutex);
118     if ( (id < heap->id_offset) || (id > (heap->heap_size+heap->id_offset)) )
119     {
120         _i965UnlockMutex(&heap->mutex);
121         return NULL;
122     }
123     id &= OBJECT_HEAP_ID_MASK;
124     obj = (object_base_p) (heap->heap_index + id * heap->object_size);
125     _i965UnlockMutex(&heap->mutex);
126
127         /* Check if the object has in fact been allocated */
128         if ( obj->next_free != ALLOCATED )
129     {
130         return NULL;
131     }
132     return obj;
133 }
134
135 /*
136  * Iterate over all objects in the heap.
137  * Returns a pointer to the first object on the heap, returns NULL if heap is empty.
138  */
139 object_base_p object_heap_first( object_heap_p heap, object_heap_iterator *iter )
140 {
141     *iter = -1;
142     return object_heap_next( heap, iter );
143 }
144
145 /*
146  * Iterate over all objects in the heap.
147  * Returns a pointer to the next object on the heap, returns NULL if heap is empty.
148  */
149 object_base_p object_heap_next( object_heap_p heap, object_heap_iterator *iter )
150 {
151     object_base_p obj;
152     int i = *iter + 1;
153     _i965LockMutex(&heap->mutex);
154     while ( i < heap->heap_size)
155     {
156         obj = (object_base_p) (heap->heap_index + i * heap->object_size);
157         if (obj->next_free == ALLOCATED)
158         {
159             _i965UnlockMutex(&heap->mutex);
160             *iter = i;
161             return obj;
162         }
163         i++;
164     }
165     _i965UnlockMutex(&heap->mutex);
166     *iter = i;
167     return NULL;
168 }
169
170
171
172 /*
173  * Frees an object
174  */
175 void object_heap_free( object_heap_p heap, object_base_p obj )
176 {
177     /* Don't complain about NULL pointers */
178     if (NULL != obj)
179     {
180         /* Check if the object has in fact been allocated */
181         ASSERT( obj->next_free == ALLOCATED );
182     
183         _i965LockMutex(&heap->mutex);
184         obj->next_free = heap->next_free;
185         heap->next_free = obj->id & OBJECT_HEAP_ID_MASK;
186         _i965UnlockMutex(&heap->mutex);
187     }
188 }
189
190 /*
191  * Destroys a heap, the heap must be empty.
192  */
193 void object_heap_destroy( object_heap_p heap )
194 {
195     object_base_p obj;
196     int i;
197
198     _i965DestroyMutex(&heap->mutex);
199
200     /* Check if heap is empty */
201     for (i = 0; i < heap->heap_size; i++)
202     {
203         /* Check if object is not still allocated */
204         obj = (object_base_p) (heap->heap_index + i * heap->object_size);
205         ASSERT( obj->next_free != ALLOCATED );
206     }
207     free(heap->heap_index);
208     heap->heap_size = 0;
209     heap->heap_index = NULL;
210     heap->next_free = LAST_FREE;
211 }