mono_thread_small_id_alloc ()
{
  _Bool D.16772;
  long int D.16773;
  long int D.16774;
  struct MonoBitSet * small_id_table.0;
  struct MonoBitSet * small_id_table.1;
  int small_id_next.2;
  unsigned int D.16786;
  unsigned int D.16787;
  unsigned int D.16790;
  int D.16791;
  unsigned int id.3;
  unsigned int D.16793;
  unsigned int D.16794;
  int D.16795;
  unsigned int D.16796;
  unsigned int D.16797;
  _Bool D.16798;
  long int D.16799;
  long int D.16800;
  unsigned int D.16803;
  unsigned int D.16804;
  unsigned int D.16805;
  int small_id_next.4;
  unsigned int small_id_next.5;
  _Bool D.16810;
  long int D.16811;
  long int D.16812;
  int hazard_table_size.6;
  int hazard_table_size.7;
  unsigned int hazard_table_size.8;
  unsigned int D.16820;
  unsigned int pagesize.9;
  unsigned int D.16822;
  unsigned int D.16823;
  unsigned int D.16824;
  struct MonoThreadHazardPointers * hazard_table.10;
  void * hazard_table.11;
  struct MonoThreadHazardPointers * hazard_table.12;
  _Bool D.16830;
  long int D.16831;
  long int D.16832;
  struct MonoThreadHazardPointers * hazard_table.13;
  int D.16836;
  sizetype D.16837;
  unsigned int pagesize.14;
  unsigned int D.16839;
  unsigned int D.16840;
  int hazard_table_size.15;
  int hazard_table_size.16;
  _Bool D.16843;
  long int D.16844;
  long int D.16845;
  struct MonoThreadHazardPointers * hazard_table.17;
  unsigned int D.16849;
  struct MonoThreadHazardPointers * D.16850;
  int highest_small_id.18;
  _Bool D.16856;
  long int D.16857;
  long int D.16858;
  int D.16861;
  int i;
  int id;

  id = -1;
  {
    int ret;

    ret = pthread_mutex_lock (&small_id_mutex.mutex);
    if (ret != 0) goto <D.16770>; else goto <D.16771>;
    <D.16770>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.16771>:
    D.16772 = ret != 0;
    D.16773 = (long int) D.16772;
    D.16774 = __builtin_expect (D.16773, 0);
    if (D.16774 != 0) goto <D.16775>; else goto <D.16776>;
    <D.16775>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 56, "ret == 0");
    <D.16776>:
  }
  small_id_table.0 = small_id_table;
  if (small_id_table.0 == 0B) goto <D.16778>; else goto <D.16779>;
  <D.16778>:
  small_id_table.1 = mono_bitset_new (1, 0);
  small_id_table = small_id_table.1;
  <D.16779>:
  small_id_table.0 = small_id_table;
  small_id_next.2 = small_id_next;
  id = mono_bitset_find_first_unset (small_id_table.0, small_id_next.2);
  if (id == -1) goto <D.16782>; else goto <D.16783>;
  <D.16782>:
  small_id_table.0 = small_id_table;
  id = mono_bitset_find_first_unset (small_id_table.0, -1);
  <D.16783>:
  if (id == -1) goto <D.16784>; else goto <D.16785>;
  <D.16784>:
  {
    struct MonoBitSet * new_table;

    small_id_table.0 = small_id_table;
    D.16786 = small_id_table.0->size;
    D.16787 = D.16786 * 2;
    if (D.16787 > 65535) goto <D.16788>; else goto <D.16789>;
    <D.16788>:
    monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "hazard-pointer.c", 68);
    <D.16789>:
    small_id_table.0 = small_id_table;
    small_id_table.0 = small_id_table;
    D.16786 = small_id_table.0->size;
    D.16787 = D.16786 * 2;
    new_table = mono_bitset_clone (small_id_table.0, D.16787);
    small_id_table.0 = small_id_table;
    D.16786 = small_id_table.0->size;
    D.16790 = D.16786 + 4294967295;
    D.16791 = (int) D.16790;
    id = mono_bitset_find_first_unset (new_table, D.16791);
    small_id_table.0 = small_id_table;
    mono_bitset_free (small_id_table.0);
    small_id_table = new_table;
  }
  <D.16785>:
  small_id_table.0 = small_id_table;
  id.3 = (unsigned int) id;
  D.16793 = id.3 / 32;
  D.16794 = small_id_table.0->data[D.16793];
  D.16795 = id & 31;
  D.16796 = 1 << D.16795;
  D.16797 = D.16794 & D.16796;
  D.16798 = D.16797 != 0;
  D.16799 = (long int) D.16798;
  D.16800 = __builtin_expect (D.16799, 0);
  if (D.16800 != 0) goto <D.16801>; else goto <D.16802>;
  <D.16801>:
  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.16802>:
  small_id_table.0 = small_id_table;
  id.3 = (unsigned int) id;
  D.16803 = id.3 / 32;
  small_id_table.0 = small_id_table;
  D.16804 = small_id_table.0->data[D.16803];
  D.16795 = id & 31;
  D.16796 = 1 << D.16795;
  D.16805 = D.16804 | D.16796;
  small_id_table.0->data[D.16803] = D.16805;
  small_id_next.2 = small_id_next;
  small_id_next.4 = small_id_next.2 + 1;
  small_id_next = small_id_next.4;
  small_id_next.2 = small_id_next;
  small_id_next.5 = (unsigned int) small_id_next.2;
  small_id_table.0 = small_id_table;
  D.16786 = small_id_table.0->size;
  if (small_id_next.5 >= D.16786) goto <D.16808>; else goto <D.16809>;
  <D.16808>:
  small_id_next = 0;
  <D.16809>:
  D.16810 = id > 16383;
  D.16811 = (long int) D.16810;
  D.16812 = __builtin_expect (D.16811, 0);
  if (D.16812 != 0) goto <D.16813>; else goto <D.16814>;
  <D.16813>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 83, "id < HAZARD_TABLE_MAX_SIZE");
  <D.16814>:
  hazard_table_size.6 = hazard_table_size;
  if (id >= hazard_table_size.6) goto <D.16816>; else goto <D.16817>;
  <D.16816>:
  {
    void * page_addr;
    int pagesize;
    int num_pages;

    pagesize = mono_pagesize ();
    hazard_table_size.7 = hazard_table_size;
    hazard_table_size.8 = (unsigned int) hazard_table_size.7;
    D.16820 = hazard_table_size.8 * 12;
    pagesize.9 = (unsigned int) pagesize;
    D.16822 = D.16820 + pagesize.9;
    D.16823 = D.16822 + 4294967295;
    pagesize.9 = (unsigned int) pagesize;
    D.16824 = D.16823 / pagesize.9;
    num_pages = (int) D.16824;
    hazard_table.10 = hazard_table;
    if (hazard_table.10 == 0B) goto <D.16826>; else goto <D.16827>;
    <D.16826>:
    hazard_table.11 = mono_valloc (0B, 196608, 0);
    hazard_table = hazard_table.11;
    <D.16827>:
    hazard_table.12 = hazard_table;
    D.16830 = hazard_table.12 == 0B;
    D.16831 = (long int) D.16830;
    D.16832 = __builtin_expect (D.16831, 0);
    if (D.16832 != 0) goto <D.16833>; else goto <D.16834>;
    <D.16833>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 99, "hazard_table != NULL");
    <D.16834>:
    hazard_table.13 = hazard_table;
    D.16836 = num_pages * pagesize;
    D.16837 = (sizetype) D.16836;
    page_addr = hazard_table.13 + D.16837;
    pagesize.14 = (unsigned int) pagesize;
    mono_mprotect (page_addr, pagesize.14, 3);
    num_pages = num_pages + 1;
    D.16836 = num_pages * pagesize;
    D.16839 = (unsigned int) D.16836;
    D.16840 = D.16839 / 12;
    hazard_table_size.15 = (int) D.16840;
    hazard_table_size = hazard_table_size.15;
    hazard_table_size.16 = hazard_table_size;
    D.16843 = id >= hazard_table_size.16;
    D.16844 = (long int) D.16843;
    D.16845 = __builtin_expect (D.16844, 0);
    if (D.16845 != 0) goto <D.16846>; else goto <D.16847>;
    <D.16846>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 108, "id < hazard_table_size");
    <D.16847>:
    i = 0;
    goto <D.16698>;
    <D.16697>:
    hazard_table.17 = hazard_table;
    id.3 = (unsigned int) id;
    D.16849 = id.3 * 12;
    D.16850 = hazard_table.17 + D.16849;
    D.16850->hazard_pointers[i] = 0B;
    i = i + 1;
    <D.16698>:
    if (i <= 2) goto <D.16697>; else goto <D.16699>;
    <D.16699>:
  }
  <D.16817>:
  highest_small_id.18 = highest_small_id;
  if (id > highest_small_id.18) goto <D.16852>; else goto <D.16853>;
  <D.16852>:
  highest_small_id = id;
  mono_memory_write_barrier ();
  <D.16853>:
  {
    int ret;

    ret = pthread_mutex_unlock (&small_id_mutex.mutex);
    if (ret != 0) goto <D.16854>; else goto <D.16855>;
    <D.16854>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.16855>:
    D.16856 = ret != 0;
    D.16857 = (long int) D.16856;
    D.16858 = __builtin_expect (D.16857, 0);
    if (D.16858 != 0) goto <D.16859>; else goto <D.16860>;
    <D.16859>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 118, "ret == 0");
    <D.16860>:
  }
  D.16861 = id;
  return D.16861;
}


mono_memory_write_barrier ()
{
  mono_memory_barrier ();
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


mono_thread_small_id_free (int id)
{
  _Bool D.16865;
  long int D.16866;
  long int D.16867;
  int iftmp.19;
  unsigned int id.20;
  struct MonoBitSet * small_id_table.21;
  unsigned int D.16877;
  _Bool D.16878;
  long int D.16879;
  long int D.16880;
  unsigned int id.22;
  unsigned int D.16884;
  unsigned int D.16885;
  int D.16886;
  unsigned int D.16887;
  unsigned int D.16888;
  _Bool D.16889;
  long int D.16890;
  long int D.16891;
  unsigned int D.16894;
  unsigned int D.16895;
  unsigned int D.16896;
  unsigned int D.16897;
  _Bool D.16900;
  long int D.16901;
  long int D.16902;

  {
    int ret;

    ret = pthread_mutex_lock (&small_id_mutex.mutex);
    if (ret != 0) goto <D.16863>; else goto <D.16864>;
    <D.16863>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.16864>:
    D.16865 = ret != 0;
    D.16866 = (long int) D.16865;
    D.16867 = __builtin_expect (D.16866, 0);
    if (D.16867 != 0) goto <D.16868>; else goto <D.16869>;
    <D.16868>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 127, "ret == 0");
    <D.16869>:
  }
  if (id < 0) goto <D.16871>; else goto <D.16874>;
  <D.16874>:
  id.20 = (unsigned int) id;
  small_id_table.21 = small_id_table;
  D.16877 = small_id_table.21->size;
  if (id.20 >= D.16877) goto <D.16871>; else goto <D.16872>;
  <D.16871>:
  iftmp.19 = 1;
  goto <D.16873>;
  <D.16872>:
  iftmp.19 = 0;
  <D.16873>:
  D.16878 = iftmp.19 != 0;
  D.16879 = (long int) D.16878;
  D.16880 = __builtin_expect (D.16879, 0);
  if (D.16880 != 0) goto <D.16881>; else goto <D.16882>;
  <D.16881>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 129, "id >= 0 && id < small_id_table->size");
  <D.16882>:
  small_id_table.21 = small_id_table;
  id.22 = (unsigned int) id;
  D.16884 = id.22 / 32;
  D.16885 = small_id_table.21->data[D.16884];
  D.16886 = id & 31;
  D.16887 = 1 << D.16886;
  D.16888 = D.16885 & D.16887;
  D.16889 = D.16888 == 0;
  D.16890 = (long int) D.16889;
  D.16891 = __builtin_expect (D.16890, 0);
  if (D.16891 != 0) goto <D.16892>; else goto <D.16893>;
  <D.16892>:
  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.16893>:
  small_id_table.21 = small_id_table;
  id.22 = (unsigned int) id;
  D.16894 = id.22 / 32;
  small_id_table.21 = small_id_table;
  D.16895 = small_id_table.21->data[D.16894];
  D.16886 = id & 31;
  D.16887 = 1 << D.16886;
  D.16896 = ~D.16887;
  D.16897 = D.16895 & D.16896;
  small_id_table.21->data[D.16894] = D.16897;
  {
    int ret;

    ret = pthread_mutex_unlock (&small_id_mutex.mutex);
    if (ret != 0) goto <D.16898>; else goto <D.16899>;
    <D.16898>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.16899>:
    D.16900 = ret != 0;
    D.16901 = (long int) D.16900;
    D.16902 = __builtin_expect (D.16901, 0);
    if (D.16902 != 0) goto <D.16903>; else goto <D.16904>;
    <D.16903>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 133, "ret == 0");
    <D.16904>:
  }
}


mono_hazard_pointer_get ()
{
  long unsigned int D.16907;
  void * D.16908;
  struct MonoThreadHazardPointers * D.16909;
  struct MonoThreadHazardPointers * hazard_table.23;
  unsigned int small_id.24;
  unsigned int D.16912;
  int small_id;

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

    D.16907 = mono_native_thread_id_get ();
    D.16908 = (void *) D.16907;
    monoeg_g_log (0B, 16, "Thread %p may have been prematurely finalized", D.16908);
    D.16909 = &emerg_hazard_table;
    return D.16909;
  }
  <D.16906>:
  hazard_table.23 = hazard_table;
  small_id.24 = (unsigned int) small_id;
  D.16912 = small_id.24 * 12;
  D.16909 = hazard_table.23 + D.16912;
  return D.16909;
}


get_hazardous_pointer (void * volatile * pp, struct MonoThreadHazardPointers * hp, int hazard_index)
{
  void * D.16916;
  unsigned int hazard_index.25;
  _Bool D.16918;
  long int D.16919;
  long int D.16920;
  void * D.16923;
  void * p;

  <D.16731>:
  p = *pp;
  if (hp == 0B) goto <D.16914>; else goto <D.16915>;
  <D.16914>:
  D.16916 = p;
  return D.16916;
  <D.16915>:
  hazard_index.25 = (unsigned int) hazard_index;
  D.16918 = hazard_index.25 > 2;
  D.16919 = (long int) D.16918;
  D.16920 = __builtin_expect (D.16919, 0);
  if (D.16920 != 0) goto <D.16921>; else goto <D.16922>;
  <D.16921>:
  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.16922>:
  hp->hazard_pointers[hazard_index] = p;
  mono_memory_write_barrier ();
  D.16923 = *pp;
  if (D.16923 != p) goto <D.16924>; else goto <D.16925>;
  <D.16924>:
  hazard_index.25 = (unsigned int) hazard_index;
  D.16918 = hazard_index.25 > 2;
  D.16919 = (long int) D.16918;
  D.16920 = __builtin_expect (D.16919, 0);
  if (D.16920 != 0) goto <D.16926>; else goto <D.16927>;
  <D.16926>:
  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.16927>:
  hp->hazard_pointers[hazard_index] = 0B;
  // predicted unlikely by continue predictor.
  goto <D.16729>;
  <D.16925>:
  goto <D.16730>;
  <D.16729>:
  goto <D.16731>;
  <D.16730>:
  D.16916 = p;
  return D.16916;
}


mono_thread_hazardous_free_or_queue (void * p, void (*MonoHazardousFreeFunc) (void *) free_func, gboolean free_func_might_lock, gboolean lock_free_context)
{
  _Bool D.16931;
  long int D.16932;
  long int D.16933;
  _Bool D.16938;
  long int D.16939;
  long int D.16940;
  int D.16943;
  long unsigned int D.16946;
  long unsigned int D.16947;
  int i;

  if (lock_free_context != 0) goto <D.16929>; else goto <D.16930>;
  <D.16929>:
  D.16931 = free_func_might_lock != 0;
  D.16932 = (long int) D.16931;
  D.16933 = __builtin_expect (D.16932, 0);
  if (D.16933 != 0) goto <D.16934>; else goto <D.16935>;
  <D.16934>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 225, "!free_func_might_lock");
  <D.16935>:
  <D.16930>:
  if (free_func_might_lock != 0) goto <D.16936>; else goto <D.16937>;
  <D.16936>:
  D.16938 = lock_free_context != 0;
  D.16939 = (long int) D.16938;
  D.16940 = __builtin_expect (D.16939, 0);
  if (D.16940 != 0) goto <D.16941>; else goto <D.16942>;
  <D.16941>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 227, "!lock_free_context");
  <D.16942>:
  <D.16937>:
  i = 0;
  goto <D.16745>;
  <D.16744>:
  try_free_delayed_free_item (lock_free_context);
  i = i + 1;
  <D.16745>:
  if (i <= 2) goto <D.16744>; else goto <D.16746>;
  <D.16746>:
  D.16943 = is_pointer_hazardous (p);
  if (D.16943 != 0) goto <D.16944>; else goto <D.16945>;
  <D.16944>:
  {
    struct DelayedFreeItem item;

    try
      {
        item.p = p;
        item.free_func = free_func;
        item.might_lock = free_func_might_lock;
        D.16946 = mono_stats.hazardous_pointer_count;
        D.16947 = D.16946 + 1;
        mono_stats.hazardous_pointer_count = D.16947;
        mono_lock_free_array_queue_push (&delayed_free_queue, &item);
      }
    finally
      {
        item = {CLOBBER};
      }
  }
  goto <D.16948>;
  <D.16945>:
  free_func (p);
  <D.16948>:
}


try_free_delayed_free_item (gboolean lock_free_context)
{
  gboolean D.16951;
  int D.16956;
  void * D.16957;
  int D.16958;
  void (*<T1a9f>) (void *) D.16959;
  struct DelayedFreeItem item;
  gboolean popped;

  try
    {
      popped = mono_lock_free_array_queue_pop (&delayed_free_queue, &item);
      if (popped == 0) goto <D.16949>; else goto <D.16950>;
      <D.16949>:
      D.16951 = 0;
      return D.16951;
      <D.16950>:
      if (lock_free_context != 0) goto <D.16955>; else goto <D.16952>;
      <D.16955>:
      D.16956 = item.might_lock;
      if (D.16956 != 0) goto <D.16953>; else goto <D.16952>;
      <D.16952>:
      D.16957 = item.p;
      D.16958 = is_pointer_hazardous (D.16957);
      if (D.16958 != 0) goto <D.16953>; else goto <D.16954>;
      <D.16953>:
      mono_lock_free_array_queue_push (&delayed_free_queue, &item);
      D.16951 = 0;
      return D.16951;
      <D.16954>:
      D.16959 = item.free_func;
      D.16957 = item.p;
      D.16959 (D.16957);
      D.16951 = 1;
      return D.16951;
    }
  finally
    {
      item = {CLOBBER};
    }
}


is_pointer_hazardous (void * p)
{
  int hazard_table_size.26;
  _Bool D.16963;
  long int D.16964;
  long int D.16965;
  struct MonoThreadHazardPointers * hazard_table.27;
  unsigned int i.28;
  unsigned int D.16970;
  struct MonoThreadHazardPointers * D.16971;
  void * D.16972;
  gboolean D.16975;
  int i;
  int j;
  int highest;

  highest = highest_small_id;
  hazard_table_size.26 = hazard_table_size;
  D.16963 = highest >= hazard_table_size.26;
  D.16964 = (long int) D.16963;
  D.16965 = __builtin_expect (D.16964, 0);
  if (D.16965 != 0) goto <D.16966>; else goto <D.16967>;
  <D.16966>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 142, "highest < hazard_table_size");
  <D.16967>:
  i = 0;
  goto <D.16716>;
  <D.16715>:
  j = 0;
  goto <D.16713>;
  <D.16712>:
  hazard_table.27 = hazard_table;
  i.28 = (unsigned int) i;
  D.16970 = i.28 * 12;
  D.16971 = hazard_table.27 + D.16970;
  D.16972 = D.16971->hazard_pointers[j];
  if (D.16972 == p) goto <D.16973>; else goto <D.16974>;
  <D.16973>:
  D.16975 = 1;
  return D.16975;
  <D.16974>:
  mono_memory_read_barrier ();
  j = j + 1;
  <D.16713>:
  if (j <= 2) goto <D.16712>; else goto <D.16714>;
  <D.16714>:
  i = i + 1;
  <D.16716>:
  if (i <= highest) goto <D.16715>; else goto <D.16717>;
  <D.16717>:
  D.16975 = 0;
  return D.16975;
}


mono_memory_read_barrier ()
{
  mono_memory_barrier ();
}


mono_thread_hazardous_try_free_all ()
{
  int D.16977;

  goto <D.16752>;
  <D.16751>:
  <D.16752>:
  D.16977 = try_free_delayed_free_item (0);
  if (D.16977 != 0) goto <D.16751>; else goto <D.16753>;
  <D.16753>:
}


mono_thread_hazardous_try_free_some ()
{
  int i;

  i = 0;
  goto <D.16759>;
  <D.16758>:
  try_free_delayed_free_item (0);
  i = i + 1;
  <D.16759>:
  if (i <= 9) goto <D.16758>; else goto <D.16760>;
  <D.16760>:
}


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);
}


