Skip to content

Instantly share code, notes, and snippets.

@schani
Last active August 29, 2015 13:57
Show Gist options
  • Save schani/9380376 to your computer and use it in GitHub Desktop.
Save schani/9380376 to your computer and use it in GitHub Desktop.
#include <assert.h>
#include <pthread.h>
#include <config.h>
#include <mono/metadata/metadata.h>
#include <mono/utils/mono-threads.h>
#include <mono/utils/hazard-pointer.h>
#include <mono/utils/mono-linked-list-set.h>
#include <mono/utils/atomic.h>
static MonoLinkedListSet lls;
enum {
STATE_OUT,
STATE_BUSY,
STATE_IN
};
#define N 10
#define NUM_ITERS 1000000
#define NUM_THREADS 4
typedef struct {
MonoLinkedListSetNode node;
int state;
} node_t;
static node_t nodes [N];
static inline void
mono_hazard_pointer_clear_all (MonoThreadHazardPointers *hp, int retain)
{
if (retain != 0)
mono_hazard_pointer_clear (hp, 0);
if (retain != 1)
mono_hazard_pointer_clear (hp, 1);
if (retain != 2)
mono_hazard_pointer_clear (hp, 2);
}
static void*
worker (void *arg)
{
MonoThreadHazardPointers *hp;
int skip = (int)(long) arg;
int i, j;
gboolean result;
mono_thread_info_register_small_id ();
hp = mono_hazard_pointer_get ();
i = 0;
for (j = 0; j < NUM_ITERS; ++j) {
switch (nodes [i].state) {
case STATE_BUSY:
break;
case STATE_OUT:
if (InterlockedCompareExchange (&nodes [i].state, STATE_BUSY, STATE_OUT) == STATE_OUT) {
result = mono_lls_find (&lls, hp, i);
assert (!result);
mono_hazard_pointer_clear_all (hp, -1);
result = mono_lls_insert (&lls, hp, &nodes [i].node);
mono_hazard_pointer_clear_all (hp, -1);
assert (nodes [i].state == STATE_BUSY);
nodes [i].state = STATE_IN;
}
break;
case STATE_IN:
if (InterlockedCompareExchange (&nodes [i].state, STATE_BUSY, STATE_IN) == STATE_IN) {
result = mono_lls_find (&lls, hp, i);
assert (result);
assert (mono_hazard_pointer_get_val (hp, 1) == &nodes [i].node);
mono_hazard_pointer_clear_all (hp, -1);
result = mono_lls_remove (&lls, hp, &nodes [i].node);
mono_hazard_pointer_clear_all (hp, -1);
assert (nodes [i].state == STATE_BUSY);
nodes [i].state = STATE_OUT;
}
break;
default:
assert (FALSE);
}
i += skip;
if (i >= N)
i -= N;
}
return NULL;
}
int
main (int argc, char *argv [])
{
int primes [] = { 1, 2, 3, 5, 7, 11, 13 };
MonoThreadInfoCallbacks thread_callbacks;
pthread_t threads [NUM_THREADS];
int i;
memset (&thread_callbacks, 0, sizeof (thread_callbacks));
mono_metadata_init ();
mono_threads_init (&thread_callbacks, 0);
mono_thread_smr_init ();
mono_lls_init (&lls, NULL);
for (i = 0; i < N; ++i) {
nodes [i].node.key = i;
nodes [i].state = STATE_OUT;
}
for (i = 0; i < NUM_THREADS; ++i) {
int result = pthread_create (&threads [i], NULL, worker, (void*)(long) primes [i]);
assert (!result);
}
for (i = 0; i < NUM_THREADS; ++i) {
int result = pthread_join (threads [i], NULL);
assert (!result);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment