Initial commit
[platform/upstream/glib2.0.git] / gthread / tests / 1bit-mutex.c
1 /*
2  * Copyright © 2008 Ryan Lortie
3  * Copyright © 2010 Codethink Limited
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * See the included COPYING file for more information.
11  */
12
13 /* LOCKS should be more than the number of contention
14  * counters in gthread.c in order to ensure we exercise
15  * the case where they overlap.
16  */
17 #define LOCKS      48
18 #define ITERATIONS 10000
19 #define THREADS    100
20
21
22 #if TEST_EMULATED_FUTEX
23   /* this is defined for the 1bit-mutex-emufutex test.
24    *
25    * we want to test the emulated futex even if futex(2) is available.
26    */
27
28   /* side-step some glib build stuff */
29   #define DISABLE_VISIBILITY
30   #define GLIB_COMPILATION
31
32   /* rebuild gbitlock.c without futex support,
33      defining our own version of the g_bit_*lock symbols
34    */
35   #define g_bit_lock            _emufutex_g_bit_lock
36   #define g_bit_trylock         _emufutex_g_bit_trylock
37   #define g_bit_unlock          _emufutex_g_bit_unlock
38   #define _g_futex_thread_init  _emufutex_g_futex_thread_init
39
40   #define G_BIT_LOCK_FORCE_FUTEX_EMULATION
41
42   #include <glib/gbitlock.c>
43 #endif
44
45 #include <glib.h>
46
47 volatile GThread *owners[LOCKS];
48 volatile gint     locks[LOCKS];
49 volatile gint     bits[LOCKS];
50
51 static void
52 acquire (int nr)
53 {
54   GThread *self;
55
56   self = g_thread_self ();
57
58   g_bit_lock (&locks[nr], bits[nr]);
59   g_assert (owners[nr] == NULL);   /* hopefully nobody else is here */
60   owners[nr] = self;
61
62   /* let some other threads try to ruin our day */
63   g_thread_yield ();
64   g_thread_yield ();
65   g_thread_yield ();
66
67   g_assert (owners[nr] == self);   /* hopefully this is still us... */
68   owners[nr] = NULL;               /* make way for the next guy */
69   g_bit_unlock (&locks[nr], bits[nr]);
70 }
71
72 static gpointer
73 thread_func (gpointer data)
74 {
75   gint i;
76
77   for (i = 0; i < ITERATIONS; i++)
78     acquire (g_random_int () % LOCKS);
79
80   return NULL;
81 }
82
83 static void
84 testcase (void)
85 {
86   GThread *threads[THREADS];
87   int i;
88
89   g_thread_init (NULL);
90
91 #ifdef TEST_EMULATED_FUTEX
92   _g_futex_thread_init ();
93   #define SUFFIX "-emufutex"
94
95   /* ensure that we are using the emulated futex by checking
96    * (at compile-time) for the existance of 'g_futex_mutex'
97    */
98   g_assert (g_futex_mutex != NULL);
99 #else
100   #define SUFFIX ""
101 #endif
102
103   for (i = 0; i < LOCKS; i++)
104     bits[i] = g_random_int () % 32;
105
106   for (i = 0; i < THREADS; i++)
107     threads[i] = g_thread_create (thread_func, NULL, TRUE, NULL);
108
109   for (i = 0; i < THREADS; i++)
110     g_thread_join (threads[i]);
111
112   for (i = 0; i < LOCKS; i++)
113     {
114       g_assert (owners[i] == NULL);
115       g_assert (locks[i] == 0);
116     }
117 }
118
119 int
120 main (int argc, char **argv)
121 {
122   g_test_init (&argc, &argv, NULL);
123
124   g_test_add_func ("/glib/1bit-mutex" SUFFIX, testcase);
125
126   return g_test_run ();
127 }