SHARE
TWEET

Untitled

a guest May 19th, 2017 41 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. Index: mono/metadata/sgen-gc.c
  2. ===================================================================
  3. --- mono/metadata/sgen-gc.c (revision 155305)
  4. +++ mono/metadata/sgen-gc.c (working copy)
  5. @@ -202,16 +202,8 @@
  6.  
  7.  #include <mono/utils/memcheck.h>
  8.  
  9. -#define OPDEF(a,b,c,d,e,f,g,h,i,j) \
  10. -   a = i,
  11. +#include "mini/mini.h"
  12.  
  13. -enum {
  14. -#include "mono/cil/opcode.def"
  15. -   CEE_LAST
  16. -};
  17. -
  18. -#undef OPDEF
  19. -
  20.  /*
  21.   * ######################################################################
  22.   * ########  Types and constants used by the GC.
  23. @@ -391,6 +383,17 @@
  24.     gboolean is_to_space;
  25.  };
  26.  
  27. +#ifdef MONO_GC_SAFE_POINTS
  28. +
  29. +void *gc_safe_point_map = NULL;
  30. +int gc_safe_point_triggered = 0;
  31. +
  32. +static void gc_safe_points_trigger_request (void);
  33. +static void gc_safe_points_dissolve_request (void);
  34. +static void mono_gc_safe_points_setup (void);
  35. +
  36. +#endif
  37. +
  38.  #define SIZEOF_GC_MEM_SECTION  ((sizeof (GCMemSection) + 7) & ~7)
  39.  
  40.  /* large object space struct: 64+ KB */
  41. @@ -5723,8 +5726,8 @@
  42.                 DEBUG (4, fprintf (gc_debug_file, "Skip (equal): %p, %p\n", (void*)me, (void*)info->id));
  43.                 continue;
  44.             }
  45. -           /*if (signum == suspend_signal_num && info->stop_count == global_stop_count)
  46. -               continue;*/
  47. +           if (signum == suspend_signal_num && info->stop_count == global_stop_count)
  48. +               continue;
  49.             result = pthread_kill (info->id, signum);
  50.             if (result == 0) {
  51.                 DEBUG (4, fprintf (gc_debug_file, "thread %p signal sent\n", info));
  52. @@ -5814,11 +5817,67 @@
  53.     return num_threads_died;
  54.  }
  55.  
  56. -/* LOCKING: assumes the GC lock is held (by the stopping thread) */
  57. +#ifdef MONO_GC_SAFE_POINTS
  58. +
  59. +/**
  60. + * Will suspend managed threads temporarily while the flag for gc safe point
  61. + * gets set.
  62. + */
  63.  static void
  64. -suspend_handler (int sig, siginfo_t *siginfo, void *context)
  65. +temporary_suspend_managed_thread (void)
  66.  {
  67. +   SgenThreadInfo *info = thread_info_lookup (pthread_self ());
  68. +   info -> stopped_ip = 0;
  69. +
  70. +   MONO_SEM_POST (suspend_ack_semaphore_ptr);
  71. +
  72. +   do {
  73. +       info->signal = 0;
  74. +       sigsuspend (&suspend_signal_mask);
  75. +   } while (info->signal != restart_signal_num);
  76. +
  77. +}
  78. +
  79. +/**
  80. + * Restart the non-native threads and run them till they reach the next safe
  81. + * point.
  82. + */
  83. +static void
  84. +nudge_to_next_safe_point (void)
  85. +{
  86. +   int i, count, result;
  87.     SgenThreadInfo *info;
  88. +   pthread_t me = pthread_self ();
  89. +
  90. +   gc_safe_points_trigger_request ();
  91. +
  92. +   count = 0;
  93. +
  94. +   for (i = 0; i < THREAD_HASH_SIZE; ++i) {
  95. +       for (info = thread_table [i]; info; info = info->next) {
  96. +           if (info -> skip || info -> stopped_ip || ARCH_THREAD_EQUALS (info->id, me)) {
  97. +               continue;
  98. +           }
  99. +           result = pthread_kill (info->id, restart_signal_num);
  100. +           if (result == 0) {
  101. +               count++;
  102. +           } else {
  103. +               info->skip = 1;
  104. +           }
  105. +       }
  106. +   }
  107. +
  108. +   wait_for_suspend_ack (count);
  109. +
  110. +   gc_safe_points_dissolve_request ();
  111. +}
  112. +
  113. +#endif // MONO_GC_SAFE_POINT
  114. +
  115. +void
  116. +reached_gc_safe_point (void *context, MonoDomain *domain, gpointer ip)
  117. +{
  118. +   SgenThreadInfo *info;
  119.     pthread_t id;
  120.     int stop_count;
  121.     int old_errno = errno;
  122. @@ -5827,8 +5886,8 @@
  123.  
  124.     id = pthread_self ();
  125.     info = thread_info_lookup (id);
  126. -   info->stopped_domain = mono_domain_get ();
  127. -   info->stopped_ip = (gpointer) ARCH_SIGCTX_IP (context);
  128. +   info->stopped_domain = domain;
  129. +   info->stopped_ip = ip;
  130.     stop_count = global_stop_count;
  131.     /* duplicate signal */
  132.     if (0 && info->stop_count == stop_count) {
  133. @@ -5873,7 +5932,36 @@
  134.     errno = old_errno;
  135.  }
  136.  
  137. +/* LOCKING: assumes the GC lock is held (by the stopping thread) */
  138.  static void
  139. +suspend_handler (int sig, siginfo_t *siginfo, void *context)
  140. +{
  141. +   MonoDomain *domain = mono_domain_get ();
  142. +   gpointer ip = (gpointer) ARCH_SIGCTX_IP (context);
  143. +   MonoJitInfo *ji;
  144. +#ifdef MONO_GC_SAFE_POINTS
  145. +   if (!mono_thread_internal_current ()) {
  146. +       // HACK!!
  147. +       /* Is this the right thing to do? Can a thread terminate between
  148. +        * the signal generation and reception? Can this be a bug? */
  149. +   reached_gc_safe_point (context, domain, ip);
  150. +       return;
  151. +   }
  152. +   ji = mono_jit_info_table_find (domain, ip);
  153. +
  154. +   if (ji) {
  155. +       /* Managed code. */
  156. +       temporary_suspend_managed_thread ();
  157. +       return;
  158. +   } else {
  159. +       reached_gc_safe_point (context, domain, ip);
  160. +   }
  161. +#else
  162. +   reached_gc_safe_point (context, domain, ip);
  163. +#endif
  164. +}
  165. +
  166. +static void
  167.  restart_handler (int sig)
  168.  {
  169.     SgenThreadInfo *info;
  170. @@ -5915,7 +6003,12 @@
  171.     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 ()));
  172.     TV_GETTIME (stop_world_time);
  173.     count = thread_handshake (suspend_signal_num);
  174. +#ifndef MONO_GC_SAFE_POINTS
  175.     count -= restart_threads_until_none_in_managed_allocator ();
  176. +#endif
  177. +#ifdef MONO_GC_SAFE_POINTS
  178. +   nudge_to_next_safe_point ();
  179. +#endif
  180.     g_assert (count >= 0);
  181.     DEBUG (3, fprintf (gc_debug_file, "world stopped %d thread(s)\n", count));
  182.     return count;
  183. @@ -7670,6 +7763,10 @@
  184.         g_error ("failed sigaction");
  185.     }
  186.  
  187. +#ifdef MONO_GC_SAFE_POINTS
  188. +   mono_gc_safe_points_setup ();
  189. +#endif
  190. +
  191.     sinfo.sa_handler = restart_handler;
  192.     if (sigaction (restart_signal_num, &sinfo, NULL) != 0) {
  193.         g_error ("failed sigaction");
  194. @@ -8084,7 +8181,47 @@
  195.     return ATYPE_NUM;
  196.  }
  197.  
  198. +#ifdef MONO_GC_SAFE_POINTS
  199.  
  200. +static void
  201. +mono_gc_safe_points_setup (void)
  202. +{
  203. +   void *tmp_map;
  204. +
  205. +   if (gc_safe_point_map) {
  206. +       return;
  207. +   }
  208. +
  209. +   tmp_map = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
  210. +   g_assert (tmp_map);
  211. +
  212. +   mono_loader_lock ();
  213. +
  214. +   if (gc_safe_point_map) {
  215. +       mono_vfree (tmp_map, mono_pagesize ());
  216. +   } else {
  217. +       gc_safe_point_map = tmp_map;
  218. +   }
  219. +
  220. +   mono_loader_unlock ();
  221. +}
  222. +
  223. +static void
  224. +gc_safe_points_trigger_request (void)
  225. +{
  226. +   mono_mprotect (gc_safe_point_map, mono_pagesize (), MONO_MMAP_NONE);
  227. +   gc_safe_point_triggered = 1;
  228. +}
  229. +
  230. +static void
  231. +gc_safe_points_dissolve_request(void)
  232. +{
  233. +   mono_mprotect (gc_safe_point_map, mono_pagesize (), MONO_MMAP_READ);
  234. +   gc_safe_point_triggered = 0;
  235. +}
  236. +
  237. +#endif // MONO_GC_SAFE_POINTS
  238. +
  239.  MonoMethod*
  240.  mono_gc_get_write_barrier (void)
  241.  {
  242. Index: mono/metadata/sgen-gc.h
  243. ===================================================================
  244. --- mono/metadata/sgen-gc.h (revision 155305)
  245. +++ mono/metadata/sgen-gc.h (working copy)
  246. @@ -46,5 +46,17 @@
  247.  /* we intercept pthread_create calls to know which threads exist */
  248.  #define USE_PTHREAD_INTERCEPT 1
  249.  
  250. +/* Define this to use GC safe points. */
  251. +#define MONO_GC_SAFE_POINTS 1
  252. +
  253. +#ifdef MONO_GC_SAFE_POINTS
  254. +
  255. +extern void *gc_safe_point_map;
  256. +extern int gc_safe_point_triggered;
  257. +
  258. +void reached_gc_safe_point (void *, MonoDomain *, gpointer);
  259. +
  260. +#endif // MONO_GC_SAFE_POINTS
  261. +
  262.  #endif /* __MONO_SGENGC_H__ */
  263.  
  264. Index: mono/mini/method-to-ir.c
  265. ===================================================================
  266. --- mono/mini/method-to-ir.c    (revision 155305)
  267. +++ mono/mini/method-to-ir.c    (working copy)
  268. @@ -52,6 +52,10 @@
  269.  #include <mono/utils/mono-compiler.h>
  270.  #include <mono/metadata/mono-basic-block.h>
  271.  
  272. +#ifdef HAVE_SGEN_GC
  273. +#include <mono/metadata/sgen-gc.h>
  274. +#endif
  275. +
  276.  #include "mini.h"
  277.  #include "trace.h"
  278.  
  279. @@ -101,6 +105,42 @@
  280.  /* Determine whenever 'ins' represents a load of the 'this' argument */
  281.  #define MONO_CHECK_THIS(ins) (mono_method_signature (cfg->method)->hasthis && ((ins)->opcode == OP_MOVE) && ((ins)->sreg1 == cfg->args [0]->dreg))
  282.  
  283. +#ifdef MONO_GC_SAFE_POINTS
  284. +
  285. +#define INSERT_GC_SAFE_POINT \
  286. +   do {\
  287. +       if (insert_safe_points) {\
  288. +           MonoInst *inst; \
  289. +           int dr = alloc_dreg (cfg, STACK_PTR); \
  290. +           MONO_INST_NEW ((cfg), (inst), OP_PCONST); \
  291. +           inst->dreg = dr; \
  292. +           (inst)->inst_p0 = gc_safe_point_map;    \
  293. +           (inst)->type = STACK_PTR;   \
  294. +           MONO_ADD_INS ((cfg)->cbb, inst); \
  295. +           dreg = alloc_preg (cfg); \
  296. +           NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, dreg, dr, 0); \
  297. +           ins->type = STACK_PTR; \
  298. +           ins->flags |= ins_flag; \
  299. +           ins_flag = 0; \
  300. +           MONO_ADD_INS (cfg -> cbb, ins); \
  301. +           bblock = cfg -> cbb; \
  302. +       } \
  303. +   } while (0)
  304. +
  305. +#define INSERT_GC_SAFE_POINT_COND(x) \
  306. +   do {\
  307. +       if ((x)) { \
  308. +           INSERT_GC_SAFE_POINT; \
  309. +       } \
  310. +   } while (0)
  311. +
  312. +#else
  313. +
  314. +#define INSERT_GC_SAFE_POINT
  315. +#define INSERT_GC_SAFE_POINT_COND(x)
  316. +
  317. +#endif
  318. +
  319.  static int ldind_to_load_membase (int opcode);
  320.  static int stind_to_store_membase (int opcode);
  321.  
  322. @@ -5109,6 +5149,22 @@
  323.     return FALSE;
  324.  }
  325.  
  326. +#ifdef MONO_GC_SAFE_POINTS
  327. +static int
  328. +safe_points_blacklisted (MonoMethod *method) {
  329. +   // TODO A way to register a method and quickly check if a method is
  330. +   // blacklisted
  331. +   static MonoMethod *wbarr = NULL;
  332. +   if (wbarr == method)
  333. +       return 1;
  334. +   if (strcmp (method -> name, "wbarrier") == 0) {
  335. +       wbarr = method;
  336. +       return 1;
  337. +   }
  338. +   return 0;
  339. +}
  340. +#endif
  341. +
  342.  /*
  343.   * mono_method_to_ir:
  344.   *
  345. @@ -5147,6 +5203,9 @@
  346.     gboolean dont_verify, dont_verify_stloc, readonly = FALSE;
  347.     int context_used;
  348.     gboolean init_locals, seq_points, skip_dead_blocks;
  349. +#ifdef MONO_GC_SAFE_POINTS
  350. +   int insert_safe_points = !safe_points_blacklisted (method);
  351. +#endif
  352.  
  353.     /* serialization and xdomain stuff may need access to private fields and methods */
  354.     dont_verify = method->klass->image->assembly->corlib_internal? TRUE: FALSE;
  355. @@ -6001,6 +6060,9 @@
  356.             CHECK_OPSIZE (5);
  357.             token = read32 (ip + 1);
  358.  
  359. +           INSERT_GC_SAFE_POINT_COND (calli &&
  360. +                   insert_safe_points);
  361. +
  362.             if (calli) {
  363.                 cmethod = NULL;
  364.                 CHECK_STACK (1);
  365. @@ -6621,6 +6683,9 @@
  366.             break;
  367.         }
  368.         case CEE_RET:
  369. +          
  370. +           INSERT_GC_SAFE_POINT;
  371. +          
  372.             if (cfg->method != method) {
  373.                 /* return from inlined method */
  374.                 /*
  375. @@ -6698,6 +6763,7 @@
  376.             break;
  377.         case CEE_BR_S:
  378.             CHECK_OPSIZE (2);
  379. +           INSERT_GC_SAFE_POINT_COND((signed char) (*(ip + 1)) < 0);
  380.             MONO_INST_NEW (cfg, ins, OP_BR);
  381.             ip++;
  382.             target = ip + 1 + (signed char)(*ip);
  383. @@ -6726,6 +6792,7 @@
  384.         case CEE_BLT_UN_S:
  385.             CHECK_OPSIZE (2);
  386.             CHECK_STACK (2);
  387. +           INSERT_GC_SAFE_POINT_COND(*(signed char*) (ip + 1) < 0);
  388.             MONO_INST_NEW (cfg, ins, *ip + BIG_BRANCH_OFFSET);
  389.             ip++;
  390.             target = ip + 1 + *(signed char*)ip;
  391. @@ -6736,12 +6803,15 @@
  392.             sp = stack_start;
  393.             inline_costs += BRANCH_COST;
  394.             break;
  395. -       case CEE_BR:
  396. +       case CEE_BR: {
  397. +           gint32 delta;
  398.             CHECK_OPSIZE (5);
  399. +           delta = (gint32) read32 (ip + 1);
  400. +           INSERT_GC_SAFE_POINT_COND(delta < 0);
  401.             MONO_INST_NEW (cfg, ins, OP_BR);
  402.             ip++;
  403.  
  404. -           target = ip + 4 + (gint32)read32(ip);
  405. +           target = ip + 4 + delta;
  406.             ip += 4;
  407.             GET_BBLOCK (cfg, tblock, target);
  408.             link_bblock (cfg, bblock, tblock);
  409. @@ -6757,6 +6827,7 @@
  410.             start_new_bblock = 1;
  411.             inline_costs += BRANCH_COST;
  412.             break;
  413. +       }
  414.         case CEE_BRFALSE_S:
  415.         case CEE_BRTRUE_S:
  416.         case CEE_BRFALSE:
  417. @@ -6774,6 +6845,8 @@
  418.             target = ip + opsize + (is_short ? *(signed char*)ip : (gint32)read32(ip));
  419.             ip += opsize;
  420.  
  421. +           INSERT_GC_SAFE_POINT_COND(target < ip);
  422. +
  423.             sp--;
  424.  
  425.             GET_BBLOCK (cfg, tblock, target);
  426. @@ -6828,12 +6901,15 @@
  427.         case CEE_BGE_UN:
  428.         case CEE_BGT_UN:
  429.         case CEE_BLE_UN:
  430. -       case CEE_BLT_UN:
  431. +       case CEE_BLT_UN: {
  432. +           gint32 delta;
  433.             CHECK_OPSIZE (5);
  434.             CHECK_STACK (2);
  435. +           delta = (gint32) read32 (ip + 1);
  436. +           INSERT_GC_SAFE_POINT_COND(delta < 0);
  437.             MONO_INST_NEW (cfg, ins, *ip);
  438.             ip++;
  439. -           target = ip + 4 + (gint32)read32(ip);
  440. +           target = ip + 4 + delta;
  441.             ip += 4;
  442.  
  443.             ADD_BINCOND (NULL);
  444. @@ -6841,6 +6917,7 @@
  445.             sp = stack_start;
  446.             inline_costs += BRANCH_COST;
  447.             break;
  448. +       }
  449.         case CEE_SWITCH: {
  450.             MonoInst *src1;
  451.             MonoBasicBlock **targets;
  452. Index: mono/mini/mini.c
  453. ===================================================================
  454. --- mono/mini/mini.c    (revision 155305)
  455. +++ mono/mini/mini.c    (working copy)
  456. @@ -52,6 +52,10 @@
  457.  #include <mono/utils/mono-mmap.h>
  458.  #include <mono/utils/dtrace.h>
  459.  
  460. +#ifdef HAVE_SGEN_GC
  461. +#include <mono/metadata/sgen-gc.h>
  462. +#endif
  463. +
  464.  #include "mini.h"
  465.  #include "tasklets.h"
  466.  #include <string.h>
  467. @@ -5287,6 +5291,15 @@
  468.  
  469.     GET_CONTEXT;
  470.  
  471. +#ifdef MONO_GC_SAFE_POINTS
  472. +   if (gc_safe_point_triggered) {
  473. +       /* TODO Find a foolproof way to check this. */
  474. +       reached_gc_safe_point (context, mono_domain_get (),
  475. +               mono_arch_ip_from_context (ctx));
  476. +       return;
  477. +   }
  478. +#endif
  479. +
  480.  #if defined(MONO_ARCH_SOFT_DEBUG_SUPPORTED) && defined(HAVE_SIG_INFO)
  481.     if (mono_arch_is_single_step_event (info, ctx)) {
  482.         mono_debugger_agent_single_step_event (ctx);
RAW Paste Data
Top