Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Index: mono/metadata/sgen-gc.c
- ===================================================================
- --- mono/metadata/sgen-gc.c (revision 155305)
- +++ mono/metadata/sgen-gc.c (working copy)
- @@ -202,16 +202,8 @@
- #include <mono/utils/memcheck.h>
- -#define OPDEF(a,b,c,d,e,f,g,h,i,j) \
- - a = i,
- +#include "mini/mini.h"
- -enum {
- -#include "mono/cil/opcode.def"
- - CEE_LAST
- -};
- -
- -#undef OPDEF
- -
- /*
- * ######################################################################
- * ######## Types and constants used by the GC.
- @@ -391,6 +383,17 @@
- gboolean is_to_space;
- };
- +#ifdef MONO_GC_SAFE_POINTS
- +
- +void *gc_safe_point_map = NULL;
- +int gc_safe_point_triggered = 0;
- +
- +static void gc_safe_points_trigger_request (void);
- +static void gc_safe_points_dissolve_request (void);
- +static void mono_gc_safe_points_setup (void);
- +
- +#endif
- +
- #define SIZEOF_GC_MEM_SECTION ((sizeof (GCMemSection) + 7) & ~7)
- /* large object space struct: 64+ KB */
- @@ -5723,8 +5726,8 @@
- DEBUG (4, fprintf (gc_debug_file, "Skip (equal): %p, %p\n", (void*)me, (void*)info->id));
- continue;
- }
- - /*if (signum == suspend_signal_num && info->stop_count == global_stop_count)
- - continue;*/
- + if (signum == suspend_signal_num && info->stop_count == global_stop_count)
- + continue;
- result = pthread_kill (info->id, signum);
- if (result == 0) {
- DEBUG (4, fprintf (gc_debug_file, "thread %p signal sent\n", info));
- @@ -5814,11 +5817,67 @@
- return num_threads_died;
- }
- -/* LOCKING: assumes the GC lock is held (by the stopping thread) */
- +#ifdef MONO_GC_SAFE_POINTS
- +
- +/**
- + * Will suspend managed threads temporarily while the flag for gc safe point
- + * gets set.
- + */
- static void
- -suspend_handler (int sig, siginfo_t *siginfo, void *context)
- +temporary_suspend_managed_thread (void)
- {
- + SgenThreadInfo *info = thread_info_lookup (pthread_self ());
- + info -> stopped_ip = 0;
- +
- + MONO_SEM_POST (suspend_ack_semaphore_ptr);
- +
- + do {
- + info->signal = 0;
- + sigsuspend (&suspend_signal_mask);
- + } while (info->signal != restart_signal_num);
- +
- +}
- +
- +/**
- + * Restart the non-native threads and run them till they reach the next safe
- + * point.
- + */
- +static void
- +nudge_to_next_safe_point (void)
- +{
- + int i, count, result;
- SgenThreadInfo *info;
- + pthread_t me = pthread_self ();
- +
- + gc_safe_points_trigger_request ();
- +
- + count = 0;
- +
- + for (i = 0; i < THREAD_HASH_SIZE; ++i) {
- + for (info = thread_table [i]; info; info = info->next) {
- + if (info -> skip || info -> stopped_ip || ARCH_THREAD_EQUALS (info->id, me)) {
- + continue;
- + }
- + result = pthread_kill (info->id, restart_signal_num);
- + if (result == 0) {
- + count++;
- + } else {
- + info->skip = 1;
- + }
- + }
- + }
- +
- + wait_for_suspend_ack (count);
- +
- + gc_safe_points_dissolve_request ();
- +}
- +
- +#endif // MONO_GC_SAFE_POINT
- +
- +void
- +reached_gc_safe_point (void *context, MonoDomain *domain, gpointer ip)
- +{
- + SgenThreadInfo *info;
- pthread_t id;
- int stop_count;
- int old_errno = errno;
- @@ -5827,8 +5886,8 @@
- id = pthread_self ();
- info = thread_info_lookup (id);
- - info->stopped_domain = mono_domain_get ();
- - info->stopped_ip = (gpointer) ARCH_SIGCTX_IP (context);
- + info->stopped_domain = domain;
- + info->stopped_ip = ip;
- stop_count = global_stop_count;
- /* duplicate signal */
- if (0 && info->stop_count == stop_count) {
- @@ -5873,7 +5932,36 @@
- errno = old_errno;
- }
- +/* LOCKING: assumes the GC lock is held (by the stopping thread) */
- static void
- +suspend_handler (int sig, siginfo_t *siginfo, void *context)
- +{
- + MonoDomain *domain = mono_domain_get ();
- + gpointer ip = (gpointer) ARCH_SIGCTX_IP (context);
- + MonoJitInfo *ji;
- +#ifdef MONO_GC_SAFE_POINTS
- + if (!mono_thread_internal_current ()) {
- + // HACK!!
- + /* Is this the right thing to do? Can a thread terminate between
- + * the signal generation and reception? Can this be a bug? */
- + reached_gc_safe_point (context, domain, ip);
- + return;
- + }
- + ji = mono_jit_info_table_find (domain, ip);
- +
- + if (ji) {
- + /* Managed code. */
- + temporary_suspend_managed_thread ();
- + return;
- + } else {
- + reached_gc_safe_point (context, domain, ip);
- + }
- +#else
- + reached_gc_safe_point (context, domain, ip);
- +#endif
- +}
- +
- +static void
- restart_handler (int sig)
- {
- SgenThreadInfo *info;
- @@ -5915,7 +6003,12 @@
- DEBUG (3, fprintf (gc_debug_file, "stopping world n %d from %p %p\n", global_stop_count, thread_info_lookup (ARCH_GET_THREAD ()), (gpointer)ARCH_GET_THREAD ()));
- TV_GETTIME (stop_world_time);
- count = thread_handshake (suspend_signal_num);
- +#ifndef MONO_GC_SAFE_POINTS
- count -= restart_threads_until_none_in_managed_allocator ();
- +#endif
- +#ifdef MONO_GC_SAFE_POINTS
- + nudge_to_next_safe_point ();
- +#endif
- g_assert (count >= 0);
- DEBUG (3, fprintf (gc_debug_file, "world stopped %d thread(s)\n", count));
- return count;
- @@ -7670,6 +7763,10 @@
- g_error ("failed sigaction");
- }
- +#ifdef MONO_GC_SAFE_POINTS
- + mono_gc_safe_points_setup ();
- +#endif
- +
- sinfo.sa_handler = restart_handler;
- if (sigaction (restart_signal_num, &sinfo, NULL) != 0) {
- g_error ("failed sigaction");
- @@ -8084,7 +8181,47 @@
- return ATYPE_NUM;
- }
- +#ifdef MONO_GC_SAFE_POINTS
- +static void
- +mono_gc_safe_points_setup (void)
- +{
- + void *tmp_map;
- +
- + if (gc_safe_point_map) {
- + return;
- + }
- +
- + tmp_map = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
- + g_assert (tmp_map);
- +
- + mono_loader_lock ();
- +
- + if (gc_safe_point_map) {
- + mono_vfree (tmp_map, mono_pagesize ());
- + } else {
- + gc_safe_point_map = tmp_map;
- + }
- +
- + mono_loader_unlock ();
- +}
- +
- +static void
- +gc_safe_points_trigger_request (void)
- +{
- + mono_mprotect (gc_safe_point_map, mono_pagesize (), MONO_MMAP_NONE);
- + gc_safe_point_triggered = 1;
- +}
- +
- +static void
- +gc_safe_points_dissolve_request(void)
- +{
- + mono_mprotect (gc_safe_point_map, mono_pagesize (), MONO_MMAP_READ);
- + gc_safe_point_triggered = 0;
- +}
- +
- +#endif // MONO_GC_SAFE_POINTS
- +
- MonoMethod*
- mono_gc_get_write_barrier (void)
- {
- Index: mono/metadata/sgen-gc.h
- ===================================================================
- --- mono/metadata/sgen-gc.h (revision 155305)
- +++ mono/metadata/sgen-gc.h (working copy)
- @@ -46,5 +46,17 @@
- /* we intercept pthread_create calls to know which threads exist */
- #define USE_PTHREAD_INTERCEPT 1
- +/* Define this to use GC safe points. */
- +#define MONO_GC_SAFE_POINTS 1
- +
- +#ifdef MONO_GC_SAFE_POINTS
- +
- +extern void *gc_safe_point_map;
- +extern int gc_safe_point_triggered;
- +
- +void reached_gc_safe_point (void *, MonoDomain *, gpointer);
- +
- +#endif // MONO_GC_SAFE_POINTS
- +
- #endif /* __MONO_SGENGC_H__ */
- Index: mono/mini/method-to-ir.c
- ===================================================================
- --- mono/mini/method-to-ir.c (revision 155305)
- +++ mono/mini/method-to-ir.c (working copy)
- @@ -52,6 +52,10 @@
- #include <mono/utils/mono-compiler.h>
- #include <mono/metadata/mono-basic-block.h>
- +#ifdef HAVE_SGEN_GC
- +#include <mono/metadata/sgen-gc.h>
- +#endif
- +
- #include "mini.h"
- #include "trace.h"
- @@ -101,6 +105,42 @@
- /* Determine whenever 'ins' represents a load of the 'this' argument */
- #define MONO_CHECK_THIS(ins) (mono_method_signature (cfg->method)->hasthis && ((ins)->opcode == OP_MOVE) && ((ins)->sreg1 == cfg->args [0]->dreg))
- +#ifdef MONO_GC_SAFE_POINTS
- +
- +#define INSERT_GC_SAFE_POINT \
- + do {\
- + if (insert_safe_points) {\
- + MonoInst *inst; \
- + int dr = alloc_dreg (cfg, STACK_PTR); \
- + MONO_INST_NEW ((cfg), (inst), OP_PCONST); \
- + inst->dreg = dr; \
- + (inst)->inst_p0 = gc_safe_point_map; \
- + (inst)->type = STACK_PTR; \
- + MONO_ADD_INS ((cfg)->cbb, inst); \
- + dreg = alloc_preg (cfg); \
- + NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, dreg, dr, 0); \
- + ins->type = STACK_PTR; \
- + ins->flags |= ins_flag; \
- + ins_flag = 0; \
- + MONO_ADD_INS (cfg -> cbb, ins); \
- + bblock = cfg -> cbb; \
- + } \
- + } while (0)
- +
- +#define INSERT_GC_SAFE_POINT_COND(x) \
- + do {\
- + if ((x)) { \
- + INSERT_GC_SAFE_POINT; \
- + } \
- + } while (0)
- +
- +#else
- +
- +#define INSERT_GC_SAFE_POINT
- +#define INSERT_GC_SAFE_POINT_COND(x)
- +
- +#endif
- +
- static int ldind_to_load_membase (int opcode);
- static int stind_to_store_membase (int opcode);
- @@ -5109,6 +5149,22 @@
- return FALSE;
- }
- +#ifdef MONO_GC_SAFE_POINTS
- +static int
- +safe_points_blacklisted (MonoMethod *method) {
- + // TODO A way to register a method and quickly check if a method is
- + // blacklisted
- + static MonoMethod *wbarr = NULL;
- + if (wbarr == method)
- + return 1;
- + if (strcmp (method -> name, "wbarrier") == 0) {
- + wbarr = method;
- + return 1;
- + }
- + return 0;
- +}
- +#endif
- +
- /*
- * mono_method_to_ir:
- *
- @@ -5147,6 +5203,9 @@
- gboolean dont_verify, dont_verify_stloc, readonly = FALSE;
- int context_used;
- gboolean init_locals, seq_points, skip_dead_blocks;
- +#ifdef MONO_GC_SAFE_POINTS
- + int insert_safe_points = !safe_points_blacklisted (method);
- +#endif
- /* serialization and xdomain stuff may need access to private fields and methods */
- dont_verify = method->klass->image->assembly->corlib_internal? TRUE: FALSE;
- @@ -6001,6 +6060,9 @@
- CHECK_OPSIZE (5);
- token = read32 (ip + 1);
- + INSERT_GC_SAFE_POINT_COND (calli &&
- + insert_safe_points);
- +
- if (calli) {
- cmethod = NULL;
- CHECK_STACK (1);
- @@ -6621,6 +6683,9 @@
- break;
- }
- case CEE_RET:
- +
- + INSERT_GC_SAFE_POINT;
- +
- if (cfg->method != method) {
- /* return from inlined method */
- /*
- @@ -6698,6 +6763,7 @@
- break;
- case CEE_BR_S:
- CHECK_OPSIZE (2);
- + INSERT_GC_SAFE_POINT_COND((signed char) (*(ip + 1)) < 0);
- MONO_INST_NEW (cfg, ins, OP_BR);
- ip++;
- target = ip + 1 + (signed char)(*ip);
- @@ -6726,6 +6792,7 @@
- case CEE_BLT_UN_S:
- CHECK_OPSIZE (2);
- CHECK_STACK (2);
- + INSERT_GC_SAFE_POINT_COND(*(signed char*) (ip + 1) < 0);
- MONO_INST_NEW (cfg, ins, *ip + BIG_BRANCH_OFFSET);
- ip++;
- target = ip + 1 + *(signed char*)ip;
- @@ -6736,12 +6803,15 @@
- sp = stack_start;
- inline_costs += BRANCH_COST;
- break;
- - case CEE_BR:
- + case CEE_BR: {
- + gint32 delta;
- CHECK_OPSIZE (5);
- + delta = (gint32) read32 (ip + 1);
- + INSERT_GC_SAFE_POINT_COND(delta < 0);
- MONO_INST_NEW (cfg, ins, OP_BR);
- ip++;
- - target = ip + 4 + (gint32)read32(ip);
- + target = ip + 4 + delta;
- ip += 4;
- GET_BBLOCK (cfg, tblock, target);
- link_bblock (cfg, bblock, tblock);
- @@ -6757,6 +6827,7 @@
- start_new_bblock = 1;
- inline_costs += BRANCH_COST;
- break;
- + }
- case CEE_BRFALSE_S:
- case CEE_BRTRUE_S:
- case CEE_BRFALSE:
- @@ -6774,6 +6845,8 @@
- target = ip + opsize + (is_short ? *(signed char*)ip : (gint32)read32(ip));
- ip += opsize;
- + INSERT_GC_SAFE_POINT_COND(target < ip);
- +
- sp--;
- GET_BBLOCK (cfg, tblock, target);
- @@ -6828,12 +6901,15 @@
- case CEE_BGE_UN:
- case CEE_BGT_UN:
- case CEE_BLE_UN:
- - case CEE_BLT_UN:
- + case CEE_BLT_UN: {
- + gint32 delta;
- CHECK_OPSIZE (5);
- CHECK_STACK (2);
- + delta = (gint32) read32 (ip + 1);
- + INSERT_GC_SAFE_POINT_COND(delta < 0);
- MONO_INST_NEW (cfg, ins, *ip);
- ip++;
- - target = ip + 4 + (gint32)read32(ip);
- + target = ip + 4 + delta;
- ip += 4;
- ADD_BINCOND (NULL);
- @@ -6841,6 +6917,7 @@
- sp = stack_start;
- inline_costs += BRANCH_COST;
- break;
- + }
- case CEE_SWITCH: {
- MonoInst *src1;
- MonoBasicBlock **targets;
- Index: mono/mini/mini.c
- ===================================================================
- --- mono/mini/mini.c (revision 155305)
- +++ mono/mini/mini.c (working copy)
- @@ -52,6 +52,10 @@
- #include <mono/utils/mono-mmap.h>
- #include <mono/utils/dtrace.h>
- +#ifdef HAVE_SGEN_GC
- +#include <mono/metadata/sgen-gc.h>
- +#endif
- +
- #include "mini.h"
- #include "tasklets.h"
- #include <string.h>
- @@ -5287,6 +5291,15 @@
- GET_CONTEXT;
- +#ifdef MONO_GC_SAFE_POINTS
- + if (gc_safe_point_triggered) {
- + /* TODO Find a foolproof way to check this. */
- + reached_gc_safe_point (context, mono_domain_get (),
- + mono_arch_ip_from_context (ctx));
- + return;
- + }
- +#endif
- +
- #if defined(MONO_ARCH_SOFT_DEBUG_SUPPORTED) && defined(HAVE_SIG_INFO)
- if (mono_arch_is_single_step_event (info, ctx)) {
- mono_debugger_agent_single_step_event (ctx);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement