/src/gstreamer/subprojects/libdrm-2.4.124/xf86drmSL.c
Line | Count | Source |
1 | | /* xf86drmSL.c -- Skip list support |
2 | | * Created: Mon May 10 09:28:13 1999 by faith@precisioninsight.com |
3 | | * |
4 | | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. |
5 | | * All Rights Reserved. |
6 | | * |
7 | | * Permission is hereby granted, free of charge, to any person obtaining a |
8 | | * copy of this software and associated documentation files (the "Software"), |
9 | | * to deal in the Software without restriction, including without limitation |
10 | | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
11 | | * and/or sell copies of the Software, and to permit persons to whom the |
12 | | * Software is furnished to do so, subject to the following conditions: |
13 | | * |
14 | | * The above copyright notice and this permission notice (including the next |
15 | | * paragraph) shall be included in all copies or substantial portions of the |
16 | | * Software. |
17 | | * |
18 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
19 | | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
20 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
21 | | * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
22 | | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
23 | | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
24 | | * DEALINGS IN THE SOFTWARE. |
25 | | * |
26 | | * Authors: Rickard E. (Rik) Faith <faith@valinux.com> |
27 | | * |
28 | | * DESCRIPTION |
29 | | * |
30 | | * This file contains a straightforward skip list implementation.n |
31 | | * |
32 | | * FUTURE ENHANCEMENTS |
33 | | * |
34 | | * REFERENCES |
35 | | * |
36 | | * [Pugh90] William Pugh. Skip Lists: A Probabilistic Alternative to |
37 | | * Balanced Trees. CACM 33(6), June 1990, pp. 668-676. |
38 | | * |
39 | | */ |
40 | | |
41 | | #include <stdio.h> |
42 | | #include <stdlib.h> |
43 | | |
44 | | #include "libdrm_macros.h" |
45 | | #include "xf86drm.h" |
46 | | |
47 | 0 | #define SL_LIST_MAGIC 0xfacade00LU |
48 | 0 | #define SL_ENTRY_MAGIC 0x00fab1edLU |
49 | 0 | #define SL_FREED_MAGIC 0xdecea5edLU |
50 | 0 | #define SL_MAX_LEVEL 16 |
51 | | #define SL_RANDOM_SEED 0xc01055a1LU |
52 | | |
53 | 0 | #define SL_RANDOM_DECL static void *state = NULL |
54 | 0 | #define SL_RANDOM_INIT(seed) if (!state) state = drmRandomCreate(seed) |
55 | 0 | #define SL_RANDOM drmRandom(state) |
56 | | |
57 | | typedef struct SLEntry { |
58 | | unsigned long magic; /* SL_ENTRY_MAGIC */ |
59 | | unsigned long key; |
60 | | void *value; |
61 | | int levels; |
62 | | struct SLEntry *forward[1]; /* variable sized array */ |
63 | | } SLEntry, *SLEntryPtr; |
64 | | |
65 | | typedef struct SkipList { |
66 | | unsigned long magic; /* SL_LIST_MAGIC */ |
67 | | int level; |
68 | | int count; |
69 | | SLEntryPtr head; |
70 | | SLEntryPtr p0; /* Position for iteration */ |
71 | | } SkipList, *SkipListPtr; |
72 | | |
73 | | static SLEntryPtr SLCreateEntry(int max_level, unsigned long key, void *value) |
74 | 0 | { |
75 | 0 | SLEntryPtr entry; |
76 | | |
77 | 0 | if (max_level < 0 || max_level > SL_MAX_LEVEL) max_level = SL_MAX_LEVEL; |
78 | |
|
79 | 0 | entry = drmMalloc(sizeof(*entry) |
80 | 0 | + (max_level + 1) * sizeof(entry->forward[0])); |
81 | 0 | if (!entry) return NULL; |
82 | 0 | entry->magic = SL_ENTRY_MAGIC; |
83 | 0 | entry->key = key; |
84 | 0 | entry->value = value; |
85 | 0 | entry->levels = max_level + 1; |
86 | |
|
87 | 0 | return entry; |
88 | 0 | } |
89 | | |
90 | | static int SLRandomLevel(void) |
91 | 0 | { |
92 | 0 | int level = 1; |
93 | 0 | SL_RANDOM_DECL; |
94 | |
|
95 | 0 | SL_RANDOM_INIT(SL_RANDOM_SEED); |
96 | | |
97 | 0 | while ((SL_RANDOM & 0x01) && level < SL_MAX_LEVEL) ++level; |
98 | 0 | return level; |
99 | 0 | } |
100 | | |
101 | | drm_public void *drmSLCreate(void) |
102 | 0 | { |
103 | 0 | SkipListPtr list; |
104 | 0 | int i; |
105 | |
|
106 | 0 | list = drmMalloc(sizeof(*list)); |
107 | 0 | if (!list) return NULL; |
108 | 0 | list->magic = SL_LIST_MAGIC; |
109 | 0 | list->level = 0; |
110 | 0 | list->head = SLCreateEntry(SL_MAX_LEVEL, 0, NULL); |
111 | 0 | list->count = 0; |
112 | |
|
113 | 0 | for (i = 0; i <= SL_MAX_LEVEL; i++) list->head->forward[i] = NULL; |
114 | | |
115 | 0 | return list; |
116 | 0 | } |
117 | | |
118 | | drm_public int drmSLDestroy(void *l) |
119 | 0 | { |
120 | 0 | SkipListPtr list = (SkipListPtr)l; |
121 | 0 | SLEntryPtr entry; |
122 | 0 | SLEntryPtr next; |
123 | |
|
124 | 0 | if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ |
125 | | |
126 | 0 | for (entry = list->head; entry; entry = next) { |
127 | 0 | if (entry->magic != SL_ENTRY_MAGIC) return -1; /* Bad magic */ |
128 | 0 | next = entry->forward[0]; |
129 | 0 | entry->magic = SL_FREED_MAGIC; |
130 | 0 | drmFree(entry); |
131 | 0 | } |
132 | | |
133 | 0 | list->magic = SL_FREED_MAGIC; |
134 | 0 | drmFree(list); |
135 | 0 | return 0; |
136 | 0 | } |
137 | | |
138 | | static SLEntryPtr SLLocate(void *l, unsigned long key, SLEntryPtr *update) |
139 | 0 | { |
140 | 0 | SkipListPtr list = (SkipListPtr)l; |
141 | 0 | SLEntryPtr entry; |
142 | 0 | int i; |
143 | |
|
144 | 0 | if (list->magic != SL_LIST_MAGIC) return NULL; |
145 | | |
146 | 0 | for (i = list->level, entry = list->head; i >= 0; i--) { |
147 | 0 | while (entry->forward[i] && entry->forward[i]->key < key) |
148 | 0 | entry = entry->forward[i]; |
149 | 0 | update[i] = entry; |
150 | 0 | } |
151 | |
|
152 | 0 | return entry->forward[0]; |
153 | 0 | } |
154 | | |
155 | | drm_public int drmSLInsert(void *l, unsigned long key, void *value) |
156 | 0 | { |
157 | 0 | SkipListPtr list = (SkipListPtr)l; |
158 | 0 | SLEntryPtr entry; |
159 | 0 | SLEntryPtr update[SL_MAX_LEVEL + 1]; |
160 | 0 | int level; |
161 | 0 | int i; |
162 | |
|
163 | 0 | if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ |
164 | | |
165 | 0 | entry = SLLocate(list, key, update); |
166 | |
|
167 | 0 | if (entry && entry->key == key) return 1; /* Already in list */ |
168 | | |
169 | | |
170 | 0 | level = SLRandomLevel(); |
171 | 0 | if (level > list->level) { |
172 | 0 | level = ++list->level; |
173 | 0 | update[level] = list->head; |
174 | 0 | } |
175 | |
|
176 | 0 | entry = SLCreateEntry(level, key, value); |
177 | | |
178 | | /* Fix up forward pointers */ |
179 | 0 | for (i = 0; i <= level; i++) { |
180 | 0 | entry->forward[i] = update[i]->forward[i]; |
181 | 0 | update[i]->forward[i] = entry; |
182 | 0 | } |
183 | |
|
184 | 0 | ++list->count; |
185 | 0 | return 0; /* Added to table */ |
186 | 0 | } |
187 | | |
188 | | drm_public int drmSLDelete(void *l, unsigned long key) |
189 | 0 | { |
190 | 0 | SkipListPtr list = (SkipListPtr)l; |
191 | 0 | SLEntryPtr update[SL_MAX_LEVEL + 1]; |
192 | 0 | SLEntryPtr entry; |
193 | 0 | int i; |
194 | |
|
195 | 0 | if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ |
196 | | |
197 | 0 | entry = SLLocate(list, key, update); |
198 | |
|
199 | 0 | if (!entry || entry->key != key) return 1; /* Not found */ |
200 | | |
201 | | /* Fix up forward pointers */ |
202 | 0 | for (i = 0; i <= list->level; i++) { |
203 | 0 | if (update[i]->forward[i] == entry) |
204 | 0 | update[i]->forward[i] = entry->forward[i]; |
205 | 0 | } |
206 | |
|
207 | 0 | entry->magic = SL_FREED_MAGIC; |
208 | 0 | drmFree(entry); |
209 | |
|
210 | 0 | while (list->level && !list->head->forward[list->level]) --list->level; |
211 | 0 | --list->count; |
212 | 0 | return 0; |
213 | 0 | } |
214 | | |
215 | | drm_public int drmSLLookup(void *l, unsigned long key, void **value) |
216 | 0 | { |
217 | 0 | SkipListPtr list = (SkipListPtr)l; |
218 | 0 | SLEntryPtr update[SL_MAX_LEVEL + 1]; |
219 | 0 | SLEntryPtr entry; |
220 | |
|
221 | 0 | entry = SLLocate(list, key, update); |
222 | |
|
223 | 0 | if (entry && entry->key == key) { |
224 | 0 | *value = entry; |
225 | 0 | return 0; |
226 | 0 | } |
227 | 0 | *value = NULL; |
228 | 0 | return -1; |
229 | 0 | } |
230 | | |
231 | | drm_public int drmSLLookupNeighbors(void *l, unsigned long key, |
232 | | unsigned long *prev_key, void **prev_value, |
233 | | unsigned long *next_key, void **next_value) |
234 | 0 | { |
235 | 0 | SkipListPtr list = (SkipListPtr)l; |
236 | 0 | SLEntryPtr update[SL_MAX_LEVEL + 1] = {0}; |
237 | 0 | int retcode = 0; |
238 | |
|
239 | 0 | SLLocate(list, key, update); |
240 | |
|
241 | 0 | *prev_key = *next_key = key; |
242 | 0 | *prev_value = *next_value = NULL; |
243 | |
|
244 | 0 | if (update[0]) { |
245 | 0 | *prev_key = update[0]->key; |
246 | 0 | *prev_value = update[0]->value; |
247 | 0 | ++retcode; |
248 | 0 | if (update[0]->forward[0]) { |
249 | 0 | *next_key = update[0]->forward[0]->key; |
250 | 0 | *next_value = update[0]->forward[0]->value; |
251 | 0 | ++retcode; |
252 | 0 | } |
253 | 0 | } |
254 | 0 | return retcode; |
255 | 0 | } |
256 | | |
257 | | drm_public int drmSLNext(void *l, unsigned long *key, void **value) |
258 | 0 | { |
259 | 0 | SkipListPtr list = (SkipListPtr)l; |
260 | 0 | SLEntryPtr entry; |
261 | | |
262 | 0 | if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ |
263 | | |
264 | 0 | entry = list->p0; |
265 | |
|
266 | 0 | if (entry) { |
267 | 0 | list->p0 = entry->forward[0]; |
268 | 0 | *key = entry->key; |
269 | 0 | *value = entry->value; |
270 | 0 | return 1; |
271 | 0 | } |
272 | 0 | list->p0 = NULL; |
273 | 0 | return 0; |
274 | 0 | } |
275 | | |
276 | | drm_public int drmSLFirst(void *l, unsigned long *key, void **value) |
277 | 0 | { |
278 | 0 | SkipListPtr list = (SkipListPtr)l; |
279 | | |
280 | 0 | if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ |
281 | | |
282 | 0 | list->p0 = list->head->forward[0]; |
283 | 0 | return drmSLNext(list, key, value); |
284 | 0 | } |
285 | | |
286 | | /* Dump internal data structures for debugging. */ |
287 | | drm_public void drmSLDump(void *l) |
288 | 0 | { |
289 | 0 | SkipListPtr list = (SkipListPtr)l; |
290 | 0 | SLEntryPtr entry; |
291 | 0 | int i; |
292 | | |
293 | 0 | if (list->magic != SL_LIST_MAGIC) { |
294 | 0 | printf("Bad magic: 0x%08lx (expected 0x%08lx)\n", |
295 | 0 | list->magic, SL_LIST_MAGIC); |
296 | 0 | return; |
297 | 0 | } |
298 | | |
299 | 0 | printf("Level = %d, count = %d\n", list->level, list->count); |
300 | 0 | for (entry = list->head; entry; entry = entry->forward[0]) { |
301 | 0 | if (entry->magic != SL_ENTRY_MAGIC) { |
302 | 0 | printf("Bad magic: 0x%08lx (expected 0x%08lx)\n", |
303 | 0 | list->magic, SL_ENTRY_MAGIC); |
304 | 0 | } |
305 | 0 | printf("\nEntry %p <0x%08lx, %p> has %2d levels\n", |
306 | 0 | entry, entry->key, entry->value, entry->levels); |
307 | 0 | for (i = 0; i < entry->levels; i++) { |
308 | 0 | if (entry->forward[i]) { |
309 | 0 | printf(" %2d: %p <0x%08lx, %p>\n", |
310 | 0 | i, |
311 | 0 | entry->forward[i], |
312 | 0 | entry->forward[i]->key, |
313 | 0 | entry->forward[i]->value); |
314 | 0 | } else { |
315 | 0 | printf(" %2d: %p\n", i, entry->forward[i]); |
316 | 0 | } |
317 | 0 | } |
318 | 0 | } |
319 | 0 | } |