X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fhash.c;h=670438add272fcef42df739083da6187cef7abfc;hb=29d70f5de966c18d563475bc5f60f252e9a900a3;hp=ddeb8c6ebc0d22dc5a900faa3a3e5517a2cead99;hpb=dd404bc94f78a1766527becee03f8ef6ae3a799b;p=mesa.git diff --git a/src/mesa/main/hash.c b/src/mesa/main/hash.c index ddeb8c6ebc0..670438add27 100644 --- a/src/mesa/main/hash.c +++ b/src/mesa/main/hash.c @@ -12,7 +12,6 @@ /* * Mesa 3-D graphics library - * Version: 6.5.1 * * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. * @@ -29,16 +28,16 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ #include "glheader.h" #include "imports.h" -#include "glapi/glthread.h" #include "hash.h" -#include "hash_table.h" +#include "util/hash_table.h" /** * Magic GLuint object name that gets stored outside of the struct hash_table. @@ -59,8 +58,7 @@ struct _mesa_HashTable { struct hash_table *ht; GLuint MaxKey; /**< highest key inserted so far */ - _glthread_Mutex Mutex; /**< mutual exclusion lock */ - _glthread_Mutex WalkMutex; /**< for _mesa_HashWalk() */ + mtx_t Mutex; /**< mutual exclusion lock */ GLboolean InDeleteAll; /**< Debug check */ /** Value that would be in the table for DELETED_KEY_VALUE. */ void *deleted_key_data; @@ -97,6 +95,12 @@ uint_hash(GLuint id) return id; } +static uint32_t +uint_key_hash(const void *key) +{ + return uint_hash((uintptr_t)key); +} + static void * uint_key(GLuint id) { @@ -115,11 +119,25 @@ _mesa_NewHashTable(void) struct _mesa_HashTable *table = CALLOC_STRUCT(_mesa_HashTable); if (table) { - table->ht = _mesa_hash_table_create(NULL, uint_key_compare); + table->ht = _mesa_hash_table_create(NULL, uint_key_hash, + uint_key_compare); + if (table->ht == NULL) { + free(table); + _mesa_error_no_memory(__func__); + return NULL; + } + _mesa_hash_table_set_deleted_key(table->ht, uint_key(DELETED_KEY_VALUE)); - _glthread_INIT_MUTEX(table->Mutex); - _glthread_INIT_MUTEX(table->WalkMutex); + /* + * Needs to be recursive, since the callback in _mesa_HashWalk() + * is allowed to call _mesa_HashRemove(). + */ + mtx_init(&table->Mutex, mtx_recursive); } + else { + _mesa_error_no_memory(__func__); + } + return table; } @@ -144,8 +162,7 @@ _mesa_DeleteHashTable(struct _mesa_HashTable *table) _mesa_hash_table_destroy(table->ht, NULL); - _glthread_DESTROY_MUTEX(table->Mutex); - _glthread_DESTROY_MUTEX(table->WalkMutex); + mtx_destroy(&table->Mutex); free(table); } @@ -166,7 +183,7 @@ _mesa_HashLookup_unlocked(struct _mesa_HashTable *table, GLuint key) if (key == DELETED_KEY_VALUE) return table->deleted_key_data; - entry = _mesa_hash_table_search(table->ht, uint_hash(key), uint_key(key)); + entry = _mesa_hash_table_search(table->ht, uint_key(key)); if (!entry) return NULL; @@ -187,23 +204,63 @@ _mesa_HashLookup(struct _mesa_HashTable *table, GLuint key) { void *res; assert(table); - _glthread_LOCK_MUTEX(table->Mutex); + mtx_lock(&table->Mutex); res = _mesa_HashLookup_unlocked(table, key); - _glthread_UNLOCK_MUTEX(table->Mutex); + mtx_unlock(&table->Mutex); return res; } /** - * Insert a key/pointer pair into the hash table. - * If an entry with this key already exists we'll replace the existing entry. - * + * Lookup an entry in the hash table without locking the mutex. + * + * The hash table mutex must be locked manually by calling + * _mesa_HashLockMutex() before calling this function. + * + * \param table the hash table. + * \param key the key. + * + * \return pointer to user's data or NULL if key not in table + */ +void * +_mesa_HashLookupLocked(struct _mesa_HashTable *table, GLuint key) +{ + return _mesa_HashLookup_unlocked(table, key); +} + + +/** + * Lock the hash table mutex. + * + * This function should be used when multiple objects need + * to be looked up in the hash table, to avoid having to lock + * and unlock the mutex each time. + * * \param table the hash table. - * \param key the key (not zero). - * \param data pointer to user data. */ void -_mesa_HashInsert(struct _mesa_HashTable *table, GLuint key, void *data) +_mesa_HashLockMutex(struct _mesa_HashTable *table) +{ + assert(table); + mtx_lock(&table->Mutex); +} + + +/** + * Unlock the hash table mutex. + * + * \param table the hash table. + */ +void +_mesa_HashUnlockMutex(struct _mesa_HashTable *table) +{ + assert(table); + mtx_unlock(&table->Mutex); +} + + +static inline void +_mesa_HashInsert_unlocked(struct _mesa_HashTable *table, GLuint key, void *data) { uint32_t hash = uint_hash(key); struct hash_entry *entry; @@ -211,26 +268,57 @@ _mesa_HashInsert(struct _mesa_HashTable *table, GLuint key, void *data) assert(table); assert(key); - _glthread_LOCK_MUTEX(table->Mutex); - if (key > table->MaxKey) table->MaxKey = key; if (key == DELETED_KEY_VALUE) { table->deleted_key_data = data; } else { - entry = _mesa_hash_table_search(table->ht, hash, uint_key(key)); + entry = _mesa_hash_table_search_pre_hashed(table->ht, hash, uint_key(key)); if (entry) { entry->data = data; } else { - _mesa_hash_table_insert(table->ht, hash, uint_key(key), data); + _mesa_hash_table_insert_pre_hashed(table->ht, hash, uint_key(key), data); } } +} + - _glthread_UNLOCK_MUTEX(table->Mutex); +/** + * Insert a key/pointer pair into the hash table without locking the mutex. + * If an entry with this key already exists we'll replace the existing entry. + * + * The hash table mutex must be locked manually by calling + * _mesa_HashLockMutex() before calling this function. + * + * \param table the hash table. + * \param key the key (not zero). + * \param data pointer to user data. + */ +void +_mesa_HashInsertLocked(struct _mesa_HashTable *table, GLuint key, void *data) +{ + _mesa_HashInsert_unlocked(table, key, data); } +/** + * Insert a key/pointer pair into the hash table. + * If an entry with this key already exists we'll replace the existing entry. + * + * \param table the hash table. + * \param key the key (not zero). + * \param data pointer to user data. + */ +void +_mesa_HashInsert(struct _mesa_HashTable *table, GLuint key, void *data) +{ + assert(table); + mtx_lock(&table->Mutex); + _mesa_HashInsert_unlocked(table, key, data); + mtx_unlock(&table->Mutex); +} + /** * Remove an entry from the hash table. @@ -241,8 +329,8 @@ _mesa_HashInsert(struct _mesa_HashTable *table, GLuint key, void *data) * While holding the hash table's lock, searches the entry with the matching * key and unlinks it. */ -void -_mesa_HashRemove(struct _mesa_HashTable *table, GLuint key) +static inline void +_mesa_HashRemove_unlocked(struct _mesa_HashTable *table, GLuint key) { struct hash_entry *entry; @@ -256,17 +344,28 @@ _mesa_HashRemove(struct _mesa_HashTable *table, GLuint key) return; } - _glthread_LOCK_MUTEX(table->Mutex); if (key == DELETED_KEY_VALUE) { table->deleted_key_data = NULL; } else { - entry = _mesa_hash_table_search(table->ht, uint_hash(key), uint_key(key)); + entry = _mesa_hash_table_search(table->ht, uint_key(key)); _mesa_hash_table_remove(table->ht, entry); } - _glthread_UNLOCK_MUTEX(table->Mutex); } +void +_mesa_HashRemoveLocked(struct _mesa_HashTable *table, GLuint key) +{ + _mesa_HashRemove_unlocked(table, key); +} + +void +_mesa_HashRemove(struct _mesa_HashTable *table, GLuint key) +{ + mtx_lock(&table->Mutex); + _mesa_HashRemove_unlocked(table, key); + mtx_unlock(&table->Mutex); +} /** * Delete all entries in a hash table, but don't delete the table itself. @@ -284,9 +383,9 @@ _mesa_HashDeleteAll(struct _mesa_HashTable *table, { struct hash_entry *entry; - ASSERT(table); - ASSERT(callback); - _glthread_LOCK_MUTEX(table->Mutex); + assert(table); + assert(callback); + mtx_lock(&table->Mutex); table->InDeleteAll = GL_TRUE; hash_table_foreach(table->ht, entry) { callback((uintptr_t)entry->key, entry->data, userData); @@ -297,17 +396,12 @@ _mesa_HashDeleteAll(struct _mesa_HashTable *table, table->deleted_key_data = NULL; } table->InDeleteAll = GL_FALSE; - _glthread_UNLOCK_MUTEX(table->Mutex); + mtx_unlock(&table->Mutex); } /** * Walk over all entries in a hash table, calling callback function for each. - * Note: we use a separate mutex in this function to avoid a recursive - * locking deadlock (in case the callback calls _mesa_HashRemove()) and to - * prevent multiple threads/contexts from getting tangled up. - * A lock-less version of this function could be used when the table will - * not be modified. * \param table the hash table to walk * \param callback the callback function * \param userData arbitrary pointer to pass along to the callback @@ -322,15 +416,15 @@ _mesa_HashWalk(const struct _mesa_HashTable *table, struct _mesa_HashTable *table2 = (struct _mesa_HashTable *) table; struct hash_entry *entry; - ASSERT(table); - ASSERT(callback); - _glthread_LOCK_MUTEX(table2->WalkMutex); + assert(table); + assert(callback); + mtx_lock(&table2->Mutex); hash_table_foreach(table->ht, entry) { callback((uintptr_t)entry->key, entry->data, userData); } if (table->deleted_key_data) callback(DELETED_KEY_VALUE, table->deleted_key_data, userData); - _glthread_UNLOCK_MUTEX(table2->WalkMutex); + mtx_unlock(&table2->Mutex); } static void @@ -370,10 +464,8 @@ GLuint _mesa_HashFindFreeKeyBlock(struct _mesa_HashTable *table, GLuint numKeys) { const GLuint maxKey = ~((GLuint) 0) - 1; - _glthread_LOCK_MUTEX(table->Mutex); if (maxKey - numKeys > table->MaxKey) { /* the quick solution */ - _glthread_UNLOCK_MUTEX(table->Mutex); return table->MaxKey + 1; } else { @@ -391,13 +483,11 @@ _mesa_HashFindFreeKeyBlock(struct _mesa_HashTable *table, GLuint numKeys) /* this key not in use, check if we've found enough */ freeCount++; if (freeCount == numKeys) { - _glthread_UNLOCK_MUTEX(table->Mutex); return freeStart; } } } /* cannot allocate a block of numKeys consecutive keys */ - _glthread_UNLOCK_MUTEX(table->Mutex); return 0; } } @@ -409,14 +499,12 @@ _mesa_HashFindFreeKeyBlock(struct _mesa_HashTable *table, GLuint numKeys) GLuint _mesa_HashNumEntries(const struct _mesa_HashTable *table) { - struct hash_entry *entry; GLuint count = 0; if (table->deleted_key_data) count++; - hash_table_foreach(table->ht, entry) - count++; + count += _mesa_hash_table_num_entries(table->ht); return count; }