Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100755 332 lines (285 sloc) 10.084 kb
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
1 /*
2 * sgen-stw.c: Stop the world functionality
3 *
4 * Author:
5 * Paolo Molaro (lupus@ximian.com)
6 * Rodrigo Kumpera (kumpera@gmail.com)
7 *
8 * Copyright 2005-2011 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
10 * Copyright 2011 Xamarin, Inc.
dee716eb »
2012-11-25 [sgen] Switch license of SGen to LGPL2.
11 * Copyright (C) 2012 Xamarin Inc
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
12 *
dee716eb »
2012-11-25 [sgen] Switch license of SGen to LGPL2.
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Library General Public
15 * License 2.0 as published by the Free Software Foundation;
16 *
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Library General Public License for more details.
21 *
22 * You should have received a copy of the GNU Library General Public
23 * License 2.0 along with this library; if not, write to the Free
24 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
25 */
26
27 #include "config.h"
28 #ifdef HAVE_SGEN_GC
29
30 #include "metadata/sgen-gc.h"
31 #include "metadata/sgen-protocol.h"
32 #include "metadata/sgen-memory-governor.h"
33 #include "metadata/profiler-private.h"
34 #include "utils/mono-time.h"
35 #include "utils/dtrace.h"
c08bca90 »
2014-04-14 [sgen] Counter for time we spend starting and stopping the world.
36 #include "utils/mono-counters.h"
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
37
38 #define TV_DECLARE SGEN_TV_DECLARE
39 #define TV_GETTIME SGEN_TV_GETTIME
40 #define TV_ELAPSED SGEN_TV_ELAPSED
41 #define TV_ELAPSED_MS SGEN_TV_ELAPSED_MS
42
43 inline static void*
44 align_pointer (void *ptr)
45 {
46 mword p = (mword)ptr;
47 p += sizeof (gpointer) - 1;
48 p &= ~ (sizeof (gpointer) - 1);
49 return (void*)p;
50 }
51
52 #ifdef USE_MONO_CTX
53 static MonoContext cur_thread_ctx = {0};
54 #else
55 static mword cur_thread_regs [ARCH_NUM_REGS] = {0};
56 #endif
57
58 static void
59 update_current_thread_stack (void *start)
60 {
61 int stack_guard = 0;
fad3d7f5 »
2013-08-13 [msvc] Implement MONO_CONTEXT_GET_CURRENT () on the msvc build.
62 #if !defined(USE_MONO_CTX)
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
63 void *reg_ptr = cur_thread_regs;
64 #endif
65 SgenThreadInfo *info = mono_thread_info_current ();
66
67 info->stack_start = align_pointer (&stack_guard);
68 g_assert (info->stack_start >= info->stack_start_limit && info->stack_start < info->stack_end);
69 #ifdef USE_MONO_CTX
70 MONO_CONTEXT_GET_CURRENT (cur_thread_ctx);
71 memcpy (&info->ctx, &cur_thread_ctx, sizeof (MonoContext));
72 if (mono_gc_get_gc_callbacks ()->thread_suspend_func)
73 mono_gc_get_gc_callbacks ()->thread_suspend_func (info->runtime_data, NULL, &info->ctx);
74 #else
75 ARCH_STORE_REGS (reg_ptr);
76 memcpy (&info->regs, reg_ptr, sizeof (info->regs));
77 if (mono_gc_get_gc_callbacks ()->thread_suspend_func)
78 mono_gc_get_gc_callbacks ()->thread_suspend_func (info->runtime_data, NULL, NULL);
79 #endif
80 }
81
82 static gboolean
83 is_ip_in_managed_allocator (MonoDomain *domain, gpointer ip)
84 {
85 MonoJitInfo *ji;
86
87 if (!mono_thread_internal_current ())
88 /* Happens during thread attach */
89 return FALSE;
90
91 if (!ip || !domain)
92 return FALSE;
93 if (!sgen_has_critical_method ())
94 return FALSE;
a31b580f »
2013-08-14 [sgen] Add a workaround for #13951. Register the jit info for GC crit…
95
96 /*
97 * mono_jit_info_table_find is not async safe since it calls into the AOT runtime to load information for
98 * missing methods (#13951). To work around this, we disable the AOT fallback. For this to work, the JIT needs
99 * to register the jit info for all GC critical methods after they are JITted/loaded.
100 */
101 ji = mono_jit_info_table_find_internal (domain, ip, FALSE);
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
102 if (!ji)
103 return FALSE;
104
5bc25b90 »
2013-09-10 [runtime] Avoid direct access to MonoJitInfo.method, use an accessor …
105 return sgen_is_critical_method (mono_jit_info_get_method (ji));
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
106 }
107
108 static int
109 restart_threads_until_none_in_managed_allocator (void)
110 {
111 SgenThreadInfo *info;
112 int num_threads_died = 0;
113 int sleep_duration = -1;
114
115 for (;;) {
116 int restart_count = 0, restarted_count = 0;
117 /* restart all threads that stopped in the
118 allocator */
119 FOREACH_THREAD_SAFE (info) {
120 gboolean result;
9cae0d73 »
2013-09-17 [sgen]We no longer need joined_stw as new threads can't join once the…
121 if (info->skip || info->gc_disabled)
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
122 continue;
9dc8efe2 »
2013-09-17 [sgen] Kill SgenThreadInfo::thread_is_dying in favor of the thread-in…
123 if (mono_thread_info_run_state (info) == STATE_RUNNING && (!info->stack_start || info->in_critical_region || info->info.inside_critical_region ||
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
124 is_ip_in_managed_allocator (info->stopped_domain, info->stopped_ip))) {
125 binary_protocol_thread_restart ((gpointer)mono_thread_info_get_tid (info));
949a0bf4 »
2013-04-02 Fix some warnings caused by casts.
126 SGEN_LOG (3, "thread %p resumed.", (void*) (size_t) info->info.native_handle);
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
127 result = sgen_resume_thread (info);
128 if (result) {
129 ++restart_count;
130 } else {
131 info->skip = 1;
132 }
133 } else {
134 /* we set the stopped_ip to
135 NULL for threads which
136 we're not restarting so
137 that we can easily identify
138 the others */
139 info->stopped_ip = NULL;
140 info->stopped_domain = NULL;
141 }
142 } END_FOREACH_THREAD_SAFE
143 /* if no threads were restarted, we're done */
144 if (restart_count == 0)
145 break;
146
147 /* wait for the threads to signal their restart */
148 sgen_wait_for_suspend_ack (restart_count);
149
150 if (sleep_duration < 0) {
7be7431b »
2014-01-17 [runtime] Add a mono_thread_info_yield () function.
151 mono_thread_info_yield ();
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
152 sleep_duration = 0;
153 } else {
154 g_usleep (sleep_duration);
155 sleep_duration += 10;
156 }
157
158 /* stop them again */
159 FOREACH_THREAD (info) {
160 gboolean result;
161 if (info->skip || info->stopped_ip == NULL)
162 continue;
163 result = sgen_suspend_thread (info);
164
165 if (result) {
166 ++restarted_count;
167 } else {
168 info->skip = 1;
169 }
170 } END_FOREACH_THREAD
171 /* some threads might have died */
172 num_threads_died += restart_count - restarted_count;
173 /* wait for the threads to signal their suspension
174 again */
175 sgen_wait_for_suspend_ack (restarted_count);
176 }
177
178 return num_threads_died;
179 }
180
181 static void
182 acquire_gc_locks (void)
183 {
184 LOCK_INTERRUPTION;
185 mono_thread_info_suspend_lock ();
186 }
187
188 static void
189 release_gc_locks (void)
190 {
191 mono_thread_info_suspend_unlock ();
192 UNLOCK_INTERRUPTION;
193 }
194
35f397ed »
2014-01-21 [sgen] Count cards for binary protocol.
195 static void
196 count_cards (long long *major_total, long long *major_marked, long long *los_total, long long *los_marked)
197 {
198 sgen_get_major_collector ()->count_cards (major_total, major_marked);
199 sgen_los_count_cards (los_total, los_marked);
200 }
201
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
202 static TV_DECLARE (stop_world_time);
203 static unsigned long max_pause_usec = 0;
204
c08bca90 »
2014-04-14 [sgen] Counter for time we spend starting and stopping the world.
205 static long long time_stop_world;
206 static long long time_restart_world;
207
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
208 /* LOCKING: assumes the GC lock is held */
209 int
210 sgen_stop_world (int generation)
211 {
c08bca90 »
2014-04-14 [sgen] Counter for time we spend starting and stopping the world.
212 TV_DECLARE (end_handshake);
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
213 int count, dead;
214
215 mono_profiler_gc_event (MONO_GC_EVENT_PRE_STOP_WORLD, generation);
0654f84b »
2012-11-05 [sgen] DTrace probes for world stop/restart.
216 MONO_GC_WORLD_STOP_BEGIN ();
3ba6b691 »
2014-01-08 [sgen] Binary protocol entries for world stop/restart with timestamps.
217 binary_protocol_world_stopping (sgen_timestamp ());
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
218 acquire_gc_locks ();
219
93f3bdf9 »
2014-02-24 [sgen] We must do bridge processing with all sgen locks taken.
220 /* We start to scan after locks are taking, this ensures we won't be interrupted. */
221 sgen_process_togglerefs ();
222
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
223 update_current_thread_stack (&count);
224
225 sgen_global_stop_count++;
6a84f65b »
2012-11-19 Replace all uses of DEBUG with SGEN_LOG and SGEN_ASSERT.
226 SGEN_LOG (3, "stopping world n %d from %p %p", sgen_global_stop_count, mono_thread_info_current (), (gpointer)mono_native_thread_id_get ());
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
227 TV_GETTIME (stop_world_time);
228 count = sgen_thread_handshake (TRUE);
229 dead = restart_threads_until_none_in_managed_allocator ();
230 if (count < dead)
231 g_error ("More threads have died (%d) that been initialy suspended %d", dead, count);
232 count -= dead;
233
6a84f65b »
2012-11-19 Replace all uses of DEBUG with SGEN_LOG and SGEN_ASSERT.
234 SGEN_LOG (3, "world stopped %d thread(s)", count);
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
235 mono_profiler_gc_event (MONO_GC_EVENT_POST_STOP_WORLD, generation);
0654f84b »
2012-11-05 [sgen] DTrace probes for world stop/restart.
236 MONO_GC_WORLD_STOP_END ();
35f397ed »
2014-01-21 [sgen] Count cards for binary protocol.
237 if (binary_protocol_is_enabled ()) {
238 long long major_total, major_marked, los_total, los_marked;
239 count_cards (&major_total, &major_marked, &los_total, &los_marked);
240 binary_protocol_world_stopped (sgen_timestamp (), major_total, major_marked, los_total, los_marked);
241 }
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
242
c08bca90 »
2014-04-14 [sgen] Counter for time we spend starting and stopping the world.
243 TV_GETTIME (end_handshake);
244 time_stop_world += TV_ELAPSED (stop_world_time, end_handshake);
245
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
246 sgen_memgov_collection_start (generation);
2fa83f0a »
2013-07-01 Suspend the world when cleaning up a domain as it's unsafe to walk th…
247 sgen_bridge_reset_data ();
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
248
249 return count;
250 }
251
252 /* LOCKING: assumes the GC lock is held */
253 int
254 sgen_restart_world (int generation, GGTimingInfo *timing)
255 {
256 int count;
257 SgenThreadInfo *info;
258 TV_DECLARE (end_sw);
c08bca90 »
2014-04-14 [sgen] Counter for time we spend starting and stopping the world.
259 TV_DECLARE (start_handshake);
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
260 TV_DECLARE (end_bridge);
261 unsigned long usec, bridge_usec;
262
35f397ed »
2014-01-21 [sgen] Count cards for binary protocol.
263 if (binary_protocol_is_enabled ()) {
264 long long major_total, major_marked, los_total, los_marked;
265 count_cards (&major_total, &major_marked, &los_total, &los_marked);
266 binary_protocol_world_restarting (generation, sgen_timestamp (), major_total, major_marked, los_total, los_marked);
267 }
268
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
269 /* notify the profiler of the leftovers */
2fa83f0a »
2013-07-01 Suspend the world when cleaning up a domain as it's unsafe to walk th…
270 /* FIXME this is the wrong spot at we can STW for non collection reasons. */
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
271 if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_GC_MOVES))
272 sgen_gc_event_moves ();
273 mono_profiler_gc_event (MONO_GC_EVENT_PRE_START_WORLD, generation);
48f06fb9 »
2012-11-16 [sgen] More information in sweep and world restart DTrace probes.
274 MONO_GC_WORLD_RESTART_BEGIN (generation);
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
275 FOREACH_THREAD (info) {
276 info->stack_start = NULL;
277 #ifdef USE_MONO_CTX
278 memset (&info->ctx, 0, sizeof (MonoContext));
279 #else
280 memset (&info->regs, 0, sizeof (info->regs));
281 #endif
282 } END_FOREACH_THREAD
283
c08bca90 »
2014-04-14 [sgen] Counter for time we spend starting and stopping the world.
284 TV_GETTIME (start_handshake);
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
285 count = sgen_thread_handshake (FALSE);
286 TV_GETTIME (end_sw);
c08bca90 »
2014-04-14 [sgen] Counter for time we spend starting and stopping the world.
287 time_restart_world += TV_ELAPSED (start_handshake, end_sw);
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
288 usec = TV_ELAPSED (stop_world_time, end_sw);
289 max_pause_usec = MAX (usec, max_pause_usec);
6a84f65b »
2012-11-19 Replace all uses of DEBUG with SGEN_LOG and SGEN_ASSERT.
290 SGEN_LOG (2, "restarted %d thread(s) (pause time: %d usec, max: %d)", count, (int)usec, (int)max_pause_usec);
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
291 mono_profiler_gc_event (MONO_GC_EVENT_POST_START_WORLD, generation);
48f06fb9 »
2012-11-16 [sgen] More information in sweep and world restart DTrace probes.
292 MONO_GC_WORLD_RESTART_END (generation);
3ba6b691 »
2014-01-08 [sgen] Binary protocol entries for world stop/restart with timestamps.
293 binary_protocol_world_restarted (generation, sgen_timestamp ());
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
294
b4320bf0 »
2013-09-25 [sgen] A better fix for the POSIX stop-world deadlock.
295 /*
296 * We must release the thread info suspend lock after doing
297 * the thread handshake. Otherwise, if the GC stops the world
298 * and a thread is in the process of starting up, but has not
299 * yet registered (it's not in the thread_list), it is
300 * possible that the thread does register while the world is
301 * stopped. When restarting the GC will then try to restart
302 * said thread, but since it never got the suspend signal, it
303 * cannot answer the restart signal, so a deadlock results.
304 */
305 release_gc_locks ();
306
971eba81 »
2013-12-06 [sgen]Fix a deadlock when the GC try to free a JI during world restar…
307 sgen_try_free_some_memory = TRUE;
56a6ae2b »
2013-02-01 [sgen] Fix hazard pointer free deadlock problem. Fixes #9828.
308
86df16b7 »
2013-09-23 Make sure we properly account for transitive liveness when processing…
309 sgen_bridge_processing_finish (generation);
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
310
311 TV_GETTIME (end_bridge);
312 bridge_usec = TV_ELAPSED (end_sw, end_bridge);
313
314 if (timing) {
315 timing [0].stw_time = usec;
316 timing [0].bridge_time = bridge_usec;
317 }
318
319 sgen_memgov_collection_end (generation, timing, timing ? 2 : 0);
320
321 return count;
322 }
323
c08bca90 »
2014-04-14 [sgen] Counter for time we spend starting and stopping the world.
324 void
325 sgen_init_stw (void)
326 {
327 mono_counters_register ("World stop", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_stop_world);
328 mono_counters_register ("World restart", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_restart_world);
329 }
330
a109d1cb »
2012-10-22 Move the sgen stop-the-world code to a separate file.
331 #endif
Something went wrong with that request. Please try again.