2 * mono-linked-list-set.h: A lock-free split ordered list.
5 * Rodrigo Kumpera (kumpera@gmail.com)
10 #ifndef __MONO_SPLIT_ORDERED_LIST_H__
11 #define __MONO_SPLIT_ORDERED_LIST_H__
13 #include <mono/utils/hazard-pointer.h>
14 #include <mono/utils/mono-membar.h>
16 typedef struct _MonoLinkedListSetNode MonoLinkedListSetNode;
18 struct _MonoLinkedListSetNode {
19 /* next must be the first element in this struct! */
20 MonoLinkedListSetNode *next;
25 MonoLinkedListSetNode *head;
26 void (*free_node_func)(void *);
30 static inline gpointer
31 mono_lls_pointer_unmask (gpointer p)
33 return (gpointer)((uintptr_t)p & ~(uintptr_t)0x3);
36 static inline uintptr_t
37 mono_lls_pointer_get_mark (gpointer n)
39 return (uintptr_t)n & 0x1;
43 Those are low level operations. prev, cur, next are returned in the hazard pointer table.
44 You must manually clean the hazard pointer table after using them.
48 mono_lls_init (MonoLinkedListSet *list, void (*free_node_func)(void *));
51 mono_lls_find (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, uintptr_t key);
54 mono_lls_insert (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value);
57 mono_lls_remove (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value);
60 get_hazardous_pointer_with_mask (gpointer volatile *pp, MonoThreadHazardPointers *hp, int hazard_index);
63 Requires the world to be stoped
65 #define MONO_LLS_FOREACH(list, element, type) {\
66 MonoLinkedListSetNode *__cur; \
67 for (__cur = (list)->head; __cur; __cur = mono_lls_pointer_unmask (__cur->next)) \
68 if (!mono_lls_pointer_get_mark (__cur->next)) { \
69 (element) = (type)__cur;
72 #define MONO_LLS_FOREACH_FILTERED(list, element, filter_func, type) {\
73 MonoLinkedListSetNode *__cur; \
74 for (__cur = (list)->head; __cur; __cur = mono_lls_pointer_unmask (__cur->next)) \
75 if (!mono_lls_pointer_get_mark (__cur->next)) { \
76 (element) = (type)__cur; \
77 if (!filter_func (element)) continue;
79 #define MONO_LLS_END_FOREACH }}
81 static inline MonoLinkedListSetNode*
82 mono_lls_info_step (MonoLinkedListSetNode *val, MonoThreadHazardPointers *hp)
84 val = (MonoLinkedListSetNode *) mono_lls_pointer_unmask (val);
85 mono_hazard_pointer_set (hp, 1, val);
90 Provides snapshot iteration
92 #define MONO_LLS_FOREACH_SAFE(list, element, type) {\
93 MonoThreadHazardPointers *__hp = mono_hazard_pointer_get (); \
94 MonoLinkedListSetNode *__cur, *__next; \
95 for (__cur = (MonoLinkedListSetNode *) mono_lls_pointer_unmask (get_hazardous_pointer ((gpointer volatile*)&(list)->head, __hp, 1)); \
97 __cur = (MonoLinkedListSetNode *) mono_lls_info_step (__next, __hp)) { \
98 __next = (MonoLinkedListSetNode *) get_hazardous_pointer_with_mask ((gpointer volatile*)&__cur->next, __hp, 0); \
99 if (!mono_lls_pointer_get_mark (__next)) { \
100 (element) = (type)__cur;
102 #define MONO_LLS_FOREACH_FILTERED_SAFE(list, element, filter_func, type) {\
103 MonoThreadHazardPointers *__hp = mono_hazard_pointer_get (); \
104 MonoLinkedListSetNode *__cur, *__next; \
105 for (__cur = (MonoLinkedListSetNode *) mono_lls_pointer_unmask (get_hazardous_pointer ((gpointer volatile*)&(list)->head, __hp, 1)); \
107 __cur = (MonoLinkedListSetNode *) mono_lls_info_step (__next, __hp)) { \
108 __next = (MonoLinkedListSetNode *) get_hazardous_pointer_with_mask ((gpointer volatile*)&__cur->next, __hp, 0); \
109 if (!mono_lls_pointer_get_mark (__next)) { \
110 (element) = (type)__cur; \
111 if (!filter_func (element)) continue;
114 #define MONO_LLS_END_FOREACH_SAFE \
117 mono_hazard_pointer_clear (__hp, 0); \
118 mono_hazard_pointer_clear (__hp, 1); \
121 #endif /* __MONO_SPLIT_ORDERED_LIST_H__ */