Commit 384cc2f9 authored by Thomas Hellstrom's avatar Thomas Hellstrom Committed by Dave Airlie

drm: Add a hash-tab rcu-safe API

While hashtab should now be RCU-safe, Add a drm_ht_xxx_api for consumers
to use to make it obvious what locking mechanism is used.

Document the way the rcu-safe interface should be used.

Don't use rcu-safe list traversal in modify operations where we should use
a spinlock / mutex anyway.
Signed-off-by: default avatarThomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 7e8d9da3
...@@ -67,7 +67,7 @@ void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key) ...@@ -67,7 +67,7 @@ void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key)
hashed_key = hash_long(key, ht->order); hashed_key = hash_long(key, ht->order);
DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key); DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key);
h_list = &ht->table[hashed_key]; h_list = &ht->table[hashed_key];
hlist_for_each_entry_rcu(entry, list, h_list, head) hlist_for_each_entry(entry, list, h_list, head)
DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key); DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key);
} }
...@@ -81,7 +81,7 @@ static struct hlist_node *drm_ht_find_key(struct drm_open_hash *ht, ...@@ -81,7 +81,7 @@ static struct hlist_node *drm_ht_find_key(struct drm_open_hash *ht,
hashed_key = hash_long(key, ht->order); hashed_key = hash_long(key, ht->order);
h_list = &ht->table[hashed_key]; h_list = &ht->table[hashed_key];
hlist_for_each_entry_rcu(entry, list, h_list, head) { hlist_for_each_entry(entry, list, h_list, head) {
if (entry->key == key) if (entry->key == key)
return list; return list;
if (entry->key > key) if (entry->key > key)
...@@ -90,6 +90,24 @@ static struct hlist_node *drm_ht_find_key(struct drm_open_hash *ht, ...@@ -90,6 +90,24 @@ static struct hlist_node *drm_ht_find_key(struct drm_open_hash *ht,
return NULL; return NULL;
} }
static struct hlist_node *drm_ht_find_key_rcu(struct drm_open_hash *ht,
unsigned long key)
{
struct drm_hash_item *entry;
struct hlist_head *h_list;
struct hlist_node *list;
unsigned int hashed_key;
hashed_key = hash_long(key, ht->order);
h_list = &ht->table[hashed_key];
hlist_for_each_entry_rcu(entry, list, h_list, head) {
if (entry->key == key)
return list;
if (entry->key > key)
break;
}
return NULL;
}
int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item) int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item)
{ {
...@@ -102,7 +120,7 @@ int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item) ...@@ -102,7 +120,7 @@ int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item)
hashed_key = hash_long(key, ht->order); hashed_key = hash_long(key, ht->order);
h_list = &ht->table[hashed_key]; h_list = &ht->table[hashed_key];
parent = NULL; parent = NULL;
hlist_for_each_entry_rcu(entry, list, h_list, head) { hlist_for_each_entry(entry, list, h_list, head) {
if (entry->key == key) if (entry->key == key)
return -EINVAL; return -EINVAL;
if (entry->key > key) if (entry->key > key)
...@@ -152,7 +170,7 @@ int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, ...@@ -152,7 +170,7 @@ int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key,
{ {
struct hlist_node *list; struct hlist_node *list;
list = drm_ht_find_key(ht, key); list = drm_ht_find_key_rcu(ht, key);
if (!list) if (!list)
return -EINVAL; return -EINVAL;
......
...@@ -61,5 +61,19 @@ extern int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key); ...@@ -61,5 +61,19 @@ extern int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key);
extern int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item); extern int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item);
extern void drm_ht_remove(struct drm_open_hash *ht); extern void drm_ht_remove(struct drm_open_hash *ht);
/*
* RCU-safe interface
*
* The user of this API needs to make sure that two or more instances of the
* hash table manipulation functions are never run simultaneously.
* The lookup function drm_ht_find_item_rcu may, however, run simultaneously
* with any of the manipulation functions as long as it's called from within
* an RCU read-locked section.
*/
#define drm_ht_insert_item_rcu drm_ht_insert_item
#define drm_ht_just_insert_please_rcu drm_ht_just_insert_please
#define drm_ht_remove_key_rcu drm_ht_remove_key
#define drm_ht_remove_item_rcu drm_ht_remove_item
#define drm_ht_find_item_rcu drm_ht_find_item
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment