g_bit_lock (volatile gint *address,
gint lock_bit)
{
+ guint mask = 1u << lock_bit;
guint v;
retry:
- v = g_atomic_int_get (address);
- if (v & (1u << lock_bit))
+ v = g_atomic_int_or (address, mask);
+ if (v & mask)
/* already locked */
{
guint class = ((gsize) address) % G_N_ELEMENTS (g_bit_lock_contended);
goto retry;
}
-
- if (!g_atomic_int_compare_and_exchange (address, v, v | (1u << lock_bit)))
- goto retry;
}
/**
g_bit_trylock (volatile gint *address,
gint lock_bit)
{
+ guint mask = 1u << lock_bit;
guint v;
- retry:
- v = g_atomic_int_get (address);
- if (v & (1u << lock_bit))
- /* already locked */
- return FALSE;
-
- if (!g_atomic_int_compare_and_exchange (address, v, v | (1u << lock_bit)))
- goto retry;
+ v = g_atomic_int_or (address, mask);
- return TRUE;
+ return ~v & mask;
}
/**
gint lock_bit)
{
guint class = ((gsize) address) % G_N_ELEMENTS (g_bit_lock_contended);
- guint v;
+ guint mask = 1u << lock_bit;
- retry:
- v = g_atomic_int_get (address);
- if (!g_atomic_int_compare_and_exchange (address, v, v & ~(1u << lock_bit)))
- goto retry;
+ g_atomic_int_and (address, ~mask);
if (g_atomic_int_get (&g_bit_lock_contended[class]))
g_futex_wake (address);
atomic_CFLAGS = -Wstrict-aliasing=2 $(INCLUDES)
atomic_LDADD = $(progs_ldadd)
+TEST_PROGS += bitlock
+bitlock_LDADD = $(progs_ldadd)
+
# some testing of gtester funcitonality
XMLLINT=xmllint
gtester-xmllint-check: # check testreport xml with xmllint if present
--- /dev/null
+#include <glib.h>
+
+#define ITERATIONS 100000000
+
+static void
+test_bitlocks (void)
+{
+ guint64 start = g_get_monotonic_time ();
+ gint lock = 0;
+ gint i;
+
+ for (i = 0; i < ITERATIONS; i++)
+ {
+ g_bit_lock (&lock, 0);
+ g_bit_unlock (&lock, 0);
+ }
+
+ {
+ gdouble elapsed;
+ gdouble rate;
+
+ elapsed = g_get_monotonic_time () - start;
+ elapsed /= 1000000;
+ rate = ITERATIONS / elapsed;
+
+ g_test_maximized_result (rate, "iterations per second");
+ }
+}
+
+int
+main (int argc, char **argv)
+{
+ g_test_init (&argc, &argv, NULL);
+
+ if (g_test_perf ())
+ g_test_add_func ("/bitlock/performance/uncontended", test_bitlocks);
+
+ return g_test_run ();
+}