aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2012-11-20 07:16:47 -0500
committerDave Airlie <airlied@redhat.com>2012-11-28 03:36:05 -0500
commit384cc2f9688994dfd505011ba3b08e0a702030b0 (patch)
tree9d7f8d1f3a68d88442d35cd13a67563571147f29
parent7e8d9da32ea02f02a23f998cd2013408a4fe49bb (diff)
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: Thomas Hellstrom <thellstrom@vmware.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/drm_hashtab.c26
-rw-r--r--include/drm/drm_hashtab.h14
2 files changed, 36 insertions, 4 deletions
diff --git a/drivers/gpu/drm/drm_hashtab.c b/drivers/gpu/drm/drm_hashtab.c
index 5729e390aa4e..80254547a3f8 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)
67 hashed_key = hash_long(key, ht->order); 67 hashed_key = hash_long(key, ht->order);
68 DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key); 68 DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key);
69 h_list = &ht->table[hashed_key]; 69 h_list = &ht->table[hashed_key];
70 hlist_for_each_entry_rcu(entry, list, h_list, head) 70 hlist_for_each_entry(entry, list, h_list, head)
71 DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key); 71 DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key);
72} 72}
73 73
@@ -81,7 +81,7 @@ static struct hlist_node *drm_ht_find_key(struct drm_open_hash *ht,
81 81
82 hashed_key = hash_long(key, ht->order); 82 hashed_key = hash_long(key, ht->order);
83 h_list = &ht->table[hashed_key]; 83 h_list = &ht->table[hashed_key];
84 hlist_for_each_entry_rcu(entry, list, h_list, head) { 84 hlist_for_each_entry(entry, list, h_list, head) {
85 if (entry->key == key) 85 if (entry->key == key)
86 return list; 86 return list;
87 if (entry->key > key) 87 if (entry->key > key)
@@ -90,6 +90,24 @@ static struct hlist_node *drm_ht_find_key(struct drm_open_hash *ht,
90 return NULL; 90 return NULL;
91} 91}
92 92
93static struct hlist_node *drm_ht_find_key_rcu(struct drm_open_hash *ht,
94 unsigned long key)
95{
96 struct drm_hash_item *entry;
97 struct hlist_head *h_list;
98 struct hlist_node *list;
99 unsigned int hashed_key;
100
101 hashed_key = hash_long(key, ht->order);
102 h_list = &ht->table[hashed_key];
103 hlist_for_each_entry_rcu(entry, list, h_list, head) {
104 if (entry->key == key)
105 return list;
106 if (entry->key > key)
107 break;
108 }
109 return NULL;
110}
93 111
94int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item) 112int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item)
95{ 113{
@@ -102,7 +120,7 @@ int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item)
102 hashed_key = hash_long(key, ht->order); 120 hashed_key = hash_long(key, ht->order);
103 h_list = &ht->table[hashed_key]; 121 h_list = &ht->table[hashed_key];
104 parent = NULL; 122 parent = NULL;
105 hlist_for_each_entry_rcu(entry, list, h_list, head) { 123 hlist_for_each_entry(entry, list, h_list, head) {
106 if (entry->key == key) 124 if (entry->key == key)
107 return -EINVAL; 125 return -EINVAL;
108 if (entry->key > key) 126 if (entry->key > key)
@@ -152,7 +170,7 @@ int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key,
152{ 170{
153 struct hlist_node *list; 171 struct hlist_node *list;
154 172
155 list = drm_ht_find_key(ht, key); 173 list = drm_ht_find_key_rcu(ht, key);
156 if (!list) 174 if (!list)
157 return -EINVAL; 175 return -EINVAL;
158 176
diff --git a/include/drm/drm_hashtab.h b/include/drm/drm_hashtab.h
index 3650d5d011ee..fce2ef3fdfff 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);
61extern int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item); 61extern int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item);
62extern void drm_ht_remove(struct drm_open_hash *ht); 62extern void drm_ht_remove(struct drm_open_hash *ht);
63 63
64/*
65 * RCU-safe interface
66 *
67 * The user of this API needs to make sure that two or more instances of the
68 * hash table manipulation functions are never run simultaneously.
69 * The lookup function drm_ht_find_item_rcu may, however, run simultaneously
70 * with any of the manipulation functions as long as it's called from within
71 * an RCU read-locked section.
72 */
73#define drm_ht_insert_item_rcu drm_ht_insert_item
74#define drm_ht_just_insert_please_rcu drm_ht_just_insert_please
75#define drm_ht_remove_key_rcu drm_ht_remove_key
76#define drm_ht_remove_item_rcu drm_ht_remove_item
77#define drm_ht_find_item_rcu drm_ht_find_item
64 78
65#endif 79#endif