2 * Copyright © 2008 Ryan Lortie
3 * Copyright © 2010 Codethink Limited
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * See the included COPYING file for more information.
15 /* LOCKS should be more than the number of contention
16 * counters in gthread.c in order to ensure we exercise
17 * the case where they overlap.
20 #define ITERATIONS 10000
25 #if TEST_EMULATED_FUTEX
27 #pragma GCC diagnostic push
28 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
30 /* this is defined for the 1bit-mutex-emufutex test.
32 * we want to test the emulated futex even if futex(2) is available.
35 /* side-step some glib build stuff */
36 #define GLIB_COMPILATION
38 /* rebuild gbitlock.c without futex support,
39 defining our own version of the g_bit_*lock symbols
41 #undef g_pointer_bit_lock
42 #undef g_pointer_bit_trylock
43 #undef g_pointer_bit_unlock
45 #define g_bit_lock _emufutex_g_bit_lock
46 #define g_bit_trylock _emufutex_g_bit_trylock
47 #define g_bit_unlock _emufutex_g_bit_unlock
48 #define g_pointer_bit_lock _emufutex_g_pointer_bit_lock
49 #define g_pointer_bit_trylock _emufutex_g_pointer_bit_trylock
50 #define g_pointer_bit_unlock _emufutex_g_pointer_bit_unlock
52 #define G_BIT_LOCK_FORCE_FUTEX_EMULATION
54 #include <glib/gbitlock.c>
56 #pragma GCC diagnostic pop
59 volatile GThread
*owners
[LOCKS
];
60 volatile gint locks
[LOCKS
];
61 volatile gpointer ptrs
[LOCKS
];
62 volatile gint bits
[LOCKS
];
66 gboolean use_pointers
)
70 self
= g_thread_self ();
72 g_assert_cmpint (((gsize
) ptrs
) % sizeof(gint
), ==, 0);
75 g_pointer_bit_trylock (&ptrs
[nr
], bits
[nr
])
76 : g_bit_trylock (&locks
[nr
], bits
[nr
])))
78 if (g_test_verbose ())
79 g_printerr ("thread %p going to block on lock %d\n", self
, nr
);
82 g_pointer_bit_lock (&ptrs
[nr
], bits
[nr
]);
84 g_bit_lock (&locks
[nr
], bits
[nr
]);
87 g_assert (owners
[nr
] == NULL
); /* hopefully nobody else is here */
90 /* let some other threads try to ruin our day */
95 g_assert (owners
[nr
] == self
); /* hopefully this is still us... */
96 owners
[nr
] = NULL
; /* make way for the next guy */
99 g_pointer_bit_unlock (&ptrs
[nr
], bits
[nr
]);
101 g_bit_unlock (&locks
[nr
], bits
[nr
]);
105 thread_func (gpointer data
)
107 gboolean use_pointers
= GPOINTER_TO_INT (data
);
111 rand
= g_rand_new ();
113 for (i
= 0; i
< ITERATIONS
; i
++)
114 acquire (g_rand_int_range (rand
, 0, LOCKS
), use_pointers
);
122 testcase (gconstpointer data
)
124 gboolean use_pointers
= GPOINTER_TO_INT (data
);
125 GThread
*threads
[THREADS
];
128 #ifdef TEST_EMULATED_FUTEX
129 #define SUFFIX "-emufutex"
131 /* ensure that we are using the emulated futex by checking
132 * (at compile-time) for the existance of 'g_futex_address_list'
134 g_assert (g_futex_address_list
== NULL
);
139 for (i
= 0; i
< LOCKS
; i
++)
140 bits
[i
] = g_random_int () % 32;
142 for (i
= 0; i
< THREADS
; i
++)
143 threads
[i
] = g_thread_new ("foo", thread_func
,
144 GINT_TO_POINTER (use_pointers
));
146 for (i
= 0; i
< THREADS
; i
++)
147 g_thread_join (threads
[i
]);
149 for (i
= 0; i
< LOCKS
; i
++)
151 g_assert (owners
[i
] == NULL
);
152 g_assert (locks
[i
] == 0);
157 main (int argc
, char **argv
)
159 g_test_init (&argc
, &argv
, NULL
);
161 g_test_add_data_func ("/glib/1bit-mutex" SUFFIX
"/int", (gpointer
) 0, testcase
);
162 g_test_add_data_func ("/glib/1bit-mutex" SUFFIX
"/pointer", (gpointer
) 1, testcase
);
164 return g_test_run ();