sgen_workers_wake_up_all ()
{
  <unnamed-unsigned:1> D.20010;
  _Bool D.20011;
  long int D.20012;
  long int D.20013;

  D.20010 = workers_state.data.gc_in_progress;
  D.20011 = ~D.20010;
  D.20012 = (long int) D.20011;
  D.20013 = __builtin_expect (D.20012, 0);
  if (D.20013 != 0) goto <D.20014>; else goto <D.20015>;
  <D.20014>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 109, "workers_state.data.gc_in_progress");
  <D.20015>:
  workers_wake_up_all ();
}


workers_wake_up_all ()
{
  int workers_num.0;

  workers_num.0 = workers_num;
  workers_wake_up (workers_num.0);
}


workers_wake_up (int max)
{
  unsigned char D.20017;
  unsigned char D.20018;
  unsigned char D.20021;
  unsigned char D.20024;
  unsigned char D.20025;
  int D.20026;
  int i;

  i = 0;
  goto <D.19852>;
  <D.19851>:
  {
    union State old_state;
    union State new_state;

    try
      {
        <D.19849>:
        new_state = workers_state;
        old_state = new_state;
        D.20017 = BIT_FIELD_REF <old_state, 8, 8>;
        D.20018 = D.20017 & 1;
        if (D.20018 != 0) goto <D.20019>; else goto <D.20020>;
        <D.20019>:
        return;
        <D.20020>:
        D.20021 = old_state.data.num_waiting;
        if (D.20021 == 0) goto <D.20022>; else goto <D.20023>;
        <D.20022>:
        return;
        <D.20023>:
        D.20024 = new_state.data.num_waiting;
        D.20025 = D.20024 + 255;
        new_state.data.num_waiting = D.20025;
        D.20026 = set_state (old_state, new_state);
        if (D.20026 == 0) goto <D.19849>; else goto <D.19850>;
        <D.19850>:
        mono_sem_post (&workers_waiting_sem);
      }
    finally
      {
        old_state = {CLOBBER};
        new_state = {CLOBBER};
      }
  }
  i = i + 1;
  <D.19852>:
  if (i < max) goto <D.19851>; else goto <D.19853>;
  <D.19853>:
}


set_state (union State old_state, union State new_state)
{
  gboolean D.20030;
  int D.20031;
  int D.20032;
  int D.20033;
  _Bool D.20034;

  D.20031 = new_state.value;
  D.20032 = old_state.value;
  D.20033 = InterlockedCompareExchange (&workers_state.value, D.20031, D.20032);
  D.20032 = old_state.value;
  D.20034 = D.20033 == D.20032;
  D.20030 = (gboolean) D.20034;
  return D.20030;
}


InterlockedCompareExchange (volatile gint32 * dest, gint32 exch, gint32 comp)
{
  gint32 D.20036;
  unsigned int comp.1;
  unsigned int exch.2;
  unsigned int D.20039;

  comp.1 = (unsigned int) comp;
  exch.2 = (unsigned int) exch;
  D.20039 = __sync_val_compare_and_swap_4 (dest, comp.1, exch.2);
  D.20036 = (gint32) D.20039;
  return D.20036;
}


sgen_workers_enqueue_job (void (*JobFunc) (struct WorkerData *, void *) func, void * data)
{
  int D.20041;
  <unnamed-unsigned:1> D.20044;
  _Bool D.20045;
  long int D.20046;
  long int D.20047;
  volatile struct JobQueueEntry * workers_job_queue.3;
  int workers_job_queue_num_entries.4;
  int workers_job_queue_num_entries.5;
  int workers_job_queue_num_entries.6;
  int workers_num_jobs_enqueued.7;
  int workers_num_jobs_enqueued.8;
  int num_entries;
  struct JobQueueEntry * entry;

  D.20041 = collection_needs_workers ();
  if (D.20041 == 0) goto <D.20042>; else goto <D.20043>;
  <D.20042>:
  func (0B, data);
  return;
  <D.20043>:
  D.20044 = workers_state.data.gc_in_progress;
  D.20045 = ~D.20044;
  D.20046 = (long int) D.20045;
  D.20047 = __builtin_expect (D.20046, 0);
  if (D.20047 != 0) goto <D.20048>; else goto <D.20049>;
  <D.20048>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 157, "workers_state.data.gc_in_progress");
  <D.20049>:
  entry = sgen_alloc_internal (26);
  entry->func = func;
  entry->data = data;
  pthread_mutex_lock (&workers_job_queue_mutex);
  workers_job_queue.3 = workers_job_queue;
  entry->next = workers_job_queue.3;
  workers_job_queue = entry;
  workers_job_queue_num_entries.4 = workers_job_queue_num_entries;
  workers_job_queue_num_entries.5 = workers_job_queue_num_entries.4 + 1;
  workers_job_queue_num_entries.6 = workers_job_queue_num_entries.5;
  workers_job_queue_num_entries = workers_job_queue_num_entries.6;
  num_entries = workers_job_queue_num_entries.6;
  workers_num_jobs_enqueued.7 = workers_num_jobs_enqueued;
  workers_num_jobs_enqueued.8 = workers_num_jobs_enqueued.7 + 1;
  workers_num_jobs_enqueued = workers_num_jobs_enqueued.8;
  pthread_mutex_unlock (&workers_job_queue_mutex);
  workers_wake_up (num_entries);
}


collection_needs_workers ()
{
  gboolean D.20057;
  int iftmp.9;
  int D.20062;
  int D.20064;

  D.20062 = sgen_collection_is_parallel ();
  if (D.20062 != 0) goto <D.20059>; else goto <D.20063>;
  <D.20063>:
  D.20064 = sgen_collection_is_concurrent ();
  if (D.20064 != 0) goto <D.20059>; else goto <D.20060>;
  <D.20059>:
  iftmp.9 = 1;
  goto <D.20061>;
  <D.20060>:
  iftmp.9 = 0;
  <D.20061>:
  D.20057 = iftmp.9;
  return D.20057;
}


sgen_workers_wait_for_jobs ()
{
  unsigned char D.20066;
  unsigned char D.20067;
  _Bool D.20068;
  long int D.20069;
  long int D.20070;
  unsigned char D.20073;
  _Bool D.20074;
  long int D.20075;
  long int D.20076;
  unsigned char D.20079;
  int D.20080;
  int workers_num.10;
  int workers_num_jobs_finished.11;
  int workers_num_jobs_enqueued.12;

  goto <D.19881>;
  <D.19880>:
  {
    union State state;

    try
      {
        state = workers_state;
        D.20066 = BIT_FIELD_REF <state, 8, 8>;
        D.20067 = D.20066 & 2;
        D.20068 = D.20067 == 0;
        D.20069 = (long int) D.20068;
        D.20070 = __builtin_expect (D.20069, 0);
        if (D.20070 != 0) goto <D.20071>; else goto <D.20072>;
        <D.20071>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 179, "state.data.gc_in_progress");
        <D.20072>:
        D.20066 = BIT_FIELD_REF <state, 8, 8>;
        D.20073 = D.20066 & 1;
        D.20074 = D.20073 != 0;
        D.20075 = (long int) D.20074;
        D.20076 = __builtin_expect (D.20075, 0);
        if (D.20076 != 0) goto <D.20077>; else goto <D.20078>;
        <D.20077>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 180, "!state.data.done_posted");
        <D.20078>:
        D.20079 = state.data.num_waiting;
        D.20080 = (int) D.20079;
        workers_num.10 = workers_num;
        if (D.20080 == workers_num.10) goto <D.20082>; else goto <D.20083>;
        <D.20082>:
        workers_wake_up_all ();
        <D.20083>:
        monoeg_g_usleep (1000);
      }
    finally
      {
        state = {CLOBBER};
      }
  }
  <D.19881>:
  workers_num_jobs_finished.11 = workers_num_jobs_finished;
  workers_num_jobs_enqueued.12 = workers_num_jobs_enqueued;
  if (workers_num_jobs_finished.11 < workers_num_jobs_enqueued.12) goto <D.19880>; else goto <D.19882>;
  <D.19882>:
}


sgen_workers_init_distribute_gray_queue ()
{
  int D.20086;
  int iftmp.13;
  struct SgenMajorCollector * D.20093;
  int D.20094;
  struct SgenMajorCollector * D.20096;
  int D.20097;

  D.20086 = collection_needs_workers ();
  if (D.20086 == 0) goto <D.20087>; else goto <D.20088>;
  <D.20087>:
  return;
  <D.20088>:
  D.20093 = sgen_get_major_collector ();
  D.20094 = D.20093->is_concurrent;
  if (D.20094 != 0) goto <D.20090>; else goto <D.20095>;
  <D.20095>:
  D.20096 = sgen_get_major_collector ();
  D.20097 = D.20096->is_parallel;
  if (D.20097 != 0) goto <D.20090>; else goto <D.20091>;
  <D.20090>:
  iftmp.13 = 1;
  goto <D.20092>;
  <D.20091>:
  iftmp.13 = 0;
  <D.20092>:
  init_distribute_gray_queue (iftmp.13);
}


init_distribute_gray_queue (gboolean locked)
{
  int workers_distribute_gray_queue_inited.14;
  int D.20102;
  _Bool D.20103;
  long int D.20104;
  long int D.20105;
  int D.20108;
  _Bool D.20109;
  _Bool D.20110;
  _Bool D.20111;
  long int D.20112;
  long int D.20113;
  void (*<T34ff>) (char *) iftmp.15;
  struct SgenMajorCollector * D.20117;
  int D.20118;

  workers_distribute_gray_queue_inited.14 = workers_distribute_gray_queue_inited;
  if (workers_distribute_gray_queue_inited.14 != 0) goto <D.20100>; else goto <D.20101>;
  <D.20100>:
  D.20102 = sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue);
  D.20103 = D.20102 == 0;
  D.20104 = (long int) D.20103;
  D.20105 = __builtin_expect (D.20104, 0);
  if (D.20105 != 0) goto <D.20106>; else goto <D.20107>;
  <D.20106>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 419, "sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue)");
  <D.20107>:
  D.20108 = workers_distribute_gray_queue.locked;
  D.20109 = D.20108 == 0;
  D.20110 = locked == 0;
  D.20111 = D.20109 ^ D.20110;
  D.20112 = (long int) D.20111;
  D.20113 = __builtin_expect (D.20112, 0);
  if (D.20113 != 0) goto <D.20114>; else goto <D.20115>;
  <D.20114>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 420, "!workers_distribute_gray_queue.locked == !locked");
  <D.20115>:
  return;
  <D.20101>:
  D.20117 = sgen_get_major_collector ();
  D.20118 = D.20117->is_concurrent;
  if (D.20118 != 0) goto <D.20119>; else goto <D.20120>;
  <D.20119>:
  iftmp.15 = concurrent_enqueue_check;
  goto <D.20121>;
  <D.20120>:
  iftmp.15 = 0B;
  <D.20121>:
  sgen_section_gray_queue_init (&workers_distribute_gray_queue, locked, iftmp.15);
  workers_distribute_gray_queue_inited = 1;
}


concurrent_enqueue_check (char * obj)
{
  int D.20123;
  _Bool D.20124;
  long int D.20125;
  long int D.20126;
  int D.20129;
  _Bool D.20130;
  long int D.20131;
  long int D.20132;
  unsigned int D.20135;
  unsigned int D.20136;
  _Bool D.20137;
  long int D.20138;
  long int D.20139;

  D.20123 = sgen_concurrent_collection_in_progress ();
  D.20124 = D.20123 == 0;
  D.20125 = (long int) D.20124;
  D.20126 = __builtin_expect (D.20125, 0);
  if (D.20126 != 0) goto <D.20127>; else goto <D.20128>;
  <D.20127>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 356, "sgen_concurrent_collection_in_progress ()");
  <D.20128>:
  D.20129 = sgen_ptr_in_nursery (obj);
  D.20130 = D.20129 != 0;
  D.20131 = (long int) D.20130;
  D.20132 = __builtin_expect (D.20131, 0);
  if (D.20132 != 0) goto <D.20133>; else goto <D.20134>;
  <D.20133>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 357, "!sgen_ptr_in_nursery (obj)");
  <D.20134>:
  D.20135 = MEM[(mword *)obj];
  D.20136 = D.20135 & 4294967292;
  D.20137 = D.20136 == 0;
  D.20138 = (long int) D.20137;
  D.20139 = __builtin_expect (D.20138, 0);
  if (D.20139 != 0) goto <D.20140>; else goto <D.20141>;
  <D.20140>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 358, "SGEN_LOAD_VTABLE (obj)");
  <D.20141>:
}


sgen_ptr_in_nursery (void * p)
{
  gboolean D.20142;
  int sgen_nursery_bits.16;
  int D.20144;
  int D.20145;
  unsigned int D.20146;
  unsigned int p.17;
  unsigned int D.20148;
  char * sgen_nursery_start.18;
  unsigned int sgen_nursery_start.19;
  _Bool D.20151;

  sgen_nursery_bits.16 = sgen_nursery_bits;
  D.20144 = 1 << sgen_nursery_bits.16;
  D.20145 = -D.20144;
  D.20146 = (unsigned int) D.20145;
  p.17 = (unsigned int) p;
  D.20148 = D.20146 & p.17;
  sgen_nursery_start.18 = sgen_nursery_start;
  sgen_nursery_start.19 = (unsigned int) sgen_nursery_start.18;
  D.20151 = D.20148 == sgen_nursery_start.19;
  D.20142 = (gboolean) D.20151;
  return D.20142;
}


sgen_workers_init (int num_workers)
{
  struct SgenMajorCollector * D.20153;
  int D.20154;
  struct SgenMajorCollector * D.20157;
  int D.20158;
  unsigned int num_workers.20;
  unsigned int D.20162;
  void * workers_data.21;
  struct WorkerData * workers_data.22;
  int iftmp.23;
  struct SgenMajorCollector * D.20169;
  int D.20170;
  struct SgenMajorCollector * D.20172;
  int D.20173;
  struct SgenMajorCollector * D.20174;
  void * (*<T3469>) (void) D.20175;
  struct SgenMajorCollector * D.20178;
  void * (*<T3469>) (void) D.20179;
  void * workers_gc_thread_major_collector_data.24;
  unsigned int i.25;
  unsigned int D.20182;
  struct WorkerData * D.20183;
  union mono_mutex_t * D.20184;
  struct SgenMajorCollector * D.20185;
  void * (*<T3469>) (void) D.20186;
  struct SgenMajorCollector * D.20189;
  void * (*<T3469>) (void) D.20190;
  void * D.20191;
  int workers_num.26;
  int i;

  D.20153 = sgen_get_major_collector ();
  D.20154 = D.20153->is_parallel;
  if (D.20154 == 0) goto <D.20155>; else goto <D.20156>;
  <D.20155>:
  D.20157 = sgen_get_major_collector ();
  D.20158 = D.20157->is_concurrent;
  if (D.20158 == 0) goto <D.20159>; else goto <D.20160>;
  <D.20159>:
  return;
  <D.20160>:
  <D.20156>:
  workers_num = num_workers;
  num_workers.20 = (unsigned int) num_workers;
  D.20162 = num_workers.20 * 2100;
  workers_data.21 = sgen_alloc_internal_dynamic (D.20162, 19, 1);
  workers_data = workers_data.21;
  workers_data.22 = workers_data;
  num_workers.20 = (unsigned int) num_workers;
  D.20162 = num_workers.20 * 2100;
  memset (workers_data.22, 0, D.20162);
  sem_init (&workers_waiting_sem, 0, 0);
  sem_init (&workers_done_sem, 0, 0);
  D.20169 = sgen_get_major_collector ();
  D.20170 = D.20169->is_concurrent;
  if (D.20170 != 0) goto <D.20166>; else goto <D.20171>;
  <D.20171>:
  D.20172 = sgen_get_major_collector ();
  D.20173 = D.20172->is_parallel;
  if (D.20173 != 0) goto <D.20166>; else goto <D.20167>;
  <D.20166>:
  iftmp.23 = 1;
  goto <D.20168>;
  <D.20167>:
  iftmp.23 = 0;
  <D.20168>:
  init_distribute_gray_queue (iftmp.23);
  D.20174 = sgen_get_major_collector ();
  D.20175 = D.20174->alloc_worker_data;
  if (D.20175 != 0B) goto <D.20176>; else goto <D.20177>;
  <D.20176>:
  D.20178 = sgen_get_major_collector ();
  D.20179 = D.20178->alloc_worker_data;
  workers_gc_thread_major_collector_data.24 = D.20179 ();
  workers_gc_thread_major_collector_data = workers_gc_thread_major_collector_data.24;
  <D.20177>:
  i = 0;
  goto <D.19954>;
  <D.19953>:
  workers_data.22 = workers_data;
  i.25 = (unsigned int) i;
  D.20182 = i.25 * 2100;
  D.20183 = workers_data.22 + D.20182;
  D.20184 = &D.20183->stealable_stack_mutex;
  pthread_mutex_init (D.20184, 0B);
  workers_data.22 = workers_data;
  i.25 = (unsigned int) i;
  D.20182 = i.25 * 2100;
  D.20183 = workers_data.22 + D.20182;
  D.20183->stealable_stack_fill = 0;
  D.20185 = sgen_get_major_collector ();
  D.20186 = D.20185->alloc_worker_data;
  if (D.20186 != 0B) goto <D.20187>; else goto <D.20188>;
  <D.20187>:
  workers_data.22 = workers_data;
  i.25 = (unsigned int) i;
  D.20182 = i.25 * 2100;
  D.20183 = workers_data.22 + D.20182;
  D.20189 = sgen_get_major_collector ();
  D.20190 = D.20189->alloc_worker_data;
  D.20191 = D.20190 ();
  D.20183->major_collector_data = D.20191;
  <D.20188>:
  i = i + 1;
  <D.19954>:
  workers_num.26 = workers_num;
  if (i < workers_num.26) goto <D.19953>; else goto <D.19955>;
  <D.19955>:
  pthread_mutex_init (&workers_job_queue_mutex, 0B);
  sgen_register_fixed_internal_mem_type (26, 12);
  mono_counters_register ("Stolen from self lock", 515, &stat_workers_stolen_from_self_lock);
  mono_counters_register ("Stolen from self no lock", 515, &stat_workers_stolen_from_self_no_lock);
  mono_counters_register ("Stolen from others", 515, &stat_workers_stolen_from_others);
  mono_counters_register ("# workers waited", 515, &stat_workers_num_waited);
}


memset (void * __dest, int __ch, size_t __len)
{
  int D.20196;
  int D.20201;
  void * D.20203;
  unsigned int D.20204;

  D.20196 = __builtin_constant_p (__len);
  if (D.20196 != 0) goto <D.20197>; else goto <D.20198>;
  <D.20197>:
  if (__len == 0) goto <D.20199>; else goto <D.20200>;
  <D.20199>:
  D.20201 = __builtin_constant_p (__ch);
  if (D.20201 == 0) goto <D.20194>; else goto <D.20202>;
  <D.20202>:
  if (__ch != 0) goto <D.20194>; else goto <D.20195>;
  <D.20194>:
  __warn_memset_zero_len ();
  D.20203 = __dest;
  return D.20203;
  <D.20195>:
  <D.20200>:
  <D.20198>:
  D.20204 = __builtin_object_size (__dest, 0);
  D.20203 = __builtin___memset_chk (__dest, __ch, __len, D.20204);
  return D.20203;
}


sgen_workers_start_all_workers ()
{
  int D.20206;
  struct SgenMajorCollector * D.20209;
  void (*<Tc1>) (void *) D.20210;
  struct SgenMajorCollector * D.20213;
  void (*<Tc1>) (void *) D.20214;
  void * workers_gc_thread_major_collector_data.27;
  unsigned char D.20216;
  unsigned char D.20217;
  _Bool D.20218;
  long int D.20219;
  long int D.20220;
  int workers_job_queue_num_entries.28;
  _Bool D.20224;
  long int D.20225;
  long int D.20226;
  int workers_started.29;
  unsigned char D.20232;
  _Bool D.20233;
  long int D.20234;
  long int D.20235;
  unsigned char D.20238;
  int D.20239;
  int workers_num.30;
  int D.20243;
  _Bool D.20246;
  long int D.20247;
  long int D.20248;
  int D.20251;
  union State old_state;
  union State new_state;
  int i;

  try
    {
      D.20206 = collection_needs_workers ();
      if (D.20206 == 0) goto <D.20207>; else goto <D.20208>;
      <D.20207>:
      return;
      <D.20208>:
      D.20209 = sgen_get_major_collector ();
      D.20210 = D.20209->init_worker_thread;
      if (D.20210 != 0B) goto <D.20211>; else goto <D.20212>;
      <D.20211>:
      D.20213 = sgen_get_major_collector ();
      D.20214 = D.20213->init_worker_thread;
      workers_gc_thread_major_collector_data.27 = workers_gc_thread_major_collector_data;
      D.20214 (workers_gc_thread_major_collector_data.27);
      <D.20212>:
      new_state = workers_state;
      old_state = new_state;
      D.20216 = BIT_FIELD_REF <old_state, 8, 8>;
      D.20217 = D.20216 & 2;
      D.20218 = D.20217 != 0;
      D.20219 = (long int) D.20218;
      D.20220 = __builtin_expect (D.20219, 0);
      if (D.20220 != 0) goto <D.20221>; else goto <D.20222>;
      <D.20221>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 504, "!old_state.data.gc_in_progress");
      <D.20222>:
      new_state.data.gc_in_progress = 1;
      workers_marking = 0;
      workers_job_queue_num_entries.28 = workers_job_queue_num_entries;
      D.20224 = workers_job_queue_num_entries.28 != 0;
      D.20225 = (long int) D.20224;
      D.20226 = __builtin_expect (D.20225, 0);
      if (D.20226 != 0) goto <D.20227>; else goto <D.20228>;
      <D.20227>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 509, "workers_job_queue_num_entries == 0");
      <D.20228>:
      workers_num_jobs_enqueued = 0;
      workers_num_jobs_finished = 0;
      workers_started.29 = workers_started;
      if (workers_started.29 != 0) goto <D.20230>; else goto <D.20231>;
      <D.20230>:
      D.20216 = BIT_FIELD_REF <old_state, 8, 8>;
      D.20232 = D.20216 & 1;
      D.20233 = D.20232 == 0;
      D.20234 = (long int) D.20233;
      D.20235 = __builtin_expect (D.20234, 0);
      if (D.20235 != 0) goto <D.20236>; else goto <D.20237>;
      <D.20236>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 514, "old_state.data.done_posted");
      <D.20237>:
      D.20238 = old_state.data.num_waiting;
      D.20239 = (int) D.20238;
      workers_num.30 = workers_num;
      if (D.20239 != workers_num.30) goto <D.20241>; else goto <D.20242>;
      <D.20241>:
      workers_num.30 = workers_num;
      D.20238 = old_state.data.num_waiting;
      D.20239 = (int) D.20238;
      monoeg_g_log (0B, 4, "Expecting all %d sgen workers to be parked, but only %d are", workers_num.30, D.20239);
      <D.19965>:
      goto <D.19965>;
      <D.20242>:
      new_state.data.done_posted = 0;
      D.20243 = set_state (old_state, new_state);
      if (D.20243 == 0) goto <D.20244>; else goto <D.20245>;
      <D.20244>:
      monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "sgen-workers.c", 523);
      <D.20245>:
      workers_wake_up_all ();
      return;
      <D.20231>:
      D.20216 = BIT_FIELD_REF <old_state, 8, 8>;
      D.20232 = D.20216 & 1;
      D.20246 = D.20232 != 0;
      D.20247 = (long int) D.20246;
      D.20248 = __builtin_expect (D.20247, 0);
      if (D.20248 != 0) goto <D.20249>; else goto <D.20250>;
      <D.20249>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 529, "!old_state.data.done_posted");
      <D.20250>:
      D.20251 = set_state (old_state, new_state);
      if (D.20251 == 0) goto <D.20252>; else goto <D.20253>;
      <D.20252>:
      monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "sgen-workers.c", 532);
      <D.20253>:
      i = 0;
      goto <D.19967>;
      <D.19966>:
      workers_start_worker (i);
      i = i + 1;
      <D.19967>:
      workers_num.30 = workers_num;
      if (i < workers_num.30) goto <D.19966>; else goto <D.19968>;
      <D.19968>:
      workers_started = 1;
    }
  finally
    {
      old_state = {CLOBBER};
      new_state = {CLOBBER};
    }
}


workers_start_worker (int index)
{
  int iftmp.31;
  int workers_num.32;
  _Bool D.20263;
  long int D.20264;
  long int D.20265;
  struct WorkerData * workers_data.33;
  unsigned int index.34;
  unsigned int D.20270;
  struct WorkerData * D.20271;
  long unsigned int D.20272;
  _Bool D.20273;
  long int D.20274;
  long int D.20275;
  MonoNativeThreadId * D.20278;
  void * D.20279;

  if (index < 0) goto <D.20258>; else goto <D.20261>;
  <D.20261>:
  workers_num.32 = workers_num;
  if (index >= workers_num.32) goto <D.20258>; else goto <D.20259>;
  <D.20258>:
  iftmp.31 = 1;
  goto <D.20260>;
  <D.20259>:
  iftmp.31 = 0;
  <D.20260>:
  D.20263 = iftmp.31 != 0;
  D.20264 = (long int) D.20263;
  D.20265 = __builtin_expect (D.20264, 0);
  if (D.20265 != 0) goto <D.20266>; else goto <D.20267>;
  <D.20266>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 485, "index >= 0 && index < workers_num");
  <D.20267>:
  workers_data.33 = workers_data;
  index.34 = (unsigned int) index;
  D.20270 = index.34 * 2100;
  D.20271 = workers_data.33 + D.20270;
  D.20272 = D.20271->thread;
  D.20273 = D.20272 != 0;
  D.20274 = (long int) D.20273;
  D.20275 = __builtin_expect (D.20274, 0);
  if (D.20275 != 0) goto <D.20276>; else goto <D.20277>;
  <D.20276>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 487, "!workers_data [index].thread");
  <D.20277>:
  workers_data.33 = workers_data;
  index.34 = (unsigned int) index;
  D.20270 = index.34 * 2100;
  D.20271 = workers_data.33 + D.20270;
  D.20278 = &D.20271->thread;
  workers_data.33 = workers_data;
  index.34 = (unsigned int) index;
  D.20270 = index.34 * 2100;
  D.20279 = workers_data.33 + D.20270;
  mono_native_thread_create (D.20278, workers_thread_func, D.20279);
}


workers_thread_func (void * data_untyped)
{
  void (*<Tc1>) (void *) D.20280;
  void * D.20283;
  int D.20284;
  int workers_marking.35;
  struct SgenGrayQueue * D.20290;
  int D.20291;
  int D.20293;
  struct SgenObjectOperations * iftmp.36;
  int D.20295;
  void (*<T35be>) (char *, struct SgenGrayQueue *) D.20299;
  int D.20300;
  _Bool D.20301;
  long int D.20302;
  long int D.20303;
  int D.20306;
  int D.20307;
  _Bool D.20308;
  long int D.20309;
  long int D.20310;
  void * D.20315;
  struct WorkerData * data;
  struct SgenMajorCollector * major;

  data = data_untyped;
  major = sgen_get_major_collector ();
  mono_thread_info_register_small_id ();
  D.20280 = major->init_worker_thread;
  if (D.20280 != 0B) goto <D.20281>; else goto <D.20282>;
  <D.20281>:
  D.20280 = major->init_worker_thread;
  D.20283 = data->major_collector_data;
  D.20280 (D.20283);
  <D.20282>:
  init_private_gray_queue (data);
  <D.19942>:
  {
    gboolean did_work;

    did_work = 0;
    goto <D.19935>;
    <D.19934>:
    did_work = 1;
    <D.19935>:
    D.20284 = workers_dequeue_and_do_job (data);
    if (D.20284 != 0) goto <D.19934>; else goto <D.19936>;
    <D.19936>:
    workers_marking.35 = workers_marking;
    if (workers_marking.35 != 0) goto <D.20288>; else goto <D.20289>;
    <D.20288>:
    D.20290 = &data->private_gray_queue;
    D.20291 = sgen_gray_object_queue_is_empty (D.20290);
    if (D.20291 == 0) goto <D.20285>; else goto <D.20292>;
    <D.20292>:
    D.20293 = workers_get_work (data);
    if (D.20293 != 0) goto <D.20285>; else goto <D.20286>;
    <D.20285>:
    {
      struct SgenObjectOperations * ops;
      struct ScanCopyContext ctx;

      try
        {
          D.20295 = sgen_concurrent_collection_in_progress ();
          if (D.20295 != 0) goto <D.20296>; else goto <D.20297>;
          <D.20296>:
          iftmp.36 = &major->major_concurrent_ops;
          goto <D.20298>;
          <D.20297>:
          iftmp.36 = &major->major_ops;
          <D.20298>:
          ops = iftmp.36;
          D.20299 = ops->scan_object;
          ctx.scan_func = D.20299;
          ctx.copy_func = 0B;
          D.20290 = &data->private_gray_queue;
          ctx.queue = D.20290;
          D.20290 = &data->private_gray_queue;
          D.20300 = sgen_gray_object_queue_is_empty (D.20290);
          D.20301 = D.20300 != 0;
          D.20302 = (long int) D.20301;
          D.20303 = __builtin_expect (D.20302, 0);
          if (D.20303 != 0) goto <D.20304>; else goto <D.20305>;
          <D.20304>:
          monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 396, "!sgen_gray_object_queue_is_empty (&data->private_gray_queue)");
          <D.20305>:
          goto <D.19940>;
          <D.19939>:
          D.20290 = &data->private_gray_queue;
          workers_gray_queue_share_redirect (D.20290);
          <D.19940>:
          D.20306 = sgen_drain_gray_stack (32, ctx);
          if (D.20306 == 0) goto <D.19939>; else goto <D.19941>;
          <D.19941>:
          D.20290 = &data->private_gray_queue;
          D.20307 = sgen_gray_object_queue_is_empty (D.20290);
          D.20308 = D.20307 == 0;
          D.20309 = (long int) D.20308;
          D.20310 = __builtin_expect (D.20309, 0);
          if (D.20310 != 0) goto <D.20311>; else goto <D.20312>;
          <D.20311>:
          monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 400, "sgen_gray_object_queue_is_empty (&data->private_gray_queue)");
          <D.20312>:
          init_private_gray_queue (data);
          did_work = 1;
        }
      finally
        {
          ctx = {CLOBBER};
        }
    }
    <D.20286>:
    <D.20289>:
    if (did_work == 0) goto <D.20313>; else goto <D.20314>;
    <D.20313>:
    workers_wait ();
    <D.20314>:
  }
  goto <D.19942>;
  D.20315 = 0B;
  return D.20315;
}


workers_dequeue_and_do_job (struct WorkerData * data)
{
  int workers_job_queue_num_entries.37;
  gboolean D.20320;
  volatile struct JobQueueEntry * workers_job_queue.38;
  int workers_job_queue_num_entries.39;
  int workers_job_queue_num_entries.40;
  int D.20328;
  _Bool D.20329;
  long int D.20330;
  long int D.20331;
  void (*<T3896>) (struct WorkerData *, void *) D.20334;
  void * D.20335;
  int D.20336;
  int D.20337;
  struct JobQueueEntry * entry;

  workers_job_queue_num_entries.37 = workers_job_queue_num_entries;
  if (workers_job_queue_num_entries.37 == 0) goto <D.20318>; else goto <D.20319>;
  <D.20318>:
  D.20320 = 0;
  return D.20320;
  <D.20319>:
  pthread_mutex_lock (&workers_job_queue_mutex);
  entry = workers_job_queue;
  if (entry != 0B) goto <D.20321>; else goto <D.20322>;
  <D.20321>:
  workers_job_queue.38 = entry->next;
  workers_job_queue = workers_job_queue.38;
  workers_job_queue_num_entries.39 = workers_job_queue_num_entries;
  workers_job_queue_num_entries.40 = workers_job_queue_num_entries.39 + -1;
  workers_job_queue_num_entries = workers_job_queue_num_entries.40;
  <D.20322>:
  pthread_mutex_unlock (&workers_job_queue_mutex);
  if (entry == 0B) goto <D.20326>; else goto <D.20327>;
  <D.20326>:
  D.20320 = 0;
  return D.20320;
  <D.20327>:
  D.20328 = collection_needs_workers ();
  D.20329 = D.20328 == 0;
  D.20330 = (long int) D.20329;
  D.20331 = __builtin_expect (D.20330, 0);
  if (D.20331 != 0) goto <D.20332>; else goto <D.20333>;
  <D.20332>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 214, "collection_needs_workers ()");
  <D.20333>:
  D.20334 = entry->func;
  D.20335 = entry->data;
  D.20334 (data, D.20335);
  sgen_free_internal (entry, 26);
  {
    int __old_x;

    <D.19888>:
    __old_x = workers_num_jobs_finished;
    D.20336 = __old_x + 1;
    D.20337 = InterlockedCompareExchange (&workers_num_jobs_finished, D.20336, __old_x);
    if (D.20337 != __old_x) goto <D.19888>; else goto <D.19889>;
    <D.19889>:
  }
  D.20320 = 1;
  return D.20320;
}


workers_get_work (struct WorkerData * data)
{
  struct SgenGrayQueue * D.20339;
  int D.20340;
  _Bool D.20341;
  long int D.20342;
  long int D.20343;
  int D.20346;
  gboolean D.20349;
  struct WorkerData * workers_data.41;
  unsigned int i.42;
  unsigned int D.20352;
  int D.20355;
  int workers_num.43;
  int D.20361;
  int D.20363;
  int D.20366;
  _Bool D.20367;
  long int D.20368;
  long int D.20369;
  struct SgenMajorCollector * major;
  int i;

  D.20339 = &data->private_gray_queue;
  D.20340 = sgen_gray_object_queue_is_empty (D.20339);
  D.20341 = D.20340 == 0;
  D.20342 = (long int) D.20341;
  D.20343 = __builtin_expect (D.20342, 0);
  if (D.20343 != 0) goto <D.20344>; else goto <D.20345>;
  <D.20344>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 275, "sgen_gray_object_queue_is_empty (&data->private_gray_queue)");
  <D.20345>:
  D.20346 = workers_steal (data, data, 1);
  if (D.20346 != 0) goto <D.20347>; else goto <D.20348>;
  <D.20347>:
  D.20349 = 1;
  return D.20349;
  <D.20348>:
  i = 0;
  goto <D.19910>;
  <D.19909>:
  {
    struct WorkerData * victim_data;

    workers_data.41 = workers_data;
    i.42 = (unsigned int) i;
    D.20352 = i.42 * 2100;
    victim_data = workers_data.41 + D.20352;
    if (data == victim_data) goto <D.20353>; else goto <D.20354>;
    <D.20353>:
    // predicted unlikely by continue predictor.
    goto <D.19908>;
    <D.20354>:
    D.20355 = workers_steal (data, victim_data, 1);
    if (D.20355 != 0) goto <D.20356>; else goto <D.20357>;
    <D.20356>:
    D.20349 = 1;
    return D.20349;
    <D.20357>:
  }
  <D.19908>:
  i = i + 1;
  <D.19910>:
  workers_num.43 = workers_num;
  if (i < workers_num.43) goto <D.19909>; else goto <D.19911>;
  <D.19911>:
  major = sgen_get_major_collector ();
  D.20361 = major->is_concurrent;
  if (D.20361 != 0) goto <D.20359>; else goto <D.20362>;
  <D.20362>:
  D.20363 = major->is_parallel;
  if (D.20363 != 0) goto <D.20359>; else goto <D.20360>;
  <D.20359>:
  {
    struct GrayQueueSection * section;

    section = sgen_section_gray_queue_dequeue (&workers_distribute_gray_queue);
    if (section != 0B) goto <D.20364>; else goto <D.20365>;
    <D.20364>:
    D.20339 = &data->private_gray_queue;
    sgen_gray_object_enqueue_section (D.20339, section);
    D.20349 = 1;
    return D.20349;
    <D.20365>:
  }
  <D.20360>:
  D.20339 = &data->private_gray_queue;
  D.20366 = sgen_gray_object_queue_is_empty (D.20339);
  D.20367 = D.20366 == 0;
  D.20368 = (long int) D.20367;
  D.20369 = __builtin_expect (D.20368, 0);
  if (D.20369 != 0) goto <D.20370>; else goto <D.20371>;
  <D.20370>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 304, "sgen_gray_object_queue_is_empty (&data->private_gray_queue)");
  <D.20371>:
  D.20349 = 0;
  return D.20349;
}


workers_steal (struct WorkerData * data, struct WorkerData * victim_data, gboolean lock)
{
  struct GrayQueueSection * D.20373;
  _Bool D.20374;
  long int D.20375;
  long int D.20376;
  int D.20379;
  gboolean D.20382;
  union mono_mutex_t * D.20385;
  int D.20386;
  int D.20389;
  int D.20390;
  char *[125] * D.20391;
  int D.20392;
  sizetype D.20393;
  sizetype n.44;
  sizetype num.45;
  sizetype D.20396;
  sizetype D.20397;
  char * * D.20398;
  unsigned int m.46;
  unsigned int D.20400;
  int D.20401;
  int D.20402;
  long long int D.20409;
  long long int stat_workers_stolen_from_self_lock.47;
  long long int stat_workers_stolen_from_self_lock.48;
  long long int stat_workers_stolen_from_self_no_lock.49;
  long long int stat_workers_stolen_from_self_no_lock.50;
  long long int stat_workers_stolen_from_others.51;
  long long int stat_workers_stolen_from_others.52;
  _Bool D.20418;
  struct SgenGrayQueue * queue;
  int num;
  int n;

  queue = &data->private_gray_queue;
  D.20373 = queue->first;
  D.20374 = D.20373 != 0B;
  D.20375 = (long int) D.20374;
  D.20376 = __builtin_expect (D.20375, 0);
  if (D.20376 != 0) goto <D.20377>; else goto <D.20378>;
  <D.20377>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 230, "!queue->first");
  <D.20378>:
  D.20379 = victim_data->stealable_stack_fill;
  if (D.20379 == 0) goto <D.20380>; else goto <D.20381>;
  <D.20380>:
  D.20382 = 0;
  return D.20382;
  <D.20381>:
  if (lock != 0) goto <D.20383>; else goto <D.20384>;
  <D.20383>:
  D.20385 = &victim_data->stealable_stack_mutex;
  D.20386 = pthread_mutex_trylock (D.20385);
  if (D.20386 != 0) goto <D.20387>; else goto <D.20388>;
  <D.20387>:
  D.20382 = 0;
  return D.20382;
  <D.20388>:
  <D.20384>:
  D.20389 = victim_data->stealable_stack_fill;
  D.20390 = D.20389 + 1;
  num = D.20390 / 2;
  n = num;
  goto <D.19900>;
  <D.19899>:
  {
    int m;

    m = MIN_EXPR <n, 125>;
    n = n - m;
    sgen_gray_object_alloc_queue_section (queue);
    D.20373 = queue->first;
    D.20391 = &D.20373->objects;
    D.20392 = victim_data->stealable_stack_fill;
    D.20393 = (sizetype) D.20392;
    n.44 = (sizetype) n;
    num.45 = (sizetype) num;
    D.20396 = n.44 - num.45;
    D.20397 = D.20393 + D.20396;
    D.20398 = &victim_data->stealable_stack[D.20397];
    m.46 = (unsigned int) m;
    D.20400 = m.46 * 4;
    memcpy (D.20391, D.20398, D.20400);
    D.20373 = queue->first;
    D.20373->end = m;
  }
  <D.19900>:
  if (n > 0) goto <D.19899>; else goto <D.19901>;
  <D.19901>:
  D.20401 = victim_data->stealable_stack_fill;
  D.20402 = D.20401 - num;
  victim_data->stealable_stack_fill = D.20402;
  if (lock != 0) goto <D.20403>; else goto <D.20404>;
  <D.20403>:
  D.20385 = &victim_data->stealable_stack_mutex;
  pthread_mutex_unlock (D.20385);
  <D.20404>:
  if (data == victim_data) goto <D.20405>; else goto <D.20406>;
  <D.20405>:
  if (lock != 0) goto <D.20407>; else goto <D.20408>;
  <D.20407>:
  D.20409 = (long long int) num;
  stat_workers_stolen_from_self_lock.47 = stat_workers_stolen_from_self_lock;
  stat_workers_stolen_from_self_lock.48 = D.20409 + stat_workers_stolen_from_self_lock.47;
  stat_workers_stolen_from_self_lock = stat_workers_stolen_from_self_lock.48;
  goto <D.20412>;
  <D.20408>:
  D.20409 = (long long int) num;
  stat_workers_stolen_from_self_no_lock.49 = stat_workers_stolen_from_self_no_lock;
  stat_workers_stolen_from_self_no_lock.50 = D.20409 + stat_workers_stolen_from_self_no_lock.49;
  stat_workers_stolen_from_self_no_lock = stat_workers_stolen_from_self_no_lock.50;
  <D.20412>:
  goto <D.20415>;
  <D.20406>:
  D.20409 = (long long int) num;
  stat_workers_stolen_from_others.51 = stat_workers_stolen_from_others;
  stat_workers_stolen_from_others.52 = D.20409 + stat_workers_stolen_from_others.51;
  stat_workers_stolen_from_others = stat_workers_stolen_from_others.52;
  <D.20415>:
  D.20418 = num != 0;
  D.20382 = (gboolean) D.20418;
  return D.20382;
}


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

  D.20421 = __builtin_object_size (__dest, 0);
  D.20420 = __builtin___memcpy_chk (__dest, __src, __len, D.20421);
  return D.20420;
}


workers_gray_queue_share_redirect (struct SgenGrayQueue * queue)
{
  int D.20423;
  <unnamed-unsigned:1> D.20426;
  union mono_mutex_t * D.20429;
  int iftmp.53;
  int D.20431;
  int D.20432;
  int D.20433;
  int D.20437;
  int D.20438;
  sizetype D.20439;
  char * * D.20440;
  sizetype D.20441;
  char * * D.20442;
  unsigned int num.54;
  unsigned int D.20444;
  sizetype D.20445;
  char * * D.20446;
  int D.20447;
  int D.20448;
  int D.20449;
  int D.20453;
  int D.20455;
  <unnamed-unsigned:1> D.20458;
  struct GrayQueueSection * section;
  struct WorkerData * data;

  data = queue->alloc_prepare_data;
  D.20423 = data->stealable_stack_fill;
  if (D.20423 != 0) goto <D.20424>; else goto <D.20425>;
  <D.20424>:
  D.20426 = workers_state.data.gc_in_progress;
  if (D.20426 != 0) goto <D.20427>; else goto <D.20428>;
  <D.20427>:
  workers_wake_up_all ();
  <D.20428>:
  return;
  <D.20425>:
  D.20429 = &data->stealable_stack_mutex;
  pthread_mutex_lock (D.20429);
  goto <D.19920>;
  <D.19919>:
  {
    int num;

    D.20431 = section->end;
    D.20432 = data->stealable_stack_fill;
    D.20433 = 512 - D.20432;
    if (D.20431 < D.20433) goto <D.20434>; else goto <D.20435>;
    <D.20434>:
    iftmp.53 = section->end;
    goto <D.20436>;
    <D.20435>:
    D.20437 = data->stealable_stack_fill;
    iftmp.53 = 512 - D.20437;
    <D.20436>:
    num = iftmp.53;
    D.20438 = data->stealable_stack_fill;
    D.20439 = (sizetype) D.20438;
    D.20440 = &data->stealable_stack[D.20439];
    D.20431 = section->end;
    D.20441 = (sizetype) D.20431;
    D.20442 = &section->objects[D.20441];
    num.54 = (unsigned int) num;
    D.20444 = num.54 * 4;
    D.20445 = -D.20444;
    D.20446 = D.20442 + D.20445;
    num.54 = (unsigned int) num;
    D.20444 = num.54 * 4;
    memcpy (D.20440, D.20446, D.20444);
    D.20431 = section->end;
    D.20447 = D.20431 - num;
    section->end = D.20447;
    D.20448 = data->stealable_stack_fill;
    D.20449 = D.20448 + num;
    data->stealable_stack_fill = D.20449;
    D.20431 = section->end;
    if (D.20431 != 0) goto <D.20450>; else goto <D.20451>;
    <D.20450>:
    sgen_gray_object_enqueue_section (queue, section);
    goto <D.20452>;
    <D.20451>:
    sgen_gray_object_free_queue_section (section);
    <D.20452>:
  }
  <D.19920>:
  D.20453 = data->stealable_stack_fill;
  if (D.20453 <= 511) goto <D.20454>; else goto <D.19921>;
  <D.20454>:
  section = sgen_gray_object_dequeue_section (queue);
  if (section != 0B) goto <D.19919>; else goto <D.19921>;
  <D.19921>:
  D.20455 = sgen_gray_object_queue_is_empty (queue);
  if (D.20455 != 0) goto <D.20456>; else goto <D.20457>;
  <D.20456>:
  workers_steal (data, data, 0);
  <D.20457>:
  D.20429 = &data->stealable_stack_mutex;
  pthread_mutex_unlock (D.20429);
  D.20458 = workers_state.data.gc_in_progress;
  if (D.20458 != 0) goto <D.20459>; else goto <D.20460>;
  <D.20459>:
  workers_wake_up_all ();
  <D.20460>:
}


sgen_gray_object_queue_is_empty (struct SgenGrayQueue * queue)
{
  gboolean D.20462;
  struct GrayQueueSection * D.20463;
  _Bool D.20464;

  D.20463 = queue->first;
  D.20464 = D.20463 == 0B;
  D.20462 = (gboolean) D.20464;
  return D.20462;
}


init_private_gray_queue (struct WorkerData * data)
{
  struct SgenGrayQueue * D.20466;
  void (*<T34ff>) (char *) iftmp.55;
  struct SgenMajorCollector * D.20468;
  int D.20469;

  D.20466 = &data->private_gray_queue;
  D.20468 = sgen_get_major_collector ();
  D.20469 = D.20468->is_concurrent;
  if (D.20469 != 0) goto <D.20470>; else goto <D.20471>;
  <D.20470>:
  iftmp.55 = concurrent_enqueue_check;
  goto <D.20472>;
  <D.20471>:
  iftmp.55 = 0B;
  <D.20472>:
  sgen_gray_object_queue_init_with_alloc_prepare (D.20466, iftmp.55, workers_gray_queue_share_redirect, data);
}


workers_wait ()
{
  long long int stat_workers_num_waited.56;
  long long int stat_workers_num_waited.57;
  unsigned char D.20475;
  unsigned char D.20476;
  _Bool D.20477;
  long int D.20478;
  long int D.20479;
  unsigned char D.20482;
  unsigned char D.20483;
  int D.20484;
  int workers_num.58;
  unsigned char D.20488;
  int D.20491;
  unsigned char D.20492;
  unsigned char D.20493;
  union State old_state;
  union State new_state;

  try
    {
      stat_workers_num_waited.56 = stat_workers_num_waited;
      stat_workers_num_waited.57 = stat_workers_num_waited.56 + 1;
      stat_workers_num_waited = stat_workers_num_waited.57;
      <D.19865>:
      new_state = workers_state;
      old_state = new_state;
      D.20475 = BIT_FIELD_REF <old_state, 8, 8>;
      D.20476 = D.20475 & 1;
      D.20477 = D.20476 != 0;
      D.20478 = (long int) D.20477;
      D.20479 = __builtin_expect (D.20478, 0);
      if (D.20479 != 0) goto <D.20480>; else goto <D.20481>;
      <D.20480>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 125, "!old_state.data.done_posted");
      <D.20481>:
      D.20482 = new_state.data.num_waiting;
      D.20483 = D.20482 + 1;
      new_state.data.num_waiting = D.20483;
      D.20482 = new_state.data.num_waiting;
      D.20484 = (int) D.20482;
      workers_num.58 = workers_num;
      if (D.20484 == workers_num.58) goto <D.20486>; else goto <D.20487>;
      <D.20486>:
      D.20475 = BIT_FIELD_REF <old_state, 8, 8>;
      D.20488 = D.20475 & 2;
      if (D.20488 == 0) goto <D.20489>; else goto <D.20490>;
      <D.20489>:
      new_state.data.done_posted = 1;
      <D.20490>:
      <D.20487>:
      D.20491 = set_state (old_state, new_state);
      if (D.20491 == 0) goto <D.19865>; else goto <D.19866>;
      <D.19866>:
      mono_memory_barrier ();
      D.20492 = BIT_FIELD_REF <new_state, 8, 8>;
      D.20493 = D.20492 & 1;
      if (D.20493 != 0) goto <D.20494>; else goto <D.20495>;
      <D.20494>:
      mono_sem_post (&workers_done_sem);
      <D.20495>:
      mono_sem_wait (&workers_waiting_sem, 0);
    }
  finally
    {
      old_state = {CLOBBER};
      new_state = {CLOBBER};
    }
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


sgen_workers_have_started ()
{
  gboolean D.20496;
  <unnamed-unsigned:1> D.20497;

  D.20497 = workers_state.data.gc_in_progress;
  D.20496 = (gboolean) D.20497;
  return D.20496;
}


sgen_workers_start_marking ()
{
  int D.20499;
  int iftmp.59;
  int workers_started.60;
  <unnamed-unsigned:1> D.20508;
  _Bool D.20509;
  long int D.20510;
  long int D.20511;
  int workers_marking.61;
  _Bool D.20515;
  long int D.20516;
  long int D.20517;

  D.20499 = collection_needs_workers ();
  if (D.20499 == 0) goto <D.20500>; else goto <D.20501>;
  <D.20500>:
  return;
  <D.20501>:
  workers_started.60 = workers_started;
  if (workers_started.60 == 0) goto <D.20503>; else goto <D.20507>;
  <D.20507>:
  D.20508 = workers_state.data.gc_in_progress;
  if (D.20508 == 0) goto <D.20503>; else goto <D.20504>;
  <D.20503>:
  iftmp.59 = 1;
  goto <D.20505>;
  <D.20504>:
  iftmp.59 = 0;
  <D.20505>:
  D.20509 = iftmp.59 != 0;
  D.20510 = (long int) D.20509;
  D.20511 = __builtin_expect (D.20510, 0);
  if (D.20511 != 0) goto <D.20512>; else goto <D.20513>;
  <D.20512>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 552, "workers_started && workers_state.data.gc_in_progress");
  <D.20513>:
  workers_marking.61 = workers_marking;
  D.20515 = workers_marking.61 != 0;
  D.20516 = (long int) D.20515;
  D.20517 = __builtin_expect (D.20516, 0);
  if (D.20517 != 0) goto <D.20518>; else goto <D.20519>;
  <D.20518>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 553, "!workers_marking");
  <D.20519>:
  workers_marking = 1;
  workers_wake_up_all ();
}


sgen_workers_join ()
{
  int D.20521;
  unsigned char D.20524;
  unsigned char D.20525;
  _Bool D.20526;
  long int D.20527;
  long int D.20528;
  unsigned char D.20531;
  _Bool D.20532;
  long int D.20533;
  long int D.20534;
  int D.20537;
  unsigned char D.20538;
  int D.20539;
  int workers_num.62;
  unsigned char D.20543;
  int D.20544;
  _Bool D.20545;
  long int D.20546;
  long int D.20547;
  _Bool D.20550;
  long int D.20551;
  long int D.20552;
  int workers_job_queue_num_entries.63;
  int D.20559;
  int D.20560;
  struct SgenMajorCollector * D.20563;
  void (*<Tc1>) (void *) D.20564;
  struct SgenMajorCollector * D.20567;
  void (*<Tc1>) (void *) D.20568;
  struct WorkerData * workers_data.64;
  unsigned int i.65;
  unsigned int D.20571;
  struct WorkerData * D.20572;
  void * D.20573;
  int workers_job_queue_num_entries.66;
  _Bool D.20575;
  long int D.20576;
  long int D.20577;
  int D.20580;
  _Bool D.20581;
  long int D.20582;
  long int D.20583;
  int D.20586;
  _Bool D.20587;
  long int D.20588;
  long int D.20589;
  struct SgenGrayQueue * D.20592;
  int D.20593;
  _Bool D.20594;
  long int D.20595;
  long int D.20596;
  union State old_state;
  union State new_state;
  int i;
  void reawaken = <<< error >>>;

  try
    {
      D.20521 = collection_needs_workers ();
      if (D.20521 == 0) goto <D.20522>; else goto <D.20523>;
      <D.20522>:
      return;
      <D.20523>:
      <D.19981>:
      new_state = workers_state;
      old_state = new_state;
      D.20524 = BIT_FIELD_REF <old_state, 8, 8>;
      D.20525 = D.20524 & 2;
      D.20526 = D.20525 == 0;
      D.20527 = (long int) D.20526;
      D.20528 = __builtin_expect (D.20527, 0);
      if (D.20528 != 0) goto <D.20529>; else goto <D.20530>;
      <D.20529>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 571, "old_state.data.gc_in_progress");
      <D.20530>:
      D.20524 = BIT_FIELD_REF <old_state, 8, 8>;
      D.20531 = D.20524 & 1;
      D.20532 = D.20531 != 0;
      D.20533 = (long int) D.20532;
      D.20534 = __builtin_expect (D.20533, 0);
      if (D.20534 != 0) goto <D.20535>; else goto <D.20536>;
      <D.20535>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 572, "!old_state.data.done_posted");
      <D.20536>:
      new_state.data.gc_in_progress = 0;
      D.20537 = set_state (old_state, new_state);
      if (D.20537 == 0) goto <D.19981>; else goto <D.19982>;
      <D.19982>:
      D.20538 = new_state.data.num_waiting;
      D.20539 = (int) D.20538;
      workers_num.62 = workers_num;
      if (D.20539 == workers_num.62) goto <D.20541>; else goto <D.20542>;
      <D.20541>:
      reawaken:
      workers_wake_up_all ();
      <D.20542>:
      mono_sem_wait (&workers_done_sem, 0);
      new_state = workers_state;
      old_state = new_state;
      D.20543 = old_state.data.num_waiting;
      D.20544 = (int) D.20543;
      workers_num.62 = workers_num;
      D.20545 = D.20544 != workers_num.62;
      D.20546 = (long int) D.20545;
      D.20547 = __builtin_expect (D.20546, 0);
      if (D.20547 != 0) goto <D.20548>; else goto <D.20549>;
      <D.20548>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 593, "old_state.data.num_waiting == workers_num");
      <D.20549>:
      D.20524 = BIT_FIELD_REF <old_state, 8, 8>;
      D.20531 = D.20524 & 1;
      D.20550 = D.20531 == 0;
      D.20551 = (long int) D.20550;
      D.20552 = __builtin_expect (D.20551, 0);
      if (D.20552 != 0) goto <D.20553>; else goto <D.20554>;
      <D.20553>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 594, "old_state.data.done_posted");
      <D.20554>:
      workers_job_queue_num_entries.63 = workers_job_queue_num_entries;
      if (workers_job_queue_num_entries.63 != 0) goto <D.20555>; else goto <D.20558>;
      <D.20558>:
      D.20559 = sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue);
      if (D.20559 == 0) goto <D.20555>; else goto <D.20556>;
      <D.20555>:
      new_state.data.done_posted = 0;
      D.20560 = set_state (old_state, new_state);
      if (D.20560 == 0) goto <D.20561>; else goto <D.20562>;
      <D.20561>:
      monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "sgen-workers.c", 613);
      <D.20562>:
      goto reawaken;
      <D.20556>:
      workers_marking = 0;
      D.20563 = sgen_get_major_collector ();
      D.20564 = D.20563->reset_worker_data;
      if (D.20564 != 0B) goto <D.20565>; else goto <D.20566>;
      <D.20565>:
      i = 0;
      goto <D.19985>;
      <D.19984>:
      D.20567 = sgen_get_major_collector ();
      D.20568 = D.20567->reset_worker_data;
      workers_data.64 = workers_data;
      i.65 = (unsigned int) i;
      D.20571 = i.65 * 2100;
      D.20572 = workers_data.64 + D.20571;
      D.20573 = D.20572->major_collector_data;
      D.20568 (D.20573);
      i = i + 1;
      <D.19985>:
      workers_num.62 = workers_num;
      if (i < workers_num.62) goto <D.19984>; else goto <D.19986>;
      <D.19986>:
      <D.20566>:
      workers_job_queue_num_entries.66 = workers_job_queue_num_entries;
      D.20575 = workers_job_queue_num_entries.66 != 0;
      D.20576 = (long int) D.20575;
      D.20577 = __builtin_expect (D.20576, 0);
      if (D.20577 != 0) goto <D.20578>; else goto <D.20579>;
      <D.20578>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 626, "workers_job_queue_num_entries == 0");
      <D.20579>:
      D.20580 = sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue);
      D.20581 = D.20580 == 0;
      D.20582 = (long int) D.20581;
      D.20583 = __builtin_expect (D.20582, 0);
      if (D.20583 != 0) goto <D.20584>; else goto <D.20585>;
      <D.20584>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 627, "sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue)");
      <D.20585>:
      i = 0;
      goto <D.19988>;
      <D.19987>:
      workers_data.64 = workers_data;
      i.65 = (unsigned int) i;
      D.20571 = i.65 * 2100;
      D.20572 = workers_data.64 + D.20571;
      D.20586 = D.20572->stealable_stack_fill;
      D.20587 = D.20586 != 0;
      D.20588 = (long int) D.20587;
      D.20589 = __builtin_expect (D.20588, 0);
      if (D.20589 != 0) goto <D.20590>; else goto <D.20591>;
      <D.20590>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 629, "!workers_data [i].stealable_stack_fill");
      <D.20591>:
      workers_data.64 = workers_data;
      i.65 = (unsigned int) i;
      D.20571 = i.65 * 2100;
      D.20572 = workers_data.64 + D.20571;
      D.20592 = &D.20572->private_gray_queue;
      D.20593 = sgen_gray_object_queue_is_empty (D.20592);
      D.20594 = D.20593 == 0;
      D.20595 = (long int) D.20594;
      D.20596 = __builtin_expect (D.20595, 0);
      if (D.20596 != 0) goto <D.20597>; else goto <D.20598>;
      <D.20597>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 630, "sgen_gray_object_queue_is_empty (&workers_data [i].private_gray_queue)");
      <D.20598>:
      i = i + 1;
      <D.19988>:
      workers_num.62 = workers_num;
      if (i < workers_num.62) goto <D.19987>; else goto <D.19989>;
      <D.19989>:
    }
  finally
    {
      old_state = {CLOBBER};
      new_state = {CLOBBER};
    }
}


sgen_workers_all_done ()
{
  unsigned char D.20602;
  unsigned char D.20603;
  _Bool D.20604;
  long int D.20605;
  long int D.20606;
  unsigned char D.20609;
  _Bool D.20610;
  long int D.20611;
  long int D.20612;
  gboolean D.20615;
  unsigned char D.20616;
  int D.20617;
  int workers_num.67;
  _Bool D.20619;
  union State state;

  try
    {
      state = workers_state;
      D.20602 = BIT_FIELD_REF <state, 8, 8>;
      D.20603 = D.20602 & 2;
      D.20604 = D.20603 == 0;
      D.20605 = (long int) D.20604;
      D.20606 = __builtin_expect (D.20605, 0);
      if (D.20606 != 0) goto <D.20607>; else goto <D.20608>;
      <D.20607>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 642, "state.data.gc_in_progress");
      <D.20608>:
      D.20602 = BIT_FIELD_REF <state, 8, 8>;
      D.20609 = D.20602 & 1;
      D.20610 = D.20609 != 0;
      D.20611 = (long int) D.20610;
      D.20612 = __builtin_expect (D.20611, 0);
      if (D.20612 != 0) goto <D.20613>; else goto <D.20614>;
      <D.20613>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 643, "!state.data.done_posted");
      <D.20614>:
      D.20616 = state.data.num_waiting;
      D.20617 = (int) D.20616;
      workers_num.67 = workers_num;
      D.20619 = D.20617 == workers_num.67;
      D.20615 = (gboolean) D.20619;
      return D.20615;
    }
  finally
    {
      state = {CLOBBER};
    }
}


sgen_is_worker_thread (MonoNativeThreadId thread)
{
  struct SgenMajorCollector * D.20622;
  gboolean (*<T36df>) (MonoNativeThreadId) D.20623;
  struct SgenMajorCollector * D.20626;
  gboolean (*<T36df>) (MonoNativeThreadId) D.20627;
  int D.20628;
  gboolean D.20631;
  struct WorkerData * workers_data.68;
  unsigned int i.69;
  unsigned int D.20634;
  struct WorkerData * D.20635;
  long unsigned int D.20636;
  int workers_num.70;
  int i;

  D.20622 = sgen_get_major_collector ();
  D.20623 = D.20622->is_worker_thread;
  if (D.20623 != 0B) goto <D.20624>; else goto <D.20625>;
  <D.20624>:
  D.20626 = sgen_get_major_collector ();
  D.20627 = D.20626->is_worker_thread;
  D.20628 = D.20627 (thread);
  if (D.20628 != 0) goto <D.20629>; else goto <D.20630>;
  <D.20629>:
  D.20631 = 1;
  return D.20631;
  <D.20630>:
  <D.20625>:
  i = 0;
  goto <D.19999>;
  <D.19998>:
  workers_data.68 = workers_data;
  i.69 = (unsigned int) i;
  D.20634 = i.69 * 2100;
  D.20635 = workers_data.68 + D.20634;
  D.20636 = D.20635->thread;
  if (D.20636 == thread) goto <D.20637>; else goto <D.20638>;
  <D.20637>:
  D.20631 = 1;
  return D.20631;
  <D.20638>:
  i = i + 1;
  <D.19999>:
  workers_num.70 = workers_num;
  if (i < workers_num.70) goto <D.19998>; else goto <D.20000>;
  <D.20000>:
  D.20631 = 0;
  return D.20631;
}


sgen_workers_get_distribute_section_gray_queue ()
{
  struct SgenSectionGrayQueue * D.20641;

  D.20641 = &workers_distribute_gray_queue;
  return D.20641;
}


sgen_workers_reset_data ()
{
  struct SgenMajorCollector * D.20643;
  void (*<Tc1>) (void *) D.20644;
  struct SgenMajorCollector * D.20647;
  void (*<Tc1>) (void *) D.20648;
  void * workers_gc_thread_major_collector_data.71;

  D.20643 = sgen_get_major_collector ();
  D.20644 = D.20643->reset_worker_data;
  if (D.20644 != 0B) goto <D.20645>; else goto <D.20646>;
  <D.20645>:
  D.20647 = sgen_get_major_collector ();
  D.20648 = D.20647->reset_worker_data;
  workers_gc_thread_major_collector_data.71 = workers_gc_thread_major_collector_data;
  D.20648 (workers_gc_thread_major_collector_data.71);
  <D.20646>:
}


