mono_thread_small_id_alloc ()
{
  _Bool D.14585;
  long int D.14586;
  long int D.14587;
  struct MonoBitSet * small_id_table.0;
  struct MonoBitSet * small_id_table.1;
  int small_id_next.2;
  long unsigned int D.14599;
  long unsigned int D.14600;
  unsigned int D.14603;
  unsigned int D.14604;
  unsigned int D.14605;
  unsigned int D.14606;
  int D.14607;
  long unsigned int D.14608;
  long unsigned int D.14609;
  long unsigned int D.14610;
  int D.14611;
  long unsigned int D.14612;
  long unsigned int D.14613;
  _Bool D.14614;
  long int D.14615;
  long int D.14616;
  long unsigned int D.14619;
  long unsigned int D.14620;
  long unsigned int D.14621;
  long unsigned int D.14622;
  int small_id_next.3;
  long unsigned int D.14624;
  _Bool D.14627;
  long int D.14628;
  long int D.14629;
  int hazard_table_size.4;
  int hazard_table_size.5;
  long unsigned int D.14636;
  long unsigned int D.14637;
  long unsigned int D.14638;
  long unsigned int D.14639;
  long unsigned int D.14640;
  long unsigned int D.14641;
  struct MonoThreadHazardPointers * hazard_table.6;
  void * hazard_table.7;
  struct MonoThreadHazardPointers * hazard_table.8;
  _Bool D.14647;
  long int D.14648;
  long int D.14649;
  struct MonoThreadHazardPointers * hazard_table.9;
  int D.14653;
  sizetype D.14654;
  long unsigned int D.14655;
  long unsigned int D.14656;
  long unsigned int D.14657;
  int hazard_table_size.10;
  int hazard_table_size.11;
  _Bool D.14660;
  long int D.14661;
  long int D.14662;
  struct MonoThreadHazardPointers * hazard_table.12;
  long unsigned int D.14666;
  struct MonoThreadHazardPointers * D.14667;
  int highest_small_id.13;
  _Bool D.14673;
  long int D.14674;
  long int D.14675;
  int D.14678;
  int i;
  int id;

  id = -1;
  {
    int ret;

    ret = pthread_mutex_lock (&small_id_mutex.mutex);
    if (ret != 0) goto <D.14583>; else goto <D.14584>;
    <D.14583>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.14584>:
    D.14585 = ret != 0;
    D.14586 = (long int) D.14585;
    D.14587 = __builtin_expect (D.14586, 0);
    if (D.14587 != 0) goto <D.14588>; else goto <D.14589>;
    <D.14588>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 56, "ret == 0");
    <D.14589>:
  }
  small_id_table.0 = small_id_table;
  if (small_id_table.0 == 0B) goto <D.14591>; else goto <D.14592>;
  <D.14591>:
  small_id_table.1 = mono_bitset_new (1, 0);
  small_id_table = small_id_table.1;
  <D.14592>:
  small_id_next.2 = small_id_next;
  small_id_table.0 = small_id_table;
  id = mono_bitset_find_first_unset (small_id_table.0, small_id_next.2);
  if (id == -1) goto <D.14595>; else goto <D.14596>;
  <D.14595>:
  small_id_table.0 = small_id_table;
  id = mono_bitset_find_first_unset (small_id_table.0, -1);
  <D.14596>:
  if (id == -1) goto <D.14597>; else goto <D.14598>;
  <D.14597>:
  {
    struct MonoBitSet * new_table;

    small_id_table.0 = small_id_table;
    D.14599 = small_id_table.0->size;
    D.14600 = D.14599 * 2;
    if (D.14600 > 65535) goto <D.14601>; else goto <D.14602>;
    <D.14601>:
    monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "hazard-pointer.c", 68);
    <D.14602>:
    small_id_table.0 = small_id_table;
    D.14599 = small_id_table.0->size;
    D.14603 = (unsigned int) D.14599;
    D.14604 = D.14603 * 2;
    small_id_table.0 = small_id_table;
    new_table = mono_bitset_clone (small_id_table.0, D.14604);
    small_id_table.0 = small_id_table;
    D.14599 = small_id_table.0->size;
    D.14605 = (unsigned int) D.14599;
    D.14606 = D.14605 + 4294967295;
    D.14607 = (int) D.14606;
    id = mono_bitset_find_first_unset (new_table, D.14607);
    small_id_table.0 = small_id_table;
    mono_bitset_free (small_id_table.0);
    small_id_table = new_table;
  }
  <D.14598>:
  small_id_table.0 = small_id_table;
  D.14608 = (long unsigned int) id;
  D.14609 = D.14608 / 64;
  D.14610 = small_id_table.0->data[D.14609];
  D.14611 = id & 63;
  D.14612 = D.14610 >> D.14611;
  D.14613 = D.14612 & 1;
  D.14614 = D.14613 != 0;
  D.14615 = (long int) D.14614;
  D.14616 = __builtin_expect (D.14615, 0);
  if (D.14616 != 0) goto <D.14617>; else goto <D.14618>;
  <D.14617>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 76, "!mono_bitset_test_fast (small_id_table, id)");
  <D.14618>:
  small_id_table.0 = small_id_table;
  D.14608 = (long unsigned int) id;
  D.14619 = D.14608 / 64;
  small_id_table.0 = small_id_table;
  D.14620 = small_id_table.0->data[D.14619];
  D.14611 = id & 63;
  D.14621 = 1 << D.14611;
  D.14622 = D.14620 | D.14621;
  small_id_table.0->data[D.14619] = D.14622;
  small_id_next.2 = small_id_next;
  small_id_next.3 = small_id_next.2 + 1;
  small_id_next = small_id_next.3;
  small_id_next.2 = small_id_next;
  D.14624 = (long unsigned int) small_id_next.2;
  small_id_table.0 = small_id_table;
  D.14599 = small_id_table.0->size;
  if (D.14624 >= D.14599) goto <D.14625>; else goto <D.14626>;
  <D.14625>:
  small_id_next = 0;
  <D.14626>:
  D.14627 = id > 16383;
  D.14628 = (long int) D.14627;
  D.14629 = __builtin_expect (D.14628, 0);
  if (D.14629 != 0) goto <D.14630>; else goto <D.14631>;
  <D.14630>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 83, "id < HAZARD_TABLE_MAX_SIZE");
  <D.14631>:
  hazard_table_size.4 = hazard_table_size;
  if (id >= hazard_table_size.4) goto <D.14633>; else goto <D.14634>;
  <D.14633>:
  {
    void * page_addr;
    int pagesize;
    int num_pages;

    pagesize = mono_pagesize ();
    hazard_table_size.5 = hazard_table_size;
    D.14636 = (long unsigned int) hazard_table_size.5;
    D.14637 = D.14636 * 24;
    D.14638 = (long unsigned int) pagesize;
    D.14639 = D.14637 + D.14638;
    D.14640 = D.14639 + 18446744073709551615;
    D.14638 = (long unsigned int) pagesize;
    D.14641 = D.14640 / D.14638;
    num_pages = (int) D.14641;
    hazard_table.6 = hazard_table;
    if (hazard_table.6 == 0B) goto <D.14643>; else goto <D.14644>;
    <D.14643>:
    hazard_table.7 = mono_valloc (0B, 393216, 0);
    hazard_table = hazard_table.7;
    <D.14644>:
    hazard_table.8 = hazard_table;
    D.14647 = hazard_table.8 == 0B;
    D.14648 = (long int) D.14647;
    D.14649 = __builtin_expect (D.14648, 0);
    if (D.14649 != 0) goto <D.14650>; else goto <D.14651>;
    <D.14650>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 99, "hazard_table != NULL");
    <D.14651>:
    hazard_table.9 = hazard_table;
    D.14653 = num_pages * pagesize;
    D.14654 = (sizetype) D.14653;
    page_addr = hazard_table.9 + D.14654;
    D.14655 = (long unsigned int) pagesize;
    mono_mprotect (page_addr, D.14655, 3);
    num_pages = num_pages + 1;
    D.14653 = num_pages * pagesize;
    D.14656 = (long unsigned int) D.14653;
    D.14657 = D.14656 / 24;
    hazard_table_size.10 = (int) D.14657;
    hazard_table_size = hazard_table_size.10;
    hazard_table_size.11 = hazard_table_size;
    D.14660 = id >= hazard_table_size.11;
    D.14661 = (long int) D.14660;
    D.14662 = __builtin_expect (D.14661, 0);
    if (D.14662 != 0) goto <D.14663>; else goto <D.14664>;
    <D.14663>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 108, "id < hazard_table_size");
    <D.14664>:
    i = 0;
    goto <D.14513>;
    <D.14512>:
    hazard_table.12 = hazard_table;
    D.14608 = (long unsigned int) id;
    D.14666 = D.14608 * 24;
    D.14667 = hazard_table.12 + D.14666;
    D.14667->hazard_pointers[i] = 0B;
    i = i + 1;
    <D.14513>:
    if (i <= 2) goto <D.14512>; else goto <D.14514>;
    <D.14514>:
  }
  <D.14634>:
  highest_small_id.13 = highest_small_id;
  if (id > highest_small_id.13) goto <D.14669>; else goto <D.14670>;
  <D.14669>:
  highest_small_id = id;
  mono_memory_write_barrier ();
  <D.14670>:
  {
    int ret;

    ret = pthread_mutex_unlock (&small_id_mutex.mutex);
    if (ret != 0) goto <D.14671>; else goto <D.14672>;
    <D.14671>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.14672>:
    D.14673 = ret != 0;
    D.14674 = (long int) D.14673;
    D.14675 = __builtin_expect (D.14674, 0);
    if (D.14675 != 0) goto <D.14676>; else goto <D.14677>;
    <D.14676>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 118, "ret == 0");
    <D.14677>:
  }
  D.14678 = id;
  return D.14678;
}


mono_memory_write_barrier ()
{
  mono_memory_barrier ();
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


mono_thread_small_id_free (int id)
{
  _Bool D.14682;
  long int D.14683;
  long int D.14684;
  int iftmp.14;
  long unsigned int D.14692;
  struct MonoBitSet * small_id_table.15;
  long unsigned int D.14694;
  _Bool D.14695;
  long int D.14696;
  long int D.14697;
  long unsigned int D.14700;
  long unsigned int D.14701;
  long unsigned int D.14702;
  int D.14703;
  long unsigned int D.14704;
  long unsigned int D.14705;
  _Bool D.14706;
  long int D.14707;
  long int D.14708;
  long unsigned int D.14711;
  long unsigned int D.14712;
  long unsigned int D.14713;
  long unsigned int D.14714;
  long unsigned int D.14715;
  _Bool D.14718;
  long int D.14719;
  long int D.14720;

  {
    int ret;

    ret = pthread_mutex_lock (&small_id_mutex.mutex);
    if (ret != 0) goto <D.14680>; else goto <D.14681>;
    <D.14680>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.14681>:
    D.14682 = ret != 0;
    D.14683 = (long int) D.14682;
    D.14684 = __builtin_expect (D.14683, 0);
    if (D.14684 != 0) goto <D.14685>; else goto <D.14686>;
    <D.14685>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 127, "ret == 0");
    <D.14686>:
  }
  if (id < 0) goto <D.14688>; else goto <D.14691>;
  <D.14691>:
  D.14692 = (long unsigned int) id;
  small_id_table.15 = small_id_table;
  D.14694 = small_id_table.15->size;
  if (D.14692 >= D.14694) goto <D.14688>; else goto <D.14689>;
  <D.14688>:
  iftmp.14 = 1;
  goto <D.14690>;
  <D.14689>:
  iftmp.14 = 0;
  <D.14690>:
  D.14695 = iftmp.14 != 0;
  D.14696 = (long int) D.14695;
  D.14697 = __builtin_expect (D.14696, 0);
  if (D.14697 != 0) goto <D.14698>; else goto <D.14699>;
  <D.14698>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 129, "id >= 0 && id < small_id_table->size");
  <D.14699>:
  small_id_table.15 = small_id_table;
  D.14700 = (long unsigned int) id;
  D.14701 = D.14700 / 64;
  D.14702 = small_id_table.15->data[D.14701];
  D.14703 = id & 63;
  D.14704 = D.14702 >> D.14703;
  D.14705 = D.14704 & 1;
  D.14706 = D.14705 == 0;
  D.14707 = (long int) D.14706;
  D.14708 = __builtin_expect (D.14707, 0);
  if (D.14708 != 0) goto <D.14709>; else goto <D.14710>;
  <D.14709>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 130, "mono_bitset_test_fast (small_id_table, id)");
  <D.14710>:
  small_id_table.15 = small_id_table;
  D.14700 = (long unsigned int) id;
  D.14711 = D.14700 / 64;
  small_id_table.15 = small_id_table;
  D.14712 = small_id_table.15->data[D.14711];
  D.14703 = id & 63;
  D.14713 = 1 << D.14703;
  D.14714 = ~D.14713;
  D.14715 = D.14712 & D.14714;
  small_id_table.15->data[D.14711] = D.14715;
  {
    int ret;

    ret = pthread_mutex_unlock (&small_id_mutex.mutex);
    if (ret != 0) goto <D.14716>; else goto <D.14717>;
    <D.14716>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.14717>:
    D.14718 = ret != 0;
    D.14719 = (long int) D.14718;
    D.14720 = __builtin_expect (D.14719, 0);
    if (D.14720 != 0) goto <D.14721>; else goto <D.14722>;
    <D.14721>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 133, "ret == 0");
    <D.14722>:
  }
}


mono_hazard_pointer_get ()
{
  long unsigned int D.14725;
  void * D.14726;
  struct MonoThreadHazardPointers * D.14727;
  struct MonoThreadHazardPointers * hazard_table.16;
  long unsigned int D.14729;
  long unsigned int D.14730;
  int small_id;

  small_id = mono_thread_info_get_small_id ();
  if (small_id < 0) goto <D.14723>; else goto <D.14724>;
  <D.14723>:
  {
    static struct MonoThreadHazardPointers emerg_hazard_table;

    D.14725 = mono_native_thread_id_get ();
    D.14726 = (void *) D.14725;
    monoeg_g_log (0B, 16, "Thread %p may have been prematurely finalized", D.14726);
    D.14727 = &emerg_hazard_table;
    return D.14727;
  }
  <D.14724>:
  hazard_table.16 = hazard_table;
  D.14729 = (long unsigned int) small_id;
  D.14730 = D.14729 * 24;
  D.14727 = hazard_table.16 + D.14730;
  return D.14727;
}


get_hazardous_pointer (void * volatile * pp, struct MonoThreadHazardPointers * hp, int hazard_index)
{
  void * D.14734;
  unsigned int hazard_index.17;
  _Bool D.14736;
  long int D.14737;
  long int D.14738;
  void * D.14741;
  void * p;

  <D.14546>:
  p = *pp;
  if (hp == 0B) goto <D.14732>; else goto <D.14733>;
  <D.14732>:
  D.14734 = p;
  return D.14734;
  <D.14733>:
  hazard_index.17 = (unsigned int) hazard_index;
  D.14736 = hazard_index.17 > 2;
  D.14737 = (long int) D.14736;
  D.14738 = __builtin_expect (D.14737, 0);
  if (D.14738 != 0) goto <D.14739>; else goto <D.14740>;
  <D.14739>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 186, "(hazard_index) >= 0 && (hazard_index) < HAZARD_POINTER_COUNT");
  <D.14740>:
  hp->hazard_pointers[hazard_index] = p;
  mono_memory_write_barrier ();
  D.14741 = *pp;
  if (D.14741 != p) goto <D.14742>; else goto <D.14743>;
  <D.14742>:
  hazard_index.17 = (unsigned int) hazard_index;
  D.14736 = hazard_index.17 > 2;
  D.14737 = (long int) D.14736;
  D.14738 = __builtin_expect (D.14737, 0);
  if (D.14738 != 0) goto <D.14744>; else goto <D.14745>;
  <D.14744>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 190, "(hazard_index) >= 0 && (hazard_index) < HAZARD_POINTER_COUNT");
  <D.14745>:
  hp->hazard_pointers[hazard_index] = 0B;
  // predicted unlikely by continue predictor.
  goto <D.14544>;
  <D.14743>:
  goto <D.14545>;
  <D.14544>:
  goto <D.14546>;
  <D.14545>:
  D.14734 = p;
  return D.14734;
}


mono_thread_hazardous_free_or_queue (void * p, void (*MonoHazardousFreeFunc) (void *) free_func, gboolean free_func_might_lock, gboolean lock_free_context)
{
  _Bool D.14749;
  long int D.14750;
  long int D.14751;
  _Bool D.14756;
  long int D.14757;
  long int D.14758;
  int D.14761;
  long unsigned int D.14764;
  long unsigned int D.14765;
  int i;

  if (lock_free_context != 0) goto <D.14747>; else goto <D.14748>;
  <D.14747>:
  D.14749 = free_func_might_lock != 0;
  D.14750 = (long int) D.14749;
  D.14751 = __builtin_expect (D.14750, 0);
  if (D.14751 != 0) goto <D.14752>; else goto <D.14753>;
  <D.14752>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 225, "!free_func_might_lock");
  <D.14753>:
  <D.14748>:
  if (free_func_might_lock != 0) goto <D.14754>; else goto <D.14755>;
  <D.14754>:
  D.14756 = lock_free_context != 0;
  D.14757 = (long int) D.14756;
  D.14758 = __builtin_expect (D.14757, 0);
  if (D.14758 != 0) goto <D.14759>; else goto <D.14760>;
  <D.14759>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 227, "!lock_free_context");
  <D.14760>:
  <D.14755>:
  i = 0;
  goto <D.14560>;
  <D.14559>:
  try_free_delayed_free_item (lock_free_context);
  i = i + 1;
  <D.14560>:
  if (i <= 2) goto <D.14559>; else goto <D.14561>;
  <D.14561>:
  D.14761 = is_pointer_hazardous (p);
  if (D.14761 != 0) goto <D.14762>; else goto <D.14763>;
  <D.14762>:
  {
    struct DelayedFreeItem item;

    try
      {
        item.p = p;
        item.free_func = free_func;
        item.might_lock = free_func_might_lock;
        D.14764 = mono_stats.hazardous_pointer_count;
        D.14765 = D.14764 + 1;
        mono_stats.hazardous_pointer_count = D.14765;
        mono_lock_free_array_queue_push (&delayed_free_queue, &item);
      }
    finally
      {
        item = {CLOBBER};
      }
  }
  goto <D.14766>;
  <D.14763>:
  free_func (p);
  <D.14766>:
}


try_free_delayed_free_item (gboolean lock_free_context)
{
  gboolean D.14769;
  int D.14774;
  void * D.14775;
  int D.14776;
  void (*<T10b3>) (void *) D.14777;
  struct DelayedFreeItem item;
  gboolean popped;

  try
    {
      popped = mono_lock_free_array_queue_pop (&delayed_free_queue, &item);
      if (popped == 0) goto <D.14767>; else goto <D.14768>;
      <D.14767>:
      D.14769 = 0;
      return D.14769;
      <D.14768>:
      if (lock_free_context != 0) goto <D.14773>; else goto <D.14770>;
      <D.14773>:
      D.14774 = item.might_lock;
      if (D.14774 != 0) goto <D.14771>; else goto <D.14770>;
      <D.14770>:
      D.14775 = item.p;
      D.14776 = is_pointer_hazardous (D.14775);
      if (D.14776 != 0) goto <D.14771>; else goto <D.14772>;
      <D.14771>:
      mono_lock_free_array_queue_push (&delayed_free_queue, &item);
      D.14769 = 0;
      return D.14769;
      <D.14772>:
      D.14777 = item.free_func;
      D.14775 = item.p;
      D.14777 (D.14775);
      D.14769 = 1;
      return D.14769;
    }
  finally
    {
      item = {CLOBBER};
    }
}


is_pointer_hazardous (void * p)
{
  int hazard_table_size.18;
  _Bool D.14781;
  long int D.14782;
  long int D.14783;
  struct MonoThreadHazardPointers * hazard_table.19;
  long unsigned int D.14787;
  long unsigned int D.14788;
  struct MonoThreadHazardPointers * D.14789;
  void * D.14790;
  gboolean D.14793;
  int i;
  int j;
  int highest;

  highest = highest_small_id;
  hazard_table_size.18 = hazard_table_size;
  D.14781 = highest >= hazard_table_size.18;
  D.14782 = (long int) D.14781;
  D.14783 = __builtin_expect (D.14782, 0);
  if (D.14783 != 0) goto <D.14784>; else goto <D.14785>;
  <D.14784>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 142, "highest < hazard_table_size");
  <D.14785>:
  i = 0;
  goto <D.14531>;
  <D.14530>:
  j = 0;
  goto <D.14528>;
  <D.14527>:
  hazard_table.19 = hazard_table;
  D.14787 = (long unsigned int) i;
  D.14788 = D.14787 * 24;
  D.14789 = hazard_table.19 + D.14788;
  D.14790 = D.14789->hazard_pointers[j];
  if (D.14790 == p) goto <D.14791>; else goto <D.14792>;
  <D.14791>:
  D.14793 = 1;
  return D.14793;
  <D.14792>:
  j = j + 1;
  <D.14528>:
  if (j <= 2) goto <D.14527>; else goto <D.14529>;
  <D.14529>:
  i = i + 1;
  <D.14531>:
  if (i <= highest) goto <D.14530>; else goto <D.14532>;
  <D.14532>:
  D.14793 = 0;
  return D.14793;
}


mono_thread_hazardous_try_free_all ()
{
  int D.14795;

  goto <D.14567>;
  <D.14566>:
  <D.14567>:
  D.14795 = try_free_delayed_free_item (0);
  if (D.14795 != 0) goto <D.14566>; else goto <D.14568>;
  <D.14568>:
}


mono_thread_hazardous_try_free_some ()
{
  int i;

  i = 0;
  goto <D.14574>;
  <D.14573>:
  try_free_delayed_free_item (0);
  i = i + 1;
  <D.14574>:
  if (i <= 9) goto <D.14573>; else goto <D.14575>;
  <D.14575>:
}


mono_thread_smr_init ()
{
  InitializeCriticalSection (&small_id_mutex);
}


mono_thread_smr_cleanup ()
{
  mono_thread_hazardous_try_free_all ();
  mono_lock_free_array_queue_cleanup (&delayed_free_queue);
}


