sgen_workers_wake_up_all ()
{
  <unnamed-unsigned:1> D.17425;
  _Bool D.17426;
  long int D.17427;
  long int D.17428;

  D.17425 = workers_state.data.gc_in_progress;
  D.17426 = ~D.17425;
  D.17427 = (long int) D.17426;
  D.17428 = __builtin_expect (D.17427, 0);
  if (D.17428 != 0) goto <D.17429>; else goto <D.17430>;
  <D.17429>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 109, "workers_state.data.gc_in_progress");
  <D.17430>:
  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 int D.17432;
  unsigned int D.17433;
  unsigned char D.17436;
  unsigned char D.17439;
  unsigned char D.17440;
  int D.17441;
  int i;

  i = 0;
  goto <D.17269>;
  <D.17268>:
  {
    union State old_state;
    union State new_state;

    try
      {
        <D.17266>:
        new_state = workers_state;
        old_state = new_state;
        D.17432 = BIT_FIELD_REF <old_state, 32, 0>;
        D.17433 = D.17432 & 256;
        if (D.17433 != 0) goto <D.17434>; else goto <D.17435>;
        <D.17434>:
        return;
        <D.17435>:
        D.17436 = old_state.data.num_waiting;
        if (D.17436 == 0) goto <D.17437>; else goto <D.17438>;
        <D.17437>:
        return;
        <D.17438>:
        D.17439 = new_state.data.num_waiting;
        D.17440 = D.17439 + 255;
        new_state.data.num_waiting = D.17440;
        D.17441 = set_state (old_state, new_state);
        if (D.17441 == 0) goto <D.17266>; else goto <D.17267>;
        <D.17267>:
        mono_sem_post (&workers_waiting_sem);
      }
    finally
      {
        old_state = {CLOBBER};
        new_state = {CLOBBER};
      }
  }
  i = i + 1;
  <D.17269>:
  if (i < max) goto <D.17268>; else goto <D.17270>;
  <D.17270>:
}


set_state (union State old_state, union State new_state)
{
  gboolean D.17445;
  int D.17446;
  int D.17447;
  int D.17448;
  _Bool D.17449;

  D.17446 = new_state.value;
  D.17447 = old_state.value;
  D.17448 = InterlockedCompareExchange (&workers_state.value, D.17446, D.17447);
  D.17447 = old_state.value;
  D.17449 = D.17448 == D.17447;
  D.17445 = (gboolean) D.17449;
  return D.17445;
}


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

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


sgen_workers_enqueue_job (void (*JobFunc) (struct WorkerData *, void *) func, void * data)
{
  int D.17456;
  <unnamed-unsigned:1> D.17459;
  _Bool D.17460;
  long int D.17461;
  long int D.17462;
  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.17456 = collection_needs_workers ();
  if (D.17456 == 0) goto <D.17457>; else goto <D.17458>;
  <D.17457>:
  func (0B, data);
  return;
  <D.17458>:
  D.17459 = workers_state.data.gc_in_progress;
  D.17460 = ~D.17459;
  D.17461 = (long int) D.17460;
  D.17462 = __builtin_expect (D.17461, 0);
  if (D.17462 != 0) goto <D.17463>; else goto <D.17464>;
  <D.17463>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 157, "workers_state.data.gc_in_progress");
  <D.17464>:
  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.17472;
  int iftmp.9;
  int D.17477;
  int D.17479;

  D.17477 = sgen_collection_is_parallel ();
  if (D.17477 != 0) goto <D.17474>; else goto <D.17478>;
  <D.17478>:
  D.17479 = sgen_collection_is_concurrent ();
  if (D.17479 != 0) goto <D.17474>; else goto <D.17475>;
  <D.17474>:
  iftmp.9 = 1;
  goto <D.17476>;
  <D.17475>:
  iftmp.9 = 0;
  <D.17476>:
  D.17472 = iftmp.9;
  return D.17472;
}


sgen_workers_wait_for_jobs ()
{
  unsigned int D.17481;
  unsigned int D.17482;
  _Bool D.17483;
  long int D.17484;
  long int D.17485;
  unsigned int D.17488;
  _Bool D.17489;
  long int D.17490;
  long int D.17491;
  unsigned char D.17494;
  int D.17495;
  int workers_num.10;
  int workers_num_jobs_finished.11;
  int workers_num_jobs_enqueued.12;

  goto <D.17298>;
  <D.17297>:
  {
    union State state;

    try
      {
        state = workers_state;
        D.17481 = BIT_FIELD_REF <state, 32, 0>;
        D.17482 = D.17481 & 512;
        D.17483 = D.17482 == 0;
        D.17484 = (long int) D.17483;
        D.17485 = __builtin_expect (D.17484, 0);
        if (D.17485 != 0) goto <D.17486>; else goto <D.17487>;
        <D.17486>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 179, "state.data.gc_in_progress");
        <D.17487>:
        D.17481 = BIT_FIELD_REF <state, 32, 0>;
        D.17488 = D.17481 & 256;
        D.17489 = D.17488 != 0;
        D.17490 = (long int) D.17489;
        D.17491 = __builtin_expect (D.17490, 0);
        if (D.17491 != 0) goto <D.17492>; else goto <D.17493>;
        <D.17492>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 180, "!state.data.done_posted");
        <D.17493>:
        D.17494 = state.data.num_waiting;
        D.17495 = (int) D.17494;
        workers_num.10 = workers_num;
        if (D.17495 == workers_num.10) goto <D.17497>; else goto <D.17498>;
        <D.17497>:
        workers_wake_up_all ();
        <D.17498>:
        monoeg_g_usleep (1000);
      }
    finally
      {
        state = {CLOBBER};
      }
  }
  <D.17298>:
  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.17297>; else goto <D.17299>;
  <D.17299>:
}


sgen_workers_init_distribute_gray_queue ()
{
  int D.17501;
  int iftmp.13;
  struct SgenMajorCollector * D.17508;
  int D.17509;
  struct SgenMajorCollector * D.17511;
  int D.17512;

  D.17501 = collection_needs_workers ();
  if (D.17501 == 0) goto <D.17502>; else goto <D.17503>;
  <D.17502>:
  return;
  <D.17503>:
  D.17508 = sgen_get_major_collector ();
  D.17509 = D.17508->is_concurrent;
  if (D.17509 != 0) goto <D.17505>; else goto <D.17510>;
  <D.17510>:
  D.17511 = sgen_get_major_collector ();
  D.17512 = D.17511->is_parallel;
  if (D.17512 != 0) goto <D.17505>; else goto <D.17506>;
  <D.17505>:
  iftmp.13 = 1;
  goto <D.17507>;
  <D.17506>:
  iftmp.13 = 0;
  <D.17507>:
  init_distribute_gray_queue (iftmp.13);
}


init_distribute_gray_queue (gboolean locked)
{
  int workers_distribute_gray_queue_inited.14;
  int D.17517;
  _Bool D.17518;
  long int D.17519;
  long int D.17520;
  int D.17523;
  _Bool D.17524;
  _Bool D.17525;
  _Bool D.17526;
  long int D.17527;
  long int D.17528;
  void (*<T2a8e>) (char *) iftmp.15;
  struct SgenMajorCollector * D.17532;
  int D.17533;

  workers_distribute_gray_queue_inited.14 = workers_distribute_gray_queue_inited;
  if (workers_distribute_gray_queue_inited.14 != 0) goto <D.17515>; else goto <D.17516>;
  <D.17515>:
  D.17517 = sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue);
  D.17518 = D.17517 == 0;
  D.17519 = (long int) D.17518;
  D.17520 = __builtin_expect (D.17519, 0);
  if (D.17520 != 0) goto <D.17521>; else goto <D.17522>;
  <D.17521>:
  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.17522>:
  D.17523 = workers_distribute_gray_queue.locked;
  D.17524 = D.17523 == 0;
  D.17525 = locked == 0;
  D.17526 = D.17524 ^ D.17525;
  D.17527 = (long int) D.17526;
  D.17528 = __builtin_expect (D.17527, 0);
  if (D.17528 != 0) goto <D.17529>; else goto <D.17530>;
  <D.17529>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 420, "!workers_distribute_gray_queue.locked == !locked");
  <D.17530>:
  return;
  <D.17516>:
  D.17532 = sgen_get_major_collector ();
  D.17533 = D.17532->is_concurrent;
  if (D.17533 != 0) goto <D.17534>; else goto <D.17535>;
  <D.17534>:
  iftmp.15 = concurrent_enqueue_check;
  goto <D.17536>;
  <D.17535>:
  iftmp.15 = 0B;
  <D.17536>:
  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.17538;
  _Bool D.17539;
  long int D.17540;
  long int D.17541;
  int D.17544;
  _Bool D.17545;
  long int D.17546;
  long int D.17547;
  unsigned int D.17550;
  unsigned int D.17551;
  _Bool D.17552;
  long int D.17553;
  long int D.17554;

  D.17538 = sgen_concurrent_collection_in_progress ();
  D.17539 = D.17538 == 0;
  D.17540 = (long int) D.17539;
  D.17541 = __builtin_expect (D.17540, 0);
  if (D.17541 != 0) goto <D.17542>; else goto <D.17543>;
  <D.17542>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 356, "sgen_concurrent_collection_in_progress ()");
  <D.17543>:
  D.17544 = sgen_ptr_in_nursery (obj);
  D.17545 = D.17544 != 0;
  D.17546 = (long int) D.17545;
  D.17547 = __builtin_expect (D.17546, 0);
  if (D.17547 != 0) goto <D.17548>; else goto <D.17549>;
  <D.17548>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 357, "!sgen_ptr_in_nursery (obj)");
  <D.17549>:
  D.17550 = MEM[(mword *)obj];
  D.17551 = D.17550 & 4294967292;
  D.17552 = D.17551 == 0;
  D.17553 = (long int) D.17552;
  D.17554 = __builtin_expect (D.17553, 0);
  if (D.17554 != 0) goto <D.17555>; else goto <D.17556>;
  <D.17555>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 358, "SGEN_LOAD_VTABLE (obj)");
  <D.17556>:
}


sgen_ptr_in_nursery (void * p)
{
  gboolean D.17557;
  int sgen_nursery_bits.16;
  int D.17559;
  int D.17560;
  unsigned int D.17561;
  unsigned int p.17;
  unsigned int D.17563;
  char * sgen_nursery_start.18;
  unsigned int sgen_nursery_start.19;
  _Bool D.17566;

  sgen_nursery_bits.16 = sgen_nursery_bits;
  D.17559 = 1 << sgen_nursery_bits.16;
  D.17560 = -D.17559;
  D.17561 = (unsigned int) D.17560;
  p.17 = (unsigned int) p;
  D.17563 = D.17561 & p.17;
  sgen_nursery_start.18 = sgen_nursery_start;
  sgen_nursery_start.19 = (unsigned int) sgen_nursery_start.18;
  D.17566 = D.17563 == sgen_nursery_start.19;
  D.17557 = (gboolean) D.17566;
  return D.17557;
}


sgen_workers_init (int num_workers)
{
  struct SgenMajorCollector * D.17568;
  int D.17569;
  struct SgenMajorCollector * D.17572;
  int D.17573;
  unsigned int num_workers.20;
  unsigned int D.17577;
  void * workers_data.21;
  struct WorkerData * workers_data.22;
  int iftmp.23;
  struct SgenMajorCollector * D.17584;
  int D.17585;
  struct SgenMajorCollector * D.17587;
  int D.17588;
  struct SgenMajorCollector * D.17589;
  void * (*<T29f8>) (void) D.17590;
  struct SgenMajorCollector * D.17593;
  void * (*<T29f8>) (void) D.17594;
  void * workers_gc_thread_major_collector_data.24;
  unsigned int i.25;
  unsigned int D.17597;
  struct WorkerData * D.17598;
  union mono_mutex_t * D.17599;
  struct SgenMajorCollector * D.17600;
  void * (*<T29f8>) (void) D.17601;
  struct SgenMajorCollector * D.17604;
  void * (*<T29f8>) (void) D.17605;
  void * D.17606;
  int workers_num.26;
  int i;

  D.17568 = sgen_get_major_collector ();
  D.17569 = D.17568->is_parallel;
  if (D.17569 == 0) goto <D.17570>; else goto <D.17571>;
  <D.17570>:
  D.17572 = sgen_get_major_collector ();
  D.17573 = D.17572->is_concurrent;
  if (D.17573 == 0) goto <D.17574>; else goto <D.17575>;
  <D.17574>:
  return;
  <D.17575>:
  <D.17571>:
  workers_num = num_workers;
  num_workers.20 = (unsigned int) num_workers;
  D.17577 = num_workers.20 * 2100;
  workers_data.21 = sgen_alloc_internal_dynamic (D.17577, 19, 1);
  workers_data = workers_data.21;
  workers_data.22 = workers_data;
  num_workers.20 = (unsigned int) num_workers;
  D.17577 = num_workers.20 * 2100;
  memset (workers_data.22, 0, D.17577);
  sem_init (&workers_waiting_sem, 0, 0);
  sem_init (&workers_done_sem, 0, 0);
  D.17584 = sgen_get_major_collector ();
  D.17585 = D.17584->is_concurrent;
  if (D.17585 != 0) goto <D.17581>; else goto <D.17586>;
  <D.17586>:
  D.17587 = sgen_get_major_collector ();
  D.17588 = D.17587->is_parallel;
  if (D.17588 != 0) goto <D.17581>; else goto <D.17582>;
  <D.17581>:
  iftmp.23 = 1;
  goto <D.17583>;
  <D.17582>:
  iftmp.23 = 0;
  <D.17583>:
  init_distribute_gray_queue (iftmp.23);
  D.17589 = sgen_get_major_collector ();
  D.17590 = D.17589->alloc_worker_data;
  if (D.17590 != 0B) goto <D.17591>; else goto <D.17592>;
  <D.17591>:
  D.17593 = sgen_get_major_collector ();
  D.17594 = D.17593->alloc_worker_data;
  workers_gc_thread_major_collector_data.24 = D.17594 ();
  workers_gc_thread_major_collector_data = workers_gc_thread_major_collector_data.24;
  <D.17592>:
  i = 0;
  goto <D.17371>;
  <D.17370>:
  workers_data.22 = workers_data;
  i.25 = (unsigned int) i;
  D.17597 = i.25 * 2100;
  D.17598 = workers_data.22 + D.17597;
  D.17599 = &D.17598->stealable_stack_mutex;
  pthread_mutex_init (D.17599, 0B);
  workers_data.22 = workers_data;
  i.25 = (unsigned int) i;
  D.17597 = i.25 * 2100;
  D.17598 = workers_data.22 + D.17597;
  D.17598->stealable_stack_fill = 0;
  D.17600 = sgen_get_major_collector ();
  D.17601 = D.17600->alloc_worker_data;
  if (D.17601 != 0B) goto <D.17602>; else goto <D.17603>;
  <D.17602>:
  workers_data.22 = workers_data;
  i.25 = (unsigned int) i;
  D.17597 = i.25 * 2100;
  D.17598 = workers_data.22 + D.17597;
  D.17604 = sgen_get_major_collector ();
  D.17605 = D.17604->alloc_worker_data;
  D.17606 = D.17605 ();
  D.17598->major_collector_data = D.17606;
  <D.17603>:
  i = i + 1;
  <D.17371>:
  workers_num.26 = workers_num;
  if (i < workers_num.26) goto <D.17370>; else goto <D.17372>;
  <D.17372>:
  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.17611;
  int D.17616;
  void * D.17618;
  unsigned int D.17619;

  D.17611 = __builtin_constant_p (__len);
  if (D.17611 != 0) goto <D.17612>; else goto <D.17613>;
  <D.17612>:
  if (__len == 0) goto <D.17614>; else goto <D.17615>;
  <D.17614>:
  D.17616 = __builtin_constant_p (__ch);
  if (D.17616 == 0) goto <D.17609>; else goto <D.17617>;
  <D.17617>:
  if (__ch != 0) goto <D.17609>; else goto <D.17610>;
  <D.17609>:
  __warn_memset_zero_len ();
  D.17618 = __dest;
  return D.17618;
  <D.17610>:
  <D.17615>:
  <D.17613>:
  D.17619 = __builtin_object_size (__dest, 0);
  D.17618 = __builtin___memset_chk (__dest, __ch, __len, D.17619);
  return D.17618;
}


sgen_workers_start_all_workers ()
{
  int D.17621;
  struct SgenMajorCollector * D.17624;
  void (*<Tc3>) (void *) D.17625;
  struct SgenMajorCollector * D.17628;
  void (*<Tc3>) (void *) D.17629;
  void * workers_gc_thread_major_collector_data.27;
  unsigned int D.17631;
  unsigned int D.17632;
  _Bool D.17633;
  long int D.17634;
  long int D.17635;
  int workers_job_queue_num_entries.28;
  _Bool D.17639;
  long int D.17640;
  long int D.17641;
  int workers_started.29;
  unsigned int D.17647;
  _Bool D.17648;
  long int D.17649;
  long int D.17650;
  unsigned char D.17653;
  int D.17654;
  int workers_num.30;
  int D.17658;
  _Bool D.17661;
  long int D.17662;
  long int D.17663;
  int D.17666;
  union State old_state;
  union State new_state;
  int i;

  try
    {
      D.17621 = collection_needs_workers ();
      if (D.17621 == 0) goto <D.17622>; else goto <D.17623>;
      <D.17622>:
      return;
      <D.17623>:
      D.17624 = sgen_get_major_collector ();
      D.17625 = D.17624->init_worker_thread;
      if (D.17625 != 0B) goto <D.17626>; else goto <D.17627>;
      <D.17626>:
      D.17628 = sgen_get_major_collector ();
      D.17629 = D.17628->init_worker_thread;
      workers_gc_thread_major_collector_data.27 = workers_gc_thread_major_collector_data;
      D.17629 (workers_gc_thread_major_collector_data.27);
      <D.17627>:
      new_state = workers_state;
      old_state = new_state;
      D.17631 = BIT_FIELD_REF <old_state, 32, 0>;
      D.17632 = D.17631 & 512;
      D.17633 = D.17632 != 0;
      D.17634 = (long int) D.17633;
      D.17635 = __builtin_expect (D.17634, 0);
      if (D.17635 != 0) goto <D.17636>; else goto <D.17637>;
      <D.17636>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 504, "!old_state.data.gc_in_progress");
      <D.17637>:
      new_state.data.gc_in_progress = 1;
      workers_marking = 0;
      workers_job_queue_num_entries.28 = workers_job_queue_num_entries;
      D.17639 = workers_job_queue_num_entries.28 != 0;
      D.17640 = (long int) D.17639;
      D.17641 = __builtin_expect (D.17640, 0);
      if (D.17641 != 0) goto <D.17642>; else goto <D.17643>;
      <D.17642>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 509, "workers_job_queue_num_entries == 0");
      <D.17643>:
      workers_num_jobs_enqueued = 0;
      workers_num_jobs_finished = 0;
      workers_started.29 = workers_started;
      if (workers_started.29 != 0) goto <D.17645>; else goto <D.17646>;
      <D.17645>:
      D.17631 = BIT_FIELD_REF <old_state, 32, 0>;
      D.17647 = D.17631 & 256;
      D.17648 = D.17647 == 0;
      D.17649 = (long int) D.17648;
      D.17650 = __builtin_expect (D.17649, 0);
      if (D.17650 != 0) goto <D.17651>; else goto <D.17652>;
      <D.17651>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 514, "old_state.data.done_posted");
      <D.17652>:
      D.17653 = old_state.data.num_waiting;
      D.17654 = (int) D.17653;
      workers_num.30 = workers_num;
      if (D.17654 != workers_num.30) goto <D.17656>; else goto <D.17657>;
      <D.17656>:
      workers_num.30 = workers_num;
      D.17653 = old_state.data.num_waiting;
      D.17654 = (int) D.17653;
      monoeg_g_log (0B, 4, "Expecting all %d sgen workers to be parked, but only %d are", workers_num.30, D.17654);
      <D.17382>:
      goto <D.17382>;
      <D.17657>:
      new_state.data.done_posted = 0;
      D.17658 = set_state (old_state, new_state);
      if (D.17658 == 0) goto <D.17659>; else goto <D.17660>;
      <D.17659>:
      monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "sgen-workers.c", 523);
      <D.17660>:
      workers_wake_up_all ();
      return;
      <D.17646>:
      D.17631 = BIT_FIELD_REF <old_state, 32, 0>;
      D.17647 = D.17631 & 256;
      D.17661 = D.17647 != 0;
      D.17662 = (long int) D.17661;
      D.17663 = __builtin_expect (D.17662, 0);
      if (D.17663 != 0) goto <D.17664>; else goto <D.17665>;
      <D.17664>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 529, "!old_state.data.done_posted");
      <D.17665>:
      D.17666 = set_state (old_state, new_state);
      if (D.17666 == 0) goto <D.17667>; else goto <D.17668>;
      <D.17667>:
      monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "sgen-workers.c", 532);
      <D.17668>:
      i = 0;
      goto <D.17384>;
      <D.17383>:
      workers_start_worker (i);
      i = i + 1;
      <D.17384>:
      workers_num.30 = workers_num;
      if (i < workers_num.30) goto <D.17383>; else goto <D.17385>;
      <D.17385>:
      workers_started = 1;
    }
  finally
    {
      old_state = {CLOBBER};
      new_state = {CLOBBER};
    }
}


workers_start_worker (int index)
{
  int iftmp.31;
  int workers_num.32;
  _Bool D.17678;
  long int D.17679;
  long int D.17680;
  struct WorkerData * workers_data.33;
  unsigned int index.34;
  unsigned int D.17685;
  struct WorkerData * D.17686;
  long unsigned int D.17687;
  _Bool D.17688;
  long int D.17689;
  long int D.17690;
  MonoNativeThreadId * D.17693;
  void * D.17694;

  if (index < 0) goto <D.17673>; else goto <D.17676>;
  <D.17676>:
  workers_num.32 = workers_num;
  if (index >= workers_num.32) goto <D.17673>; else goto <D.17674>;
  <D.17673>:
  iftmp.31 = 1;
  goto <D.17675>;
  <D.17674>:
  iftmp.31 = 0;
  <D.17675>:
  D.17678 = iftmp.31 != 0;
  D.17679 = (long int) D.17678;
  D.17680 = __builtin_expect (D.17679, 0);
  if (D.17680 != 0) goto <D.17681>; else goto <D.17682>;
  <D.17681>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 485, "index >= 0 && index < workers_num");
  <D.17682>:
  workers_data.33 = workers_data;
  index.34 = (unsigned int) index;
  D.17685 = index.34 * 2100;
  D.17686 = workers_data.33 + D.17685;
  D.17687 = D.17686->thread;
  D.17688 = D.17687 != 0;
  D.17689 = (long int) D.17688;
  D.17690 = __builtin_expect (D.17689, 0);
  if (D.17690 != 0) goto <D.17691>; else goto <D.17692>;
  <D.17691>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 487, "!workers_data [index].thread");
  <D.17692>:
  workers_data.33 = workers_data;
  index.34 = (unsigned int) index;
  D.17685 = index.34 * 2100;
  D.17686 = workers_data.33 + D.17685;
  D.17693 = &D.17686->thread;
  workers_data.33 = workers_data;
  index.34 = (unsigned int) index;
  D.17685 = index.34 * 2100;
  D.17694 = workers_data.33 + D.17685;
  mono_native_thread_create (D.17693, workers_thread_func, D.17694);
}


workers_thread_func (void * data_untyped)
{
  void (*<Tc3>) (void *) D.17695;
  void * D.17698;
  int D.17699;
  int workers_marking.35;
  struct SgenGrayQueue * D.17705;
  int D.17706;
  int D.17708;
  struct SgenObjectOperations * iftmp.36;
  int D.17710;
  void (*<T2b4d>) (char *, struct SgenGrayQueue *) D.17714;
  int D.17715;
  _Bool D.17716;
  long int D.17717;
  long int D.17718;
  int D.17721;
  int D.17722;
  _Bool D.17723;
  long int D.17724;
  long int D.17725;
  void * D.17730;
  struct WorkerData * data;
  struct SgenMajorCollector * major;

  data = data_untyped;
  major = sgen_get_major_collector ();
  mono_thread_info_register_small_id ();
  D.17695 = major->init_worker_thread;
  if (D.17695 != 0B) goto <D.17696>; else goto <D.17697>;
  <D.17696>:
  D.17695 = major->init_worker_thread;
  D.17698 = data->major_collector_data;
  D.17695 (D.17698);
  <D.17697>:
  init_private_gray_queue (data);
  <D.17359>:
  {
    gboolean did_work;

    did_work = 0;
    goto <D.17352>;
    <D.17351>:
    did_work = 1;
    <D.17352>:
    D.17699 = workers_dequeue_and_do_job (data);
    if (D.17699 != 0) goto <D.17351>; else goto <D.17353>;
    <D.17353>:
    workers_marking.35 = workers_marking;
    if (workers_marking.35 != 0) goto <D.17703>; else goto <D.17704>;
    <D.17703>:
    D.17705 = &data->private_gray_queue;
    D.17706 = sgen_gray_object_queue_is_empty (D.17705);
    if (D.17706 == 0) goto <D.17700>; else goto <D.17707>;
    <D.17707>:
    D.17708 = workers_get_work (data);
    if (D.17708 != 0) goto <D.17700>; else goto <D.17701>;
    <D.17700>:
    {
      struct SgenObjectOperations * ops;
      struct ScanCopyContext ctx;

      try
        {
          D.17710 = sgen_concurrent_collection_in_progress ();
          if (D.17710 != 0) goto <D.17711>; else goto <D.17712>;
          <D.17711>:
          iftmp.36 = &major->major_concurrent_ops;
          goto <D.17713>;
          <D.17712>:
          iftmp.36 = &major->major_ops;
          <D.17713>:
          ops = iftmp.36;
          D.17714 = ops->scan_object;
          ctx.scan_func = D.17714;
          ctx.copy_func = 0B;
          D.17705 = &data->private_gray_queue;
          ctx.queue = D.17705;
          D.17705 = &data->private_gray_queue;
          D.17715 = sgen_gray_object_queue_is_empty (D.17705);
          D.17716 = D.17715 != 0;
          D.17717 = (long int) D.17716;
          D.17718 = __builtin_expect (D.17717, 0);
          if (D.17718 != 0) goto <D.17719>; else goto <D.17720>;
          <D.17719>:
          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.17720>:
          goto <D.17357>;
          <D.17356>:
          D.17705 = &data->private_gray_queue;
          workers_gray_queue_share_redirect (D.17705);
          <D.17357>:
          D.17721 = sgen_drain_gray_stack (32, ctx);
          if (D.17721 == 0) goto <D.17356>; else goto <D.17358>;
          <D.17358>:
          D.17705 = &data->private_gray_queue;
          D.17722 = sgen_gray_object_queue_is_empty (D.17705);
          D.17723 = D.17722 == 0;
          D.17724 = (long int) D.17723;
          D.17725 = __builtin_expect (D.17724, 0);
          if (D.17725 != 0) goto <D.17726>; else goto <D.17727>;
          <D.17726>:
          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.17727>:
          init_private_gray_queue (data);
          did_work = 1;
        }
      finally
        {
          ctx = {CLOBBER};
        }
    }
    <D.17701>:
    <D.17704>:
    if (did_work == 0) goto <D.17728>; else goto <D.17729>;
    <D.17728>:
    workers_wait ();
    <D.17729>:
  }
  goto <D.17359>;
  D.17730 = 0B;
  return D.17730;
}


workers_dequeue_and_do_job (struct WorkerData * data)
{
  int workers_job_queue_num_entries.37;
  gboolean D.17735;
  volatile struct JobQueueEntry * workers_job_queue.38;
  int workers_job_queue_num_entries.39;
  int workers_job_queue_num_entries.40;
  int D.17743;
  _Bool D.17744;
  long int D.17745;
  long int D.17746;
  void (*<T2e25>) (struct WorkerData *, void *) D.17749;
  void * D.17750;
  int D.17751;
  int D.17752;
  struct JobQueueEntry * entry;

  workers_job_queue_num_entries.37 = workers_job_queue_num_entries;
  if (workers_job_queue_num_entries.37 == 0) goto <D.17733>; else goto <D.17734>;
  <D.17733>:
  D.17735 = 0;
  return D.17735;
  <D.17734>:
  pthread_mutex_lock (&workers_job_queue_mutex);
  entry = workers_job_queue;
  if (entry != 0B) goto <D.17736>; else goto <D.17737>;
  <D.17736>:
  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.17737>:
  pthread_mutex_unlock (&workers_job_queue_mutex);
  if (entry == 0B) goto <D.17741>; else goto <D.17742>;
  <D.17741>:
  D.17735 = 0;
  return D.17735;
  <D.17742>:
  D.17743 = collection_needs_workers ();
  D.17744 = D.17743 == 0;
  D.17745 = (long int) D.17744;
  D.17746 = __builtin_expect (D.17745, 0);
  if (D.17746 != 0) goto <D.17747>; else goto <D.17748>;
  <D.17747>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 214, "collection_needs_workers ()");
  <D.17748>:
  D.17749 = entry->func;
  D.17750 = entry->data;
  D.17749 (data, D.17750);
  sgen_free_internal (entry, 26);
  {
    int __old_x;

    <D.17305>:
    __old_x = workers_num_jobs_finished;
    D.17751 = __old_x + 1;
    D.17752 = InterlockedCompareExchange (&workers_num_jobs_finished, D.17751, __old_x);
    if (D.17752 != __old_x) goto <D.17305>; else goto <D.17306>;
    <D.17306>:
  }
  D.17735 = 1;
  return D.17735;
}


workers_get_work (struct WorkerData * data)
{
  struct SgenGrayQueue * D.17754;
  int D.17755;
  _Bool D.17756;
  long int D.17757;
  long int D.17758;
  int D.17761;
  gboolean D.17764;
  struct WorkerData * workers_data.41;
  unsigned int i.42;
  unsigned int D.17767;
  int D.17770;
  int workers_num.43;
  int D.17776;
  int D.17778;
  int D.17781;
  _Bool D.17782;
  long int D.17783;
  long int D.17784;
  struct SgenMajorCollector * major;
  int i;

  D.17754 = &data->private_gray_queue;
  D.17755 = sgen_gray_object_queue_is_empty (D.17754);
  D.17756 = D.17755 == 0;
  D.17757 = (long int) D.17756;
  D.17758 = __builtin_expect (D.17757, 0);
  if (D.17758 != 0) goto <D.17759>; else goto <D.17760>;
  <D.17759>:
  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.17760>:
  D.17761 = workers_steal (data, data, 1);
  if (D.17761 != 0) goto <D.17762>; else goto <D.17763>;
  <D.17762>:
  D.17764 = 1;
  return D.17764;
  <D.17763>:
  i = 0;
  goto <D.17327>;
  <D.17326>:
  {
    struct WorkerData * victim_data;

    workers_data.41 = workers_data;
    i.42 = (unsigned int) i;
    D.17767 = i.42 * 2100;
    victim_data = workers_data.41 + D.17767;
    if (data == victim_data) goto <D.17768>; else goto <D.17769>;
    <D.17768>:
    // predicted unlikely by continue predictor.
    goto <D.17325>;
    <D.17769>:
    D.17770 = workers_steal (data, victim_data, 1);
    if (D.17770 != 0) goto <D.17771>; else goto <D.17772>;
    <D.17771>:
    D.17764 = 1;
    return D.17764;
    <D.17772>:
  }
  <D.17325>:
  i = i + 1;
  <D.17327>:
  workers_num.43 = workers_num;
  if (i < workers_num.43) goto <D.17326>; else goto <D.17328>;
  <D.17328>:
  major = sgen_get_major_collector ();
  D.17776 = major->is_concurrent;
  if (D.17776 != 0) goto <D.17774>; else goto <D.17777>;
  <D.17777>:
  D.17778 = major->is_parallel;
  if (D.17778 != 0) goto <D.17774>; else goto <D.17775>;
  <D.17774>:
  {
    struct GrayQueueSection * section;

    section = sgen_section_gray_queue_dequeue (&workers_distribute_gray_queue);
    if (section != 0B) goto <D.17779>; else goto <D.17780>;
    <D.17779>:
    D.17754 = &data->private_gray_queue;
    sgen_gray_object_enqueue_section (D.17754, section);
    D.17764 = 1;
    return D.17764;
    <D.17780>:
  }
  <D.17775>:
  D.17754 = &data->private_gray_queue;
  D.17781 = sgen_gray_object_queue_is_empty (D.17754);
  D.17782 = D.17781 == 0;
  D.17783 = (long int) D.17782;
  D.17784 = __builtin_expect (D.17783, 0);
  if (D.17784 != 0) goto <D.17785>; else goto <D.17786>;
  <D.17785>:
  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.17786>:
  D.17764 = 0;
  return D.17764;
}


workers_steal (struct WorkerData * data, struct WorkerData * victim_data, gboolean lock)
{
  struct GrayQueueSection * D.17788;
  _Bool D.17789;
  long int D.17790;
  long int D.17791;
  int D.17794;
  gboolean D.17797;
  union mono_mutex_t * D.17800;
  int D.17801;
  int D.17804;
  int D.17805;
  char *[125] * D.17806;
  int D.17807;
  sizetype D.17808;
  sizetype n.44;
  sizetype num.45;
  sizetype D.17811;
  sizetype D.17812;
  char * * D.17813;
  unsigned int m.46;
  unsigned int D.17815;
  int D.17816;
  int D.17817;
  long long int D.17824;
  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.17833;
  struct SgenGrayQueue * queue;
  int num;
  int n;

  queue = &data->private_gray_queue;
  D.17788 = queue->first;
  D.17789 = D.17788 != 0B;
  D.17790 = (long int) D.17789;
  D.17791 = __builtin_expect (D.17790, 0);
  if (D.17791 != 0) goto <D.17792>; else goto <D.17793>;
  <D.17792>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 230, "!queue->first");
  <D.17793>:
  D.17794 = victim_data->stealable_stack_fill;
  if (D.17794 == 0) goto <D.17795>; else goto <D.17796>;
  <D.17795>:
  D.17797 = 0;
  return D.17797;
  <D.17796>:
  if (lock != 0) goto <D.17798>; else goto <D.17799>;
  <D.17798>:
  D.17800 = &victim_data->stealable_stack_mutex;
  D.17801 = pthread_mutex_trylock (D.17800);
  if (D.17801 != 0) goto <D.17802>; else goto <D.17803>;
  <D.17802>:
  D.17797 = 0;
  return D.17797;
  <D.17803>:
  <D.17799>:
  D.17804 = victim_data->stealable_stack_fill;
  D.17805 = D.17804 + 1;
  num = D.17805 / 2;
  n = num;
  goto <D.17317>;
  <D.17316>:
  {
    int m;

    m = MIN_EXPR <n, 125>;
    n = n - m;
    sgen_gray_object_alloc_queue_section (queue);
    D.17788 = queue->first;
    D.17806 = &D.17788->objects;
    D.17807 = victim_data->stealable_stack_fill;
    D.17808 = (sizetype) D.17807;
    n.44 = (sizetype) n;
    num.45 = (sizetype) num;
    D.17811 = n.44 - num.45;
    D.17812 = D.17808 + D.17811;
    D.17813 = &victim_data->stealable_stack[D.17812];
    m.46 = (unsigned int) m;
    D.17815 = m.46 * 4;
    memcpy (D.17806, D.17813, D.17815);
    D.17788 = queue->first;
    D.17788->end = m;
  }
  <D.17317>:
  if (n > 0) goto <D.17316>; else goto <D.17318>;
  <D.17318>:
  D.17816 = victim_data->stealable_stack_fill;
  D.17817 = D.17816 - num;
  victim_data->stealable_stack_fill = D.17817;
  if (lock != 0) goto <D.17818>; else goto <D.17819>;
  <D.17818>:
  D.17800 = &victim_data->stealable_stack_mutex;
  pthread_mutex_unlock (D.17800);
  <D.17819>:
  if (data == victim_data) goto <D.17820>; else goto <D.17821>;
  <D.17820>:
  if (lock != 0) goto <D.17822>; else goto <D.17823>;
  <D.17822>:
  D.17824 = (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.17824 + stat_workers_stolen_from_self_lock.47;
  stat_workers_stolen_from_self_lock = stat_workers_stolen_from_self_lock.48;
  goto <D.17827>;
  <D.17823>:
  D.17824 = (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.17824 + stat_workers_stolen_from_self_no_lock.49;
  stat_workers_stolen_from_self_no_lock = stat_workers_stolen_from_self_no_lock.50;
  <D.17827>:
  goto <D.17830>;
  <D.17821>:
  D.17824 = (long long int) num;
  stat_workers_stolen_from_others.51 = stat_workers_stolen_from_others;
  stat_workers_stolen_from_others.52 = D.17824 + stat_workers_stolen_from_others.51;
  stat_workers_stolen_from_others = stat_workers_stolen_from_others.52;
  <D.17830>:
  D.17833 = num != 0;
  D.17797 = (gboolean) D.17833;
  return D.17797;
}


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

  D.17836 = __builtin_object_size (__dest, 0);
  D.17835 = __builtin___memcpy_chk (__dest, __src, __len, D.17836);
  return D.17835;
}


workers_gray_queue_share_redirect (struct SgenGrayQueue * queue)
{
  int D.17838;
  <unnamed-unsigned:1> D.17841;
  union mono_mutex_t * D.17844;
  int iftmp.53;
  int D.17846;
  int D.17847;
  int D.17848;
  int D.17852;
  int D.17853;
  sizetype D.17854;
  char * * D.17855;
  sizetype D.17856;
  char * * D.17857;
  unsigned int num.54;
  unsigned int D.17859;
  sizetype D.17860;
  char * * D.17861;
  int D.17862;
  int D.17863;
  int D.17864;
  int D.17868;
  int D.17870;
  <unnamed-unsigned:1> D.17873;
  struct GrayQueueSection * section;
  struct WorkerData * data;

  data = queue->alloc_prepare_data;
  D.17838 = data->stealable_stack_fill;
  if (D.17838 != 0) goto <D.17839>; else goto <D.17840>;
  <D.17839>:
  D.17841 = workers_state.data.gc_in_progress;
  if (D.17841 != 0) goto <D.17842>; else goto <D.17843>;
  <D.17842>:
  workers_wake_up_all ();
  <D.17843>:
  return;
  <D.17840>:
  D.17844 = &data->stealable_stack_mutex;
  pthread_mutex_lock (D.17844);
  goto <D.17337>;
  <D.17336>:
  {
    int num;

    D.17846 = section->end;
    D.17847 = data->stealable_stack_fill;
    D.17848 = 512 - D.17847;
    if (D.17846 < D.17848) goto <D.17849>; else goto <D.17850>;
    <D.17849>:
    iftmp.53 = section->end;
    goto <D.17851>;
    <D.17850>:
    D.17852 = data->stealable_stack_fill;
    iftmp.53 = 512 - D.17852;
    <D.17851>:
    num = iftmp.53;
    D.17853 = data->stealable_stack_fill;
    D.17854 = (sizetype) D.17853;
    D.17855 = &data->stealable_stack[D.17854];
    D.17846 = section->end;
    D.17856 = (sizetype) D.17846;
    D.17857 = &section->objects[D.17856];
    num.54 = (unsigned int) num;
    D.17859 = num.54 * 4;
    D.17860 = -D.17859;
    D.17861 = D.17857 + D.17860;
    num.54 = (unsigned int) num;
    D.17859 = num.54 * 4;
    memcpy (D.17855, D.17861, D.17859);
    D.17846 = section->end;
    D.17862 = D.17846 - num;
    section->end = D.17862;
    D.17863 = data->stealable_stack_fill;
    D.17864 = D.17863 + num;
    data->stealable_stack_fill = D.17864;
    D.17846 = section->end;
    if (D.17846 != 0) goto <D.17865>; else goto <D.17866>;
    <D.17865>:
    sgen_gray_object_enqueue_section (queue, section);
    goto <D.17867>;
    <D.17866>:
    sgen_gray_object_free_queue_section (section);
    <D.17867>:
  }
  <D.17337>:
  D.17868 = data->stealable_stack_fill;
  if (D.17868 <= 511) goto <D.17869>; else goto <D.17338>;
  <D.17869>:
  section = sgen_gray_object_dequeue_section (queue);
  if (section != 0B) goto <D.17336>; else goto <D.17338>;
  <D.17338>:
  D.17870 = sgen_gray_object_queue_is_empty (queue);
  if (D.17870 != 0) goto <D.17871>; else goto <D.17872>;
  <D.17871>:
  workers_steal (data, data, 0);
  <D.17872>:
  D.17844 = &data->stealable_stack_mutex;
  pthread_mutex_unlock (D.17844);
  D.17873 = workers_state.data.gc_in_progress;
  if (D.17873 != 0) goto <D.17874>; else goto <D.17875>;
  <D.17874>:
  workers_wake_up_all ();
  <D.17875>:
}


sgen_gray_object_queue_is_empty (struct SgenGrayQueue * queue)
{
  gboolean D.17877;
  struct GrayQueueSection * D.17878;
  _Bool D.17879;

  D.17878 = queue->first;
  D.17879 = D.17878 == 0B;
  D.17877 = (gboolean) D.17879;
  return D.17877;
}


init_private_gray_queue (struct WorkerData * data)
{
  struct SgenGrayQueue * D.17881;
  void (*<T2a8e>) (char *) iftmp.55;
  struct SgenMajorCollector * D.17883;
  int D.17884;

  D.17881 = &data->private_gray_queue;
  D.17883 = sgen_get_major_collector ();
  D.17884 = D.17883->is_concurrent;
  if (D.17884 != 0) goto <D.17885>; else goto <D.17886>;
  <D.17885>:
  iftmp.55 = concurrent_enqueue_check;
  goto <D.17887>;
  <D.17886>:
  iftmp.55 = 0B;
  <D.17887>:
  sgen_gray_object_queue_init_with_alloc_prepare (D.17881, 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 int D.17890;
  unsigned int D.17891;
  _Bool D.17892;
  long int D.17893;
  long int D.17894;
  unsigned char D.17897;
  unsigned char D.17898;
  int D.17899;
  int workers_num.58;
  unsigned int D.17903;
  int D.17906;
  unsigned int D.17907;
  unsigned int D.17908;
  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.17282>:
      new_state = workers_state;
      old_state = new_state;
      D.17890 = BIT_FIELD_REF <old_state, 32, 0>;
      D.17891 = D.17890 & 256;
      D.17892 = D.17891 != 0;
      D.17893 = (long int) D.17892;
      D.17894 = __builtin_expect (D.17893, 0);
      if (D.17894 != 0) goto <D.17895>; else goto <D.17896>;
      <D.17895>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 125, "!old_state.data.done_posted");
      <D.17896>:
      D.17897 = new_state.data.num_waiting;
      D.17898 = D.17897 + 1;
      new_state.data.num_waiting = D.17898;
      D.17897 = new_state.data.num_waiting;
      D.17899 = (int) D.17897;
      workers_num.58 = workers_num;
      if (D.17899 == workers_num.58) goto <D.17901>; else goto <D.17902>;
      <D.17901>:
      D.17890 = BIT_FIELD_REF <old_state, 32, 0>;
      D.17903 = D.17890 & 512;
      if (D.17903 == 0) goto <D.17904>; else goto <D.17905>;
      <D.17904>:
      new_state.data.done_posted = 1;
      <D.17905>:
      <D.17902>:
      D.17906 = set_state (old_state, new_state);
      if (D.17906 == 0) goto <D.17282>; else goto <D.17283>;
      <D.17283>:
      mono_memory_barrier ();
      D.17907 = BIT_FIELD_REF <new_state, 32, 0>;
      D.17908 = D.17907 & 256;
      if (D.17908 != 0) goto <D.17909>; else goto <D.17910>;
      <D.17909>:
      mono_sem_post (&workers_done_sem);
      <D.17910>:
      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.17911;
  <unnamed-unsigned:1> D.17912;

  D.17912 = workers_state.data.gc_in_progress;
  D.17911 = (gboolean) D.17912;
  return D.17911;
}


sgen_workers_start_marking ()
{
  int D.17914;
  int iftmp.59;
  int workers_started.60;
  <unnamed-unsigned:1> D.17923;
  _Bool D.17924;
  long int D.17925;
  long int D.17926;
  int workers_marking.61;
  _Bool D.17930;
  long int D.17931;
  long int D.17932;

  D.17914 = collection_needs_workers ();
  if (D.17914 == 0) goto <D.17915>; else goto <D.17916>;
  <D.17915>:
  return;
  <D.17916>:
  workers_started.60 = workers_started;
  if (workers_started.60 == 0) goto <D.17918>; else goto <D.17922>;
  <D.17922>:
  D.17923 = workers_state.data.gc_in_progress;
  if (D.17923 == 0) goto <D.17918>; else goto <D.17919>;
  <D.17918>:
  iftmp.59 = 1;
  goto <D.17920>;
  <D.17919>:
  iftmp.59 = 0;
  <D.17920>:
  D.17924 = iftmp.59 != 0;
  D.17925 = (long int) D.17924;
  D.17926 = __builtin_expect (D.17925, 0);
  if (D.17926 != 0) goto <D.17927>; else goto <D.17928>;
  <D.17927>:
  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.17928>:
  workers_marking.61 = workers_marking;
  D.17930 = workers_marking.61 != 0;
  D.17931 = (long int) D.17930;
  D.17932 = __builtin_expect (D.17931, 0);
  if (D.17932 != 0) goto <D.17933>; else goto <D.17934>;
  <D.17933>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 553, "!workers_marking");
  <D.17934>:
  workers_marking = 1;
  workers_wake_up_all ();
}


sgen_workers_join ()
{
  int D.17936;
  unsigned int D.17939;
  unsigned int D.17940;
  _Bool D.17941;
  long int D.17942;
  long int D.17943;
  unsigned int D.17946;
  _Bool D.17947;
  long int D.17948;
  long int D.17949;
  int D.17952;
  unsigned char D.17953;
  int D.17954;
  int workers_num.62;
  unsigned char D.17958;
  int D.17959;
  _Bool D.17960;
  long int D.17961;
  long int D.17962;
  _Bool D.17965;
  long int D.17966;
  long int D.17967;
  int workers_job_queue_num_entries.63;
  int D.17974;
  int D.17975;
  struct SgenMajorCollector * D.17978;
  void (*<Tc3>) (void *) D.17979;
  struct SgenMajorCollector * D.17982;
  void (*<Tc3>) (void *) D.17983;
  struct WorkerData * workers_data.64;
  unsigned int i.65;
  unsigned int D.17986;
  struct WorkerData * D.17987;
  void * D.17988;
  int workers_job_queue_num_entries.66;
  _Bool D.17990;
  long int D.17991;
  long int D.17992;
  int D.17995;
  _Bool D.17996;
  long int D.17997;
  long int D.17998;
  int D.18001;
  _Bool D.18002;
  long int D.18003;
  long int D.18004;
  struct SgenGrayQueue * D.18007;
  int D.18008;
  _Bool D.18009;
  long int D.18010;
  long int D.18011;
  union State old_state;
  union State new_state;
  int i;
  void reawaken = <<< error >>>;

  try
    {
      D.17936 = collection_needs_workers ();
      if (D.17936 == 0) goto <D.17937>; else goto <D.17938>;
      <D.17937>:
      return;
      <D.17938>:
      <D.17398>:
      new_state = workers_state;
      old_state = new_state;
      D.17939 = BIT_FIELD_REF <old_state, 32, 0>;
      D.17940 = D.17939 & 512;
      D.17941 = D.17940 == 0;
      D.17942 = (long int) D.17941;
      D.17943 = __builtin_expect (D.17942, 0);
      if (D.17943 != 0) goto <D.17944>; else goto <D.17945>;
      <D.17944>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 571, "old_state.data.gc_in_progress");
      <D.17945>:
      D.17939 = BIT_FIELD_REF <old_state, 32, 0>;
      D.17946 = D.17939 & 256;
      D.17947 = D.17946 != 0;
      D.17948 = (long int) D.17947;
      D.17949 = __builtin_expect (D.17948, 0);
      if (D.17949 != 0) goto <D.17950>; else goto <D.17951>;
      <D.17950>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 572, "!old_state.data.done_posted");
      <D.17951>:
      new_state.data.gc_in_progress = 0;
      D.17952 = set_state (old_state, new_state);
      if (D.17952 == 0) goto <D.17398>; else goto <D.17399>;
      <D.17399>:
      D.17953 = new_state.data.num_waiting;
      D.17954 = (int) D.17953;
      workers_num.62 = workers_num;
      if (D.17954 == workers_num.62) goto <D.17956>; else goto <D.17957>;
      <D.17956>:
      reawaken:
      workers_wake_up_all ();
      <D.17957>:
      mono_sem_wait (&workers_done_sem, 0);
      new_state = workers_state;
      old_state = new_state;
      D.17958 = old_state.data.num_waiting;
      D.17959 = (int) D.17958;
      workers_num.62 = workers_num;
      D.17960 = D.17959 != workers_num.62;
      D.17961 = (long int) D.17960;
      D.17962 = __builtin_expect (D.17961, 0);
      if (D.17962 != 0) goto <D.17963>; else goto <D.17964>;
      <D.17963>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 593, "old_state.data.num_waiting == workers_num");
      <D.17964>:
      D.17939 = BIT_FIELD_REF <old_state, 32, 0>;
      D.17946 = D.17939 & 256;
      D.17965 = D.17946 == 0;
      D.17966 = (long int) D.17965;
      D.17967 = __builtin_expect (D.17966, 0);
      if (D.17967 != 0) goto <D.17968>; else goto <D.17969>;
      <D.17968>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 594, "old_state.data.done_posted");
      <D.17969>:
      workers_job_queue_num_entries.63 = workers_job_queue_num_entries;
      if (workers_job_queue_num_entries.63 != 0) goto <D.17970>; else goto <D.17973>;
      <D.17973>:
      D.17974 = sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue);
      if (D.17974 == 0) goto <D.17970>; else goto <D.17971>;
      <D.17970>:
      new_state.data.done_posted = 0;
      D.17975 = set_state (old_state, new_state);
      if (D.17975 == 0) goto <D.17976>; else goto <D.17977>;
      <D.17976>:
      monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "sgen-workers.c", 613);
      <D.17977>:
      goto reawaken;
      <D.17971>:
      workers_marking = 0;
      D.17978 = sgen_get_major_collector ();
      D.17979 = D.17978->reset_worker_data;
      if (D.17979 != 0B) goto <D.17980>; else goto <D.17981>;
      <D.17980>:
      i = 0;
      goto <D.17402>;
      <D.17401>:
      D.17982 = sgen_get_major_collector ();
      D.17983 = D.17982->reset_worker_data;
      workers_data.64 = workers_data;
      i.65 = (unsigned int) i;
      D.17986 = i.65 * 2100;
      D.17987 = workers_data.64 + D.17986;
      D.17988 = D.17987->major_collector_data;
      D.17983 (D.17988);
      i = i + 1;
      <D.17402>:
      workers_num.62 = workers_num;
      if (i < workers_num.62) goto <D.17401>; else goto <D.17403>;
      <D.17403>:
      <D.17981>:
      workers_job_queue_num_entries.66 = workers_job_queue_num_entries;
      D.17990 = workers_job_queue_num_entries.66 != 0;
      D.17991 = (long int) D.17990;
      D.17992 = __builtin_expect (D.17991, 0);
      if (D.17992 != 0) goto <D.17993>; else goto <D.17994>;
      <D.17993>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 626, "workers_job_queue_num_entries == 0");
      <D.17994>:
      D.17995 = sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue);
      D.17996 = D.17995 == 0;
      D.17997 = (long int) D.17996;
      D.17998 = __builtin_expect (D.17997, 0);
      if (D.17998 != 0) goto <D.17999>; else goto <D.18000>;
      <D.17999>:
      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.18000>:
      i = 0;
      goto <D.17405>;
      <D.17404>:
      workers_data.64 = workers_data;
      i.65 = (unsigned int) i;
      D.17986 = i.65 * 2100;
      D.17987 = workers_data.64 + D.17986;
      D.18001 = D.17987->stealable_stack_fill;
      D.18002 = D.18001 != 0;
      D.18003 = (long int) D.18002;
      D.18004 = __builtin_expect (D.18003, 0);
      if (D.18004 != 0) goto <D.18005>; else goto <D.18006>;
      <D.18005>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 629, "!workers_data [i].stealable_stack_fill");
      <D.18006>:
      workers_data.64 = workers_data;
      i.65 = (unsigned int) i;
      D.17986 = i.65 * 2100;
      D.17987 = workers_data.64 + D.17986;
      D.18007 = &D.17987->private_gray_queue;
      D.18008 = sgen_gray_object_queue_is_empty (D.18007);
      D.18009 = D.18008 == 0;
      D.18010 = (long int) D.18009;
      D.18011 = __builtin_expect (D.18010, 0);
      if (D.18011 != 0) goto <D.18012>; else goto <D.18013>;
      <D.18012>:
      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.18013>:
      i = i + 1;
      <D.17405>:
      workers_num.62 = workers_num;
      if (i < workers_num.62) goto <D.17404>; else goto <D.17406>;
      <D.17406>:
    }
  finally
    {
      old_state = {CLOBBER};
      new_state = {CLOBBER};
    }
}


sgen_workers_all_done ()
{
  unsigned int D.18017;
  unsigned int D.18018;
  _Bool D.18019;
  long int D.18020;
  long int D.18021;
  unsigned int D.18024;
  _Bool D.18025;
  long int D.18026;
  long int D.18027;
  gboolean D.18030;
  unsigned char D.18031;
  int D.18032;
  int workers_num.67;
  _Bool D.18034;
  union State state;

  try
    {
      state = workers_state;
      D.18017 = BIT_FIELD_REF <state, 32, 0>;
      D.18018 = D.18017 & 512;
      D.18019 = D.18018 == 0;
      D.18020 = (long int) D.18019;
      D.18021 = __builtin_expect (D.18020, 0);
      if (D.18021 != 0) goto <D.18022>; else goto <D.18023>;
      <D.18022>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 642, "state.data.gc_in_progress");
      <D.18023>:
      D.18017 = BIT_FIELD_REF <state, 32, 0>;
      D.18024 = D.18017 & 256;
      D.18025 = D.18024 != 0;
      D.18026 = (long int) D.18025;
      D.18027 = __builtin_expect (D.18026, 0);
      if (D.18027 != 0) goto <D.18028>; else goto <D.18029>;
      <D.18028>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 643, "!state.data.done_posted");
      <D.18029>:
      D.18031 = state.data.num_waiting;
      D.18032 = (int) D.18031;
      workers_num.67 = workers_num;
      D.18034 = D.18032 == workers_num.67;
      D.18030 = (gboolean) D.18034;
      return D.18030;
    }
  finally
    {
      state = {CLOBBER};
    }
}


sgen_is_worker_thread (MonoNativeThreadId thread)
{
  struct SgenMajorCollector * D.18037;
  gboolean (*<T2c6e>) (MonoNativeThreadId) D.18038;
  struct SgenMajorCollector * D.18041;
  gboolean (*<T2c6e>) (MonoNativeThreadId) D.18042;
  int D.18043;
  gboolean D.18046;
  struct WorkerData * workers_data.68;
  unsigned int i.69;
  unsigned int D.18049;
  struct WorkerData * D.18050;
  long unsigned int D.18051;
  int workers_num.70;
  int i;

  D.18037 = sgen_get_major_collector ();
  D.18038 = D.18037->is_worker_thread;
  if (D.18038 != 0B) goto <D.18039>; else goto <D.18040>;
  <D.18039>:
  D.18041 = sgen_get_major_collector ();
  D.18042 = D.18041->is_worker_thread;
  D.18043 = D.18042 (thread);
  if (D.18043 != 0) goto <D.18044>; else goto <D.18045>;
  <D.18044>:
  D.18046 = 1;
  return D.18046;
  <D.18045>:
  <D.18040>:
  i = 0;
  goto <D.17416>;
  <D.17415>:
  workers_data.68 = workers_data;
  i.69 = (unsigned int) i;
  D.18049 = i.69 * 2100;
  D.18050 = workers_data.68 + D.18049;
  D.18051 = D.18050->thread;
  if (D.18051 == thread) goto <D.18052>; else goto <D.18053>;
  <D.18052>:
  D.18046 = 1;
  return D.18046;
  <D.18053>:
  i = i + 1;
  <D.17416>:
  workers_num.70 = workers_num;
  if (i < workers_num.70) goto <D.17415>; else goto <D.17417>;
  <D.17417>:
  D.18046 = 0;
  return D.18046;
}


sgen_workers_get_distribute_section_gray_queue ()
{
  struct SgenSectionGrayQueue * D.18056;

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


sgen_workers_reset_data ()
{
  struct SgenMajorCollector * D.18058;
  void (*<Tc3>) (void *) D.18059;
  struct SgenMajorCollector * D.18062;
  void (*<Tc3>) (void *) D.18063;
  void * workers_gc_thread_major_collector_data.71;

  D.18058 = sgen_get_major_collector ();
  D.18059 = D.18058->reset_worker_data;
  if (D.18059 != 0B) goto <D.18060>; else goto <D.18061>;
  <D.18060>:
  D.18062 = sgen_get_major_collector ();
  D.18063 = D.18062->reset_worker_data;
  workers_gc_thread_major_collector_data.71 = workers_gc_thread_major_collector_data;
  D.18063 (workers_gc_thread_major_collector_data.71);
  <D.18061>:
}


