mono_thread_small_id_alloc ()
{
  _Bool D.14221;
  long int D.14222;
  long int D.14223;
  struct MonoBitSet * small_id_table.0;
  struct MonoBitSet * small_id_table.1;
  int small_id_next.2;
  unsigned int D.14235;
  unsigned int D.14236;
  unsigned int D.14239;
  int D.14240;
  unsigned int id.3;
  unsigned int D.14242;
  unsigned int D.14243;
  int D.14244;
  unsigned int D.14245;
  unsigned int D.14246;
  _Bool D.14247;
  long int D.14248;
  long int D.14249;
  unsigned int D.14252;
  unsigned int D.14253;
  unsigned int D.14254;
  int small_id_next.4;
  unsigned int small_id_next.5;
  _Bool D.14259;
  long int D.14260;
  long int D.14261;
  int hazard_table_size.6;
  int hazard_table_size.7;
  unsigned int hazard_table_size.8;
  unsigned int D.14269;
  unsigned int pagesize.9;
  unsigned int D.14271;
  unsigned int D.14272;
  unsigned int D.14273;
  struct MonoThreadHazardPointers * hazard_table.10;
  void * hazard_table.11;
  struct MonoThreadHazardPointers * hazard_table.12;
  _Bool D.14279;
  long int D.14280;
  long int D.14281;
  struct MonoThreadHazardPointers * hazard_table.13;
  int D.14285;
  sizetype D.14286;
  unsigned int pagesize.14;
  unsigned int D.14288;
  unsigned int D.14289;
  int hazard_table_size.15;
  int hazard_table_size.16;
  _Bool D.14292;
  long int D.14293;
  long int D.14294;
  struct MonoThreadHazardPointers * hazard_table.17;
  unsigned int D.14298;
  struct MonoThreadHazardPointers * D.14299;
  int highest_small_id.18;
  _Bool D.14305;
  long int D.14306;
  long int D.14307;
  int D.14310;
  int i;
  int id;

  id = -1;
  {
    int ret;

    ret = pthread_mutex_lock (&small_id_mutex.mutex);
    if (ret != 0) goto <D.14219>; else goto <D.14220>;
    <D.14219>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.14220>:
    D.14221 = ret != 0;
    D.14222 = (long int) D.14221;
    D.14223 = __builtin_expect (D.14222, 0);
    if (D.14223 != 0) goto <D.14224>; else goto <D.14225>;
    <D.14224>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 56, "ret == 0");
    <D.14225>:
  }
  small_id_table.0 = small_id_table;
  if (small_id_table.0 == 0B) goto <D.14227>; else goto <D.14228>;
  <D.14227>:
  small_id_table.1 = mono_bitset_new (1, 0);
  small_id_table = small_id_table.1;
  <D.14228>:
  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.14231>; else goto <D.14232>;
  <D.14231>:
  small_id_table.0 = small_id_table;
  id = mono_bitset_find_first_unset (small_id_table.0, -1);
  <D.14232>:
  if (id == -1) goto <D.14233>; else goto <D.14234>;
  <D.14233>:
  {
    struct MonoBitSet * new_table;

    small_id_table.0 = small_id_table;
    D.14235 = small_id_table.0->size;
    D.14236 = D.14235 * 2;
    if (D.14236 > 65535) goto <D.14237>; else goto <D.14238>;
    <D.14237>:
    monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "hazard-pointer.c", 68);
    <D.14238>:
    small_id_table.0 = small_id_table;
    D.14235 = small_id_table.0->size;
    D.14236 = D.14235 * 2;
    small_id_table.0 = small_id_table;
    new_table = mono_bitset_clone (small_id_table.0, D.14236);
    small_id_table.0 = small_id_table;
    D.14235 = small_id_table.0->size;
    D.14239 = D.14235 + 4294967295;
    D.14240 = (int) D.14239;
    id = mono_bitset_find_first_unset (new_table, D.14240);
    small_id_table.0 = small_id_table;
    mono_bitset_free (small_id_table.0);
    small_id_table = new_table;
  }
  <D.14234>:
  small_id_table.0 = small_id_table;
  id.3 = (unsigned int) id;
  D.14242 = id.3 / 32;
  D.14243 = small_id_table.0->data[D.14242];
  D.14244 = id & 31;
  D.14245 = 1 << D.14244;
  D.14246 = D.14243 & D.14245;
  D.14247 = D.14246 != 0;
  D.14248 = (long int) D.14247;
  D.14249 = __builtin_expect (D.14248, 0);
  if (D.14249 != 0) goto <D.14250>; else goto <D.14251>;
  <D.14250>:
  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.14251>:
  small_id_table.0 = small_id_table;
  id.3 = (unsigned int) id;
  D.14252 = id.3 / 32;
  small_id_table.0 = small_id_table;
  D.14253 = small_id_table.0->data[D.14252];
  D.14244 = id & 31;
  D.14245 = 1 << D.14244;
  D.14254 = D.14253 | D.14245;
  small_id_table.0->data[D.14252] = D.14254;
  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.14235 = small_id_table.0->size;
  if (small_id_next.5 >= D.14235) goto <D.14257>; else goto <D.14258>;
  <D.14257>:
  small_id_next = 0;
  <D.14258>:
  D.14259 = id > 16383;
  D.14260 = (long int) D.14259;
  D.14261 = __builtin_expect (D.14260, 0);
  if (D.14261 != 0) goto <D.14262>; else goto <D.14263>;
  <D.14262>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 83, "id < HAZARD_TABLE_MAX_SIZE");
  <D.14263>:
  hazard_table_size.6 = hazard_table_size;
  if (id >= hazard_table_size.6) goto <D.14265>; else goto <D.14266>;
  <D.14265>:
  {
    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.14269 = hazard_table_size.8 * 12;
    pagesize.9 = (unsigned int) pagesize;
    D.14271 = D.14269 + pagesize.9;
    D.14272 = D.14271 + 4294967295;
    pagesize.9 = (unsigned int) pagesize;
    D.14273 = D.14272 / pagesize.9;
    num_pages = (int) D.14273;
    hazard_table.10 = hazard_table;
    if (hazard_table.10 == 0B) goto <D.14275>; else goto <D.14276>;
    <D.14275>:
    hazard_table.11 = mono_valloc (0B, 196608, 0);
    hazard_table = hazard_table.11;
    <D.14276>:
    hazard_table.12 = hazard_table;
    D.14279 = hazard_table.12 == 0B;
    D.14280 = (long int) D.14279;
    D.14281 = __builtin_expect (D.14280, 0);
    if (D.14281 != 0) goto <D.14282>; else goto <D.14283>;
    <D.14282>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 99, "hazard_table != NULL");
    <D.14283>:
    hazard_table.13 = hazard_table;
    D.14285 = num_pages * pagesize;
    D.14286 = (sizetype) D.14285;
    page_addr = hazard_table.13 + D.14286;
    pagesize.14 = (unsigned int) pagesize;
    mono_mprotect (page_addr, pagesize.14, 3);
    num_pages = num_pages + 1;
    D.14285 = num_pages * pagesize;
    D.14288 = (unsigned int) D.14285;
    D.14289 = D.14288 / 12;
    hazard_table_size.15 = (int) D.14289;
    hazard_table_size = hazard_table_size.15;
    hazard_table_size.16 = hazard_table_size;
    D.14292 = id >= hazard_table_size.16;
    D.14293 = (long int) D.14292;
    D.14294 = __builtin_expect (D.14293, 0);
    if (D.14294 != 0) goto <D.14295>; else goto <D.14296>;
    <D.14295>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 108, "id < hazard_table_size");
    <D.14296>:
    i = 0;
    goto <D.14149>;
    <D.14148>:
    hazard_table.17 = hazard_table;
    id.3 = (unsigned int) id;
    D.14298 = id.3 * 12;
    D.14299 = hazard_table.17 + D.14298;
    D.14299->hazard_pointers[i] = 0B;
    i = i + 1;
    <D.14149>:
    if (i <= 2) goto <D.14148>; else goto <D.14150>;
    <D.14150>:
  }
  <D.14266>:
  highest_small_id.18 = highest_small_id;
  if (id > highest_small_id.18) goto <D.14301>; else goto <D.14302>;
  <D.14301>:
  highest_small_id = id;
  mono_memory_write_barrier ();
  <D.14302>:
  {
    int ret;

    ret = pthread_mutex_unlock (&small_id_mutex.mutex);
    if (ret != 0) goto <D.14303>; else goto <D.14304>;
    <D.14303>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.14304>:
    D.14305 = ret != 0;
    D.14306 = (long int) D.14305;
    D.14307 = __builtin_expect (D.14306, 0);
    if (D.14307 != 0) goto <D.14308>; else goto <D.14309>;
    <D.14308>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 118, "ret == 0");
    <D.14309>:
  }
  D.14310 = id;
  return D.14310;
}


mono_memory_write_barrier ()
{
  mono_memory_barrier ();
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


mono_thread_small_id_free (int id)
{
  _Bool D.14314;
  long int D.14315;
  long int D.14316;
  int iftmp.19;
  unsigned int id.20;
  struct MonoBitSet * small_id_table.21;
  unsigned int D.14326;
  _Bool D.14327;
  long int D.14328;
  long int D.14329;
  unsigned int id.22;
  unsigned int D.14333;
  unsigned int D.14334;
  int D.14335;
  unsigned int D.14336;
  unsigned int D.14337;
  _Bool D.14338;
  long int D.14339;
  long int D.14340;
  unsigned int D.14343;
  unsigned int D.14344;
  unsigned int D.14345;
  unsigned int D.14346;
  _Bool D.14349;
  long int D.14350;
  long int D.14351;

  {
    int ret;

    ret = pthread_mutex_lock (&small_id_mutex.mutex);
    if (ret != 0) goto <D.14312>; else goto <D.14313>;
    <D.14312>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.14313>:
    D.14314 = ret != 0;
    D.14315 = (long int) D.14314;
    D.14316 = __builtin_expect (D.14315, 0);
    if (D.14316 != 0) goto <D.14317>; else goto <D.14318>;
    <D.14317>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 127, "ret == 0");
    <D.14318>:
  }
  if (id < 0) goto <D.14320>; else goto <D.14323>;
  <D.14323>:
  id.20 = (unsigned int) id;
  small_id_table.21 = small_id_table;
  D.14326 = small_id_table.21->size;
  if (id.20 >= D.14326) goto <D.14320>; else goto <D.14321>;
  <D.14320>:
  iftmp.19 = 1;
  goto <D.14322>;
  <D.14321>:
  iftmp.19 = 0;
  <D.14322>:
  D.14327 = iftmp.19 != 0;
  D.14328 = (long int) D.14327;
  D.14329 = __builtin_expect (D.14328, 0);
  if (D.14329 != 0) goto <D.14330>; else goto <D.14331>;
  <D.14330>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 129, "id >= 0 && id < small_id_table->size");
  <D.14331>:
  small_id_table.21 = small_id_table;
  id.22 = (unsigned int) id;
  D.14333 = id.22 / 32;
  D.14334 = small_id_table.21->data[D.14333];
  D.14335 = id & 31;
  D.14336 = 1 << D.14335;
  D.14337 = D.14334 & D.14336;
  D.14338 = D.14337 == 0;
  D.14339 = (long int) D.14338;
  D.14340 = __builtin_expect (D.14339, 0);
  if (D.14340 != 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", 130, "mono_bitset_test_fast (small_id_table, id)");
  <D.14342>:
  small_id_table.21 = small_id_table;
  id.22 = (unsigned int) id;
  D.14343 = id.22 / 32;
  small_id_table.21 = small_id_table;
  D.14344 = small_id_table.21->data[D.14343];
  D.14335 = id & 31;
  D.14336 = 1 << D.14335;
  D.14345 = ~D.14336;
  D.14346 = D.14344 & D.14345;
  small_id_table.21->data[D.14343] = D.14346;
  {
    int ret;

    ret = pthread_mutex_unlock (&small_id_mutex.mutex);
    if (ret != 0) goto <D.14347>; else goto <D.14348>;
    <D.14347>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.14348>:
    D.14349 = ret != 0;
    D.14350 = (long int) D.14349;
    D.14351 = __builtin_expect (D.14350, 0);
    if (D.14351 != 0) goto <D.14352>; else goto <D.14353>;
    <D.14352>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 133, "ret == 0");
    <D.14353>:
  }
}


mono_hazard_pointer_get ()
{
  long unsigned int D.14356;
  void * D.14357;
  struct MonoThreadHazardPointers * D.14358;
  struct MonoThreadHazardPointers * hazard_table.23;
  unsigned int small_id.24;
  unsigned int D.14361;
  int small_id;

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

    D.14356 = mono_native_thread_id_get ();
    D.14357 = (void *) D.14356;
    monoeg_g_log (0B, 16, "Thread %p may have been prematurely finalized", D.14357);
    D.14358 = &emerg_hazard_table;
    return D.14358;
  }
  <D.14355>:
  hazard_table.23 = hazard_table;
  small_id.24 = (unsigned int) small_id;
  D.14361 = small_id.24 * 12;
  D.14358 = hazard_table.23 + D.14361;
  return D.14358;
}


get_hazardous_pointer (void * volatile * pp, struct MonoThreadHazardPointers * hp, int hazard_index)
{
  void * D.14365;
  unsigned int hazard_index.25;
  _Bool D.14367;
  long int D.14368;
  long int D.14369;
  void * D.14372;
  void * p;

  <D.14182>:
  p = *pp;
  if (hp == 0B) goto <D.14363>; else goto <D.14364>;
  <D.14363>:
  D.14365 = p;
  return D.14365;
  <D.14364>:
  hazard_index.25 = (unsigned int) hazard_index;
  D.14367 = hazard_index.25 > 2;
  D.14368 = (long int) D.14367;
  D.14369 = __builtin_expect (D.14368, 0);
  if (D.14369 != 0) goto <D.14370>; else goto <D.14371>;
  <D.14370>:
  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.14371>:
  hp->hazard_pointers[hazard_index] = p;
  mono_memory_write_barrier ();
  D.14372 = *pp;
  if (D.14372 != p) goto <D.14373>; else goto <D.14374>;
  <D.14373>:
  hazard_index.25 = (unsigned int) hazard_index;
  D.14367 = hazard_index.25 > 2;
  D.14368 = (long int) D.14367;
  D.14369 = __builtin_expect (D.14368, 0);
  if (D.14369 != 0) goto <D.14375>; else goto <D.14376>;
  <D.14375>:
  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.14376>:
  hp->hazard_pointers[hazard_index] = 0B;
  // predicted unlikely by continue predictor.
  goto <D.14180>;
  <D.14374>:
  goto <D.14181>;
  <D.14180>:
  goto <D.14182>;
  <D.14181>:
  D.14365 = p;
  return D.14365;
}


mono_thread_hazardous_free_or_queue (void * p, void (*MonoHazardousFreeFunc) (void *) free_func, gboolean free_func_might_lock, gboolean lock_free_context)
{
  _Bool D.14380;
  long int D.14381;
  long int D.14382;
  _Bool D.14387;
  long int D.14388;
  long int D.14389;
  int D.14392;
  long unsigned int D.14395;
  long unsigned int D.14396;
  int i;

  if (lock_free_context != 0) goto <D.14378>; else goto <D.14379>;
  <D.14378>:
  D.14380 = free_func_might_lock != 0;
  D.14381 = (long int) D.14380;
  D.14382 = __builtin_expect (D.14381, 0);
  if (D.14382 != 0) goto <D.14383>; else goto <D.14384>;
  <D.14383>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 225, "!free_func_might_lock");
  <D.14384>:
  <D.14379>:
  if (free_func_might_lock != 0) goto <D.14385>; else goto <D.14386>;
  <D.14385>:
  D.14387 = lock_free_context != 0;
  D.14388 = (long int) D.14387;
  D.14389 = __builtin_expect (D.14388, 0);
  if (D.14389 != 0) goto <D.14390>; else goto <D.14391>;
  <D.14390>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 227, "!lock_free_context");
  <D.14391>:
  <D.14386>:
  i = 0;
  goto <D.14196>;
  <D.14195>:
  try_free_delayed_free_item (lock_free_context);
  i = i + 1;
  <D.14196>:
  if (i <= 2) goto <D.14195>; else goto <D.14197>;
  <D.14197>:
  D.14392 = is_pointer_hazardous (p);
  if (D.14392 != 0) goto <D.14393>; else goto <D.14394>;
  <D.14393>:
  {
    struct DelayedFreeItem item;

    try
      {
        item.p = p;
        item.free_func = free_func;
        item.might_lock = free_func_might_lock;
        D.14395 = mono_stats.hazardous_pointer_count;
        D.14396 = D.14395 + 1;
        mono_stats.hazardous_pointer_count = D.14396;
        mono_lock_free_array_queue_push (&delayed_free_queue, &item);
      }
    finally
      {
        item = {CLOBBER};
      }
  }
  goto <D.14397>;
  <D.14394>:
  free_func (p);
  <D.14397>:
}


try_free_delayed_free_item (gboolean lock_free_context)
{
  gboolean D.14400;
  int D.14405;
  void * D.14406;
  int D.14407;
  void (*<T1005>) (void *) D.14408;
  struct DelayedFreeItem item;
  gboolean popped;

  try
    {
      popped = mono_lock_free_array_queue_pop (&delayed_free_queue, &item);
      if (popped == 0) goto <D.14398>; else goto <D.14399>;
      <D.14398>:
      D.14400 = 0;
      return D.14400;
      <D.14399>:
      if (lock_free_context != 0) goto <D.14404>; else goto <D.14401>;
      <D.14404>:
      D.14405 = item.might_lock;
      if (D.14405 != 0) goto <D.14402>; else goto <D.14401>;
      <D.14401>:
      D.14406 = item.p;
      D.14407 = is_pointer_hazardous (D.14406);
      if (D.14407 != 0) goto <D.14402>; else goto <D.14403>;
      <D.14402>:
      mono_lock_free_array_queue_push (&delayed_free_queue, &item);
      D.14400 = 0;
      return D.14400;
      <D.14403>:
      D.14408 = item.free_func;
      D.14406 = item.p;
      D.14408 (D.14406);
      D.14400 = 1;
      return D.14400;
    }
  finally
    {
      item = {CLOBBER};
    }
}


is_pointer_hazardous (void * p)
{
  int hazard_table_size.26;
  _Bool D.14412;
  long int D.14413;
  long int D.14414;
  struct MonoThreadHazardPointers * hazard_table.27;
  unsigned int i.28;
  unsigned int D.14419;
  struct MonoThreadHazardPointers * D.14420;
  void * D.14421;
  gboolean D.14424;
  int i;
  int j;
  int highest;

  highest = highest_small_id;
  hazard_table_size.26 = hazard_table_size;
  D.14412 = highest >= hazard_table_size.26;
  D.14413 = (long int) D.14412;
  D.14414 = __builtin_expect (D.14413, 0);
  if (D.14414 != 0) goto <D.14415>; else goto <D.14416>;
  <D.14415>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "hazard-pointer.c", 142, "highest < hazard_table_size");
  <D.14416>:
  i = 0;
  goto <D.14167>;
  <D.14166>:
  j = 0;
  goto <D.14164>;
  <D.14163>:
  hazard_table.27 = hazard_table;
  i.28 = (unsigned int) i;
  D.14419 = i.28 * 12;
  D.14420 = hazard_table.27 + D.14419;
  D.14421 = D.14420->hazard_pointers[j];
  if (D.14421 == p) goto <D.14422>; else goto <D.14423>;
  <D.14422>:
  D.14424 = 1;
  return D.14424;
  <D.14423>:
  j = j + 1;
  <D.14164>:
  if (j <= 2) goto <D.14163>; else goto <D.14165>;
  <D.14165>:
  i = i + 1;
  <D.14167>:
  if (i <= highest) goto <D.14166>; else goto <D.14168>;
  <D.14168>:
  D.14424 = 0;
  return D.14424;
}


mono_thread_hazardous_try_free_all ()
{
  int D.14426;

  goto <D.14203>;
  <D.14202>:
  <D.14203>:
  D.14426 = try_free_delayed_free_item (0);
  if (D.14426 != 0) goto <D.14202>; else goto <D.14204>;
  <D.14204>:
}


mono_thread_hazardous_try_free_some ()
{
  int i;

  i = 0;
  goto <D.14210>;
  <D.14209>:
  try_free_delayed_free_item (0);
  i = i + 1;
  <D.14210>:
  if (i <= 9) goto <D.14209>; else goto <D.14211>;
  <D.14211>:
}


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


