sgen_workers_wake_up_all ()
{
  <unnamed-unsigned:1> D.17445;
  _Bool D.17446;
  long int D.17447;
  long int D.17448;

  D.17445 = workers_state.data.gc_in_progress;
  D.17446 = ~D.17445;
  D.17447 = (long int) D.17446;
  D.17448 = __builtin_expect (D.17447, 0);
  if (D.17448 != 0) goto <D.17449>; else goto <D.17450>;
  <D.17449>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 109, "workers_state.data.gc_in_progress");
  <D.17450>:
  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.17452;
  unsigned char D.17453;
  unsigned char D.17456;
  unsigned char D.17459;
  unsigned char D.17460;
  int D.17461;
  int i;

  i = 0;
  goto <D.17289>;
  <D.17288>:
  {
    union State old_state;
    union State new_state;

    try
      {
        <D.17286>:
        new_state = workers_state;
        old_state = new_state;
        D.17452 = BIT_FIELD_REF <old_state, 8, 8>;
        D.17453 = D.17452 & 1;
        if (D.17453 != 0) goto <D.17454>; else goto <D.17455>;
        <D.17454>:
        return;
        <D.17455>:
        D.17456 = old_state.data.num_waiting;
        if (D.17456 == 0) goto <D.17457>; else goto <D.17458>;
        <D.17457>:
        return;
        <D.17458>:
        D.17459 = new_state.data.num_waiting;
        D.17460 = D.17459 + 255;
        new_state.data.num_waiting = D.17460;
        D.17461 = set_state (old_state, new_state);
        if (D.17461 == 0) goto <D.17286>; else goto <D.17287>;
        <D.17287>:
        mono_sem_post (&workers_waiting_sem);
      }
    finally
      {
        old_state = {CLOBBER};
        new_state = {CLOBBER};
      }
  }
  i = i + 1;
  <D.17289>:
  if (i < max) goto <D.17288>; else goto <D.17290>;
  <D.17290>:
}


set_state (union State old_state, union State new_state)
{
  gboolean D.17465;
  int D.17466;
  int D.17467;
  int D.17468;
  _Bool D.17469;

  D.17466 = old_state.value;
  D.17467 = new_state.value;
  D.17468 = InterlockedCompareExchange (&workers_state.value, D.17467, D.17466);
  D.17466 = old_state.value;
  D.17469 = D.17468 == D.17466;
  D.17465 = (gboolean) D.17469;
  return D.17465;
}


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

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


sgen_workers_enqueue_job (void (*JobFunc) (struct WorkerData *, void *) func, void * data)
{
  int D.17476;
  <unnamed-unsigned:1> D.17479;
  _Bool D.17480;
  long int D.17481;
  long int D.17482;
  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.17476 = collection_needs_workers ();
  if (D.17476 == 0) goto <D.17477>; else goto <D.17478>;
  <D.17477>:
  func (0B, data);
  return;
  <D.17478>:
  D.17479 = workers_state.data.gc_in_progress;
  D.17480 = ~D.17479;
  D.17481 = (long int) D.17480;
  D.17482 = __builtin_expect (D.17481, 0);
  if (D.17482 != 0) goto <D.17483>; else goto <D.17484>;
  <D.17483>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 157, "workers_state.data.gc_in_progress");
  <D.17484>:
  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.17492;
  int iftmp.9;
  int D.17497;
  int D.17499;

  D.17497 = sgen_collection_is_parallel ();
  if (D.17497 != 0) goto <D.17494>; else goto <D.17498>;
  <D.17498>:
  D.17499 = sgen_collection_is_concurrent ();
  if (D.17499 != 0) goto <D.17494>; else goto <D.17495>;
  <D.17494>:
  iftmp.9 = 1;
  goto <D.17496>;
  <D.17495>:
  iftmp.9 = 0;
  <D.17496>:
  D.17492 = iftmp.9;
  return D.17492;
}


sgen_workers_wait_for_jobs ()
{
  unsigned char D.17501;
  unsigned char D.17502;
  _Bool D.17503;
  long int D.17504;
  long int D.17505;
  unsigned char D.17508;
  _Bool D.17509;
  long int D.17510;
  long int D.17511;
  unsigned char D.17514;
  int D.17515;
  int workers_num.10;
  int workers_num_jobs_finished.11;
  int workers_num_jobs_enqueued.12;

  goto <D.17318>;
  <D.17317>:
  {
    union State state;

    try
      {
        state = workers_state;
        D.17501 = BIT_FIELD_REF <state, 8, 8>;
        D.17502 = D.17501 & 2;
        D.17503 = D.17502 == 0;
        D.17504 = (long int) D.17503;
        D.17505 = __builtin_expect (D.17504, 0);
        if (D.17505 != 0) goto <D.17506>; else goto <D.17507>;
        <D.17506>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 179, "state.data.gc_in_progress");
        <D.17507>:
        D.17501 = BIT_FIELD_REF <state, 8, 8>;
        D.17508 = D.17501 & 1;
        D.17509 = D.17508 != 0;
        D.17510 = (long int) D.17509;
        D.17511 = __builtin_expect (D.17510, 0);
        if (D.17511 != 0) goto <D.17512>; else goto <D.17513>;
        <D.17512>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 180, "!state.data.done_posted");
        <D.17513>:
        D.17514 = state.data.num_waiting;
        D.17515 = (int) D.17514;
        workers_num.10 = workers_num;
        if (D.17515 == workers_num.10) goto <D.17517>; else goto <D.17518>;
        <D.17517>:
        workers_wake_up_all ();
        <D.17518>:
        monoeg_g_usleep (1000);
      }
    finally
      {
        state = {CLOBBER};
      }
  }
  <D.17318>:
  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.17317>; else goto <D.17319>;
  <D.17319>:
}


sgen_workers_init_distribute_gray_queue ()
{
  int D.17521;
  int iftmp.13;
  struct SgenMajorCollector * D.17528;
  int D.17529;
  struct SgenMajorCollector * D.17531;
  int D.17532;

  D.17521 = collection_needs_workers ();
  if (D.17521 == 0) goto <D.17522>; else goto <D.17523>;
  <D.17522>:
  return;
  <D.17523>:
  D.17528 = sgen_get_major_collector ();
  D.17529 = D.17528->is_concurrent;
  if (D.17529 != 0) goto <D.17525>; else goto <D.17530>;
  <D.17530>:
  D.17531 = sgen_get_major_collector ();
  D.17532 = D.17531->is_parallel;
  if (D.17532 != 0) goto <D.17525>; else goto <D.17526>;
  <D.17525>:
  iftmp.13 = 1;
  goto <D.17527>;
  <D.17526>:
  iftmp.13 = 0;
  <D.17527>:
  init_distribute_gray_queue (iftmp.13);
}


init_distribute_gray_queue (gboolean locked)
{
  int workers_distribute_gray_queue_inited.14;
  int D.17537;
  _Bool D.17538;
  long int D.17539;
  long int D.17540;
  int D.17543;
  _Bool D.17544;
  _Bool D.17545;
  _Bool D.17546;
  long int D.17547;
  long int D.17548;
  void (*<T2a94>) (char *) iftmp.15;
  struct SgenMajorCollector * D.17552;
  int D.17553;

  workers_distribute_gray_queue_inited.14 = workers_distribute_gray_queue_inited;
  if (workers_distribute_gray_queue_inited.14 != 0) goto <D.17535>; else goto <D.17536>;
  <D.17535>:
  D.17537 = sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue);
  D.17538 = D.17537 == 0;
  D.17539 = (long int) D.17538;
  D.17540 = __builtin_expect (D.17539, 0);
  if (D.17540 != 0) goto <D.17541>; else goto <D.17542>;
  <D.17541>:
  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.17542>:
  D.17543 = workers_distribute_gray_queue.locked;
  D.17544 = D.17543 == 0;
  D.17545 = locked == 0;
  D.17546 = D.17544 ^ D.17545;
  D.17547 = (long int) D.17546;
  D.17548 = __builtin_expect (D.17547, 0);
  if (D.17548 != 0) goto <D.17549>; else goto <D.17550>;
  <D.17549>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 420, "!workers_distribute_gray_queue.locked == !locked");
  <D.17550>:
  return;
  <D.17536>:
  D.17552 = sgen_get_major_collector ();
  D.17553 = D.17552->is_concurrent;
  if (D.17553 != 0) goto <D.17554>; else goto <D.17555>;
  <D.17554>:
  iftmp.15 = concurrent_enqueue_check;
  goto <D.17556>;
  <D.17555>:
  iftmp.15 = 0B;
  <D.17556>:
  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.17558;
  _Bool D.17559;
  long int D.17560;
  long int D.17561;
  int D.17564;
  _Bool D.17565;
  long int D.17566;
  long int D.17567;
  unsigned int D.17570;
  unsigned int D.17571;
  _Bool D.17572;
  long int D.17573;
  long int D.17574;

  D.17558 = sgen_concurrent_collection_in_progress ();
  D.17559 = D.17558 == 0;
  D.17560 = (long int) D.17559;
  D.17561 = __builtin_expect (D.17560, 0);
  if (D.17561 != 0) goto <D.17562>; else goto <D.17563>;
  <D.17562>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 356, "sgen_concurrent_collection_in_progress ()");
  <D.17563>:
  D.17564 = sgen_ptr_in_nursery (obj);
  D.17565 = D.17564 != 0;
  D.17566 = (long int) D.17565;
  D.17567 = __builtin_expect (D.17566, 0);
  if (D.17567 != 0) goto <D.17568>; else goto <D.17569>;
  <D.17568>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 357, "!sgen_ptr_in_nursery (obj)");
  <D.17569>:
  D.17570 = MEM[(mword *)obj];
  D.17571 = D.17570 & 4294967292;
  D.17572 = D.17571 == 0;
  D.17573 = (long int) D.17572;
  D.17574 = __builtin_expect (D.17573, 0);
  if (D.17574 != 0) goto <D.17575>; else goto <D.17576>;
  <D.17575>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 358, "SGEN_LOAD_VTABLE (obj)");
  <D.17576>:
}


sgen_ptr_in_nursery (void * p)
{
  gboolean D.17577;
  int sgen_nursery_bits.16;
  int D.17579;
  int D.17580;
  unsigned int D.17581;
  unsigned int p.17;
  unsigned int D.17583;
  char * sgen_nursery_start.18;
  unsigned int sgen_nursery_start.19;
  _Bool D.17586;

  sgen_nursery_bits.16 = sgen_nursery_bits;
  D.17579 = 1 << sgen_nursery_bits.16;
  D.17580 = -D.17579;
  D.17581 = (unsigned int) D.17580;
  p.17 = (unsigned int) p;
  D.17583 = D.17581 & p.17;
  sgen_nursery_start.18 = sgen_nursery_start;
  sgen_nursery_start.19 = (unsigned int) sgen_nursery_start.18;
  D.17586 = D.17583 == sgen_nursery_start.19;
  D.17577 = (gboolean) D.17586;
  return D.17577;
}


sgen_workers_init (int num_workers)
{
  struct SgenMajorCollector * D.17588;
  int D.17589;
  struct SgenMajorCollector * D.17592;
  int D.17593;
  unsigned int num_workers.20;
  unsigned int D.17597;
  void * workers_data.21;
  struct WorkerData * workers_data.22;
  int iftmp.23;
  struct SgenMajorCollector * D.17604;
  int D.17605;
  struct SgenMajorCollector * D.17607;
  int D.17608;
  struct SgenMajorCollector * D.17609;
  void * (*<T29fe>) (void) D.17610;
  struct SgenMajorCollector * D.17613;
  void * (*<T29fe>) (void) D.17614;
  void * workers_gc_thread_major_collector_data.24;
  unsigned int i.25;
  unsigned int D.17617;
  struct WorkerData * D.17618;
  union mono_mutex_t * D.17619;
  struct SgenMajorCollector * D.17620;
  void * (*<T29fe>) (void) D.17621;
  struct SgenMajorCollector * D.17624;
  void * (*<T29fe>) (void) D.17625;
  void * D.17626;
  int workers_num.26;
  int i;

  D.17588 = sgen_get_major_collector ();
  D.17589 = D.17588->is_parallel;
  if (D.17589 == 0) goto <D.17590>; else goto <D.17591>;
  <D.17590>:
  D.17592 = sgen_get_major_collector ();
  D.17593 = D.17592->is_concurrent;
  if (D.17593 == 0) goto <D.17594>; else goto <D.17595>;
  <D.17594>:
  return;
  <D.17595>:
  <D.17591>:
  workers_num = num_workers;
  num_workers.20 = (unsigned int) num_workers;
  D.17597 = num_workers.20 * 2100;
  workers_data.21 = sgen_alloc_internal_dynamic (D.17597, 19, 1);
  workers_data = workers_data.21;
  num_workers.20 = (unsigned int) num_workers;
  D.17597 = num_workers.20 * 2100;
  workers_data.22 = workers_data;
  memset (workers_data.22, 0, D.17597);
  sem_init (&workers_waiting_sem, 0, 0);
  sem_init (&workers_done_sem, 0, 0);
  D.17604 = sgen_get_major_collector ();
  D.17605 = D.17604->is_concurrent;
  if (D.17605 != 0) goto <D.17601>; else goto <D.17606>;
  <D.17606>:
  D.17607 = sgen_get_major_collector ();
  D.17608 = D.17607->is_parallel;
  if (D.17608 != 0) goto <D.17601>; else goto <D.17602>;
  <D.17601>:
  iftmp.23 = 1;
  goto <D.17603>;
  <D.17602>:
  iftmp.23 = 0;
  <D.17603>:
  init_distribute_gray_queue (iftmp.23);
  D.17609 = sgen_get_major_collector ();
  D.17610 = D.17609->alloc_worker_data;
  if (D.17610 != 0B) goto <D.17611>; else goto <D.17612>;
  <D.17611>:
  D.17613 = sgen_get_major_collector ();
  D.17614 = D.17613->alloc_worker_data;
  workers_gc_thread_major_collector_data.24 = D.17614 ();
  workers_gc_thread_major_collector_data = workers_gc_thread_major_collector_data.24;
  <D.17612>:
  i = 0;
  goto <D.17391>;
  <D.17390>:
  workers_data.22 = workers_data;
  i.25 = (unsigned int) i;
  D.17617 = i.25 * 2100;
  D.17618 = workers_data.22 + D.17617;
  D.17619 = &D.17618->stealable_stack_mutex;
  pthread_mutex_init (D.17619, 0B);
  workers_data.22 = workers_data;
  i.25 = (unsigned int) i;
  D.17617 = i.25 * 2100;
  D.17618 = workers_data.22 + D.17617;
  D.17618->stealable_stack_fill = 0;
  D.17620 = sgen_get_major_collector ();
  D.17621 = D.17620->alloc_worker_data;
  if (D.17621 != 0B) goto <D.17622>; else goto <D.17623>;
  <D.17622>:
  workers_data.22 = workers_data;
  i.25 = (unsigned int) i;
  D.17617 = i.25 * 2100;
  D.17618 = workers_data.22 + D.17617;
  D.17624 = sgen_get_major_collector ();
  D.17625 = D.17624->alloc_worker_data;
  D.17626 = D.17625 ();
  D.17618->major_collector_data = D.17626;
  <D.17623>:
  i = i + 1;
  <D.17391>:
  workers_num.26 = workers_num;
  if (i < workers_num.26) goto <D.17390>; else goto <D.17392>;
  <D.17392>:
  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.17631;
  int D.17636;
  void * D.17638;
  unsigned int D.17639;

  D.17631 = __builtin_constant_p (__len);
  if (D.17631 != 0) goto <D.17632>; else goto <D.17633>;
  <D.17632>:
  if (__len == 0) goto <D.17634>; else goto <D.17635>;
  <D.17634>:
  D.17636 = __builtin_constant_p (__ch);
  if (D.17636 == 0) goto <D.17629>; else goto <D.17637>;
  <D.17637>:
  if (__ch != 0) goto <D.17629>; else goto <D.17630>;
  <D.17629>:
  __warn_memset_zero_len ();
  D.17638 = __dest;
  return D.17638;
  <D.17630>:
  <D.17635>:
  <D.17633>:
  D.17639 = __builtin_object_size (__dest, 0);
  D.17638 = __builtin___memset_chk (__dest, __ch, __len, D.17639);
  return D.17638;
}


sgen_workers_start_all_workers ()
{
  int D.17641;
  struct SgenMajorCollector * D.17644;
  void (*<Tbf>) (void *) D.17645;
  struct SgenMajorCollector * D.17648;
  void (*<Tbf>) (void *) D.17649;
  void * workers_gc_thread_major_collector_data.27;
  unsigned char D.17651;
  unsigned char D.17652;
  _Bool D.17653;
  long int D.17654;
  long int D.17655;
  int workers_job_queue_num_entries.28;
  _Bool D.17659;
  long int D.17660;
  long int D.17661;
  int workers_started.29;
  unsigned char D.17667;
  _Bool D.17668;
  long int D.17669;
  long int D.17670;
  unsigned char D.17673;
  int D.17674;
  int workers_num.30;
  int D.17678;
  _Bool D.17681;
  long int D.17682;
  long int D.17683;
  int D.17686;
  union State old_state;
  union State new_state;
  int i;

  try
    {
      D.17641 = collection_needs_workers ();
      if (D.17641 == 0) goto <D.17642>; else goto <D.17643>;
      <D.17642>:
      return;
      <D.17643>:
      D.17644 = sgen_get_major_collector ();
      D.17645 = D.17644->init_worker_thread;
      if (D.17645 != 0B) goto <D.17646>; else goto <D.17647>;
      <D.17646>:
      D.17648 = sgen_get_major_collector ();
      D.17649 = D.17648->init_worker_thread;
      workers_gc_thread_major_collector_data.27 = workers_gc_thread_major_collector_data;
      D.17649 (workers_gc_thread_major_collector_data.27);
      <D.17647>:
      new_state = workers_state;
      old_state = new_state;
      D.17651 = BIT_FIELD_REF <old_state, 8, 8>;
      D.17652 = D.17651 & 2;
      D.17653 = D.17652 != 0;
      D.17654 = (long int) D.17653;
      D.17655 = __builtin_expect (D.17654, 0);
      if (D.17655 != 0) goto <D.17656>; else goto <D.17657>;
      <D.17656>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 504, "!old_state.data.gc_in_progress");
      <D.17657>:
      new_state.data.gc_in_progress = 1;
      workers_marking = 0;
      workers_job_queue_num_entries.28 = workers_job_queue_num_entries;
      D.17659 = workers_job_queue_num_entries.28 != 0;
      D.17660 = (long int) D.17659;
      D.17661 = __builtin_expect (D.17660, 0);
      if (D.17661 != 0) goto <D.17662>; else goto <D.17663>;
      <D.17662>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 509, "workers_job_queue_num_entries == 0");
      <D.17663>:
      workers_num_jobs_enqueued = 0;
      workers_num_jobs_finished = 0;
      workers_started.29 = workers_started;
      if (workers_started.29 != 0) goto <D.17665>; else goto <D.17666>;
      <D.17665>:
      D.17651 = BIT_FIELD_REF <old_state, 8, 8>;
      D.17667 = D.17651 & 1;
      D.17668 = D.17667 == 0;
      D.17669 = (long int) D.17668;
      D.17670 = __builtin_expect (D.17669, 0);
      if (D.17670 != 0) goto <D.17671>; else goto <D.17672>;
      <D.17671>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 514, "old_state.data.done_posted");
      <D.17672>:
      D.17673 = old_state.data.num_waiting;
      D.17674 = (int) D.17673;
      workers_num.30 = workers_num;
      if (D.17674 != workers_num.30) goto <D.17676>; else goto <D.17677>;
      <D.17676>:
      D.17673 = old_state.data.num_waiting;
      D.17674 = (int) D.17673;
      workers_num.30 = workers_num;
      monoeg_g_log (0B, 4, "Expecting all %d sgen workers to be parked, but only %d are", workers_num.30, D.17674);
      <D.17402>:
      goto <D.17402>;
      <D.17677>:
      new_state.data.done_posted = 0;
      D.17678 = set_state (old_state, new_state);
      if (D.17678 == 0) goto <D.17679>; else goto <D.17680>;
      <D.17679>:
      monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "sgen-workers.c", 523);
      <D.17680>:
      workers_wake_up_all ();
      return;
      <D.17666>:
      D.17651 = BIT_FIELD_REF <old_state, 8, 8>;
      D.17667 = D.17651 & 1;
      D.17681 = D.17667 != 0;
      D.17682 = (long int) D.17681;
      D.17683 = __builtin_expect (D.17682, 0);
      if (D.17683 != 0) goto <D.17684>; else goto <D.17685>;
      <D.17684>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 529, "!old_state.data.done_posted");
      <D.17685>:
      D.17686 = set_state (old_state, new_state);
      if (D.17686 == 0) goto <D.17687>; else goto <D.17688>;
      <D.17687>:
      monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "sgen-workers.c", 532);
      <D.17688>:
      i = 0;
      goto <D.17404>;
      <D.17403>:
      workers_start_worker (i);
      i = i + 1;
      <D.17404>:
      workers_num.30 = workers_num;
      if (i < workers_num.30) goto <D.17403>; else goto <D.17405>;
      <D.17405>:
      workers_started = 1;
    }
  finally
    {
      old_state = {CLOBBER};
      new_state = {CLOBBER};
    }
}


workers_start_worker (int index)
{
  int iftmp.31;
  int workers_num.32;
  _Bool D.17698;
  long int D.17699;
  long int D.17700;
  struct WorkerData * workers_data.33;
  unsigned int index.34;
  unsigned int D.17705;
  struct WorkerData * D.17706;
  long unsigned int D.17707;
  _Bool D.17708;
  long int D.17709;
  long int D.17710;
  void * D.17713;
  MonoNativeThreadId * D.17714;

  if (index < 0) goto <D.17693>; else goto <D.17696>;
  <D.17696>:
  workers_num.32 = workers_num;
  if (index >= workers_num.32) goto <D.17693>; else goto <D.17694>;
  <D.17693>:
  iftmp.31 = 1;
  goto <D.17695>;
  <D.17694>:
  iftmp.31 = 0;
  <D.17695>:
  D.17698 = iftmp.31 != 0;
  D.17699 = (long int) D.17698;
  D.17700 = __builtin_expect (D.17699, 0);
  if (D.17700 != 0) goto <D.17701>; else goto <D.17702>;
  <D.17701>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 485, "index >= 0 && index < workers_num");
  <D.17702>:
  workers_data.33 = workers_data;
  index.34 = (unsigned int) index;
  D.17705 = index.34 * 2100;
  D.17706 = workers_data.33 + D.17705;
  D.17707 = D.17706->thread;
  D.17708 = D.17707 != 0;
  D.17709 = (long int) D.17708;
  D.17710 = __builtin_expect (D.17709, 0);
  if (D.17710 != 0) goto <D.17711>; else goto <D.17712>;
  <D.17711>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 487, "!workers_data [index].thread");
  <D.17712>:
  workers_data.33 = workers_data;
  index.34 = (unsigned int) index;
  D.17705 = index.34 * 2100;
  D.17713 = workers_data.33 + D.17705;
  workers_data.33 = workers_data;
  index.34 = (unsigned int) index;
  D.17705 = index.34 * 2100;
  D.17706 = workers_data.33 + D.17705;
  D.17714 = &D.17706->thread;
  mono_native_thread_create (D.17714, workers_thread_func, D.17713);
}


workers_thread_func (void * data_untyped)
{
  void (*<Tbf>) (void *) D.17715;
  void * D.17718;
  int D.17719;
  int workers_marking.35;
  struct SgenGrayQueue * D.17725;
  int D.17726;
  int D.17728;
  struct SgenObjectOperations * iftmp.36;
  int D.17730;
  void (*<T2b53>) (char *, struct SgenGrayQueue *) D.17734;
  int D.17735;
  _Bool D.17736;
  long int D.17737;
  long int D.17738;
  int D.17741;
  int D.17742;
  _Bool D.17743;
  long int D.17744;
  long int D.17745;
  void * D.17750;
  struct WorkerData * data;
  struct SgenMajorCollector * major;

  data = data_untyped;
  major = sgen_get_major_collector ();
  mono_thread_info_register_small_id ();
  D.17715 = major->init_worker_thread;
  if (D.17715 != 0B) goto <D.17716>; else goto <D.17717>;
  <D.17716>:
  D.17715 = major->init_worker_thread;
  D.17718 = data->major_collector_data;
  D.17715 (D.17718);
  <D.17717>:
  init_private_gray_queue (data);
  <D.17379>:
  {
    gboolean did_work;

    did_work = 0;
    goto <D.17372>;
    <D.17371>:
    did_work = 1;
    <D.17372>:
    D.17719 = workers_dequeue_and_do_job (data);
    if (D.17719 != 0) goto <D.17371>; else goto <D.17373>;
    <D.17373>:
    workers_marking.35 = workers_marking;
    if (workers_marking.35 != 0) goto <D.17723>; else goto <D.17724>;
    <D.17723>:
    D.17725 = &data->private_gray_queue;
    D.17726 = sgen_gray_object_queue_is_empty (D.17725);
    if (D.17726 == 0) goto <D.17720>; else goto <D.17727>;
    <D.17727>:
    D.17728 = workers_get_work (data);
    if (D.17728 != 0) goto <D.17720>; else goto <D.17721>;
    <D.17720>:
    {
      struct SgenObjectOperations * ops;
      struct ScanCopyContext ctx;

      try
        {
          D.17730 = sgen_concurrent_collection_in_progress ();
          if (D.17730 != 0) goto <D.17731>; else goto <D.17732>;
          <D.17731>:
          iftmp.36 = &major->major_concurrent_ops;
          goto <D.17733>;
          <D.17732>:
          iftmp.36 = &major->major_ops;
          <D.17733>:
          ops = iftmp.36;
          D.17734 = ops->scan_object;
          ctx.scan_func = D.17734;
          ctx.copy_func = 0B;
          D.17725 = &data->private_gray_queue;
          ctx.queue = D.17725;
          D.17725 = &data->private_gray_queue;
          D.17735 = sgen_gray_object_queue_is_empty (D.17725);
          D.17736 = D.17735 != 0;
          D.17737 = (long int) D.17736;
          D.17738 = __builtin_expect (D.17737, 0);
          if (D.17738 != 0) goto <D.17739>; else goto <D.17740>;
          <D.17739>:
          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.17740>:
          goto <D.17377>;
          <D.17376>:
          D.17725 = &data->private_gray_queue;
          workers_gray_queue_share_redirect (D.17725);
          <D.17377>:
          D.17741 = sgen_drain_gray_stack (32, ctx);
          if (D.17741 == 0) goto <D.17376>; else goto <D.17378>;
          <D.17378>:
          D.17725 = &data->private_gray_queue;
          D.17742 = sgen_gray_object_queue_is_empty (D.17725);
          D.17743 = D.17742 == 0;
          D.17744 = (long int) D.17743;
          D.17745 = __builtin_expect (D.17744, 0);
          if (D.17745 != 0) goto <D.17746>; else goto <D.17747>;
          <D.17746>:
          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.17747>:
          init_private_gray_queue (data);
          did_work = 1;
        }
      finally
        {
          ctx = {CLOBBER};
        }
    }
    <D.17721>:
    <D.17724>:
    if (did_work == 0) goto <D.17748>; else goto <D.17749>;
    <D.17748>:
    workers_wait ();
    <D.17749>:
  }
  goto <D.17379>;
  D.17750 = 0B;
  return D.17750;
}


workers_dequeue_and_do_job (struct WorkerData * data)
{
  int workers_job_queue_num_entries.37;
  gboolean D.17755;
  volatile struct JobQueueEntry * workers_job_queue.38;
  int workers_job_queue_num_entries.39;
  int workers_job_queue_num_entries.40;
  int D.17763;
  _Bool D.17764;
  long int D.17765;
  long int D.17766;
  void (*<T2e2b>) (struct WorkerData *, void *) D.17769;
  void * D.17770;
  int D.17771;
  int D.17772;
  struct JobQueueEntry * entry;

  workers_job_queue_num_entries.37 = workers_job_queue_num_entries;
  if (workers_job_queue_num_entries.37 == 0) goto <D.17753>; else goto <D.17754>;
  <D.17753>:
  D.17755 = 0;
  return D.17755;
  <D.17754>:
  pthread_mutex_lock (&workers_job_queue_mutex);
  entry = workers_job_queue;
  if (entry != 0B) goto <D.17756>; else goto <D.17757>;
  <D.17756>:
  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.17757>:
  pthread_mutex_unlock (&workers_job_queue_mutex);
  if (entry == 0B) goto <D.17761>; else goto <D.17762>;
  <D.17761>:
  D.17755 = 0;
  return D.17755;
  <D.17762>:
  D.17763 = collection_needs_workers ();
  D.17764 = D.17763 == 0;
  D.17765 = (long int) D.17764;
  D.17766 = __builtin_expect (D.17765, 0);
  if (D.17766 != 0) goto <D.17767>; else goto <D.17768>;
  <D.17767>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 214, "collection_needs_workers ()");
  <D.17768>:
  D.17769 = entry->func;
  D.17770 = entry->data;
  D.17769 (data, D.17770);
  sgen_free_internal (entry, 26);
  {
    int __old_x;

    <D.17325>:
    __old_x = workers_num_jobs_finished;
    D.17771 = __old_x + 1;
    D.17772 = InterlockedCompareExchange (&workers_num_jobs_finished, D.17771, __old_x);
    if (D.17772 != __old_x) goto <D.17325>; else goto <D.17326>;
    <D.17326>:
  }
  D.17755 = 1;
  return D.17755;
}


workers_get_work (struct WorkerData * data)
{
  struct SgenGrayQueue * D.17774;
  int D.17775;
  _Bool D.17776;
  long int D.17777;
  long int D.17778;
  int D.17781;
  gboolean D.17784;
  struct WorkerData * workers_data.41;
  unsigned int i.42;
  unsigned int D.17787;
  int D.17790;
  int workers_num.43;
  int D.17796;
  int D.17798;
  int D.17801;
  _Bool D.17802;
  long int D.17803;
  long int D.17804;
  struct SgenMajorCollector * major;
  int i;

  D.17774 = &data->private_gray_queue;
  D.17775 = sgen_gray_object_queue_is_empty (D.17774);
  D.17776 = D.17775 == 0;
  D.17777 = (long int) D.17776;
  D.17778 = __builtin_expect (D.17777, 0);
  if (D.17778 != 0) goto <D.17779>; else goto <D.17780>;
  <D.17779>:
  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.17780>:
  D.17781 = workers_steal (data, data, 1);
  if (D.17781 != 0) goto <D.17782>; else goto <D.17783>;
  <D.17782>:
  D.17784 = 1;
  return D.17784;
  <D.17783>:
  i = 0;
  goto <D.17347>;
  <D.17346>:
  {
    struct WorkerData * victim_data;

    workers_data.41 = workers_data;
    i.42 = (unsigned int) i;
    D.17787 = i.42 * 2100;
    victim_data = workers_data.41 + D.17787;
    if (data == victim_data) goto <D.17788>; else goto <D.17789>;
    <D.17788>:
    // predicted unlikely by continue predictor.
    goto <D.17345>;
    <D.17789>:
    D.17790 = workers_steal (data, victim_data, 1);
    if (D.17790 != 0) goto <D.17791>; else goto <D.17792>;
    <D.17791>:
    D.17784 = 1;
    return D.17784;
    <D.17792>:
  }
  <D.17345>:
  i = i + 1;
  <D.17347>:
  workers_num.43 = workers_num;
  if (i < workers_num.43) goto <D.17346>; else goto <D.17348>;
  <D.17348>:
  major = sgen_get_major_collector ();
  D.17796 = major->is_concurrent;
  if (D.17796 != 0) goto <D.17794>; else goto <D.17797>;
  <D.17797>:
  D.17798 = major->is_parallel;
  if (D.17798 != 0) goto <D.17794>; else goto <D.17795>;
  <D.17794>:
  {
    struct GrayQueueSection * section;

    section = sgen_section_gray_queue_dequeue (&workers_distribute_gray_queue);
    if (section != 0B) goto <D.17799>; else goto <D.17800>;
    <D.17799>:
    D.17774 = &data->private_gray_queue;
    sgen_gray_object_enqueue_section (D.17774, section);
    D.17784 = 1;
    return D.17784;
    <D.17800>:
  }
  <D.17795>:
  D.17774 = &data->private_gray_queue;
  D.17801 = sgen_gray_object_queue_is_empty (D.17774);
  D.17802 = D.17801 == 0;
  D.17803 = (long int) D.17802;
  D.17804 = __builtin_expect (D.17803, 0);
  if (D.17804 != 0) goto <D.17805>; else goto <D.17806>;
  <D.17805>:
  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.17806>:
  D.17784 = 0;
  return D.17784;
}


workers_steal (struct WorkerData * data, struct WorkerData * victim_data, gboolean lock)
{
  struct GrayQueueSection * D.17808;
  _Bool D.17809;
  long int D.17810;
  long int D.17811;
  int D.17814;
  gboolean D.17817;
  union mono_mutex_t * D.17820;
  int D.17821;
  int D.17824;
  int D.17825;
  unsigned int m.44;
  unsigned int D.17827;
  int D.17828;
  sizetype D.17829;
  sizetype n.45;
  sizetype num.46;
  sizetype D.17832;
  sizetype D.17833;
  char * * D.17834;
  char *[125] * D.17835;
  int D.17836;
  int D.17837;
  long long int D.17844;
  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.17853;
  struct SgenGrayQueue * queue;
  int num;
  int n;

  queue = &data->private_gray_queue;
  D.17808 = queue->first;
  D.17809 = D.17808 != 0B;
  D.17810 = (long int) D.17809;
  D.17811 = __builtin_expect (D.17810, 0);
  if (D.17811 != 0) goto <D.17812>; else goto <D.17813>;
  <D.17812>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 230, "!queue->first");
  <D.17813>:
  D.17814 = victim_data->stealable_stack_fill;
  if (D.17814 == 0) goto <D.17815>; else goto <D.17816>;
  <D.17815>:
  D.17817 = 0;
  return D.17817;
  <D.17816>:
  if (lock != 0) goto <D.17818>; else goto <D.17819>;
  <D.17818>:
  D.17820 = &victim_data->stealable_stack_mutex;
  D.17821 = pthread_mutex_trylock (D.17820);
  if (D.17821 != 0) goto <D.17822>; else goto <D.17823>;
  <D.17822>:
  D.17817 = 0;
  return D.17817;
  <D.17823>:
  <D.17819>:
  D.17824 = victim_data->stealable_stack_fill;
  D.17825 = D.17824 + 1;
  num = D.17825 / 2;
  n = num;
  goto <D.17337>;
  <D.17336>:
  {
    int m;

    m = MIN_EXPR <n, 125>;
    n = n - m;
    sgen_gray_object_alloc_queue_section (queue);
    m.44 = (unsigned int) m;
    D.17827 = m.44 * 4;
    D.17828 = victim_data->stealable_stack_fill;
    D.17829 = (sizetype) D.17828;
    n.45 = (sizetype) n;
    num.46 = (sizetype) num;
    D.17832 = n.45 - num.46;
    D.17833 = D.17829 + D.17832;
    D.17834 = &victim_data->stealable_stack[D.17833];
    D.17808 = queue->first;
    D.17835 = &D.17808->objects;
    memcpy (D.17835, D.17834, D.17827);
    D.17808 = queue->first;
    D.17808->end = m;
  }
  <D.17337>:
  if (n > 0) goto <D.17336>; else goto <D.17338>;
  <D.17338>:
  D.17836 = victim_data->stealable_stack_fill;
  D.17837 = D.17836 - num;
  victim_data->stealable_stack_fill = D.17837;
  if (lock != 0) goto <D.17838>; else goto <D.17839>;
  <D.17838>:
  D.17820 = &victim_data->stealable_stack_mutex;
  pthread_mutex_unlock (D.17820);
  <D.17839>:
  if (data == victim_data) goto <D.17840>; else goto <D.17841>;
  <D.17840>:
  if (lock != 0) goto <D.17842>; else goto <D.17843>;
  <D.17842>:
  D.17844 = (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.17844 + stat_workers_stolen_from_self_lock.47;
  stat_workers_stolen_from_self_lock = stat_workers_stolen_from_self_lock.48;
  goto <D.17847>;
  <D.17843>:
  D.17844 = (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.17844 + stat_workers_stolen_from_self_no_lock.49;
  stat_workers_stolen_from_self_no_lock = stat_workers_stolen_from_self_no_lock.50;
  <D.17847>:
  goto <D.17850>;
  <D.17841>:
  D.17844 = (long long int) num;
  stat_workers_stolen_from_others.51 = stat_workers_stolen_from_others;
  stat_workers_stolen_from_others.52 = D.17844 + stat_workers_stolen_from_others.51;
  stat_workers_stolen_from_others = stat_workers_stolen_from_others.52;
  <D.17850>:
  D.17853 = num != 0;
  D.17817 = (gboolean) D.17853;
  return D.17817;
}


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

  D.17856 = __builtin_object_size (__dest, 0);
  D.17855 = __builtin___memcpy_chk (__dest, __src, __len, D.17856);
  return D.17855;
}


workers_gray_queue_share_redirect (struct SgenGrayQueue * queue)
{
  int D.17858;
  <unnamed-unsigned:1> D.17861;
  union mono_mutex_t * D.17864;
  int iftmp.53;
  int D.17866;
  int D.17867;
  int D.17868;
  int D.17872;
  unsigned int num.54;
  unsigned int D.17874;
  sizetype D.17875;
  char * * D.17876;
  sizetype D.17877;
  char * * D.17878;
  int D.17879;
  sizetype D.17880;
  char * * D.17881;
  int D.17882;
  int D.17883;
  int D.17884;
  int D.17888;
  int D.17890;
  <unnamed-unsigned:1> D.17893;
  struct GrayQueueSection * section;
  struct WorkerData * data;

  data = queue->alloc_prepare_data;
  D.17858 = data->stealable_stack_fill;
  if (D.17858 != 0) goto <D.17859>; else goto <D.17860>;
  <D.17859>:
  D.17861 = workers_state.data.gc_in_progress;
  if (D.17861 != 0) goto <D.17862>; else goto <D.17863>;
  <D.17862>:
  workers_wake_up_all ();
  <D.17863>:
  return;
  <D.17860>:
  D.17864 = &data->stealable_stack_mutex;
  pthread_mutex_lock (D.17864);
  goto <D.17357>;
  <D.17356>:
  {
    int num;

    D.17866 = section->end;
    D.17867 = data->stealable_stack_fill;
    D.17868 = 512 - D.17867;
    if (D.17866 < D.17868) goto <D.17869>; else goto <D.17870>;
    <D.17869>:
    iftmp.53 = section->end;
    goto <D.17871>;
    <D.17870>:
    D.17872 = data->stealable_stack_fill;
    iftmp.53 = 512 - D.17872;
    <D.17871>:
    num = iftmp.53;
    num.54 = (unsigned int) num;
    D.17874 = num.54 * 4;
    D.17866 = section->end;
    D.17875 = (sizetype) D.17866;
    D.17876 = &section->objects[D.17875];
    num.54 = (unsigned int) num;
    D.17874 = num.54 * 4;
    D.17877 = -D.17874;
    D.17878 = D.17876 + D.17877;
    D.17879 = data->stealable_stack_fill;
    D.17880 = (sizetype) D.17879;
    D.17881 = &data->stealable_stack[D.17880];
    memcpy (D.17881, D.17878, D.17874);
    D.17866 = section->end;
    D.17882 = D.17866 - num;
    section->end = D.17882;
    D.17883 = data->stealable_stack_fill;
    D.17884 = D.17883 + num;
    data->stealable_stack_fill = D.17884;
    D.17866 = section->end;
    if (D.17866 != 0) goto <D.17885>; else goto <D.17886>;
    <D.17885>:
    sgen_gray_object_enqueue_section (queue, section);
    goto <D.17887>;
    <D.17886>:
    sgen_gray_object_free_queue_section (section);
    <D.17887>:
  }
  <D.17357>:
  D.17888 = data->stealable_stack_fill;
  if (D.17888 <= 511) goto <D.17889>; else goto <D.17358>;
  <D.17889>:
  section = sgen_gray_object_dequeue_section (queue);
  if (section != 0B) goto <D.17356>; else goto <D.17358>;
  <D.17358>:
  D.17890 = sgen_gray_object_queue_is_empty (queue);
  if (D.17890 != 0) goto <D.17891>; else goto <D.17892>;
  <D.17891>:
  workers_steal (data, data, 0);
  <D.17892>:
  D.17864 = &data->stealable_stack_mutex;
  pthread_mutex_unlock (D.17864);
  D.17893 = workers_state.data.gc_in_progress;
  if (D.17893 != 0) goto <D.17894>; else goto <D.17895>;
  <D.17894>:
  workers_wake_up_all ();
  <D.17895>:
}


sgen_gray_object_queue_is_empty (struct SgenGrayQueue * queue)
{
  gboolean D.17897;
  struct GrayQueueSection * D.17898;
  _Bool D.17899;

  D.17898 = queue->first;
  D.17899 = D.17898 == 0B;
  D.17897 = (gboolean) D.17899;
  return D.17897;
}


init_private_gray_queue (struct WorkerData * data)
{
  void (*<T2a94>) (char *) iftmp.55;
  struct SgenMajorCollector * D.17902;
  int D.17903;
  struct SgenGrayQueue * D.17907;

  D.17902 = sgen_get_major_collector ();
  D.17903 = D.17902->is_concurrent;
  if (D.17903 != 0) goto <D.17904>; else goto <D.17905>;
  <D.17904>:
  iftmp.55 = concurrent_enqueue_check;
  goto <D.17906>;
  <D.17905>:
  iftmp.55 = 0B;
  <D.17906>:
  D.17907 = &data->private_gray_queue;
  sgen_gray_object_queue_init_with_alloc_prepare (D.17907, 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.17910;
  unsigned char D.17911;
  _Bool D.17912;
  long int D.17913;
  long int D.17914;
  unsigned char D.17917;
  unsigned char D.17918;
  int D.17919;
  int workers_num.58;
  unsigned char D.17923;
  int D.17926;
  unsigned char D.17927;
  unsigned char D.17928;
  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.17302>:
      new_state = workers_state;
      old_state = new_state;
      D.17910 = BIT_FIELD_REF <old_state, 8, 8>;
      D.17911 = D.17910 & 1;
      D.17912 = D.17911 != 0;
      D.17913 = (long int) D.17912;
      D.17914 = __builtin_expect (D.17913, 0);
      if (D.17914 != 0) goto <D.17915>; else goto <D.17916>;
      <D.17915>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 125, "!old_state.data.done_posted");
      <D.17916>:
      D.17917 = new_state.data.num_waiting;
      D.17918 = D.17917 + 1;
      new_state.data.num_waiting = D.17918;
      D.17917 = new_state.data.num_waiting;
      D.17919 = (int) D.17917;
      workers_num.58 = workers_num;
      if (D.17919 == workers_num.58) goto <D.17921>; else goto <D.17922>;
      <D.17921>:
      D.17910 = BIT_FIELD_REF <old_state, 8, 8>;
      D.17923 = D.17910 & 2;
      if (D.17923 == 0) goto <D.17924>; else goto <D.17925>;
      <D.17924>:
      new_state.data.done_posted = 1;
      <D.17925>:
      <D.17922>:
      D.17926 = set_state (old_state, new_state);
      if (D.17926 == 0) goto <D.17302>; else goto <D.17303>;
      <D.17303>:
      mono_memory_barrier ();
      D.17927 = BIT_FIELD_REF <new_state, 8, 8>;
      D.17928 = D.17927 & 1;
      if (D.17928 != 0) goto <D.17929>; else goto <D.17930>;
      <D.17929>:
      mono_sem_post (&workers_done_sem);
      <D.17930>:
      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.17931;
  <unnamed-unsigned:1> D.17932;

  D.17932 = workers_state.data.gc_in_progress;
  D.17931 = (gboolean) D.17932;
  return D.17931;
}


sgen_workers_start_marking ()
{
  int D.17934;
  int iftmp.59;
  int workers_started.60;
  <unnamed-unsigned:1> D.17943;
  _Bool D.17944;
  long int D.17945;
  long int D.17946;
  int workers_marking.61;
  _Bool D.17950;
  long int D.17951;
  long int D.17952;

  D.17934 = collection_needs_workers ();
  if (D.17934 == 0) goto <D.17935>; else goto <D.17936>;
  <D.17935>:
  return;
  <D.17936>:
  workers_started.60 = workers_started;
  if (workers_started.60 == 0) goto <D.17938>; else goto <D.17942>;
  <D.17942>:
  D.17943 = workers_state.data.gc_in_progress;
  if (D.17943 == 0) goto <D.17938>; else goto <D.17939>;
  <D.17938>:
  iftmp.59 = 1;
  goto <D.17940>;
  <D.17939>:
  iftmp.59 = 0;
  <D.17940>:
  D.17944 = iftmp.59 != 0;
  D.17945 = (long int) D.17944;
  D.17946 = __builtin_expect (D.17945, 0);
  if (D.17946 != 0) goto <D.17947>; else goto <D.17948>;
  <D.17947>:
  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.17948>:
  workers_marking.61 = workers_marking;
  D.17950 = workers_marking.61 != 0;
  D.17951 = (long int) D.17950;
  D.17952 = __builtin_expect (D.17951, 0);
  if (D.17952 != 0) goto <D.17953>; else goto <D.17954>;
  <D.17953>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 553, "!workers_marking");
  <D.17954>:
  workers_marking = 1;
  workers_wake_up_all ();
}


sgen_workers_join ()
{
  int D.17956;
  unsigned char D.17959;
  unsigned char D.17960;
  _Bool D.17961;
  long int D.17962;
  long int D.17963;
  unsigned char D.17966;
  _Bool D.17967;
  long int D.17968;
  long int D.17969;
  int D.17972;
  unsigned char D.17973;
  int D.17974;
  int workers_num.62;
  unsigned char D.17978;
  int D.17979;
  _Bool D.17980;
  long int D.17981;
  long int D.17982;
  _Bool D.17985;
  long int D.17986;
  long int D.17987;
  int workers_job_queue_num_entries.63;
  int D.17994;
  int D.17995;
  struct SgenMajorCollector * D.17998;
  void (*<Tbf>) (void *) D.17999;
  struct SgenMajorCollector * D.18002;
  void (*<Tbf>) (void *) D.18003;
  struct WorkerData * workers_data.64;
  unsigned int i.65;
  unsigned int D.18006;
  struct WorkerData * D.18007;
  void * D.18008;
  int workers_job_queue_num_entries.66;
  _Bool D.18010;
  long int D.18011;
  long int D.18012;
  int D.18015;
  _Bool D.18016;
  long int D.18017;
  long int D.18018;
  int D.18021;
  _Bool D.18022;
  long int D.18023;
  long int D.18024;
  struct SgenGrayQueue * D.18027;
  int D.18028;
  _Bool D.18029;
  long int D.18030;
  long int D.18031;
  union State old_state;
  union State new_state;
  int i;
  void reawaken = <<< error >>>;

  try
    {
      D.17956 = collection_needs_workers ();
      if (D.17956 == 0) goto <D.17957>; else goto <D.17958>;
      <D.17957>:
      return;
      <D.17958>:
      <D.17418>:
      new_state = workers_state;
      old_state = new_state;
      D.17959 = BIT_FIELD_REF <old_state, 8, 8>;
      D.17960 = D.17959 & 2;
      D.17961 = D.17960 == 0;
      D.17962 = (long int) D.17961;
      D.17963 = __builtin_expect (D.17962, 0);
      if (D.17963 != 0) goto <D.17964>; else goto <D.17965>;
      <D.17964>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 571, "old_state.data.gc_in_progress");
      <D.17965>:
      D.17959 = BIT_FIELD_REF <old_state, 8, 8>;
      D.17966 = D.17959 & 1;
      D.17967 = D.17966 != 0;
      D.17968 = (long int) D.17967;
      D.17969 = __builtin_expect (D.17968, 0);
      if (D.17969 != 0) goto <D.17970>; else goto <D.17971>;
      <D.17970>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 572, "!old_state.data.done_posted");
      <D.17971>:
      new_state.data.gc_in_progress = 0;
      D.17972 = set_state (old_state, new_state);
      if (D.17972 == 0) goto <D.17418>; else goto <D.17419>;
      <D.17419>:
      D.17973 = new_state.data.num_waiting;
      D.17974 = (int) D.17973;
      workers_num.62 = workers_num;
      if (D.17974 == workers_num.62) goto <D.17976>; else goto <D.17977>;
      <D.17976>:
      reawaken:
      workers_wake_up_all ();
      <D.17977>:
      mono_sem_wait (&workers_done_sem, 0);
      new_state = workers_state;
      old_state = new_state;
      D.17978 = old_state.data.num_waiting;
      D.17979 = (int) D.17978;
      workers_num.62 = workers_num;
      D.17980 = D.17979 != workers_num.62;
      D.17981 = (long int) D.17980;
      D.17982 = __builtin_expect (D.17981, 0);
      if (D.17982 != 0) goto <D.17983>; else goto <D.17984>;
      <D.17983>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 593, "old_state.data.num_waiting == workers_num");
      <D.17984>:
      D.17959 = BIT_FIELD_REF <old_state, 8, 8>;
      D.17966 = D.17959 & 1;
      D.17985 = D.17966 == 0;
      D.17986 = (long int) D.17985;
      D.17987 = __builtin_expect (D.17986, 0);
      if (D.17987 != 0) goto <D.17988>; else goto <D.17989>;
      <D.17988>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 594, "old_state.data.done_posted");
      <D.17989>:
      workers_job_queue_num_entries.63 = workers_job_queue_num_entries;
      if (workers_job_queue_num_entries.63 != 0) goto <D.17990>; else goto <D.17993>;
      <D.17993>:
      D.17994 = sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue);
      if (D.17994 == 0) goto <D.17990>; else goto <D.17991>;
      <D.17990>:
      new_state.data.done_posted = 0;
      D.17995 = set_state (old_state, new_state);
      if (D.17995 == 0) goto <D.17996>; else goto <D.17997>;
      <D.17996>:
      monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "sgen-workers.c", 613);
      <D.17997>:
      goto reawaken;
      <D.17991>:
      workers_marking = 0;
      D.17998 = sgen_get_major_collector ();
      D.17999 = D.17998->reset_worker_data;
      if (D.17999 != 0B) goto <D.18000>; else goto <D.18001>;
      <D.18000>:
      i = 0;
      goto <D.17422>;
      <D.17421>:
      D.18002 = sgen_get_major_collector ();
      D.18003 = D.18002->reset_worker_data;
      workers_data.64 = workers_data;
      i.65 = (unsigned int) i;
      D.18006 = i.65 * 2100;
      D.18007 = workers_data.64 + D.18006;
      D.18008 = D.18007->major_collector_data;
      D.18003 (D.18008);
      i = i + 1;
      <D.17422>:
      workers_num.62 = workers_num;
      if (i < workers_num.62) goto <D.17421>; else goto <D.17423>;
      <D.17423>:
      <D.18001>:
      workers_job_queue_num_entries.66 = workers_job_queue_num_entries;
      D.18010 = workers_job_queue_num_entries.66 != 0;
      D.18011 = (long int) D.18010;
      D.18012 = __builtin_expect (D.18011, 0);
      if (D.18012 != 0) goto <D.18013>; else goto <D.18014>;
      <D.18013>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 626, "workers_job_queue_num_entries == 0");
      <D.18014>:
      D.18015 = sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue);
      D.18016 = D.18015 == 0;
      D.18017 = (long int) D.18016;
      D.18018 = __builtin_expect (D.18017, 0);
      if (D.18018 != 0) goto <D.18019>; else goto <D.18020>;
      <D.18019>:
      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.18020>:
      i = 0;
      goto <D.17425>;
      <D.17424>:
      workers_data.64 = workers_data;
      i.65 = (unsigned int) i;
      D.18006 = i.65 * 2100;
      D.18007 = workers_data.64 + D.18006;
      D.18021 = D.18007->stealable_stack_fill;
      D.18022 = D.18021 != 0;
      D.18023 = (long int) D.18022;
      D.18024 = __builtin_expect (D.18023, 0);
      if (D.18024 != 0) goto <D.18025>; else goto <D.18026>;
      <D.18025>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 629, "!workers_data [i].stealable_stack_fill");
      <D.18026>:
      workers_data.64 = workers_data;
      i.65 = (unsigned int) i;
      D.18006 = i.65 * 2100;
      D.18007 = workers_data.64 + D.18006;
      D.18027 = &D.18007->private_gray_queue;
      D.18028 = sgen_gray_object_queue_is_empty (D.18027);
      D.18029 = D.18028 == 0;
      D.18030 = (long int) D.18029;
      D.18031 = __builtin_expect (D.18030, 0);
      if (D.18031 != 0) goto <D.18032>; else goto <D.18033>;
      <D.18032>:
      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.18033>:
      i = i + 1;
      <D.17425>:
      workers_num.62 = workers_num;
      if (i < workers_num.62) goto <D.17424>; else goto <D.17426>;
      <D.17426>:
    }
  finally
    {
      old_state = {CLOBBER};
      new_state = {CLOBBER};
    }
}


sgen_workers_all_done ()
{
  unsigned char D.18037;
  unsigned char D.18038;
  _Bool D.18039;
  long int D.18040;
  long int D.18041;
  unsigned char D.18044;
  _Bool D.18045;
  long int D.18046;
  long int D.18047;
  gboolean D.18050;
  unsigned char D.18051;
  int D.18052;
  int workers_num.67;
  _Bool D.18054;
  union State state;

  try
    {
      state = workers_state;
      D.18037 = BIT_FIELD_REF <state, 8, 8>;
      D.18038 = D.18037 & 2;
      D.18039 = D.18038 == 0;
      D.18040 = (long int) D.18039;
      D.18041 = __builtin_expect (D.18040, 0);
      if (D.18041 != 0) goto <D.18042>; else goto <D.18043>;
      <D.18042>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 642, "state.data.gc_in_progress");
      <D.18043>:
      D.18037 = BIT_FIELD_REF <state, 8, 8>;
      D.18044 = D.18037 & 1;
      D.18045 = D.18044 != 0;
      D.18046 = (long int) D.18045;
      D.18047 = __builtin_expect (D.18046, 0);
      if (D.18047 != 0) goto <D.18048>; else goto <D.18049>;
      <D.18048>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 643, "!state.data.done_posted");
      <D.18049>:
      D.18051 = state.data.num_waiting;
      D.18052 = (int) D.18051;
      workers_num.67 = workers_num;
      D.18054 = D.18052 == workers_num.67;
      D.18050 = (gboolean) D.18054;
      return D.18050;
    }
  finally
    {
      state = {CLOBBER};
    }
}


sgen_is_worker_thread (MonoNativeThreadId thread)
{
  struct SgenMajorCollector * D.18057;
  gboolean (*<T2c74>) (MonoNativeThreadId) D.18058;
  struct SgenMajorCollector * D.18061;
  gboolean (*<T2c74>) (MonoNativeThreadId) D.18062;
  int D.18063;
  gboolean D.18066;
  struct WorkerData * workers_data.68;
  unsigned int i.69;
  unsigned int D.18069;
  struct WorkerData * D.18070;
  long unsigned int D.18071;
  int workers_num.70;
  int i;

  D.18057 = sgen_get_major_collector ();
  D.18058 = D.18057->is_worker_thread;
  if (D.18058 != 0B) goto <D.18059>; else goto <D.18060>;
  <D.18059>:
  D.18061 = sgen_get_major_collector ();
  D.18062 = D.18061->is_worker_thread;
  D.18063 = D.18062 (thread);
  if (D.18063 != 0) goto <D.18064>; else goto <D.18065>;
  <D.18064>:
  D.18066 = 1;
  return D.18066;
  <D.18065>:
  <D.18060>:
  i = 0;
  goto <D.17436>;
  <D.17435>:
  workers_data.68 = workers_data;
  i.69 = (unsigned int) i;
  D.18069 = i.69 * 2100;
  D.18070 = workers_data.68 + D.18069;
  D.18071 = D.18070->thread;
  if (D.18071 == thread) goto <D.18072>; else goto <D.18073>;
  <D.18072>:
  D.18066 = 1;
  return D.18066;
  <D.18073>:
  i = i + 1;
  <D.17436>:
  workers_num.70 = workers_num;
  if (i < workers_num.70) goto <D.17435>; else goto <D.17437>;
  <D.17437>:
  D.18066 = 0;
  return D.18066;
}


sgen_workers_get_distribute_section_gray_queue ()
{
  struct SgenSectionGrayQueue * D.18076;

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


sgen_workers_reset_data ()
{
  struct SgenMajorCollector * D.18078;
  void (*<Tbf>) (void *) D.18079;
  struct SgenMajorCollector * D.18082;
  void (*<Tbf>) (void *) D.18083;
  void * workers_gc_thread_major_collector_data.71;

  D.18078 = sgen_get_major_collector ();
  D.18079 = D.18078->reset_worker_data;
  if (D.18079 != 0B) goto <D.18080>; else goto <D.18081>;
  <D.18080>:
  D.18082 = sgen_get_major_collector ();
  D.18083 = D.18082->reset_worker_data;
  workers_gc_thread_major_collector_data.71 = workers_gc_thread_major_collector_data;
  D.18083 (workers_gc_thread_major_collector_data.71);
  <D.18081>:
}


