5 #include <mono/metadata/metadata.h>
6 #include <mono/utils/mono-threads.h>
7 #include <mono/utils/hazard-pointer.h>
8 #include <mono/utils/mono-linked-list-set.h>
9 #include <mono/utils/atomic.h>
11 static MonoLinkedListSet lls;
20 #define NUM_ITERS 1000000
24 MonoLinkedListSetNode node;
35 static node_t nodes [N];
38 mono_hazard_pointer_clear_all (MonoThreadHazardPointers *hp, int retain)
41 mono_hazard_pointer_clear (hp, 0);
43 mono_hazard_pointer_clear (hp, 1);
45 mono_hazard_pointer_clear (hp, 2);
51 node_t *node = (node_t *)n;
52 assert (node->state == STATE_BUSY);
53 node->state = STATE_OUT;
59 thread_data_t *thread_data = (thread_data_t *)arg;
60 MonoThreadHazardPointers *hp;
61 int skip = thread_data->skip;
65 mono_thread_info_register_small_id ();
67 hp = mono_hazard_pointer_get ();
70 for (j = 0; j < NUM_ITERS; ++j) {
71 switch (nodes [i].state) {
73 mono_thread_hazardous_try_free_some ();
76 if (InterlockedCompareExchange (&nodes [i].state, STATE_BUSY, STATE_OUT) == STATE_OUT) {
77 result = mono_lls_find (&lls, hp, i, HAZARD_FREE_SAFE_CTX);
79 mono_hazard_pointer_clear_all (hp, -1);
81 result = mono_lls_insert (&lls, hp, &nodes [i].node, HAZARD_FREE_SAFE_CTX);
82 mono_hazard_pointer_clear_all (hp, -1);
84 assert (nodes [i].state == STATE_BUSY);
85 nodes [i].state = STATE_IN;
87 ++thread_data->num_adds;
91 if (InterlockedCompareExchange (&nodes [i].state, STATE_BUSY, STATE_IN) == STATE_IN) {
92 result = mono_lls_find (&lls, hp, i, HAZARD_FREE_SAFE_CTX);
94 assert (mono_hazard_pointer_get_val (hp, 1) == &nodes [i].node);
95 mono_hazard_pointer_clear_all (hp, -1);
97 result = mono_lls_remove (&lls, hp, &nodes [i].node, HAZARD_FREE_SAFE_CTX);
98 mono_hazard_pointer_clear_all (hp, -1);
100 ++thread_data->num_removes;
116 main (int argc, char *argv [])
118 int primes [] = { 1, 2, 3, 5, 7, 11, 13, 17 };
119 MonoThreadInfoCallbacks thread_callbacks;
120 thread_data_t thread_data [NUM_THREADS];
123 memset (&thread_callbacks, 0, sizeof (thread_callbacks));
125 mono_metadata_init ();
127 mono_threads_init (&thread_callbacks, 0);
129 mono_lls_init (&lls, free_node, HAZARD_FREE_NO_LOCK);
131 for (i = 0; i < N; ++i) {
132 nodes [i].node.key = i;
133 nodes [i].state = STATE_OUT;
136 for (i = 0; i < NUM_THREADS; ++i) {
139 thread_data [i].num_adds = thread_data [i].num_removes = 0;
140 thread_data [i].skip = primes [i];
141 result = pthread_create (&thread_data [i].thread, NULL, worker, &thread_data [i]);
145 for (i = 0; i < NUM_THREADS; ++i) {
146 int result = pthread_join (thread_data [i].thread, NULL);
148 printf ("thread %d adds %d removes %d\n", i, thread_data [i].num_adds, thread_data [i].num_removes);