* Copyright 2005-2011 Novell, Inc (http://www.novell.com)
* Copyright 2011 Xamarin Inc (http://www.xamarin.com)
* Copyright 2011 Xamarin, Inc.
+ * Copyright (C) 2012 Xamarin Inc
*
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License 2.0 as published by the Free Software Foundation;
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License 2.0 along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "config.h"
update_current_thread_stack (void *start)
{
int stack_guard = 0;
-#ifndef USE_MONO_CTX
+#if !defined(USE_MONO_CTX)
void *reg_ptr = cur_thread_regs;
#endif
SgenThreadInfo *info = mono_thread_info_current ();
return FALSE;
if (!sgen_has_critical_method ())
return FALSE;
- ji = mono_jit_info_table_find (domain, ip);
+
+ /*
+ * mono_jit_info_table_find is not async safe since it calls into the AOT runtime to load information for
+ * missing methods (#13951). To work around this, we disable the AOT fallback. For this to work, the JIT needs
+ * to register the jit info for all GC critical methods after they are JITted/loaded.
+ */
+ ji = mono_jit_info_table_find_internal (domain, ip, FALSE);
if (!ji)
return FALSE;
- return sgen_is_critical_method (ji->method);
+ return sgen_is_critical_method (mono_jit_info_get_method (ji));
}
static int
allocator */
FOREACH_THREAD_SAFE (info) {
gboolean result;
- if (info->skip || info->gc_disabled || !info->joined_stw)
+ if (info->skip || info->gc_disabled)
continue;
- if (!info->thread_is_dying && (!info->stack_start || info->in_critical_region ||
+ if (mono_thread_info_run_state (info) == STATE_RUNNING && (!info->stack_start || info->in_critical_region || info->info.inside_critical_region ||
is_ip_in_managed_allocator (info->stopped_domain, info->stopped_ip))) {
binary_protocol_thread_restart ((gpointer)mono_thread_info_get_tid (info));
- SGEN_LOG (3, "thread %p resumed.", (void*)info->info.native_handle);
+ SGEN_LOG (3, "thread %p resumed.", (void*) (size_t) info->info.native_handle);
result = sgen_resume_thread (info);
if (result) {
++restart_count;
UNLOCK_INTERRUPTION;
}
-static void
-stw_bridge_process (void)
-{
- sgen_bridge_processing_stw_step ();
-}
-
-static void
-bridge_process (int generation)
-{
- sgen_bridge_processing_finish (generation);
-}
-
static TV_DECLARE (stop_world_time);
static unsigned long max_pause_usec = 0;
sgen_process_togglerefs ();
mono_profiler_gc_event (MONO_GC_EVENT_PRE_STOP_WORLD, generation);
+ MONO_GC_WORLD_STOP_BEGIN ();
acquire_gc_locks ();
update_current_thread_stack (&count);
SGEN_LOG (3, "world stopped %d thread(s)", count);
mono_profiler_gc_event (MONO_GC_EVENT_POST_STOP_WORLD, generation);
+ MONO_GC_WORLD_STOP_END ();
sgen_memgov_collection_start (generation);
+ sgen_bridge_reset_data ();
return count;
}
unsigned long usec, bridge_usec;
/* notify the profiler of the leftovers */
+ /* FIXME this is the wrong spot at we can STW for non collection reasons. */
if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_GC_MOVES))
sgen_gc_event_moves ();
mono_profiler_gc_event (MONO_GC_EVENT_PRE_START_WORLD, generation);
+ MONO_GC_WORLD_RESTART_BEGIN (generation);
FOREACH_THREAD (info) {
info->stack_start = NULL;
#ifdef USE_MONO_CTX
#endif
} END_FOREACH_THREAD
- stw_bridge_process ();
- release_gc_locks ();
-
count = sgen_thread_handshake (FALSE);
TV_GETTIME (end_sw);
usec = TV_ELAPSED (stop_world_time, end_sw);
max_pause_usec = MAX (usec, max_pause_usec);
SGEN_LOG (2, "restarted %d thread(s) (pause time: %d usec, max: %d)", count, (int)usec, (int)max_pause_usec);
mono_profiler_gc_event (MONO_GC_EVENT_POST_START_WORLD, generation);
+ MONO_GC_WORLD_RESTART_END (generation);
+
+ /*
+ * We must release the thread info suspend lock after doing
+ * the thread handshake. Otherwise, if the GC stops the world
+ * and a thread is in the process of starting up, but has not
+ * yet registered (it's not in the thread_list), it is
+ * possible that the thread does register while the world is
+ * stopped. When restarting the GC will then try to restart
+ * said thread, but since it never got the suspend signal, it
+ * cannot answer the restart signal, so a deadlock results.
+ */
+ release_gc_locks ();
- bridge_process (generation);
+ sgen_try_free_some_memory = TRUE;
+
+ sgen_bridge_processing_finish (generation);
TV_GETTIME (end_bridge);
bridge_usec = TV_ELAPSED (end_sw, end_bridge);