Implement pointer sized bitlocks

Based on a patch from Alexander Larsson.

https://bugzilla.gnome.org/show_bug.cgi?id=651467
This commit is contained in:
Ryan Lortie
2011-05-25 11:08:20 +02:00
committed by Matthias Clasen
parent 1a80405a36
commit df0b208831
4 changed files with 265 additions and 10 deletions

View File

@@ -18,6 +18,7 @@
#define ITERATIONS 10000
#define THREADS 100
#include <glib.h>
#if TEST_EMULATED_FUTEX
/* this is defined for the 1bit-mutex-emufutex test.
@@ -31,9 +32,16 @@
/* rebuild gbitlock.c without futex support,
defining our own version of the g_bit_*lock symbols
*/
#undef g_pointer_bit_lock
#undef g_pointer_bit_trylock
#undef g_pointer_bit_unlock
#define g_bit_lock _emufutex_g_bit_lock
#define g_bit_trylock _emufutex_g_bit_trylock
#define g_bit_unlock _emufutex_g_bit_unlock
#define g_pointer_bit_lock _emufutex_g_pointer_bit_lock
#define g_pointer_bit_trylock _emufutex_g_pointer_bit_trylock
#define g_pointer_bit_unlock _emufutex_g_pointer_bit_unlock
#define _g_futex_thread_init _emufutex_g_futex_thread_init
#define G_BIT_LOCK_FORCE_FUTEX_EMULATION
@@ -41,24 +49,32 @@
#include <glib/gbitlock.c>
#endif
#include <glib.h>
volatile GThread *owners[LOCKS];
volatile gint locks[LOCKS];
volatile gpointer ptrs[LOCKS];
volatile gint bits[LOCKS];
static void
acquire (int nr)
acquire (int nr,
gboolean use_pointers)
{
GThread *self;
self = g_thread_self ();
if (!g_bit_trylock (&locks[nr], bits[nr]))
g_assert_cmpint (((gsize) ptrs) % 8, ==, 0);
if (!(use_pointers ?
g_pointer_bit_trylock (&ptrs[nr], bits[nr])
: g_bit_trylock (&locks[nr], bits[nr])))
{
if (g_test_verbose ())
g_print ("thread %p going to block on lock %d\n", self, nr);
g_bit_lock (&locks[nr], bits[nr]);
if (use_pointers)
g_pointer_bit_lock (&ptrs[nr], bits[nr]);
else
g_bit_lock (&locks[nr], bits[nr]);
}
g_assert (owners[nr] == NULL); /* hopefully nobody else is here */
@@ -71,23 +87,34 @@ acquire (int nr)
g_assert (owners[nr] == self); /* hopefully this is still us... */
owners[nr] = NULL; /* make way for the next guy */
g_bit_unlock (&locks[nr], bits[nr]);
if (use_pointers)
g_pointer_bit_unlock (&ptrs[nr], bits[nr]);
else
g_bit_unlock (&locks[nr], bits[nr]);
}
static gpointer
thread_func (gpointer data)
{
gboolean use_pointers = GPOINTER_TO_INT (data);
gint i;
GRand *rand;
rand = g_rand_new ();
for (i = 0; i < ITERATIONS; i++)
acquire (g_random_int () % LOCKS);
acquire (g_rand_int_range (rand, 0, LOCKS), use_pointers);
g_rand_free (rand);
return NULL;
}
static void
testcase (void)
testcase (gconstpointer data)
{
gboolean use_pointers = GPOINTER_TO_INT (data);
GThread *threads[THREADS];
int i;
@@ -109,7 +136,9 @@ testcase (void)
bits[i] = g_random_int () % 32;
for (i = 0; i < THREADS; i++)
threads[i] = g_thread_create (thread_func, NULL, TRUE, NULL);
threads[i] = g_thread_create (thread_func,
GINT_TO_POINTER (use_pointers),
TRUE, NULL);
for (i = 0; i < THREADS; i++)
g_thread_join (threads[i]);
@@ -126,7 +155,8 @@ main (int argc, char **argv)
{
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/glib/1bit-mutex" SUFFIX, testcase);
g_test_add_data_func ("/glib/1bit-mutex" SUFFIX "/int", (gpointer) 0, testcase);
g_test_add_data_func ("/glib/1bit-mutex" SUFFIX "/pointer", (gpointer) 1, testcase);
return g_test_run ();
}