mono_thread_small_id_alloc ()
{
  _Bool D.14187;
  long int D.14188;
  long int D.14189;
  struct MonoBitSet * small_id_table.0;
  struct MonoBitSet * small_id_table.1;
  int small_id_next.2;
  unsigned int D.14201;
  unsigned int D.14202;
  unsigned int D.14205;
  int D.14206;
  unsigned int id.3;
  unsigned int D.14208;
  unsigned int D.14209;
  int D.14210;
  unsigned int D.14211;
  unsigned int D.14212;
  _Bool D.14213;
  long int D.14214;
  long int D.14215;
  unsigned int D.14218;
  unsigned int D.14219;
  unsigned int D.14220;
  int small_id_next.4;
  unsigned int small_id_next.5;
  _Bool D.14225;
  long int D.14226;
  long int D.14227;
  int hazard_table_size.6;
  int hazard_table_size.7;
  unsigned int hazard_table_size.8;
  unsigned int D.14235;
  unsigned int pagesize.9;
  unsigned int D.14237;
  unsigned int D.14238;
  unsigned int D.14239;
  struct MonoThreadHazardPointers * hazard_table.10;
  void * hazard_table.11;
  struct MonoThreadHazardPointers * hazard_table.12;
  _Bool D.14245;
  long int D.14246;
  long int D.14247;
  struct MonoThreadHazardPointers * hazard_table.13;
  int D.14251;
  sizetype D.14252;
  unsigned int pagesize.14;
  unsigned int D.14254;
  unsigned int D.14255;
  int hazard_table_size.15;
  int hazard_table_size.16;
  _Bool D.14258;
  long int D.14259;
  long int D.14260;
  struct MonoThreadHazardPointers * hazard_table.17;
  unsigned int D.14264;
  struct MonoThreadHazardPointers * D.14265;
  int highest_small_id.18;
  _Bool D.14271;
  long int D.14272;
  long int D.14273;
  int D.14276;
  int i;
  int id;

  id = -1;
  {
    int ret;

    ret = pthread_mutex_lock (&small_id_mutex.mutex);
    if (ret != 0) goto <D.14185>; else goto <D.14186>;
    <D.14185>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.14186>:
    D.14187 = ret != 0;
    D.14188 = (long int) D.14187;
    D.14189 = __builtin_expect (D.14188, 0);
    if (D.14189 != 0) goto <D.14190>; else goto <D.14191>;
    <D.14190>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 56, "ret == 0");
    <D.14191>:
  }
  small_id_table.0 = small_id_table;
  if (small_id_table.0 == 0B) goto <D.14193>; else goto <D.14194>;
  <D.14193>:
  small_id_table.1 = mono_bitset_new (1, 0);
  small_id_table = small_id_table.1;
  <D.14194>:
  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.14197>; else goto <D.14198>;
  <D.14197>:
  small_id_table.0 = small_id_table;
  id = mono_bitset_find_first_unset (small_id_table.0, -1);
  <D.14198>:
  if (id == -1) goto <D.14199>; else goto <D.14200>;
  <D.14199>:
  {
    struct MonoBitSet * new_table;

    small_id_table.0 = small_id_table;
    D.14201 = small_id_table.0->size;
    D.14202 = D.14201 * 2;
    if (D.14202 > 65535) goto <D.14203>; else goto <D.14204>;
    <D.14203>:
    monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "hazard-pointer.c", 68);
    <D.14204>:
    small_id_table.0 = small_id_table;
    small_id_table.0 = small_id_table;
    D.14201 = small_id_table.0->size;
    D.14202 = D.14201 * 2;
    new_table = mono_bitset_clone (small_id_table.0, D.14202);
    small_id_table.0 = small_id_table;
    D.14201 = small_id_table.0->size;
    D.14205 = D.14201 + 4294967295;
    D.14206 = (int) D.14205;
    id = mono_bitset_find_first_unset (new_table, D.14206);
    small_id_table.0 = small_id_table;
    mono_bitset_free (small_id_table.0);
    small_id_table = new_table;
  }
  <D.14200>:
  small_id_table.0 = small_id_table;
  id.3 = (unsigned int) id;
  D.14208 = id.3 / 32;
  D.14209 = small_id_table.0->data[D.14208];
  D.14210 = id & 31;
  D.14211 = 1 << D.14210;
  D.14212 = D.14209 & D.14211;
  D.14213 = D.14212 != 0;
  D.14214 = (long int) D.14213;
  D.14215 = __builtin_expect (D.14214, 0);
  if (D.14215 != 0) goto <D.14216>; else goto <D.14217>;
  <D.14216>:
  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.14217>:
  small_id_table.0 = small_id_table;
  id.3 = (unsigned int) id;
  D.14218 = id.3 / 32;
  small_id_table.0 = small_id_table;
  D.14219 = small_id_table.0->data[D.14218];
  D.14210 = id & 31;
  D.14211 = 1 << D.14210;
  D.14220 = D.14219 | D.14211;
  small_id_table.0->data[D.14218] = D.14220;
  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.14201 = small_id_table.0->size;
  if (small_id_next.5 >= D.14201) goto <D.14223>; else goto <D.14224>;
  <D.14223>:
  small_id_next = 0;
  <D.14224>:
  D.14225 = id > 16383;
  D.14226 = (long int) D.14225;
  D.14227 = __builtin_expect (D.14226, 0);
  if (D.14227 != 0) goto <D.14228>; else goto <D.14229>;
  <D.14228>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 83, "id < HAZARD_TABLE_MAX_SIZE");
  <D.14229>:
  hazard_table_size.6 = hazard_table_size;
  if (id >= hazard_table_size.6) goto <D.14231>; else goto <D.14232>;
  <D.14231>:
  {
    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.14235 = hazard_table_size.8 * 12;
    pagesize.9 = (unsigned int) pagesize;
    D.14237 = D.14235 + pagesize.9;
    D.14238 = D.14237 + 4294967295;
    pagesize.9 = (unsigned int) pagesize;
    D.14239 = D.14238 / pagesize.9;
    num_pages = (int) D.14239;
    hazard_table.10 = hazard_table;
    if (hazard_table.10 == 0B) goto <D.14241>; else goto <D.14242>;
    <D.14241>:
    hazard_table.11 = mono_valloc (0B, 196608, 0);
    hazard_table = hazard_table.11;
    <D.14242>:
    hazard_table.12 = hazard_table;
    D.14245 = hazard_table.12 == 0B;
    D.14246 = (long int) D.14245;
    D.14247 = __builtin_expect (D.14246, 0);
    if (D.14247 != 0) goto <D.14248>; else goto <D.14249>;
    <D.14248>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 99, "hazard_table != NULL");
    <D.14249>:
    hazard_table.13 = hazard_table;
    D.14251 = num_pages * pagesize;
    D.14252 = (sizetype) D.14251;
    page_addr = hazard_table.13 + D.14252;
    pagesize.14 = (unsigned int) pagesize;
    mono_mprotect (page_addr, pagesize.14, 3);
    num_pages = num_pages + 1;
    D.14251 = num_pages * pagesize;
    D.14254 = (unsigned int) D.14251;
    D.14255 = D.14254 / 12;
    hazard_table_size.15 = (int) D.14255;
    hazard_table_size = hazard_table_size.15;
    hazard_table_size.16 = hazard_table_size;
    D.14258 = id >= hazard_table_size.16;
    D.14259 = (long int) D.14258;
    D.14260 = __builtin_expect (D.14259, 0);
    if (D.14260 != 0) goto <D.14261>; else goto <D.14262>;
    <D.14261>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 108, "id < hazard_table_size");
    <D.14262>:
    i = 0;
    goto <D.14115>;
    <D.14114>:
    hazard_table.17 = hazard_table;
    id.3 = (unsigned int) id;
    D.14264 = id.3 * 12;
    D.14265 = hazard_table.17 + D.14264;
    D.14265->hazard_pointers[i] = 0B;
    i = i + 1;
    <D.14115>:
    if (i <= 2) goto <D.14114>; else goto <D.14116>;
    <D.14116>:
  }
  <D.14232>:
  highest_small_id.18 = highest_small_id;
  if (id > highest_small_id.18) goto <D.14267>; else goto <D.14268>;
  <D.14267>:
  highest_small_id = id;
  mono_memory_write_barrier ();
  <D.14268>:
  {
    int ret;

    ret = pthread_mutex_unlock (&small_id_mutex.mutex);
    if (ret != 0) goto <D.14269>; else goto <D.14270>;
    <D.14269>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.14270>:
    D.14271 = ret != 0;
    D.14272 = (long int) D.14271;
    D.14273 = __builtin_expect (D.14272, 0);
    if (D.14273 != 0) goto <D.14274>; else goto <D.14275>;
    <D.14274>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 118, "ret == 0");
    <D.14275>:
  }
  D.14276 = id;
  return D.14276;
}


mono_memory_write_barrier ()
{
  mono_memory_barrier ();
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


mono_thread_small_id_free (int id)
{
  _Bool D.14280;
  long int D.14281;
  long int D.14282;
  int iftmp.19;
  unsigned int id.20;
  struct MonoBitSet * small_id_table.21;
  unsigned int D.14292;
  _Bool D.14293;
  long int D.14294;
  long int D.14295;
  unsigned int id.22;
  unsigned int D.14299;
  unsigned int D.14300;
  int D.14301;
  unsigned int D.14302;
  unsigned int D.14303;
  _Bool D.14304;
  long int D.14305;
  long int D.14306;
  unsigned int D.14309;
  unsigned int D.14310;
  unsigned int D.14311;
  unsigned int D.14312;
  _Bool D.14315;
  long int D.14316;
  long int D.14317;

  {
    int ret;

    ret = pthread_mutex_lock (&small_id_mutex.mutex);
    if (ret != 0) goto <D.14278>; else goto <D.14279>;
    <D.14278>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.14279>:
    D.14280 = ret != 0;
    D.14281 = (long int) D.14280;
    D.14282 = __builtin_expect (D.14281, 0);
    if (D.14282 != 0) goto <D.14283>; else goto <D.14284>;
    <D.14283>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 127, "ret == 0");
    <D.14284>:
  }
  if (id < 0) goto <D.14286>; else goto <D.14289>;
  <D.14289>:
  id.20 = (unsigned int) id;
  small_id_table.21 = small_id_table;
  D.14292 = small_id_table.21->size;
  if (id.20 >= D.14292) goto <D.14286>; else goto <D.14287>;
  <D.14286>:
  iftmp.19 = 1;
  goto <D.14288>;
  <D.14287>:
  iftmp.19 = 0;
  <D.14288>:
  D.14293 = iftmp.19 != 0;
  D.14294 = (long int) D.14293;
  D.14295 = __builtin_expect (D.14294, 0);
  if (D.14295 != 0) goto <D.14296>; else goto <D.14297>;
  <D.14296>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 129, "id >= 0 && id < small_id_table->size");
  <D.14297>:
  small_id_table.21 = small_id_table;
  id.22 = (unsigned int) id;
  D.14299 = id.22 / 32;
  D.14300 = small_id_table.21->data[D.14299];
  D.14301 = id & 31;
  D.14302 = 1 << D.14301;
  D.14303 = D.14300 & D.14302;
  D.14304 = D.14303 == 0;
  D.14305 = (long int) D.14304;
  D.14306 = __builtin_expect (D.14305, 0);
  if (D.14306 != 0) goto <D.14307>; else goto <D.14308>;
  <D.14307>:
  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.14308>:
  small_id_table.21 = small_id_table;
  id.22 = (unsigned int) id;
  D.14309 = id.22 / 32;
  small_id_table.21 = small_id_table;
  D.14310 = small_id_table.21->data[D.14309];
  D.14301 = id & 31;
  D.14302 = 1 << D.14301;
  D.14311 = ~D.14302;
  D.14312 = D.14310 & D.14311;
  small_id_table.21->data[D.14309] = D.14312;
  {
    int ret;

    ret = pthread_mutex_unlock (&small_id_mutex.mutex);
    if (ret != 0) goto <D.14313>; else goto <D.14314>;
    <D.14313>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.14314>:
    D.14315 = ret != 0;
    D.14316 = (long int) D.14315;
    D.14317 = __builtin_expect (D.14316, 0);
    if (D.14317 != 0) goto <D.14318>; else goto <D.14319>;
    <D.14318>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 133, "ret == 0");
    <D.14319>:
  }
}


mono_hazard_pointer_get ()
{
  long unsigned int D.14322;
  void * D.14323;
  struct MonoThreadHazardPointers * D.14324;
  struct MonoThreadHazardPointers * hazard_table.23;
  unsigned int small_id.24;
  unsigned int D.14327;
  int small_id;

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

    D.14322 = mono_native_thread_id_get ();
    D.14323 = (void *) D.14322;
    monoeg_g_log (0B, 16, "Thread %p may have been prematurely finalized", D.14323);
    D.14324 = &emerg_hazard_table;
    return D.14324;
  }
  <D.14321>:
  hazard_table.23 = hazard_table;
  small_id.24 = (unsigned int) small_id;
  D.14327 = small_id.24 * 12;
  D.14324 = hazard_table.23 + D.14327;
  return D.14324;
}


get_hazardous_pointer (void * volatile * pp, struct MonoThreadHazardPointers * hp, int hazard_index)
{
  void * D.14331;
  unsigned int hazard_index.25;
  _Bool D.14333;
  long int D.14334;
  long int D.14335;
  void * D.14338;
  void * p;

  <D.14148>:
  p = *pp;
  if (hp == 0B) goto <D.14329>; else goto <D.14330>;
  <D.14329>:
  D.14331 = p;
  return D.14331;
  <D.14330>:
  hazard_index.25 = (unsigned int) hazard_index;
  D.14333 = hazard_index.25 > 2;
  D.14334 = (long int) D.14333;
  D.14335 = __builtin_expect (D.14334, 0);
  if (D.14335 != 0) goto <D.14336>; else goto <D.14337>;
  <D.14336>:
  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.14337>:
  hp->hazard_pointers[hazard_index] = p;
  mono_memory_write_barrier ();
  D.14338 = *pp;
  if (D.14338 != p) goto <D.14339>; else goto <D.14340>;
  <D.14339>:
  hazard_index.25 = (unsigned int) hazard_index;
  D.14333 = hazard_index.25 > 2;
  D.14334 = (long int) D.14333;
  D.14335 = __builtin_expect (D.14334, 0);
  if (D.14335 != 0) goto <D.14341>; else goto <D.14342>;
  <D.14341>:
  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.14342>:
  hp->hazard_pointers[hazard_index] = 0B;
  // predicted unlikely by continue predictor.
  goto <D.14146>;
  <D.14340>:
  goto <D.14147>;
  <D.14146>:
  goto <D.14148>;
  <D.14147>:
  D.14331 = p;
  return D.14331;
}


mono_thread_hazardous_free_or_queue (void * p, void (*MonoHazardousFreeFunc) (void *) free_func, gboolean free_func_might_lock, gboolean lock_free_context)
{
  _Bool D.14346;
  long int D.14347;
  long int D.14348;
  _Bool D.14353;
  long int D.14354;
  long int D.14355;
  int D.14358;
  long unsigned int D.14361;
  long unsigned int D.14362;
  int i;

  if (lock_free_context != 0) goto <D.14344>; else goto <D.14345>;
  <D.14344>:
  D.14346 = free_func_might_lock != 0;
  D.14347 = (long int) D.14346;
  D.14348 = __builtin_expect (D.14347, 0);
  if (D.14348 != 0) goto <D.14349>; else goto <D.14350>;
  <D.14349>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 225, "!free_func_might_lock");
  <D.14350>:
  <D.14345>:
  if (free_func_might_lock != 0) goto <D.14351>; else goto <D.14352>;
  <D.14351>:
  D.14353 = lock_free_context != 0;
  D.14354 = (long int) D.14353;
  D.14355 = __builtin_expect (D.14354, 0);
  if (D.14355 != 0) goto <D.14356>; else goto <D.14357>;
  <D.14356>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 227, "!lock_free_context");
  <D.14357>:
  <D.14352>:
  i = 0;
  goto <D.14162>;
  <D.14161>:
  try_free_delayed_free_item (lock_free_context);
  i = i + 1;
  <D.14162>:
  if (i <= 2) goto <D.14161>; else goto <D.14163>;
  <D.14163>:
  D.14358 = is_pointer_hazardous (p);
  if (D.14358 != 0) goto <D.14359>; else goto <D.14360>;
  <D.14359>:
  {
    struct DelayedFreeItem item;

    try
      {
        item.p = p;
        item.free_func = free_func;
        item.might_lock = free_func_might_lock;
        D.14361 = mono_stats.hazardous_pointer_count;
        D.14362 = D.14361 + 1;
        mono_stats.hazardous_pointer_count = D.14362;
        mono_lock_free_array_queue_push (&delayed_free_queue, &item);
      }
    finally
      {
        item = {CLOBBER};
      }
  }
  goto <D.14363>;
  <D.14360>:
  free_func (p);
  <D.14363>:
}


try_free_delayed_free_item (gboolean lock_free_context)
{
  gboolean D.14366;
  int D.14371;
  void * D.14372;
  int D.14373;
  void (*<T100e>) (void *) D.14374;
  struct DelayedFreeItem item;
  gboolean popped;

  try
    {
      popped = mono_lock_free_array_queue_pop (&delayed_free_queue, &item);
      if (popped == 0) goto <D.14364>; else goto <D.14365>;
      <D.14364>:
      D.14366 = 0;
      return D.14366;
      <D.14365>:
      if (lock_free_context != 0) goto <D.14370>; else goto <D.14367>;
      <D.14370>:
      D.14371 = item.might_lock;
      if (D.14371 != 0) goto <D.14368>; else goto <D.14367>;
      <D.14367>:
      D.14372 = item.p;
      D.14373 = is_pointer_hazardous (D.14372);
      if (D.14373 != 0) goto <D.14368>; else goto <D.14369>;
      <D.14368>:
      mono_lock_free_array_queue_push (&delayed_free_queue, &item);
      D.14366 = 0;
      return D.14366;
      <D.14369>:
      D.14374 = item.free_func;
      D.14372 = item.p;
      D.14374 (D.14372);
      D.14366 = 1;
      return D.14366;
    }
  finally
    {
      item = {CLOBBER};
    }
}


is_pointer_hazardous (void * p)
{
  int hazard_table_size.26;
  _Bool D.14378;
  long int D.14379;
  long int D.14380;
  struct MonoThreadHazardPointers * hazard_table.27;
  unsigned int i.28;
  unsigned int D.14385;
  struct MonoThreadHazardPointers * D.14386;
  void * D.14387;
  gboolean D.14390;
  int i;
  int j;
  int highest;

  highest = highest_small_id;
  hazard_table_size.26 = hazard_table_size;
  D.14378 = highest >= hazard_table_size.26;
  D.14379 = (long int) D.14378;
  D.14380 = __builtin_expect (D.14379, 0);
  if (D.14380 != 0) goto <D.14381>; else goto <D.14382>;
  <D.14381>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 142, "highest < hazard_table_size");
  <D.14382>:
  i = 0;
  goto <D.14133>;
  <D.14132>:
  j = 0;
  goto <D.14130>;
  <D.14129>:
  hazard_table.27 = hazard_table;
  i.28 = (unsigned int) i;
  D.14385 = i.28 * 12;
  D.14386 = hazard_table.27 + D.14385;
  D.14387 = D.14386->hazard_pointers[j];
  if (D.14387 == p) goto <D.14388>; else goto <D.14389>;
  <D.14388>:
  D.14390 = 1;
  return D.14390;
  <D.14389>:
  mono_memory_read_barrier ();
  j = j + 1;
  <D.14130>:
  if (j <= 2) goto <D.14129>; else goto <D.14131>;
  <D.14131>:
  i = i + 1;
  <D.14133>:
  if (i <= highest) goto <D.14132>; else goto <D.14134>;
  <D.14134>:
  D.14390 = 0;
  return D.14390;
}


mono_memory_read_barrier ()
{
  mono_memory_barrier ();
}


mono_thread_hazardous_try_free_all ()
{
  int D.14392;

  goto <D.14169>;
  <D.14168>:
  <D.14169>:
  D.14392 = try_free_delayed_free_item (0);
  if (D.14392 != 0) goto <D.14168>; else goto <D.14170>;
  <D.14170>:
}


mono_thread_hazardous_try_free_some ()
{
  int i;

  i = 0;
  goto <D.14176>;
  <D.14175>:
  try_free_delayed_free_item (0);
  i = i + 1;
  <D.14176>:
  if (i <= 9) goto <D.14175>; else goto <D.14177>;
  <D.14177>:
}


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


