mono_thread_small_id_alloc ()
{
  _Bool D.15115;
  long int D.15116;
  long int D.15117;
  struct MonoBitSet * small_id_table.0;
  struct MonoBitSet * small_id_table.1;
  int small_id_next.2;
  long unsigned int D.15129;
  long unsigned int D.15130;
  unsigned int D.15133;
  unsigned int D.15134;
  unsigned int D.15135;
  unsigned int D.15136;
  int D.15137;
  long unsigned int D.15138;
  long unsigned int D.15139;
  long unsigned int D.15140;
  int D.15141;
  long unsigned int D.15142;
  long unsigned int D.15143;
  _Bool D.15144;
  long int D.15145;
  long int D.15146;
  long unsigned int D.15149;
  long unsigned int D.15150;
  long unsigned int D.15151;
  long unsigned int D.15152;
  int small_id_next.3;
  long unsigned int D.15154;
  _Bool D.15157;
  long int D.15158;
  long int D.15159;
  int hazard_table_size.4;
  int hazard_table_size.5;
  long unsigned int D.15166;
  long unsigned int D.15167;
  long unsigned int D.15168;
  long unsigned int D.15169;
  long unsigned int D.15170;
  long unsigned int D.15171;
  struct MonoThreadHazardPointers * hazard_table.6;
  void * hazard_table.7;
  struct MonoThreadHazardPointers * hazard_table.8;
  _Bool D.15177;
  long int D.15178;
  long int D.15179;
  struct MonoThreadHazardPointers * hazard_table.9;
  int D.15183;
  sizetype D.15184;
  long unsigned int D.15185;
  long unsigned int D.15186;
  long unsigned int D.15187;
  int hazard_table_size.10;
  int hazard_table_size.11;
  _Bool D.15190;
  long int D.15191;
  long int D.15192;
  struct MonoThreadHazardPointers * hazard_table.12;
  long unsigned int D.15196;
  struct MonoThreadHazardPointers * D.15197;
  int highest_small_id.13;
  _Bool D.15203;
  long int D.15204;
  long int D.15205;
  int D.15208;
  int i;
  int id;

  id = -1;
  {
    int ret;

    ret = pthread_mutex_lock (&small_id_mutex.mutex);
    if (ret != 0) goto <D.15113>; else goto <D.15114>;
    <D.15113>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.15114>:
    D.15115 = ret != 0;
    D.15116 = (long int) D.15115;
    D.15117 = __builtin_expect (D.15116, 0);
    if (D.15117 != 0) goto <D.15118>; else goto <D.15119>;
    <D.15118>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 56, "ret == 0");
    <D.15119>:
  }
  small_id_table.0 = small_id_table;
  if (small_id_table.0 == 0B) goto <D.15121>; else goto <D.15122>;
  <D.15121>:
  small_id_table.1 = mono_bitset_new (1, 0);
  small_id_table = small_id_table.1;
  <D.15122>:
  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.15125>; else goto <D.15126>;
  <D.15125>:
  small_id_table.0 = small_id_table;
  id = mono_bitset_find_first_unset (small_id_table.0, -1);
  <D.15126>:
  if (id == -1) goto <D.15127>; else goto <D.15128>;
  <D.15127>:
  {
    struct MonoBitSet * new_table;

    small_id_table.0 = small_id_table;
    D.15129 = small_id_table.0->size;
    D.15130 = D.15129 * 2;
    if (D.15130 > 65535) goto <D.15131>; else goto <D.15132>;
    <D.15131>:
    monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "hazard-pointer.c", 68);
    <D.15132>:
    small_id_table.0 = small_id_table;
    small_id_table.0 = small_id_table;
    D.15129 = small_id_table.0->size;
    D.15133 = (unsigned int) D.15129;
    D.15134 = D.15133 * 2;
    new_table = mono_bitset_clone (small_id_table.0, D.15134);
    small_id_table.0 = small_id_table;
    D.15129 = small_id_table.0->size;
    D.15135 = (unsigned int) D.15129;
    D.15136 = D.15135 + 4294967295;
    D.15137 = (int) D.15136;
    id = mono_bitset_find_first_unset (new_table, D.15137);
    small_id_table.0 = small_id_table;
    mono_bitset_free (small_id_table.0);
    small_id_table = new_table;
  }
  <D.15128>:
  small_id_table.0 = small_id_table;
  D.15138 = (long unsigned int) id;
  D.15139 = D.15138 / 64;
  D.15140 = small_id_table.0->data[D.15139];
  D.15141 = id & 63;
  D.15142 = D.15140 >> D.15141;
  D.15143 = D.15142 & 1;
  D.15144 = D.15143 != 0;
  D.15145 = (long int) D.15144;
  D.15146 = __builtin_expect (D.15145, 0);
  if (D.15146 != 0) goto <D.15147>; else goto <D.15148>;
  <D.15147>:
  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.15148>:
  small_id_table.0 = small_id_table;
  D.15138 = (long unsigned int) id;
  D.15149 = D.15138 / 64;
  small_id_table.0 = small_id_table;
  D.15150 = small_id_table.0->data[D.15149];
  D.15141 = id & 63;
  D.15151 = 1 << D.15141;
  D.15152 = D.15150 | D.15151;
  small_id_table.0->data[D.15149] = D.15152;
  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.15154 = (long unsigned int) small_id_next.2;
  small_id_table.0 = small_id_table;
  D.15129 = small_id_table.0->size;
  if (D.15154 >= D.15129) goto <D.15155>; else goto <D.15156>;
  <D.15155>:
  small_id_next = 0;
  <D.15156>:
  D.15157 = id > 16383;
  D.15158 = (long int) D.15157;
  D.15159 = __builtin_expect (D.15158, 0);
  if (D.15159 != 0) goto <D.15160>; else goto <D.15161>;
  <D.15160>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 83, "id < HAZARD_TABLE_MAX_SIZE");
  <D.15161>:
  hazard_table_size.4 = hazard_table_size;
  if (id >= hazard_table_size.4) goto <D.15163>; else goto <D.15164>;
  <D.15163>:
  {
    void * page_addr;
    int pagesize;
    int num_pages;

    pagesize = mono_pagesize ();
    hazard_table_size.5 = hazard_table_size;
    D.15166 = (long unsigned int) hazard_table_size.5;
    D.15167 = D.15166 * 24;
    D.15168 = (long unsigned int) pagesize;
    D.15169 = D.15167 + D.15168;
    D.15170 = D.15169 + 18446744073709551615;
    D.15168 = (long unsigned int) pagesize;
    D.15171 = D.15170 / D.15168;
    num_pages = (int) D.15171;
    hazard_table.6 = hazard_table;
    if (hazard_table.6 == 0B) goto <D.15173>; else goto <D.15174>;
    <D.15173>:
    hazard_table.7 = mono_valloc (0B, 393216, 0);
    hazard_table = hazard_table.7;
    <D.15174>:
    hazard_table.8 = hazard_table;
    D.15177 = hazard_table.8 == 0B;
    D.15178 = (long int) D.15177;
    D.15179 = __builtin_expect (D.15178, 0);
    if (D.15179 != 0) goto <D.15180>; else goto <D.15181>;
    <D.15180>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 99, "hazard_table != NULL");
    <D.15181>:
    hazard_table.9 = hazard_table;
    D.15183 = num_pages * pagesize;
    D.15184 = (sizetype) D.15183;
    page_addr = hazard_table.9 + D.15184;
    D.15185 = (long unsigned int) pagesize;
    mono_mprotect (page_addr, D.15185, 3);
    num_pages = num_pages + 1;
    D.15183 = num_pages * pagesize;
    D.15186 = (long unsigned int) D.15183;
    D.15187 = D.15186 / 24;
    hazard_table_size.10 = (int) D.15187;
    hazard_table_size = hazard_table_size.10;
    hazard_table_size.11 = hazard_table_size;
    D.15190 = id >= hazard_table_size.11;
    D.15191 = (long int) D.15190;
    D.15192 = __builtin_expect (D.15191, 0);
    if (D.15192 != 0) goto <D.15193>; else goto <D.15194>;
    <D.15193>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 108, "id < hazard_table_size");
    <D.15194>:
    i = 0;
    goto <D.15043>;
    <D.15042>:
    hazard_table.12 = hazard_table;
    D.15138 = (long unsigned int) id;
    D.15196 = D.15138 * 24;
    D.15197 = hazard_table.12 + D.15196;
    D.15197->hazard_pointers[i] = 0B;
    i = i + 1;
    <D.15043>:
    if (i <= 2) goto <D.15042>; else goto <D.15044>;
    <D.15044>:
  }
  <D.15164>:
  highest_small_id.13 = highest_small_id;
  if (id > highest_small_id.13) goto <D.15199>; else goto <D.15200>;
  <D.15199>:
  highest_small_id = id;
  mono_memory_write_barrier ();
  <D.15200>:
  {
    int ret;

    ret = pthread_mutex_unlock (&small_id_mutex.mutex);
    if (ret != 0) goto <D.15201>; else goto <D.15202>;
    <D.15201>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.15202>:
    D.15203 = ret != 0;
    D.15204 = (long int) D.15203;
    D.15205 = __builtin_expect (D.15204, 0);
    if (D.15205 != 0) goto <D.15206>; else goto <D.15207>;
    <D.15206>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 118, "ret == 0");
    <D.15207>:
  }
  D.15208 = id;
  return D.15208;
}


mono_memory_write_barrier ()
{
  mono_memory_barrier ();
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


mono_thread_small_id_free (int id)
{
  _Bool D.15212;
  long int D.15213;
  long int D.15214;
  int iftmp.14;
  long unsigned int D.15222;
  struct MonoBitSet * small_id_table.15;
  long unsigned int D.15224;
  _Bool D.15225;
  long int D.15226;
  long int D.15227;
  long unsigned int D.15230;
  long unsigned int D.15231;
  long unsigned int D.15232;
  int D.15233;
  long unsigned int D.15234;
  long unsigned int D.15235;
  _Bool D.15236;
  long int D.15237;
  long int D.15238;
  long unsigned int D.15241;
  long unsigned int D.15242;
  long unsigned int D.15243;
  long unsigned int D.15244;
  long unsigned int D.15245;
  _Bool D.15248;
  long int D.15249;
  long int D.15250;

  {
    int ret;

    ret = pthread_mutex_lock (&small_id_mutex.mutex);
    if (ret != 0) goto <D.15210>; else goto <D.15211>;
    <D.15210>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.15211>:
    D.15212 = ret != 0;
    D.15213 = (long int) D.15212;
    D.15214 = __builtin_expect (D.15213, 0);
    if (D.15214 != 0) goto <D.15215>; else goto <D.15216>;
    <D.15215>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 127, "ret == 0");
    <D.15216>:
  }
  if (id < 0) goto <D.15218>; else goto <D.15221>;
  <D.15221>:
  D.15222 = (long unsigned int) id;
  small_id_table.15 = small_id_table;
  D.15224 = small_id_table.15->size;
  if (D.15222 >= D.15224) goto <D.15218>; else goto <D.15219>;
  <D.15218>:
  iftmp.14 = 1;
  goto <D.15220>;
  <D.15219>:
  iftmp.14 = 0;
  <D.15220>:
  D.15225 = iftmp.14 != 0;
  D.15226 = (long int) D.15225;
  D.15227 = __builtin_expect (D.15226, 0);
  if (D.15227 != 0) goto <D.15228>; else goto <D.15229>;
  <D.15228>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 129, "id >= 0 && id < small_id_table->size");
  <D.15229>:
  small_id_table.15 = small_id_table;
  D.15230 = (long unsigned int) id;
  D.15231 = D.15230 / 64;
  D.15232 = small_id_table.15->data[D.15231];
  D.15233 = id & 63;
  D.15234 = D.15232 >> D.15233;
  D.15235 = D.15234 & 1;
  D.15236 = D.15235 == 0;
  D.15237 = (long int) D.15236;
  D.15238 = __builtin_expect (D.15237, 0);
  if (D.15238 != 0) goto <D.15239>; else goto <D.15240>;
  <D.15239>:
  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.15240>:
  small_id_table.15 = small_id_table;
  D.15230 = (long unsigned int) id;
  D.15241 = D.15230 / 64;
  small_id_table.15 = small_id_table;
  D.15242 = small_id_table.15->data[D.15241];
  D.15233 = id & 63;
  D.15243 = 1 << D.15233;
  D.15244 = ~D.15243;
  D.15245 = D.15242 & D.15244;
  small_id_table.15->data[D.15241] = D.15245;
  {
    int ret;

    ret = pthread_mutex_unlock (&small_id_mutex.mutex);
    if (ret != 0) goto <D.15246>; else goto <D.15247>;
    <D.15246>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.15247>:
    D.15248 = ret != 0;
    D.15249 = (long int) D.15248;
    D.15250 = __builtin_expect (D.15249, 0);
    if (D.15250 != 0) goto <D.15251>; else goto <D.15252>;
    <D.15251>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 133, "ret == 0");
    <D.15252>:
  }
}


mono_hazard_pointer_get ()
{
  long unsigned int D.15255;
  void * D.15256;
  struct MonoThreadHazardPointers * D.15257;
  struct MonoThreadHazardPointers * hazard_table.16;
  long unsigned int D.15259;
  long unsigned int D.15260;
  int small_id;

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

    D.15255 = mono_native_thread_id_get ();
    D.15256 = (void *) D.15255;
    monoeg_g_log (0B, 16, "Thread %p may have been prematurely finalized", D.15256);
    D.15257 = &emerg_hazard_table;
    return D.15257;
  }
  <D.15254>:
  hazard_table.16 = hazard_table;
  D.15259 = (long unsigned int) small_id;
  D.15260 = D.15259 * 24;
  D.15257 = hazard_table.16 + D.15260;
  return D.15257;
}


get_hazardous_pointer (void * volatile * pp, struct MonoThreadHazardPointers * hp, int hazard_index)
{
  void * D.15264;
  unsigned int hazard_index.17;
  _Bool D.15266;
  long int D.15267;
  long int D.15268;
  void * D.15271;
  void * p;

  <D.15076>:
  p = *pp;
  if (hp == 0B) goto <D.15262>; else goto <D.15263>;
  <D.15262>:
  D.15264 = p;
  return D.15264;
  <D.15263>:
  hazard_index.17 = (unsigned int) hazard_index;
  D.15266 = hazard_index.17 > 2;
  D.15267 = (long int) D.15266;
  D.15268 = __builtin_expect (D.15267, 0);
  if (D.15268 != 0) goto <D.15269>; else goto <D.15270>;
  <D.15269>:
  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.15270>:
  hp->hazard_pointers[hazard_index] = p;
  mono_memory_write_barrier ();
  D.15271 = *pp;
  if (D.15271 != p) goto <D.15272>; else goto <D.15273>;
  <D.15272>:
  hazard_index.17 = (unsigned int) hazard_index;
  D.15266 = hazard_index.17 > 2;
  D.15267 = (long int) D.15266;
  D.15268 = __builtin_expect (D.15267, 0);
  if (D.15268 != 0) goto <D.15274>; else goto <D.15275>;
  <D.15274>:
  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.15275>:
  hp->hazard_pointers[hazard_index] = 0B;
  // predicted unlikely by continue predictor.
  goto <D.15074>;
  <D.15273>:
  goto <D.15075>;
  <D.15074>:
  goto <D.15076>;
  <D.15075>:
  D.15264 = p;
  return D.15264;
}


mono_thread_hazardous_free_or_queue (void * p, void (*MonoHazardousFreeFunc) (void *) free_func, gboolean free_func_might_lock, gboolean lock_free_context)
{
  _Bool D.15279;
  long int D.15280;
  long int D.15281;
  _Bool D.15286;
  long int D.15287;
  long int D.15288;
  int D.15291;
  long unsigned int D.15294;
  long unsigned int D.15295;
  int i;

  if (lock_free_context != 0) goto <D.15277>; else goto <D.15278>;
  <D.15277>:
  D.15279 = free_func_might_lock != 0;
  D.15280 = (long int) D.15279;
  D.15281 = __builtin_expect (D.15280, 0);
  if (D.15281 != 0) goto <D.15282>; else goto <D.15283>;
  <D.15282>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 225, "!free_func_might_lock");
  <D.15283>:
  <D.15278>:
  if (free_func_might_lock != 0) goto <D.15284>; else goto <D.15285>;
  <D.15284>:
  D.15286 = lock_free_context != 0;
  D.15287 = (long int) D.15286;
  D.15288 = __builtin_expect (D.15287, 0);
  if (D.15288 != 0) goto <D.15289>; else goto <D.15290>;
  <D.15289>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 227, "!lock_free_context");
  <D.15290>:
  <D.15285>:
  i = 0;
  goto <D.15090>;
  <D.15089>:
  try_free_delayed_free_item (lock_free_context);
  i = i + 1;
  <D.15090>:
  if (i <= 2) goto <D.15089>; else goto <D.15091>;
  <D.15091>:
  D.15291 = is_pointer_hazardous (p);
  if (D.15291 != 0) goto <D.15292>; else goto <D.15293>;
  <D.15292>:
  {
    struct DelayedFreeItem item;

    try
      {
        item.p = p;
        item.free_func = free_func;
        item.might_lock = free_func_might_lock;
        D.15294 = mono_stats.hazardous_pointer_count;
        D.15295 = D.15294 + 1;
        mono_stats.hazardous_pointer_count = D.15295;
        mono_lock_free_array_queue_push (&delayed_free_queue, &item);
      }
    finally
      {
        item = {CLOBBER};
      }
  }
  goto <D.15296>;
  <D.15293>:
  free_func (p);
  <D.15296>:
}


try_free_delayed_free_item (gboolean lock_free_context)
{
  gboolean D.15299;
  int D.15304;
  void * D.15305;
  int D.15306;
  void (*<T10e8>) (void *) D.15307;
  struct DelayedFreeItem item;
  gboolean popped;

  try
    {
      popped = mono_lock_free_array_queue_pop (&delayed_free_queue, &item);
      if (popped == 0) goto <D.15297>; else goto <D.15298>;
      <D.15297>:
      D.15299 = 0;
      return D.15299;
      <D.15298>:
      if (lock_free_context != 0) goto <D.15303>; else goto <D.15300>;
      <D.15303>:
      D.15304 = item.might_lock;
      if (D.15304 != 0) goto <D.15301>; else goto <D.15300>;
      <D.15300>:
      D.15305 = item.p;
      D.15306 = is_pointer_hazardous (D.15305);
      if (D.15306 != 0) goto <D.15301>; else goto <D.15302>;
      <D.15301>:
      mono_lock_free_array_queue_push (&delayed_free_queue, &item);
      D.15299 = 0;
      return D.15299;
      <D.15302>:
      D.15307 = item.free_func;
      D.15305 = item.p;
      D.15307 (D.15305);
      D.15299 = 1;
      return D.15299;
    }
  finally
    {
      item = {CLOBBER};
    }
}


is_pointer_hazardous (void * p)
{
  int hazard_table_size.18;
  _Bool D.15311;
  long int D.15312;
  long int D.15313;
  struct MonoThreadHazardPointers * hazard_table.19;
  long unsigned int D.15317;
  long unsigned int D.15318;
  struct MonoThreadHazardPointers * D.15319;
  void * D.15320;
  gboolean D.15323;
  int i;
  int j;
  int highest;

  highest = highest_small_id;
  hazard_table_size.18 = hazard_table_size;
  D.15311 = highest >= hazard_table_size.18;
  D.15312 = (long int) D.15311;
  D.15313 = __builtin_expect (D.15312, 0);
  if (D.15313 != 0) goto <D.15314>; else goto <D.15315>;
  <D.15314>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 142, "highest < hazard_table_size");
  <D.15315>:
  i = 0;
  goto <D.15061>;
  <D.15060>:
  j = 0;
  goto <D.15058>;
  <D.15057>:
  hazard_table.19 = hazard_table;
  D.15317 = (long unsigned int) i;
  D.15318 = D.15317 * 24;
  D.15319 = hazard_table.19 + D.15318;
  D.15320 = D.15319->hazard_pointers[j];
  if (D.15320 == p) goto <D.15321>; else goto <D.15322>;
  <D.15321>:
  D.15323 = 1;
  return D.15323;
  <D.15322>:
  mono_memory_read_barrier ();
  j = j + 1;
  <D.15058>:
  if (j <= 2) goto <D.15057>; else goto <D.15059>;
  <D.15059>:
  i = i + 1;
  <D.15061>:
  if (i <= highest) goto <D.15060>; else goto <D.15062>;
  <D.15062>:
  D.15323 = 0;
  return D.15323;
}


mono_memory_read_barrier ()
{
  mono_memory_barrier ();
}


mono_thread_hazardous_try_free_all ()
{
  int D.15325;

  goto <D.15097>;
  <D.15096>:
  <D.15097>:
  D.15325 = try_free_delayed_free_item (0);
  if (D.15325 != 0) goto <D.15096>; else goto <D.15098>;
  <D.15098>:
}


mono_thread_hazardous_try_free_some ()
{
  int i;

  i = 0;
  goto <D.15104>;
  <D.15103>:
  try_free_delayed_free_item (0);
  i = i + 1;
  <D.15104>:
  if (i <= 9) goto <D.15103>; else goto <D.15105>;
  <D.15105>:
}


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


