sgen_stop_world (int generation)
{
  unsigned int sgen_global_stop_count.0;
  unsigned int sgen_global_stop_count.1;
  struct FILE * gc_debug_file.2;
  struct SgenThreadInfo * D.20295;
  long unsigned int D.20296;
  void * D.20297;
  long long int stop_world_time.3;
  int count.4;
  int count.5;
  int count.6;
  int D.20306;
  int count;
  int dead;

  try
    {
      sgen_process_togglerefs ();
      mono_profiler_gc_event (6, generation);
      acquire_gc_locks ();
      update_current_thread_stack (&count);
      sgen_global_stop_count.0 = sgen_global_stop_count;
      sgen_global_stop_count.1 = sgen_global_stop_count.0 + 1;
      sgen_global_stop_count = sgen_global_stop_count.1;
      if (0 != 0) goto <D.20292>; else goto <D.20293>;
      <D.20292>:
      gc_debug_file.2 = gc_debug_file;
      sgen_global_stop_count.0 = sgen_global_stop_count;
      D.20295 = mono_thread_info_current ();
      D.20296 = mono_native_thread_id_get ();
      D.20297 = (void *) D.20296;
      fprintf (gc_debug_file.2, "stopping world n %d from %p %p\n", sgen_global_stop_count.0, D.20295, D.20297);
      gc_debug_file.2 = gc_debug_file;
      fflush (gc_debug_file.2);
      <D.20293>:
      stop_world_time.3 = mono_100ns_ticks ();
      stop_world_time = stop_world_time.3;
      count.4 = sgen_thread_handshake (1);
      count = count.4;
      dead = restart_threads_until_none_in_managed_allocator ();
      count.5 = count;
      if (count.5 < dead) goto <D.20301>; else goto <D.20302>;
      <D.20301>:
      count.5 = count;
      monoeg_g_log (0B, 4, "More threads have died (%d) that been initialy suspended %d", dead, count.5);
      <D.20272>:
      goto <D.20272>;
      <D.20302>:
      count.5 = count;
      count.6 = count.5 - dead;
      count = count.6;
      if (0 != 0) goto <D.20304>; else goto <D.20305>;
      <D.20304>:
      gc_debug_file.2 = gc_debug_file;
      count.5 = count;
      fprintf (gc_debug_file.2, "world stopped %d thread(s)\n", count.5);
      gc_debug_file.2 = gc_debug_file;
      fflush (gc_debug_file.2);
      <D.20305>:
      mono_profiler_gc_event (7, generation);
      sgen_memgov_collection_start (generation);
      sgen_bridge_reset_data ();
      D.20306 = count;
      return D.20306;
    }
  finally
    {
      count = {CLOBBER};
    }
}


acquire_gc_locks ()
{
  pthread_mutex_lock (&sgen_interruption_mutex);
  mono_thread_info_suspend_lock ();
}


update_current_thread_stack (void * start)
{
  void * D.20309;
  int iftmp.7;
  void * D.20314;
  void * D.20315;
  void * D.20317;
  _Bool D.20318;
  long int D.20319;
  long int D.20320;
  int D.20323;
  struct MonoContext * D.20324;
  struct MonoGCCallbacks * D.20325;
  void (*<T346e>) (void *, void *, struct MonoContext *) D.20326;
  struct MonoGCCallbacks * D.20329;
  void (*<T346e>) (void *, void *, struct MonoContext *) D.20330;
  void * D.20331;
  int stack_guard;
  struct SgenThreadInfo * info;

  try
    {
      stack_guard = 0;
      info = mono_thread_info_current ();
      D.20309 = align_pointer (&stack_guard);
      info->stack_start = D.20309;
      D.20314 = info->stack_start;
      D.20315 = info->stack_start_limit;
      if (D.20314 < D.20315) goto <D.20311>; else goto <D.20316>;
      <D.20316>:
      D.20314 = info->stack_start;
      D.20317 = info->stack_end;
      if (D.20314 >= D.20317) goto <D.20311>; else goto <D.20312>;
      <D.20311>:
      iftmp.7 = 1;
      goto <D.20313>;
      <D.20312>:
      iftmp.7 = 0;
      <D.20313>:
      D.20318 = iftmp.7 != 0;
      D.20319 = (long int) D.20318;
      D.20320 = __builtin_expect (D.20319, 0);
      if (D.20320 != 0) goto <D.20321>; else goto <D.20322>;
      <D.20321>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-stw.c", 67, "info->stack_start >= info->stack_start_limit && info->stack_start < info->stack_end");
      <D.20322>:
      __asm__ __volatile__("push {r0}
push {r1}
mov r0, %0
ldr r1, [sp, #4]
str r1, [r0]!
ldr r1, [sp, #0]
str r1, [r0]!
stmia r0!, {r2-r12}
str sp, [r0]!
str lr, [r0]!
mov r1, pc
str r1, [r0]!
pop {r1}
pop {r0}
" :  : "r" &cur_thread_ctx.regs : "memory");
      D.20323 = cur_thread_ctx.regs[15];
      cur_thread_ctx.pc = D.20323;
      D.20324 = &info->ctx;
      memcpy (D.20324, &cur_thread_ctx, 208);
      D.20325 = mono_gc_get_gc_callbacks ();
      D.20326 = D.20325->thread_suspend_func;
      if (D.20326 != 0B) goto <D.20327>; else goto <D.20328>;
      <D.20327>:
      D.20329 = mono_gc_get_gc_callbacks ();
      D.20330 = D.20329->thread_suspend_func;
      D.20331 = info->runtime_data;
      D.20324 = &info->ctx;
      D.20330 (D.20331, 0B, D.20324);
      <D.20328>:
    }
  finally
    {
      stack_guard = {CLOBBER};
    }
}


align_pointer (void * ptr)
{
  void * D.20332;
  mword p;

  p = (mword) ptr;
  p = p + 3;
  p = p & 4294967292;
  D.20332 = (void *) p;
  return D.20332;
}


memcpy (void * restrict __dest, const void * restrict __src, size_t __len)
{
  void * D.20334;
  unsigned int D.20335;

  D.20335 = __builtin_object_size (__dest, 0);
  D.20334 = __builtin___memcpy_chk (__dest, __src, __len, D.20335);
  return D.20334;
}


restart_threads_until_none_in_managed_allocator ()
{
  struct MonoLinkedListSet * D.20337;
  struct MonoLinkedListSetNode * * D.20338;
  void * D.20339;
  struct MonoLinkedListSetNode * * D.20340;
  unsigned int D.20341;
  int D.20346;
  int D.20348;
  int D.20352;
  int D.20353;
  void * D.20355;
  int D.20357;
  int D.20359;
  struct MonoDomain * D.20361;
  void * D.20362;
  int D.20363;
  struct FILE * gc_debug_file.8;
  int D.20367;
  void * D.20368;
  long unsigned int sleep_duration.9;
  struct MonoLinkedListSet * D.20381;
  struct MonoLinkedListSetNode * D.20382;
  unsigned int D.20383;
  int D.20392;
  int D.20393;
  struct SgenThreadInfo * info;
  int num_threads_died;
  int sleep_duration;

  num_threads_died = 0;
  sleep_duration = -1;
  <D.20258>:
  {
    int restart_count;
    int restarted_count;

    restart_count = 0;
    restarted_count = 0;
    {
      struct MonoThreadHazardPointers * __hp;
      struct MonoLinkedListSetNode * __cur;
      struct MonoLinkedListSetNode * __next;

      __hp = mono_hazard_pointer_get ();
      D.20337 = mono_thread_info_list_head ();
      D.20338 = &D.20337->head;
      D.20339 = get_hazardous_pointer (D.20338, __hp, 1);
      __cur = mono_lls_pointer_unmask (D.20339);
      goto <D.20249>;
      <D.20248>:
      D.20340 = &__cur->next;
      __next = get_hazardous_pointer_with_mask (D.20340, __hp, 0);
      D.20341 = mono_lls_pointer_get_mark (__next);
      if (D.20341 == 0) goto <D.20342>; else goto <D.20343>;
      <D.20342>:
      info = __cur;
      {
        gboolean result;

        D.20346 = info->skip;
        if (D.20346 != 0) goto <D.20344>; else goto <D.20347>;
        <D.20347>:
        D.20348 = info->gc_disabled;
        if (D.20348 != 0) goto <D.20344>; else goto <D.20345>;
        <D.20344>:
        // predicted unlikely by continue predictor.
        goto <D.20247>;
        <D.20345>:
        D.20352 = MEM[(struct MonoThreadInfo *)info].thread_state;
        D.20353 = D.20352 & 15;
        if (D.20353 == 1) goto <D.20354>; else goto <D.20349>;
        <D.20354>:
        D.20355 = info->stack_start;
        if (D.20355 == 0B) goto <D.20350>; else goto <D.20356>;
        <D.20356>:
        D.20357 = info->in_critical_region;
        if (D.20357 != 0) goto <D.20350>; else goto <D.20358>;
        <D.20358>:
        D.20359 = info->info.inside_critical_region;
        if (D.20359 != 0) goto <D.20350>; else goto <D.20360>;
        <D.20360>:
        D.20361 = info->stopped_domain;
        D.20362 = info->stopped_ip;
        D.20363 = is_ip_in_managed_allocator (D.20361, D.20362);
        if (D.20363 != 0) goto <D.20350>; else goto <D.20349>;
        <D.20350>:
        if (0 != 0) goto <D.20364>; else goto <D.20365>;
        <D.20364>:
        gc_debug_file.8 = gc_debug_file;
        D.20367 = info->info.native_handle;
        D.20368 = (void *) D.20367;
        fprintf (gc_debug_file.8, "thread %p resumed.\n", D.20368);
        gc_debug_file.8 = gc_debug_file;
        fflush (gc_debug_file.8);
        <D.20365>:
        result = sgen_resume_thread (info);
        if (result != 0) goto <D.20369>; else goto <D.20370>;
        <D.20369>:
        restart_count = restart_count + 1;
        goto <D.20371>;
        <D.20370>:
        info->skip = 1;
        <D.20371>:
        goto <D.20351>;
        <D.20349>:
        info->stopped_ip = 0B;
        info->stopped_domain = 0B;
        <D.20351>:
      }
      <D.20343>:
      <D.20247>:
      __cur = mono_lls_info_step (__next, __hp);
      <D.20249>:
      if (__cur != 0B) goto <D.20248>; else goto <D.20250>;
      <D.20250>:
      if (0 != 0) goto <D.20372>; else goto <D.20373>;
      <D.20372>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-stw.c", 141, "(0) >= 0 && (0) < HAZARD_POINTER_COUNT");
      <D.20373>:
      __hp->hazard_pointers[0] = 0B;
      if (0 != 0) goto <D.20374>; else goto <D.20375>;
      <D.20374>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-stw.c", 141, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
      <D.20375>:
      __hp->hazard_pointers[1] = 0B;
    }
    if (restart_count == 0) goto <D.20251>; else goto <D.20376>;
    <D.20376>:
    sgen_wait_for_suspend_ack (restart_count);
    if (sleep_duration < 0) goto <D.20377>; else goto <D.20378>;
    <D.20377>:
    sched_yield ();
    sleep_duration = 0;
    goto <D.20379>;
    <D.20378>:
    sleep_duration.9 = (long unsigned int) sleep_duration;
    monoeg_g_usleep (sleep_duration.9);
    sleep_duration = sleep_duration + 10;
    <D.20379>:
    {
      struct MonoLinkedListSetNode * __cur;

      D.20381 = mono_thread_info_list_head ();
      __cur = D.20381->head;
      goto <D.20256>;
      <D.20255>:
      D.20382 = __cur->next;
      D.20383 = mono_lls_pointer_get_mark (D.20382);
      if (D.20383 == 0) goto <D.20384>; else goto <D.20385>;
      <D.20384>:
      info = __cur;
      {
        gboolean result;

        D.20346 = info->skip;
        if (D.20346 != 0) goto <D.20386>; else goto <D.20388>;
        <D.20388>:
        D.20362 = info->stopped_ip;
        if (D.20362 == 0B) goto <D.20386>; else goto <D.20387>;
        <D.20386>:
        // predicted unlikely by continue predictor.
        goto <D.20254>;
        <D.20387>:
        result = sgen_suspend_thread (info);
        if (result != 0) goto <D.20389>; else goto <D.20390>;
        <D.20389>:
        restarted_count = restarted_count + 1;
        goto <D.20391>;
        <D.20390>:
        info->skip = 1;
        <D.20391>:
      }
      <D.20385>:
      <D.20254>:
      D.20382 = __cur->next;
      __cur = mono_lls_pointer_unmask (D.20382);
      <D.20256>:
      if (__cur != 0B) goto <D.20255>; else goto <D.20257>;
      <D.20257>:
    }
    D.20392 = restart_count - restarted_count;
    num_threads_died = D.20392 + num_threads_died;
    sgen_wait_for_suspend_ack (restarted_count);
  }
  goto <D.20258>;
  <D.20251>:
  D.20393 = num_threads_died;
  return D.20393;
}


is_ip_in_managed_allocator (struct MonoDomain * domain, void * ip)
{
  struct MonoInternalThread * D.20395;
  gboolean D.20398;
  _Bool D.20399;
  _Bool D.20400;
  _Bool D.20401;
  int D.20404;
  struct MonoMethod * D.20409;
  struct MonoJitInfo * ji;

  D.20395 = mono_thread_internal_current ();
  if (D.20395 == 0B) goto <D.20396>; else goto <D.20397>;
  <D.20396>:
  D.20398 = 0;
  return D.20398;
  <D.20397>:
  D.20399 = ip == 0B;
  D.20400 = domain == 0B;
  D.20401 = D.20399 | D.20400;
  if (D.20401 != 0) goto <D.20402>; else goto <D.20403>;
  <D.20402>:
  D.20398 = 0;
  return D.20398;
  <D.20403>:
  D.20404 = sgen_has_critical_method ();
  if (D.20404 == 0) goto <D.20405>; else goto <D.20406>;
  <D.20405>:
  D.20398 = 0;
  return D.20398;
  <D.20406>:
  ji = mono_jit_info_table_find_internal (domain, ip, 0);
  if (ji == 0B) goto <D.20407>; else goto <D.20408>;
  <D.20407>:
  D.20398 = 0;
  return D.20398;
  <D.20408>:
  D.20409 = mono_jit_info_get_method (ji);
  D.20398 = sgen_is_critical_method (D.20409);
  return D.20398;
}


mono_lls_info_step (struct MonoLinkedListSetNode * val, struct MonoThreadHazardPointers * hp)
{
  struct MonoLinkedListSetNode * D.20413;

  val = mono_lls_pointer_unmask (val);
  if (0 != 0) goto <D.20411>; else goto <D.20412>;
  <D.20411>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "../../mono/utils/mono-linked-list-set.h", 77, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.20412>:
  hp->hazard_pointers[1] = val;
  mono_memory_write_barrier ();
  D.20413 = val;
  return D.20413;
}


mono_memory_write_barrier ()
{
  mono_memory_barrier ();
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


mono_lls_pointer_get_mark (void * n)
{
  uintptr_t D.20415;
  unsigned int n.10;

  n.10 = (unsigned int) n;
  D.20415 = n.10 & 1;
  return D.20415;
}


mono_lls_pointer_unmask (void * p)
{
  void * D.20418;
  unsigned int p.11;
  unsigned int D.20420;

  p.11 = (unsigned int) p;
  D.20420 = p.11 & 4294967292;
  D.20418 = (void *) D.20420;
  return D.20418;
}


sgen_restart_world (int generation, struct GGTimingInfo * timing)
{
  <unnamed type> mono_profiler_events.12;
  unsigned int D.20423;
  _Bool D.20424;
  long int D.20425;
  long int D.20426;
  struct MonoLinkedListSet * D.20429;
  struct MonoLinkedListSetNode * D.20430;
  unsigned int D.20431;
  struct MonoContext * D.20434;
  long long int stop_world_time.13;
  long long int D.20436;
  long long int D.20437;
  long unsigned int max_pause_usec.14;
  long unsigned int max_pause_usec.15;
  int gc_debug_level.16;
  _Bool D.20441;
  long int D.20442;
  long int D.20443;
  struct FILE * gc_debug_file.17;
  int usec.18;
  int max_pause_usec.19;
  long long int D.20449;
  long long int D.20450;
  long long int D.20453;
  long long int D.20454;
  int iftmp.20;
  int D.20459;
  int count;
  struct SgenThreadInfo * info;
  gint64 end_sw;
  gint64 end_bridge;
  long unsigned int usec;
  long unsigned int bridge_usec;

  mono_profiler_events.12 = mono_profiler_events;
  D.20423 = mono_profiler_events.12 & 524288;
  D.20424 = D.20423 != 0;
  D.20425 = (long int) D.20424;
  D.20426 = __builtin_expect (D.20425, 0);
  if (D.20426 != 0) goto <D.20427>; else goto <D.20428>;
  <D.20427>:
  sgen_gc_event_moves ();
  <D.20428>:
  mono_profiler_gc_event (8, generation);
  {
    struct MonoLinkedListSetNode * __cur;

    D.20429 = mono_thread_info_list_head ();
    __cur = D.20429->head;
    goto <D.20285>;
    <D.20284>:
    D.20430 = __cur->next;
    D.20431 = mono_lls_pointer_get_mark (D.20430);
    if (D.20431 == 0) goto <D.20432>; else goto <D.20433>;
    <D.20432>:
    info = __cur;
    info->stack_start = 0B;
    D.20434 = &info->ctx;
    memset (D.20434, 0, 208);
    <D.20433>:
    D.20430 = __cur->next;
    __cur = mono_lls_pointer_unmask (D.20430);
    <D.20285>:
    if (__cur != 0B) goto <D.20284>; else goto <D.20286>;
    <D.20286>:
  }
  count = sgen_thread_handshake (0);
  end_sw = mono_100ns_ticks ();
  stop_world_time.13 = stop_world_time;
  D.20436 = end_sw - stop_world_time.13;
  D.20437 = D.20436 / 10;
  usec = (long unsigned int) D.20437;
  max_pause_usec.14 = max_pause_usec;
  max_pause_usec.15 = MAX_EXPR <max_pause_usec.14, usec>;
  max_pause_usec = max_pause_usec.15;
  gc_debug_level.16 = gc_debug_level;
  D.20441 = gc_debug_level.16 > 1;
  D.20442 = (long int) D.20441;
  D.20443 = __builtin_expect (D.20442, 0);
  if (D.20443 != 0) goto <D.20444>; else goto <D.20445>;
  <D.20444>:
  gc_debug_file.17 = gc_debug_file;
  usec.18 = (int) usec;
  max_pause_usec.14 = max_pause_usec;
  max_pause_usec.19 = (int) max_pause_usec.14;
  fprintf (gc_debug_file.17, "restarted %d thread(s) (pause time: %d usec, max: %d)\n", count, usec.18, max_pause_usec.19);
  gc_debug_file.17 = gc_debug_file;
  fflush (gc_debug_file.17);
  <D.20445>:
  mono_profiler_gc_event (9, generation);
  release_gc_locks ();
  sgen_try_free_some_memory = 1;
  sgen_bridge_processing_finish (generation);
  end_bridge = mono_100ns_ticks ();
  D.20449 = end_bridge - end_sw;
  D.20450 = D.20449 / 10;
  bridge_usec = (long unsigned int) D.20450;
  if (timing != 0B) goto <D.20451>; else goto <D.20452>;
  <D.20451>:
  D.20453 = (long long int) usec;
  timing->stw_time = D.20453;
  D.20454 = (long long int) bridge_usec;
  timing->bridge_time = D.20454;
  <D.20452>:
  if (timing != 0B) goto <D.20456>; else goto <D.20457>;
  <D.20456>:
  iftmp.20 = 2;
  goto <D.20458>;
  <D.20457>:
  iftmp.20 = 0;
  <D.20458>:
  sgen_memgov_collection_end (generation, timing, iftmp.20);
  D.20459 = count;
  return D.20459;
}


memset (void * __dest, int __ch, size_t __len)
{
  int D.20463;
  int D.20468;
  void * D.20470;
  unsigned int D.20471;

  D.20463 = __builtin_constant_p (__len);
  if (D.20463 != 0) goto <D.20464>; else goto <D.20465>;
  <D.20464>:
  if (__len == 0) goto <D.20466>; else goto <D.20467>;
  <D.20466>:
  D.20468 = __builtin_constant_p (__ch);
  if (D.20468 == 0) goto <D.20461>; else goto <D.20469>;
  <D.20469>:
  if (__ch != 0) goto <D.20461>; else goto <D.20462>;
  <D.20461>:
  __warn_memset_zero_len ();
  D.20470 = __dest;
  return D.20470;
  <D.20462>:
  <D.20467>:
  <D.20465>:
  D.20471 = __builtin_object_size (__dest, 0);
  D.20470 = __builtin___memset_chk (__dest, __ch, __len, D.20471);
  return D.20470;
}


fprintf (struct FILE * restrict __stream, const char * restrict __fmt)
{
  int D.20473;

  D.20473 = __fprintf_chk (__stream, 1, __fmt, __builtin_va_arg_pack ());
  return D.20473;
}


release_gc_locks ()
{
  mono_thread_info_suspend_unlock ();
  pthread_mutex_unlock (&sgen_interruption_mutex);
}


