Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Thomas Hellstrom and committed by
Dave Airlie
384cc2f9 7e8d9da3

+36 -4
+22 -4
drivers/gpu/drm/drm_hashtab.c
··· 67 67 hashed_key = hash_long(key, ht->order); 68 68 DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key); 69 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 71 DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key); 72 72 } 73 73 74 74 static struct hlist_node *drm_ht_find_key(struct drm_open_hash *ht, 75 75 unsigned long key) 76 + { 77 + struct drm_hash_item *entry; 78 + struct hlist_head *h_list; 79 + struct hlist_node *list; 80 + unsigned int hashed_key; 81 + 82 + hashed_key = hash_long(key, ht->order); 83 + h_list = &ht->table[hashed_key]; 84 + hlist_for_each_entry(entry, list, h_list, head) { 85 + if (entry->key == key) 86 + return list; 87 + if (entry->key > key) 88 + break; 89 + } 90 + return NULL; 91 + } 92 + 93 + static struct hlist_node *drm_ht_find_key_rcu(struct drm_open_hash *ht, 94 + unsigned long key) 76 95 { 77 96 struct drm_hash_item *entry; 78 97 struct hlist_head *h_list; ··· 109 90 return NULL; 110 91 } 111 92 112 - 113 93 int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item) 114 94 { 115 95 struct drm_hash_item *entry; ··· 120 102 hashed_key = hash_long(key, ht->order); 121 103 h_list = &ht->table[hashed_key]; 122 104 parent = NULL; 123 - hlist_for_each_entry_rcu(entry, list, h_list, head) { 105 + hlist_for_each_entry(entry, list, h_list, head) { 124 106 if (entry->key == key) 125 107 return -EINVAL; 126 108 if (entry->key > key) ··· 170 152 { 171 153 struct hlist_node *list; 172 154 173 - list = drm_ht_find_key(ht, key); 155 + list = drm_ht_find_key_rcu(ht, key); 174 156 if (!list) 175 157 return -EINVAL; 176 158
+14
include/drm/drm_hashtab.h
··· 61 61 extern int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item); 62 62 extern 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 79 #endif