1 /**
2  * \file
3  * Linearizable property bag.
4  *
5  * Authors:
6  *   Rodrigo Kumpera (kumpera@gmail.com)
7  *
8  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
9  */
10 #include <mono/metadata/property-bag.h>
11 #include <mono/utils/atomic.h>
12 #include <mono/utils/mono-membar.h>
13 
14 /*
15  * mono_property_bag_get:
16  *
17  *   Return the value of the property with TAG or NULL.
18  * This doesn't take any locks.
19  */
20 void*
mono_property_bag_get(MonoPropertyBag * bag,int tag)21 mono_property_bag_get (MonoPropertyBag *bag, int tag)
22 {
23 	MonoPropertyBagItem *item;
24 
25 	for (item = bag->head; item && item->tag <= tag; item = item->next) {
26 		if (item->tag == tag)
27 			return item;
28 	}
29 	return NULL;
30 }
31 
32 /*
33  * mono_property_bag_add:
34  *
35  *   Store VALUE in the property bag. Return the previous value
36  * with the same tag, or NULL. VALUE should point to a structure
37  * extending the MonoPropertyBagItem structure with the 'tag'
38  * field set.
39  * This doesn't take any locks.
40  */
41 void*
mono_property_bag_add(MonoPropertyBag * bag,void * value)42 mono_property_bag_add (MonoPropertyBag *bag, void *value)
43 {
44 	MonoPropertyBagItem *cur, **prev, *item = value;
45 	int tag = item->tag;
46 	mono_memory_barrier (); //publish the values in value
47 
48 retry:
49 	prev = &bag->head;
50 	while (1) {
51 		cur = *prev;
52 		if (!cur || cur->tag > tag) {
53 			item->next = cur;
54 			if (mono_atomic_cas_ptr ((void*)prev, item, cur) == cur)
55 				return item;
56 			goto retry;
57 		} else if (cur->tag == tag) {
58 			return cur;
59 		} else {
60 			prev = &cur->next;
61 		}
62 	}
63 	return value;
64 }
65