tests/1bitmutex: Hack to build with -Werror=missing-prototypes
[platform/upstream/glib.git] / glib / 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 #include <glib.h>
22
23 #if TEST_EMULATED_FUTEX
24
25 #pragma GCC diagnostic push
26 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
27
28   /* this is defined for the 1bit-mutex-emufutex test.
29    *
30    * we want to test the emulated futex even if futex(2) is available.
31    */
32
33   /* side-step some glib build stuff */
34   #define GLIB_COMPILATION
35
36   /* rebuild gbitlock.c without futex support,
37      defining our own version of the g_bit_*lock symbols
38    */
39   #undef g_pointer_bit_lock
40   #undef g_pointer_bit_trylock
41   #undef g_pointer_bit_unlock
42
43   #define g_bit_lock            _emufutex_g_bit_lock
44   #define g_bit_trylock         _emufutex_g_bit_trylock
45   #define g_bit_unlock          _emufutex_g_bit_unlock
46   #define g_pointer_bit_lock    _emufutex_g_pointer_bit_lock
47   #define g_pointer_bit_trylock _emufutex_g_pointer_bit_trylock
48   #define g_pointer_bit_unlock  _emufutex_g_pointer_bit_unlock
49
50   #define G_BIT_LOCK_FORCE_FUTEX_EMULATION
51
52   #include <glib/gbitlock.c>
53
54 #pragma GCC diagnostic pop
55 #endif
56
57 volatile GThread *owners[LOCKS];
58 volatile gint     locks[LOCKS];
59 volatile gpointer ptrs[LOCKS];
60 volatile gint     bits[LOCKS];
61
62 static void
63 acquire (int      nr,
64          gboolean use_pointers)
65 {
66   GThread *self;
67
68   self = g_thread_self ();
69
70   g_assert_cmpint (((gsize) ptrs) % sizeof(gint), ==, 0);
71
72   if (!(use_pointers ?
73           g_pointer_bit_trylock (&ptrs[nr], bits[nr])
74         : g_bit_trylock (&locks[nr], bits[nr])))
75     {
76       if (g_test_verbose ())
77         g_print ("thread %p going to block on lock %d\n", self, nr);
78
79       if (use_pointers)
80         g_pointer_bit_lock (&ptrs[nr], bits[nr]);
81       else
82         g_bit_lock (&locks[nr], bits[nr]);
83     }
84
85   g_assert (owners[nr] == NULL);   /* hopefully nobody else is here */
86   owners[nr] = self;
87
88   /* let some other threads try to ruin our day */
89   g_thread_yield ();
90   g_thread_yield ();
91   g_thread_yield ();
92
93   g_assert (owners[nr] == self);   /* hopefully this is still us... */
94   owners[nr] = NULL;               /* make way for the next guy */
95
96   if (use_pointers)
97     g_pointer_bit_unlock (&ptrs[nr], bits[nr]);
98   else
99     g_bit_unlock (&locks[nr], bits[nr]);
100 }
101
102 static gpointer
103 thread_func (gpointer data)
104 {
105   gboolean use_pointers = GPOINTER_TO_INT (data);
106   gint i;
107   GRand *rand;
108
109   rand = g_rand_new ();
110
111   for (i = 0; i < ITERATIONS; i++)
112     acquire (g_rand_int_range (rand, 0, LOCKS), use_pointers);
113
114   g_rand_free (rand);
115
116   return NULL;
117 }
118
119 static void
120 testcase (gconstpointer data)
121 {
122   gboolean use_pointers = GPOINTER_TO_INT (data);
123   GThread *threads[THREADS];
124   int i;
125
126 #ifdef TEST_EMULATED_FUTEX
127   #define SUFFIX "-emufutex"
128
129   /* ensure that we are using the emulated futex by checking
130    * (at compile-time) for the existance of 'g_futex_address_list'
131    */
132   g_assert (g_futex_address_list == NULL);
133 #else
134   #define SUFFIX ""
135 #endif
136
137   for (i = 0; i < LOCKS; i++)
138     bits[i] = g_random_int () % 32;
139
140   for (i = 0; i < THREADS; i++)
141     threads[i] = g_thread_new ("foo", thread_func,
142                                GINT_TO_POINTER (use_pointers));
143
144   for (i = 0; i < THREADS; i++)
145     g_thread_join (threads[i]);
146
147   for (i = 0; i < LOCKS; i++)
148     {
149       g_assert (owners[i] == NULL);
150       g_assert (locks[i] == 0);
151     }
152 }
153
154 int
155 main (int argc, char **argv)
156 {
157   g_test_init (&argc, &argv, NULL);
158
159   g_test_add_data_func ("/glib/1bit-mutex" SUFFIX "/int", (gpointer) 0, testcase);
160   g_test_add_data_func ("/glib/1bit-mutex" SUFFIX "/pointer", (gpointer) 1, testcase);
161
162   return g_test_run ();
163 }