mesa/version: only enable GL4.1 with correct limits.
[mesa.git] / src / mesa / main / hash.c
1 /**
2 * \file hash.c
3 * Generic hash table.
4 *
5 * Used for display lists, texture objects, vertex/fragment programs,
6 * buffer objects, etc. The hash functions are thread-safe.
7 *
8 * \note key=0 is illegal.
9 *
10 * \author Brian Paul
11 */
12
13 /*
14 * Mesa 3-D graphics library
15 *
16 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
17 *
18 * Permission is hereby granted, free of charge, to any person obtaining a
19 * copy of this software and associated documentation files (the "Software"),
20 * to deal in the Software without restriction, including without limitation
21 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
22 * and/or sell copies of the Software, and to permit persons to whom the
23 * Software is furnished to do so, subject to the following conditions:
24 *
25 * The above copyright notice and this permission notice shall be included
26 * in all copies or substantial portions of the Software.
27 *
28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
29 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
31 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
32 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
33 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
34 * OTHER DEALINGS IN THE SOFTWARE.
35 */
36
37 #include "errors.h"
38 #include "glheader.h"
39 #include "hash.h"
40 #include "util/hash_table.h"
41 #include "util/u_memory.h"
42
43
44 /**
45 * Create a new hash table.
46 *
47 * \return pointer to a new, empty hash table.
48 */
49 struct _mesa_HashTable *
50 _mesa_NewHashTable(void)
51 {
52 struct _mesa_HashTable *table = CALLOC_STRUCT(_mesa_HashTable);
53
54 if (table) {
55 table->ht = _mesa_hash_table_create(NULL, uint_key_hash,
56 uint_key_compare);
57 if (table->ht == NULL) {
58 free(table);
59 _mesa_error_no_memory(__func__);
60 return NULL;
61 }
62
63 _mesa_hash_table_set_deleted_key(table->ht, uint_key(DELETED_KEY_VALUE));
64 /*
65 * Needs to be recursive, since the callback in _mesa_HashWalk()
66 * is allowed to call _mesa_HashRemove().
67 */
68 mtx_init(&table->Mutex, mtx_recursive);
69 }
70 else {
71 _mesa_error_no_memory(__func__);
72 }
73
74 return table;
75 }
76
77
78
79 /**
80 * Delete a hash table.
81 * Frees each entry on the hash table and then the hash table structure itself.
82 * Note that the caller should have already traversed the table and deleted
83 * the objects in the table (i.e. We don't free the entries' data pointer).
84 *
85 * \param table the hash table to delete.
86 */
87 void
88 _mesa_DeleteHashTable(struct _mesa_HashTable *table)
89 {
90 assert(table);
91
92 if (_mesa_hash_table_next_entry(table->ht, NULL) != NULL) {
93 _mesa_problem(NULL, "In _mesa_DeleteHashTable, found non-freed data");
94 }
95
96 _mesa_hash_table_destroy(table->ht, NULL);
97
98 mtx_destroy(&table->Mutex);
99 free(table);
100 }
101
102
103
104 /**
105 * Lookup an entry in the hash table, without locking.
106 * \sa _mesa_HashLookup
107 */
108 static inline void *
109 _mesa_HashLookup_unlocked(struct _mesa_HashTable *table, GLuint key)
110 {
111 const struct hash_entry *entry;
112
113 assert(table);
114 assert(key);
115
116 if (key == DELETED_KEY_VALUE)
117 return table->deleted_key_data;
118
119 entry = _mesa_hash_table_search_pre_hashed(table->ht,
120 uint_hash(key),
121 uint_key(key));
122 if (!entry)
123 return NULL;
124
125 return entry->data;
126 }
127
128
129 /**
130 * Lookup an entry in the hash table.
131 *
132 * \param table the hash table.
133 * \param key the key.
134 *
135 * \return pointer to user's data or NULL if key not in table
136 */
137 void *
138 _mesa_HashLookup(struct _mesa_HashTable *table, GLuint key)
139 {
140 void *res;
141 _mesa_HashLockMutex(table);
142 res = _mesa_HashLookup_unlocked(table, key);
143 _mesa_HashUnlockMutex(table);
144 return res;
145 }
146
147
148 /**
149 * Lookup an entry in the hash table without locking the mutex.
150 *
151 * The hash table mutex must be locked manually by calling
152 * _mesa_HashLockMutex() before calling this function.
153 *
154 * \param table the hash table.
155 * \param key the key.
156 *
157 * \return pointer to user's data or NULL if key not in table
158 */
159 void *
160 _mesa_HashLookupLocked(struct _mesa_HashTable *table, GLuint key)
161 {
162 return _mesa_HashLookup_unlocked(table, key);
163 }
164
165
166 static inline void
167 _mesa_HashInsert_unlocked(struct _mesa_HashTable *table, GLuint key, void *data)
168 {
169 uint32_t hash = uint_hash(key);
170 struct hash_entry *entry;
171
172 assert(table);
173 assert(key);
174
175 if (key > table->MaxKey)
176 table->MaxKey = key;
177
178 if (key == DELETED_KEY_VALUE) {
179 table->deleted_key_data = data;
180 } else {
181 entry = _mesa_hash_table_search_pre_hashed(table->ht, hash, uint_key(key));
182 if (entry) {
183 entry->data = data;
184 } else {
185 _mesa_hash_table_insert_pre_hashed(table->ht, hash, uint_key(key), data);
186 }
187 }
188 }
189
190
191 /**
192 * Insert a key/pointer pair into the hash table without locking the mutex.
193 * If an entry with this key already exists we'll replace the existing entry.
194 *
195 * The hash table mutex must be locked manually by calling
196 * _mesa_HashLockMutex() before calling this function.
197 *
198 * \param table the hash table.
199 * \param key the key (not zero).
200 * \param data pointer to user data.
201 */
202 void
203 _mesa_HashInsertLocked(struct _mesa_HashTable *table, GLuint key, void *data)
204 {
205 _mesa_HashInsert_unlocked(table, key, data);
206 }
207
208
209 /**
210 * Insert a key/pointer pair into the hash table.
211 * If an entry with this key already exists we'll replace the existing entry.
212 *
213 * \param table the hash table.
214 * \param key the key (not zero).
215 * \param data pointer to user data.
216 */
217 void
218 _mesa_HashInsert(struct _mesa_HashTable *table, GLuint key, void *data)
219 {
220 _mesa_HashLockMutex(table);
221 _mesa_HashInsert_unlocked(table, key, data);
222 _mesa_HashUnlockMutex(table);
223 }
224
225
226 /**
227 * Remove an entry from the hash table.
228 *
229 * \param table the hash table.
230 * \param key key of entry to remove.
231 *
232 * While holding the hash table's lock, searches the entry with the matching
233 * key and unlinks it.
234 */
235 static inline void
236 _mesa_HashRemove_unlocked(struct _mesa_HashTable *table, GLuint key)
237 {
238 struct hash_entry *entry;
239
240 assert(table);
241 assert(key);
242
243 /* assert if _mesa_HashRemove illegally called from _mesa_HashDeleteAll
244 * callback function. Have to check this outside of mutex lock.
245 */
246 assert(!table->InDeleteAll);
247
248 if (key == DELETED_KEY_VALUE) {
249 table->deleted_key_data = NULL;
250 } else {
251 entry = _mesa_hash_table_search_pre_hashed(table->ht,
252 uint_hash(key),
253 uint_key(key));
254 _mesa_hash_table_remove(table->ht, entry);
255 }
256 }
257
258
259 void
260 _mesa_HashRemoveLocked(struct _mesa_HashTable *table, GLuint key)
261 {
262 _mesa_HashRemove_unlocked(table, key);
263 }
264
265 void
266 _mesa_HashRemove(struct _mesa_HashTable *table, GLuint key)
267 {
268 _mesa_HashLockMutex(table);
269 _mesa_HashRemove_unlocked(table, key);
270 _mesa_HashUnlockMutex(table);
271 }
272
273 /**
274 * Delete all entries in a hash table, but don't delete the table itself.
275 * Invoke the given callback function for each table entry.
276 *
277 * \param table the hash table to delete
278 * \param callback the callback function
279 * \param userData arbitrary pointer to pass along to the callback
280 * (this is typically a struct gl_context pointer)
281 */
282 void
283 _mesa_HashDeleteAll(struct _mesa_HashTable *table,
284 void (*callback)(GLuint key, void *data, void *userData),
285 void *userData)
286 {
287 assert(callback);
288 _mesa_HashLockMutex(table);
289 table->InDeleteAll = GL_TRUE;
290 hash_table_foreach(table->ht, entry) {
291 callback((uintptr_t)entry->key, entry->data, userData);
292 _mesa_hash_table_remove(table->ht, entry);
293 }
294 if (table->deleted_key_data) {
295 callback(DELETED_KEY_VALUE, table->deleted_key_data, userData);
296 table->deleted_key_data = NULL;
297 }
298 table->InDeleteAll = GL_FALSE;
299 _mesa_HashUnlockMutex(table);
300 }
301
302
303 /**
304 * Walk over all entries in a hash table, calling callback function for each.
305 * \param table the hash table to walk
306 * \param callback the callback function
307 * \param userData arbitrary pointer to pass along to the callback
308 * (this is typically a struct gl_context pointer)
309 */
310 static void
311 hash_walk_unlocked(const struct _mesa_HashTable *table,
312 void (*callback)(GLuint key, void *data, void *userData),
313 void *userData)
314 {
315 assert(table);
316 assert(callback);
317
318 hash_table_foreach(table->ht, entry) {
319 callback((uintptr_t)entry->key, entry->data, userData);
320 }
321 if (table->deleted_key_data)
322 callback(DELETED_KEY_VALUE, table->deleted_key_data, userData);
323 }
324
325
326 void
327 _mesa_HashWalk(const struct _mesa_HashTable *table,
328 void (*callback)(GLuint key, void *data, void *userData),
329 void *userData)
330 {
331 /* cast-away const */
332 struct _mesa_HashTable *table2 = (struct _mesa_HashTable *) table;
333
334 _mesa_HashLockMutex(table2);
335 hash_walk_unlocked(table, callback, userData);
336 _mesa_HashUnlockMutex(table2);
337 }
338
339 void
340 _mesa_HashWalkLocked(const struct _mesa_HashTable *table,
341 void (*callback)(GLuint key, void *data, void *userData),
342 void *userData)
343 {
344 hash_walk_unlocked(table, callback, userData);
345 }
346
347 static void
348 debug_print_entry(GLuint key, void *data, void *userData)
349 {
350 _mesa_debug(NULL, "%u %p\n", key, data);
351 }
352
353 /**
354 * Dump contents of hash table for debugging.
355 *
356 * \param table the hash table.
357 */
358 void
359 _mesa_HashPrint(const struct _mesa_HashTable *table)
360 {
361 if (table->deleted_key_data)
362 debug_print_entry(DELETED_KEY_VALUE, table->deleted_key_data, NULL);
363 _mesa_HashWalk(table, debug_print_entry, NULL);
364 }
365
366
367 /**
368 * Find a block of adjacent unused hash keys.
369 *
370 * \param table the hash table.
371 * \param numKeys number of keys needed.
372 *
373 * \return Starting key of free block or 0 if failure.
374 *
375 * If there are enough free keys between the maximum key existing in the table
376 * (_mesa_HashTable::MaxKey) and the maximum key possible, then simply return
377 * the adjacent key. Otherwise do a full search for a free key block in the
378 * allowable key range.
379 */
380 GLuint
381 _mesa_HashFindFreeKeyBlock(struct _mesa_HashTable *table, GLuint numKeys)
382 {
383 const GLuint maxKey = ~((GLuint) 0) - 1;
384 if (maxKey - numKeys > table->MaxKey) {
385 /* the quick solution */
386 return table->MaxKey + 1;
387 }
388 else {
389 /* the slow solution */
390 GLuint freeCount = 0;
391 GLuint freeStart = 1;
392 GLuint key;
393 for (key = 1; key != maxKey; key++) {
394 if (_mesa_HashLookup_unlocked(table, key)) {
395 /* darn, this key is already in use */
396 freeCount = 0;
397 freeStart = key+1;
398 }
399 else {
400 /* this key not in use, check if we've found enough */
401 freeCount++;
402 if (freeCount == numKeys) {
403 return freeStart;
404 }
405 }
406 }
407 /* cannot allocate a block of numKeys consecutive keys */
408 return 0;
409 }
410 }
411
412
413 /**
414 * Return the number of entries in the hash table.
415 */
416 GLuint
417 _mesa_HashNumEntries(const struct _mesa_HashTable *table)
418 {
419 GLuint count = 0;
420
421 if (table->deleted_key_data)
422 count++;
423
424 count += _mesa_hash_table_num_entries(table->ht);
425
426 return count;
427 }