3131#include "term_hash.h"
3232#include "utils.h"
3333
34- #ifndef AVM_NO_SMP
35- #define SMP_RDLOCK (persistent_term ) smp_spinlock_lock(&(persistent_term)->lock)
36- #define SMP_WRLOCK (persistent_term ) smp_spinlock_lock(&(persistent_term)->lock)
37- #define SMP_UNLOCK (persistent_term ) smp_spinlock_unlock(&(persistent_term)->lock)
38- #else
39- #define SMP_RDLOCK (persistent_term ) UNUSED(persistent_term)
40- #define SMP_WRLOCK (persistent_term ) UNUSED(persistent_term)
41- #define SMP_UNLOCK (persistent_term ) UNUSED(persistent_term)
42- #endif
43-
4434struct PersistentTermEntry
4535{
4636 struct PersistentTermEntry * next ;
@@ -52,6 +42,7 @@ struct PersistentTermEntry
5242
5343static persistent_term_result_t find_entry (
5444 PersistentTerm * persistent_term ,
45+ uint32_t bucket_index ,
5546 term key ,
5647 struct PersistentTermEntry * * * out_link ,
5748 struct PersistentTermEntry * * out_entry ,
@@ -71,13 +62,13 @@ void persistent_term_init(PersistentTerm *persistent_term)
7162 }
7263
7364#ifndef AVM_NO_SMP
74- smp_spinlock_init ( & persistent_term -> lock );
65+ persistent_term -> lock = smp_rwlock_create ( );
7566#endif
7667}
7768
7869void persistent_term_destroy (PersistentTerm * persistent_term , GlobalContext * global )
7970{
80- SMP_WRLOCK (persistent_term );
71+ SMP_RWLOCK_WRLOCK (persistent_term -> lock );
8172 for (size_t i = 0 ; i < PERSISTENT_TERM_NUM_BUCKETS ; i ++ ) {
8273 struct PersistentTermEntry * entry = persistent_term -> buckets [i ];
8374 while (entry != NULL ) {
@@ -97,7 +88,11 @@ void persistent_term_destroy(PersistentTerm *persistent_term, GlobalContext *glo
9788 persistent_term -> retired_entries = NULL ;
9889 persistent_term -> count = 0 ;
9990 persistent_term -> memory = 0 ;
100- SMP_UNLOCK (persistent_term );
91+ SMP_RWLOCK_UNLOCK (persistent_term -> lock );
92+ #ifndef AVM_NO_SMP
93+ smp_rwlock_destroy (persistent_term -> lock );
94+ persistent_term -> lock = NULL ;
95+ #endif
10196}
10297
10398persistent_term_result_t persistent_term_put (
@@ -107,44 +102,48 @@ persistent_term_result_t persistent_term_put(
107102 bool put_new ,
108103 GlobalContext * global )
109104{
110- SMP_WRLOCK (persistent_term );
105+ uint32_t bucket_index = term_hash (key , global ) % PERSISTENT_TERM_NUM_BUCKETS ;
106+
107+ struct PersistentTermEntry * new_entry = entry_new (key , value );
108+ if (IS_NULL_PTR (new_entry )) {
109+ return PersistentTermAllocationError ;
110+ }
111+
112+ SMP_RWLOCK_WRLOCK (persistent_term -> lock );
111113
112114 struct PersistentTermEntry * * link ;
113115 struct PersistentTermEntry * entry ;
114- persistent_term_result_t result = find_entry (persistent_term , key , & link , & entry , global );
116+ persistent_term_result_t result = find_entry (persistent_term , bucket_index , key , & link , & entry , global );
115117 if (UNLIKELY (result != PersistentTermOk )) {
116- SMP_UNLOCK (persistent_term );
118+ SMP_RWLOCK_UNLOCK (persistent_term -> lock );
119+ entry_destroy (new_entry , global );
117120 return result ;
118121 }
119122
120123 if (entry != NULL ) {
121124 bool equal = term_is_equal (entry -> value , value , global , & result );
122125 if (UNLIKELY (result != PersistentTermOk )) {
123- SMP_UNLOCK (persistent_term );
126+ SMP_RWLOCK_UNLOCK (persistent_term -> lock );
127+ entry_destroy (new_entry , global );
124128 return result ;
125129 }
126130
127131 if (equal ) {
128- SMP_UNLOCK (persistent_term );
132+ SMP_RWLOCK_UNLOCK (persistent_term -> lock );
133+ entry_destroy (new_entry , global );
129134 return PersistentTermOk ;
130135 }
131136
132137 if (put_new ) {
133- SMP_UNLOCK (persistent_term );
138+ SMP_RWLOCK_UNLOCK (persistent_term -> lock );
139+ entry_destroy (new_entry , global );
134140 return PersistentTermExists ;
135141 }
136142 }
137143
138- struct PersistentTermEntry * new_entry = entry_new (key , value );
139- if (IS_NULL_PTR (new_entry )) {
140- SMP_UNLOCK (persistent_term );
141- return PersistentTermAllocationError ;
142- }
143-
144144 if (entry == NULL ) {
145- uint32_t idx = term_hash (key , global ) % PERSISTENT_TERM_NUM_BUCKETS ;
146- new_entry -> next = persistent_term -> buckets [idx ];
147- persistent_term -> buckets [idx ] = new_entry ;
145+ new_entry -> next = persistent_term -> buckets [bucket_index ];
146+ persistent_term -> buckets [bucket_index ] = new_entry ;
148147 persistent_term -> count ++ ;
149148 persistent_term -> memory += new_entry -> memory ;
150149 } else {
@@ -154,7 +153,7 @@ persistent_term_result_t persistent_term_put(
154153 retire_entry (persistent_term , entry );
155154 }
156155
157- SMP_UNLOCK (persistent_term );
156+ SMP_RWLOCK_UNLOCK (persistent_term -> lock );
158157 return PersistentTermOk ;
159158}
160159
@@ -166,22 +165,24 @@ persistent_term_result_t persistent_term_get(
166165{
167166 assert (value != NULL );
168167
169- SMP_RDLOCK (persistent_term );
168+ uint32_t bucket_index = term_hash (key , global ) % PERSISTENT_TERM_NUM_BUCKETS ;
169+
170+ SMP_RWLOCK_RDLOCK (persistent_term -> lock );
170171
171172 struct PersistentTermEntry * entry ;
172- persistent_term_result_t result = find_entry (persistent_term , key , NULL , & entry , global );
173+ persistent_term_result_t result = find_entry (persistent_term , bucket_index , key , NULL , & entry , global );
173174 if (UNLIKELY (result != PersistentTermOk )) {
174- SMP_UNLOCK (persistent_term );
175+ SMP_RWLOCK_UNLOCK (persistent_term -> lock );
175176 return result ;
176177 }
177178
178179 if (entry == NULL ) {
179- SMP_UNLOCK (persistent_term );
180+ SMP_RWLOCK_UNLOCK (persistent_term -> lock );
180181 return PersistentTermNotFound ;
181182 }
182183
183184 * value = entry -> value ;
184- SMP_UNLOCK (persistent_term );
185+ SMP_RWLOCK_UNLOCK (persistent_term -> lock );
185186 return PersistentTermOk ;
186187}
187188
@@ -195,18 +196,20 @@ persistent_term_result_t persistent_term_erase(
195196
196197 * removed = false;
197198
198- SMP_WRLOCK (persistent_term );
199+ uint32_t bucket_index = term_hash (key , global ) % PERSISTENT_TERM_NUM_BUCKETS ;
200+
201+ SMP_RWLOCK_WRLOCK (persistent_term -> lock );
199202
200203 struct PersistentTermEntry * * link ;
201204 struct PersistentTermEntry * entry ;
202- persistent_term_result_t result = find_entry (persistent_term , key , & link , & entry , global );
205+ persistent_term_result_t result = find_entry (persistent_term , bucket_index , key , & link , & entry , global );
203206 if (UNLIKELY (result != PersistentTermOk )) {
204- SMP_UNLOCK (persistent_term );
207+ SMP_RWLOCK_UNLOCK (persistent_term -> lock );
205208 return result ;
206209 }
207210
208211 if (entry == NULL ) {
209- SMP_UNLOCK (persistent_term );
212+ SMP_RWLOCK_UNLOCK (persistent_term -> lock );
210213 return PersistentTermOk ;
211214 }
212215
@@ -215,7 +218,7 @@ persistent_term_result_t persistent_term_erase(
215218 retire_entry (persistent_term , entry );
216219
217220 * removed = true;
218- SMP_UNLOCK (persistent_term );
221+ SMP_RWLOCK_UNLOCK (persistent_term -> lock );
219222 return PersistentTermOk ;
220223}
221224
@@ -226,33 +229,32 @@ persistent_term_result_t persistent_term_get_all_maybe_gc(
226229{
227230 assert (ret != NULL );
228231
229- SMP_RDLOCK (persistent_term );
232+ SMP_RWLOCK_RDLOCK (persistent_term -> lock );
230233
231234 size_t needed = 0 ;
232235 for (size_t i = 0 ; i < PERSISTENT_TERM_NUM_BUCKETS ; i ++ ) {
233236 for (struct PersistentTermEntry * entry = persistent_term -> buckets [i ]; entry != NULL ; entry = entry -> next ) {
234- needed += CONS_SIZE + TUPLE_SIZE (2 ) + memory_estimate_usage ( entry -> key ) ;
237+ needed += CONS_SIZE + TUPLE_SIZE (2 );
235238 }
236239 }
237240
238241 if (UNLIKELY (memory_ensure_free_opt (ctx , needed , MEMORY_CAN_SHRINK ) != MEMORY_GC_OK )) {
239- SMP_UNLOCK (persistent_term );
242+ SMP_RWLOCK_UNLOCK (persistent_term -> lock );
240243 return PersistentTermAllocationError ;
241244 }
242245
243246 term list = term_nil ();
244247 for (size_t i = 0 ; i < PERSISTENT_TERM_NUM_BUCKETS ; i ++ ) {
245248 for (struct PersistentTermEntry * entry = persistent_term -> buckets [i ]; entry != NULL ; entry = entry -> next ) {
246249 term tuple = term_alloc_tuple (2 , & ctx -> heap );
247- term key = memory_copy_term_tree (& ctx -> heap , entry -> key );
248- term_put_tuple_element (tuple , 0 , key );
250+ term_put_tuple_element (tuple , 0 , entry -> key );
249251 term_put_tuple_element (tuple , 1 , entry -> value );
250252 list = term_list_prepend (tuple , list , & ctx -> heap );
251253 }
252254 }
253255
254256 * ret = list ;
255- SMP_UNLOCK (persistent_term );
257+ SMP_RWLOCK_UNLOCK (persistent_term -> lock );
256258 return PersistentTermOk ;
257259}
258260
@@ -261,14 +263,15 @@ void persistent_term_info(PersistentTerm *persistent_term, size_t *count, size_t
261263 assert (count != NULL );
262264 assert (memory != NULL );
263265
264- SMP_RDLOCK (persistent_term );
266+ SMP_RWLOCK_RDLOCK (persistent_term -> lock );
265267 * count = persistent_term -> count ;
266268 * memory = persistent_term -> memory ;
267- SMP_UNLOCK (persistent_term );
269+ SMP_RWLOCK_UNLOCK (persistent_term -> lock );
268270}
269271
270272static persistent_term_result_t find_entry (
271273 PersistentTerm * persistent_term ,
274+ uint32_t bucket_index ,
272275 term key ,
273276 struct PersistentTermEntry * * * out_link ,
274277 struct PersistentTermEntry * * out_entry ,
@@ -278,8 +281,7 @@ static persistent_term_result_t find_entry(
278281
279282 * out_entry = NULL ;
280283
281- uint32_t idx = term_hash (key , global ) % PERSISTENT_TERM_NUM_BUCKETS ;
282- struct PersistentTermEntry * * link = & persistent_term -> buckets [idx ];
284+ struct PersistentTermEntry * * link = & persistent_term -> buckets [bucket_index ];
283285 while (* link != NULL ) {
284286 persistent_term_result_t result = PersistentTermOk ;
285287 bool equal = term_is_equal ((* link )-> key , key , global , & result );
0 commit comments