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: Thomas Hellstrom <thellstrom at vmware.com>
---
 drivers/gpu/drm/drm_hashtab.c |   26 ++++++++++++++++++++++----
 include/drm/drm_hashtab.h     |   14 ++++++++++++++
 2 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_hashtab.c b/drivers/gpu/drm/drm_hashtab.c
index 5729e39..8025454 100644
--- a/drivers/gpu/drm/drm_hashtab.c
+++ b/drivers/gpu/drm/drm_hashtab.c
@@ -67,7 +67,7 @@ void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned 
long key)
        hashed_key = hash_long(key, ht->order);
        DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, 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);
 }

@@ -81,7 +81,7 @@ static struct hlist_node *drm_ht_find_key(struct 
drm_open_hash *ht,

        hashed_key = hash_long(key, ht->order);
        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)
                        return list;
                if (entry->key > key)
@@ -90,6 +90,24 @@ static struct hlist_node *drm_ht_find_key(struct 
drm_open_hash *ht,
        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)
 {
@@ -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);
        h_list = &ht->table[hashed_key];
        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)
                        return -EINVAL;
                if (entry->key > key)
@@ -152,7 +170,7 @@ int drm_ht_find_item(struct drm_open_hash *ht, unsigned 
long key,
 {
        struct hlist_node *list;

-       list = drm_ht_find_key(ht, key);
+       list = drm_ht_find_key_rcu(ht, key);
        if (!list)
                return -EINVAL;

diff --git a/include/drm/drm_hashtab.h b/include/drm/drm_hashtab.h
index 3650d5d..fce2ef3 100644
--- a/include/drm/drm_hashtab.h
+++ b/include/drm/drm_hashtab.h
@@ -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 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
-- 
1.7.4.4

Reply via email to