nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* |
2 | * Author: Simon McVittie <simon.mcvittie@collabora.co.uk> |
||
3 | * Copyright © 2011 Nokia Corporation |
||
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 | #define GLIB_DISABLE_DEPRECATION_WARNINGS |
||
14 | |||
15 | #include <glib.h> |
||
16 | |||
17 | /* On smcv's laptop, 1e4 iterations didn't always exhibit the bug, but 1e5 |
||
18 | * iterations exhibited it 10/10 times in practice. YMMV. */ |
||
19 | #define ITERATIONS 100000 |
||
20 | |||
21 | static GStaticPrivate sp; |
||
22 | static GMutex *mutex; |
||
23 | static GCond *cond; |
||
24 | static guint i; |
||
25 | |||
26 | static volatile gint freed = 0; |
||
27 | |||
28 | static void |
||
29 | notify (gpointer p) |
||
30 | { |
||
31 | if (!g_atomic_int_compare_and_exchange (&freed, 0, 1)) |
||
32 | { |
||
33 | g_error ("someone already freed it after %u iterations", i); |
||
34 | } |
||
35 | } |
||
36 | |||
37 | static gpointer thread_func (gpointer nil) |
||
38 | { |
||
39 | /* wait for main thread to reach its g_cond_wait call */ |
||
40 | g_mutex_lock (mutex); |
||
41 | |||
42 | g_static_private_set (&sp, &sp, notify); |
||
43 | g_cond_broadcast (cond); |
||
44 | g_mutex_unlock (mutex); |
||
45 | |||
46 | return nil; |
||
47 | } |
||
48 | |||
49 | static void |
||
50 | testcase (void) |
||
51 | { |
||
52 | g_test_bug ("642026"); |
||
53 | |||
54 | mutex = g_mutex_new (); |
||
55 | cond = g_cond_new (); |
||
56 | |||
57 | g_mutex_lock (mutex); |
||
58 | |||
59 | for (i = 0; i < ITERATIONS; i++) |
||
60 | { |
||
61 | GThread *t1; |
||
62 | |||
63 | g_static_private_init (&sp); |
||
64 | freed = 0; |
||
65 | |||
66 | t1 = g_thread_create (thread_func, NULL, TRUE, NULL); |
||
67 | |||
68 | /* wait for t1 to set up its thread-private data */ |
||
69 | g_cond_wait (cond, mutex); |
||
70 | |||
71 | /* exercise the bug, by racing with t1 to free the private data */ |
||
72 | g_static_private_free (&sp); |
||
73 | g_thread_join (t1); |
||
74 | } |
||
75 | |||
76 | g_cond_free (cond); |
||
77 | g_mutex_unlock (mutex); |
||
78 | g_mutex_free (mutex); |
||
79 | } |
||
80 | |||
81 | int |
||
82 | main (int argc, |
||
83 | char **argv) |
||
84 | { |
||
85 | g_test_init (&argc, &argv, NULL); |
||
86 | g_test_bug_base ("https://bugzilla.gnome.org/show_bug.cgi?id="); |
||
87 | |||
88 | g_test_add_func ("/glib/642026", testcase); |
||
89 | |||
90 | return g_test_run (); |
||
91 | } |