__attribute__((visibility ("hidden")))
mono_thread_info_lookup (MonoNativeThreadId id)
{
  int D.13097;
  struct MonoThreadInfo * D.13100;
  struct MonoThreadHazardPointers * hp;

  hp = mono_hazard_pointer_get ();
  D.13097 = mono_lls_find (&thread_list, hp, id);
  if (D.13097 == 0) goto <D.13098>; else goto <D.13099>;
  <D.13098>:
  mono_hazard_pointer_clear_all (hp, -1);
  D.13100 = 0B;
  return D.13100;
  <D.13099>:
  mono_hazard_pointer_clear_all (hp, 1);
  D.13100 = hp->hazard_pointers[1];
  return D.13100;
}


mono_hazard_pointer_clear_all (struct MonoThreadHazardPointers * hp, int retain)
{
  if (retain != 0) goto <D.13102>; else goto <D.13103>;
  <D.13102>:
  if (0 != 0) goto <D.13104>; else goto <D.13105>;
  <D.13104>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 58, "(0) >= 0 && (0) < HAZARD_POINTER_COUNT");
  <D.13105>:
  hp->hazard_pointers[0] = 0B;
  <D.13103>:
  if (retain != 1) goto <D.13106>; else goto <D.13107>;
  <D.13106>:
  if (0 != 0) goto <D.13108>; else goto <D.13109>;
  <D.13108>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 60, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13109>:
  hp->hazard_pointers[1] = 0B;
  <D.13107>:
  if (retain != 2) goto <D.13110>; else goto <D.13111>;
  <D.13110>:
  if (0 != 0) goto <D.13112>; else goto <D.13113>;
  <D.13112>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 62, "(2) >= 0 && (2) < HAZARD_POINTER_COUNT");
  <D.13113>:
  hp->hazard_pointers[2] = 0B;
  <D.13111>:
}


__attribute__((visibility ("hidden")))
mono_thread_info_register_small_id ()
{
  unsigned int small_id_key.0;
  int D.13115;
  long unsigned int D.13116;
  void * D.13117;
  int D.13118;
  int small_id;

  small_id = mono_thread_small_id_alloc ();
  small_id_key.0 = small_id_key;
  D.13115 = small_id + 1;
  D.13116 = (long unsigned int) D.13115;
  D.13117 = (void *) D.13116;
  mono_native_tls_set_value (small_id_key.0, D.13117);
  D.13118 = small_id;
  return D.13118;
}


mono_native_tls_set_value (pthread_key_t key, void * value)
{
  int D.13120;
  int D.13121;
  _Bool D.13122;

  D.13121 = pthread_setspecific (key, value);
  D.13122 = D.13121 == 0;
  D.13120 = (int) D.13122;
  return D.13120;
}


__attribute__((visibility ("hidden")))
mono_thread_info_current ()
{
  unsigned int thread_info_key.1;
  struct MonoThreadInfo * D.13127;
  long unsigned int D.13128;
  _Bool D.13129;
  long int D.13130;
  long int D.13131;
  struct MonoThreadHazardPointers * D.13136;
  struct MonoThreadInfo * info;

  thread_info_key.1 = thread_info_key;
  info = pthread_getspecific (thread_info_key.1);
  if (info != 0B) goto <D.13125>; else goto <D.13126>;
  <D.13125>:
  D.13127 = info;
  return D.13127;
  <D.13126>:
  D.13128 = mono_native_thread_id_get ();
  info = mono_thread_info_lookup (D.13128);
  D.13129 = info == 0B;
  D.13130 = (long int) D.13129;
  D.13131 = __builtin_expect (D.13130, 0);
  if (D.13131 != 0) goto <D.13132>; else goto <D.13133>;
  <D.13132>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 242, "info");
  <D.13133>:
  if (0 != 0) goto <D.13134>; else goto <D.13135>;
  <D.13134>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 245, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13135>:
  D.13136 = mono_hazard_pointer_get ();
  D.13136->hazard_pointers[1] = 0B;
  D.13127 = info;
  return D.13127;
}


__attribute__((visibility ("hidden")))
mono_thread_info_get_small_id ()
{
  unsigned int small_id_key.2;
  int D.13141;
  long int val.3;
  int D.13143;
  void * val;

  small_id_key.2 = small_id_key;
  val = pthread_getspecific (small_id_key.2);
  if (val == 0B) goto <D.13139>; else goto <D.13140>;
  <D.13139>:
  D.13141 = -1;
  return D.13141;
  <D.13140>:
  val.3 = (long int) val;
  D.13143 = (int) val.3;
  D.13141 = D.13143 + -1;
  return D.13141;
}


__attribute__((visibility ("hidden")))
mono_thread_info_list_head ()
{
  struct MonoLinkedListSet * D.13145;

  D.13145 = &thread_list;
  return D.13145;
}


__attribute__((visibility ("hidden")))
mono_thread_info_attach (void * baseptr)
{
  int mono_threads_inited.4;
  struct MonoThreadInfo * D.13150;
  unsigned int thread_info_key.5;
  int thread_info_size.6;
  long unsigned int D.13155;
  void * D.13156;
  void (*<T1d73>) (struct MonoThreadInfo *) D.13160;
  struct MonoThreadInfo * info;

  mono_threads_inited.4 = mono_threads_inited;
  if (mono_threads_inited.4 == 0) goto <D.13148>; else goto <D.13149>;
  <D.13148>:
  D.13150 = 0B;
  return D.13150;
  <D.13149>:
  thread_info_key.5 = thread_info_key;
  info = pthread_getspecific (thread_info_key.5);
  if (info == 0B) goto <D.13152>; else goto <D.13153>;
  <D.13152>:
  thread_info_size.6 = thread_info_size;
  D.13155 = (long unsigned int) thread_info_size.6;
  info = monoeg_malloc0 (D.13155);
  D.13156 = register_thread (info, baseptr);
  if (D.13156 == 0B) goto <D.13157>; else goto <D.13158>;
  <D.13157>:
  D.13150 = 0B;
  return D.13150;
  <D.13158>:
  goto <D.13159>;
  <D.13153>:
  D.13160 = threads_callbacks.thread_attach;
  if (D.13160 != 0B) goto <D.13161>; else goto <D.13162>;
  <D.13161>:
  D.13160 = threads_callbacks.thread_attach;
  D.13160 (info);
  <D.13162>:
  <D.13159>:
  D.13150 = info;
  return D.13150;
}


register_thread (struct MonoThreadInfo * info, void * baseptr)
{
  long unsigned int D.13164;
  unsigned int small_id.7;
  union MonoSemType * D.13166;
  union MonoSemType * D.13167;
  union MonoSemType * D.13168;
  unsigned int thread_info_key.8;
  void * (*<T1d6f>) (struct MonoThreadInfo *, void *) D.13170;
  void * D.13173;
  void * D.13176;
  _Bool D.13177;
  long int D.13178;
  long int D.13179;
  int small_id;
  gboolean result;

  small_id = mono_thread_info_register_small_id ();
  D.13164 = mono_native_thread_id_get ();
  info->node.key = D.13164;
  small_id.7 = (unsigned int) small_id;
  info->small_id = small_id.7;
  D.13166 = &info->suspend_semaphore;
  sem_init (D.13166, 0, 1);
  D.13167 = &info->resume_semaphore;
  sem_init (D.13167, 0, 0);
  D.13168 = &info->finish_resume_semaphore;
  sem_init (D.13168, 0, 0);
  thread_info_key.8 = thread_info_key;
  mono_native_tls_set_value (thread_info_key.8, info);
  D.13170 = threads_callbacks.thread_register;
  if (D.13170 != 0B) goto <D.13171>; else goto <D.13172>;
  <D.13171>:
  D.13170 = threads_callbacks.thread_register;
  D.13173 = D.13170 (info, baseptr);
  if (D.13173 == 0B) goto <D.13174>; else goto <D.13175>;
  <D.13174>:
  monoeg_g_log (0B, 16, "thread registation failed\n");
  monoeg_g_free (info);
  D.13176 = 0B;
  return D.13176;
  <D.13175>:
  <D.13172>:
  mono_threads_platform_register (info);
  info->thread_state = 1;
  mono_thread_info_suspend_lock ();
  result = mono_thread_info_insert (info);
  D.13177 = result == 0;
  D.13178 = (long int) D.13177;
  D.13179 = __builtin_expect (D.13178, 0);
  if (D.13179 != 0) goto <D.13180>; else goto <D.13181>;
  <D.13180>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 159, "result");
  <D.13181>:
  mono_thread_info_suspend_unlock ();
  D.13176 = info;
  return D.13176;
}


mono_thread_info_insert (struct MonoThreadInfo * info)
{
  int D.13183;
  gboolean D.13186;
  struct MonoThreadHazardPointers * hp;

  hp = mono_hazard_pointer_get ();
  D.13183 = mono_lls_insert (&thread_list, hp, info);
  if (D.13183 == 0) goto <D.13184>; else goto <D.13185>;
  <D.13184>:
  mono_hazard_pointer_clear_all (hp, -1);
  D.13186 = 0;
  return D.13186;
  <D.13185>:
  mono_hazard_pointer_clear_all (hp, -1);
  D.13186 = 1;
  return D.13186;
}


__attribute__((visibility ("hidden")))
mono_thread_info_dettach ()
{
  int mono_threads_inited.9;
  unsigned int thread_info_key.10;
  struct MonoThreadInfo * info;

  mono_threads_inited.9 = mono_threads_inited;
  if (mono_threads_inited.9 == 0) goto <D.13189>; else goto <D.13190>;
  <D.13189>:
  return;
  <D.13190>:
  thread_info_key.10 = thread_info_key;
  info = pthread_getspecific (thread_info_key.10);
  if (info != 0B) goto <D.13192>; else goto <D.13193>;
  <D.13192>:
  unregister_thread (info);
  thread_info_key.10 = thread_info_key;
  mono_native_tls_set_value (thread_info_key.10, 0B);
  <D.13193>:
}


unregister_thread (void * arg)
{
  unsigned int D.13195;
  _Bool D.13196;
  long int D.13197;
  long int D.13198;
  unsigned int small_id_key.11;
  unsigned int D.13202;
  long unsigned int D.13203;
  void * D.13204;
  void (*<T1d73>) (struct MonoThreadInfo *) D.13205;
  void (*<T1d73>) (struct MonoThreadInfo *) D.13208;
  struct MonoThreadInfo * info;
  int small_id;

  info = arg;
  D.13195 = info->small_id;
  small_id = (int) D.13195;
  D.13196 = info == 0B;
  D.13197 = (long int) D.13196;
  D.13198 = __builtin_expect (D.13197, 0);
  if (D.13198 != 0) goto <D.13199>; else goto <D.13200>;
  <D.13199>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 169, "info");
  <D.13200>:
  small_id_key.11 = small_id_key;
  D.13195 = info->small_id;
  D.13202 = D.13195 + 1;
  D.13203 = (long unsigned int) D.13202;
  D.13204 = (void *) D.13203;
  mono_native_tls_set_value (small_id_key.11, D.13204);
  info->thread_state = 2;
  D.13205 = threads_callbacks.thread_detach;
  if (D.13205 != 0B) goto <D.13206>; else goto <D.13207>;
  <D.13206>:
  D.13205 = threads_callbacks.thread_detach;
  D.13205 (info);
  <D.13207>:
  mono_thread_info_suspend_lock ();
  D.13208 = threads_callbacks.thread_unregister;
  if (D.13208 != 0B) goto <D.13209>; else goto <D.13210>;
  <D.13209>:
  D.13208 = threads_callbacks.thread_unregister;
  D.13208 (info);
  <D.13210>:
  mono_threads_unregister_current_thread (info);
  info->thread_state = 3;
  mono_thread_info_suspend_unlock ();
  mono_thread_hazardous_free_or_queue (info, free_thread_info, 1, 0);
  mono_thread_small_id_free (small_id);
}


free_thread_info (void * mem)
{
  union MonoSemType * D.13211;
  union MonoSemType * D.13212;
  union MonoSemType * D.13213;
  struct MonoThreadInfo * info;

  info = mem;
  D.13211 = &info->suspend_semaphore;
  sem_destroy (D.13211);
  D.13212 = &info->resume_semaphore;
  sem_destroy (D.13212);
  D.13213 = &info->finish_resume_semaphore;
  sem_destroy (D.13213);
  mono_threads_platform_free (info);
  monoeg_g_free (info);
}


mono_threads_unregister_current_thread (struct MonoThreadInfo * info)
{
  long unsigned int D.13214;
  long unsigned int D.13215;
  _Bool D.13216;
  long int D.13217;
  long int D.13218;
  _Bool D.13221;
  long int D.13222;
  long int D.13223;
  gboolean result;

  D.13214 = info->node.key;
  D.13215 = mono_native_thread_id_get ();
  D.13216 = D.13214 != D.13215;
  D.13217 = (long int) D.13216;
  D.13218 = __builtin_expect (D.13217, 0);
  if (D.13218 != 0) goto <D.13219>; else goto <D.13220>;
  <D.13219>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 218, "mono_thread_info_get_tid (info) == mono_native_thread_id_get ()");
  <D.13220>:
  result = mono_thread_info_remove (info);
  D.13221 = result == 0;
  D.13222 = (long int) D.13221;
  D.13223 = __builtin_expect (D.13222, 0);
  if (D.13223 != 0) goto <D.13224>; else goto <D.13225>;
  <D.13224>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 220, "result");
  <D.13225>:
}


mono_thread_info_remove (struct MonoThreadInfo * info)
{
  gboolean D.13226;
  struct MonoThreadHazardPointers * hp;
  gboolean res;

  hp = mono_hazard_pointer_get ();
  res = mono_lls_remove (&thread_list, hp, info);
  mono_hazard_pointer_clear_all (hp, -1);
  D.13226 = res;
  return D.13226;
}


__attribute__((visibility ("hidden")))
mono_threads_init (struct MonoThreadInfoCallbacks * callbacks, size_t info_size)
{
  int D.13228;
  _Bool D.13229;
  long int D.13230;
  long int D.13231;
  gboolean res;

  threads_callbacks = *callbacks;
  D.13228 = (int) info_size;
  thread_info_size = D.13228;
  res = mono_native_tls_alloc (&thread_info_key, unregister_thread);
  D.13229 = res == 0;
  D.13230 = (long int) D.13229;
  D.13231 = __builtin_expect (D.13230, 0);
  if (D.13231 != 0) goto <D.13232>; else goto <D.13233>;
  <D.13232>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 318, "res");
  <D.13233>:
  res = mono_native_tls_alloc (&small_id_key, 0B);
  D.13229 = res == 0;
  D.13230 = (long int) D.13229;
  D.13231 = __builtin_expect (D.13230, 0);
  if (D.13231 != 0) goto <D.13234>; else goto <D.13235>;
  <D.13234>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 321, "res");
  <D.13235>:
  sem_init (&global_suspend_semaphore, 0, 1);
  mono_lls_init (&thread_list, 0B);
  mono_thread_smr_init ();
  mono_threads_init_platform ();
  mono_threads_inited = 1;
  if (0 != 0) goto <D.13236>; else goto <D.13237>;
  <D.13236>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 335, "sizeof (MonoNativeThreadId) <= sizeof (uintptr_t)");
  <D.13237>:
}


mono_native_tls_alloc (pthread_key_t * key, void * destructor)
{
  int D.13238;
  void (*<Tc6>) (void *) destructor.12;
  int D.13240;
  _Bool D.13241;

  destructor.12 = (void (*<Tc6>) (void *)) destructor;
  D.13240 = pthread_key_create (key, destructor.12);
  D.13241 = D.13240 == 0;
  D.13238 = (int) D.13241;
  return D.13238;
}


__attribute__((visibility ("hidden")))
mono_threads_runtime_init (struct MonoThreadInfoRuntimeCallbacks * callbacks)
{
  runtime_callbacks = *callbacks;
}


__attribute__((visibility ("hidden")))
mono_threads_get_callbacks ()
{
  struct MonoThreadInfoCallbacks * D.13243;

  D.13243 = &threads_callbacks;
  return D.13243;
}


__attribute__((visibility ("hidden")))
mono_threads_get_runtime_callbacks ()
{
  struct MonoThreadInfoRuntimeCallbacks * D.13245;

  D.13245 = &runtime_callbacks;
  return D.13245;
}


__attribute__((visibility ("hidden")))
mono_thread_info_self_suspend ()
{
  union MonoSemType * D.13249;
  int D.13250;
  int D.13251;
  _Bool D.13252;
  long int D.13253;
  long int D.13254;
  int D.13257;
  int D.13258;
  int D.13259;
  struct MonoThreadInfoRuntimeCallbacks * D.13260;
  gboolean (*<T1d8c>) (struct MonoThreadUnwindState *, void *) D.13261;
  struct MonoThreadUnwindState * D.13262;
  _Bool D.13263;
  long int D.13264;
  long int D.13265;
  union MonoSemType * D.13268;
  int D.13269;
  void (*<Tc6>) (void *) D.13270;
  _Bool D.13271;
  long int D.13272;
  long int D.13273;
  union MonoSemType * D.13276;
  gboolean ret;
  struct MonoThreadInfo * info;

  info = mono_thread_info_current ();
  if (info == 0B) goto <D.13247>; else goto <D.13248>;
  <D.13247>:
  return;
  <D.13248>:
  goto <D.13016>;
  <D.13015>:
  <D.13016>:
  D.13249 = &info->suspend_semaphore;
  D.13250 = mono_sem_wait (D.13249, 0);
  if (D.13250 != 0) goto <D.13015>; else goto <D.13017>;
  <D.13017>:
  D.13251 = info->suspend_count;
  D.13252 = D.13251 != 0;
  D.13253 = (long int) D.13252;
  D.13254 = __builtin_expect (D.13253, 0);
  if (D.13254 != 0) goto <D.13255>; else goto <D.13256>;
  <D.13255>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 413, "info->suspend_count == 0");
  <D.13256>:
  D.13251 = info->suspend_count;
  D.13257 = D.13251 + 1;
  info->suspend_count = D.13257;
  D.13258 = info->thread_state;
  D.13259 = D.13258 | 32;
  info->thread_state = D.13259;
  D.13260 = mono_threads_get_runtime_callbacks ();
  D.13261 = D.13260->thread_state_init_from_sigctx;
  D.13262 = &info->suspend_state;
  ret = D.13261 (D.13262, 0B);
  D.13263 = ret == 0;
  D.13264 = (long int) D.13263;
  D.13265 = __builtin_expect (D.13264, 0);
  if (D.13265 != 0) goto <D.13266>; else goto <D.13267>;
  <D.13266>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 419, "ret");
  <D.13267>:
  D.13249 = &info->suspend_semaphore;
  mono_sem_post (D.13249);
  goto <D.13019>;
  <D.13018>:
  <D.13019>:
  D.13268 = &info->resume_semaphore;
  D.13269 = mono_sem_wait (D.13268, 0);
  if (D.13269 != 0) goto <D.13018>; else goto <D.13020>;
  <D.13020>:
  D.13270 = info->async_target;
  D.13271 = D.13270 != 0B;
  D.13272 = (long int) D.13271;
  D.13273 = __builtin_expect (D.13272, 0);
  if (D.13273 != 0) goto <D.13274>; else goto <D.13275>;
  <D.13274>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 425, "!info->async_target");
  <D.13275>:
  D.13276 = &info->finish_resume_semaphore;
  mono_sem_post (D.13276);
}


__attribute__((visibility ("hidden")))
mono_thread_info_resume (MonoNativeThreadId tid)
{
  gboolean D.13280;
  union MonoSemType * D.13281;
  int D.13282;
  int D.13283;
  long unsigned int D.13288;
  _Bool D.13289;
  long int D.13290;
  long int D.13291;
  int D.13294;
  struct MonoThreadInfo * D.13299;
  gboolean result;
  struct MonoThreadHazardPointers * hp;
  struct MonoThreadInfo * info;

  result = 1;
  hp = mono_hazard_pointer_get ();
  info = mono_thread_info_lookup (tid);
  if (info == 0B) goto <D.13278>; else goto <D.13279>;
  <D.13278>:
  D.13280 = 0;
  return D.13280;
  <D.13279>:
  goto <D.13035>;
  <D.13034>:
  <D.13035>:
  D.13281 = &info->suspend_semaphore;
  D.13282 = mono_sem_wait (D.13281, 0);
  if (D.13282 != 0) goto <D.13034>; else goto <D.13036>;
  <D.13036>:
  D.13283 = info->suspend_count;
  if (D.13283 <= 0) goto <D.13284>; else goto <D.13285>;
  <D.13284>:
  D.13281 = &info->suspend_semaphore;
  mono_sem_post (D.13281);
  if (0 != 0) goto <D.13286>; else goto <D.13287>;
  <D.13286>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 459, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13287>:
  hp->hazard_pointers[1] = 0B;
  D.13280 = 0;
  return D.13280;
  <D.13285>:
  D.13288 = info->node.key;
  D.13289 = D.13288 == 0;
  D.13290 = (long int) D.13289;
  D.13291 = __builtin_expect (D.13290, 0);
  if (D.13291 != 0) goto <D.13292>; else goto <D.13293>;
  <D.13292>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 467, "mono_thread_info_get_tid (info)");
  <D.13293>:
  D.13283 = info->suspend_count;
  D.13294 = D.13283 + -1;
  info->suspend_count = D.13294;
  D.13283 = info->suspend_count;
  if (D.13283 == 0) goto <D.13295>; else goto <D.13296>;
  <D.13295>:
  result = mono_thread_info_resume_internal (info);
  <D.13296>:
  D.13281 = &info->suspend_semaphore;
  mono_sem_post (D.13281);
  if (0 != 0) goto <D.13297>; else goto <D.13298>;
  <D.13297>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 473, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13298>:
  hp->hazard_pointers[1] = 0B;
  D.13299 = mono_thread_info_current ();
  D.13299->inside_critical_region = 0;
  D.13280 = result;
  return D.13280;
}


mono_thread_info_resume_internal (struct MonoThreadInfo * info)
{
  int D.13301;
  int D.13302;
  union MonoSemType * D.13305;
  union MonoSemType * D.13306;
  int D.13307;
  int D.13309;
  gboolean D.13310;
  gboolean result;

  D.13301 = info->thread_state;
  D.13302 = D.13301 & 240;
  if (D.13302 == 32) goto <D.13303>; else goto <D.13304>;
  <D.13303>:
  D.13305 = &info->resume_semaphore;
  mono_sem_post (D.13305);
  goto <D.13026>;
  <D.13025>:
  <D.13026>:
  D.13306 = &info->finish_resume_semaphore;
  D.13307 = mono_sem_wait (D.13306, 0);
  if (D.13307 != 0) goto <D.13025>; else goto <D.13027>;
  <D.13027>:
  result = 1;
  goto <D.13308>;
  <D.13304>:
  result = mono_threads_core_resume (info);
  <D.13308>:
  D.13301 = info->thread_state;
  D.13309 = D.13301 & -241;
  info->thread_state = D.13309;
  D.13310 = result;
  return D.13310;
}


__attribute__((visibility ("hidden")))
mono_thread_info_finish_suspend ()
{
  struct MonoThreadInfo * D.13312;

  D.13312 = mono_thread_info_current ();
  D.13312->inside_critical_region = 0;
}


__attribute__((visibility ("hidden")))
mono_thread_info_safe_suspend_sync (MonoNativeThreadId id, gboolean interrupt_kernel)
{
  long unsigned int D.13313;
  _Bool D.13314;
  long int D.13315;
  long int D.13316;
  void * id.13;
  struct MonoThreadInfo * D.13322;
  int D.13323;
  int D.13325;
  long unsigned int D.13331;
  struct MonoThreadInfo * D.13332;
  struct MonoThreadInfo * info;
  int sleep_duration;

  info = 0B;
  sleep_duration = 0;
  D.13313 = mono_native_thread_id_get ();
  D.13314 = D.13313 == id;
  D.13315 = (long int) D.13314;
  D.13316 = __builtin_expect (D.13315, 0);
  if (D.13316 != 0) goto <D.13317>; else goto <D.13318>;
  <D.13317>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 527, "id != mono_native_thread_id_get ()");
  <D.13318>:
  mono_thread_info_suspend_lock ();
  <D.13052>:
  info = mono_thread_info_suspend_sync (id, interrupt_kernel);
  if (info == 0B) goto <D.13319>; else goto <D.13320>;
  <D.13319>:
  id.13 = (void *) id;
  monoeg_g_log (0B, 16, "failed to suspend thread %p, hopefully it is dead", id.13);
  mono_thread_info_suspend_unlock ();
  D.13322 = 0B;
  return D.13322;
  <D.13320>:
  D.13323 = is_thread_in_critical_region (info);
  if (D.13323 == 0) goto <D.13051>; else goto <D.13324>;
  <D.13324>:
  D.13325 = mono_thread_info_resume (id);
  if (D.13325 == 0) goto <D.13326>; else goto <D.13327>;
  <D.13326>:
  id.13 = (void *) id;
  monoeg_g_log (0B, 16, "failed to result thread %p, hopefully it is dead", id.13);
  mono_thread_info_suspend_unlock ();
  D.13322 = 0B;
  return D.13322;
  <D.13327>:
  if (sleep_duration == 0) goto <D.13328>; else goto <D.13329>;
  <D.13328>:
  sched_yield ();
  goto <D.13330>;
  <D.13329>:
  D.13331 = (long unsigned int) sleep_duration;
  monoeg_g_usleep (D.13331);
  <D.13330>:
  sleep_duration = sleep_duration + 10;
  goto <D.13052>;
  <D.13051>:
  D.13332 = mono_thread_info_current ();
  D.13332->inside_critical_region = 1;
  mono_thread_info_suspend_unlock ();
  D.13322 = info;
  return D.13322;
}


mono_thread_info_suspend_sync (MonoNativeThreadId tid, gboolean interrupt_kernel)
{
  struct MonoThreadInfo * D.13336;
  union MonoSemType * D.13337;
  int D.13338;
  int D.13339;
  int D.13340;
  int D.13345;
  int D.13348;
  int D.13351;
  int D.13358;
  struct MonoThreadHazardPointers * hp;
  struct MonoThreadInfo * info;

  hp = mono_hazard_pointer_get ();
  info = mono_thread_info_lookup (tid);
  if (info == 0B) goto <D.13334>; else goto <D.13335>;
  <D.13334>:
  D.13336 = 0B;
  return D.13336;
  <D.13335>:
  goto <D.13008>;
  <D.13007>:
  <D.13008>:
  D.13337 = &info->suspend_semaphore;
  D.13338 = mono_sem_wait (D.13337, 0);
  if (D.13338 != 0) goto <D.13007>; else goto <D.13009>;
  <D.13009>:
  D.13339 = info->thread_state;
  D.13340 = D.13339 & 15;
  if (D.13340 > 1) goto <D.13341>; else goto <D.13342>;
  <D.13341>:
  if (0 != 0) goto <D.13343>; else goto <D.13344>;
  <D.13343>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 371, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13344>:
  hp->hazard_pointers[1] = 0B;
  D.13336 = 0B;
  return D.13336;
  <D.13342>:
  D.13345 = info->suspend_count;
  if (D.13345 != 0) goto <D.13346>; else goto <D.13347>;
  <D.13346>:
  D.13345 = info->suspend_count;
  D.13348 = D.13345 + 1;
  info->suspend_count = D.13348;
  if (0 != 0) goto <D.13349>; else goto <D.13350>;
  <D.13349>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 379, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13350>:
  hp->hazard_pointers[1] = 0B;
  D.13337 = &info->suspend_semaphore;
  mono_sem_post (D.13337);
  D.13336 = info;
  return D.13336;
  <D.13347>:
  D.13351 = mono_threads_core_suspend (info);
  if (D.13351 == 0) goto <D.13352>; else goto <D.13353>;
  <D.13352>:
  D.13337 = &info->suspend_semaphore;
  mono_sem_post (D.13337);
  if (0 != 0) goto <D.13354>; else goto <D.13355>;
  <D.13354>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 386, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13355>:
  hp->hazard_pointers[1] = 0B;
  D.13336 = 0B;
  return D.13336;
  <D.13353>:
  if (interrupt_kernel != 0) goto <D.13356>; else goto <D.13357>;
  <D.13356>:
  mono_threads_core_interrupt (info);
  <D.13357>:
  D.13345 = info->suspend_count;
  D.13348 = D.13345 + 1;
  info->suspend_count = D.13348;
  D.13339 = info->thread_state;
  D.13358 = D.13339 | 16;
  info->thread_state = D.13358;
  D.13337 = &info->suspend_semaphore;
  mono_sem_post (D.13337);
  if (0 != 0) goto <D.13359>; else goto <D.13360>;
  <D.13359>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 396, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13360>:
  hp->hazard_pointers[1] = 0B;
  D.13336 = info;
  return D.13336;
}


is_thread_in_critical_region (struct MonoThreadInfo * info)
{
  int D.13362;
  gboolean D.13365;
  void * D.13366;
  long unsigned int D.13369;
  char * D.13370;
  gboolean (*<T1d7b>) (void *) D.13373;
  struct MonoMethod * method;
  struct MonoJitInfo * ji;

  D.13362 = info->inside_critical_region;
  if (D.13362 != 0) goto <D.13363>; else goto <D.13364>;
  <D.13363>:
  D.13365 = 1;
  return D.13365;
  <D.13364>:
  D.13366 = info->suspend_state.unwind_data[0];
  if (D.13366 == 0B) goto <D.13367>; else goto <D.13368>;
  <D.13367>:
  D.13365 = 0;
  return D.13365;
  <D.13368>:
  D.13366 = info->suspend_state.unwind_data[0];
  D.13369 = info->suspend_state.ctx.uc_mcontext.psw.addr;
  D.13370 = (char *) D.13369;
  ji = mono_jit_info_table_find (D.13366, D.13370);
  if (ji == 0B) goto <D.13371>; else goto <D.13372>;
  <D.13371>:
  D.13365 = 0;
  return D.13365;
  <D.13372>:
  method = mono_jit_info_get_method (ji);
  D.13373 = threads_callbacks.mono_method_is_critical;
  D.13365 = D.13373 (method);
  return D.13365;
}


__attribute__((visibility ("hidden")))
mono_thread_info_setup_async_call (struct MonoThreadInfo * info, void (*<Tc6>) (void *) target_func, void * user_data)
{
  int D.13375;
  _Bool D.13376;
  long int D.13377;
  long int D.13378;
  void (*<Tc6>) (void *) D.13381;
  _Bool D.13382;
  long int D.13383;
  long int D.13384;

  D.13375 = info->suspend_count;
  D.13376 = D.13375 == 0;
  D.13377 = (long int) D.13376;
  D.13378 = __builtin_expect (D.13377, 0);
  if (D.13378 != 0) goto <D.13379>; else goto <D.13380>;
  <D.13379>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 577, "info->suspend_count");
  <D.13380>:
  D.13381 = info->async_target;
  D.13382 = D.13381 != 0B;
  D.13383 = (long int) D.13382;
  D.13384 = __builtin_expect (D.13383, 0);
  if (D.13384 != 0) goto <D.13385>; else goto <D.13386>;
  <D.13385>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 579, "!info->async_target");
  <D.13386>:
  info->async_target = target_func;
  info->user_data = user_data;
}


__attribute__((visibility ("hidden")))
mono_thread_info_suspend_lock ()
{
  int D.13387;

  goto <D.13063>;
  <D.13062>:
  <D.13063>:
  D.13387 = mono_sem_wait (&global_suspend_semaphore, 0);
  if (D.13387 != 0) goto <D.13062>; else goto <D.13064>;
  <D.13064>:
}


__attribute__((visibility ("hidden")))
mono_thread_info_suspend_unlock ()
{
  mono_sem_post (&global_suspend_semaphore);
}


__attribute__((visibility ("hidden")))
mono_thread_info_disable_new_interrupt (gboolean disable)
{
  disable_new_interrupt = disable;
}


__attribute__((visibility ("hidden")))
mono_thread_info_abort_socket_syscall_for_close (MonoNativeThreadId tid)
{
  long unsigned int D.13390;
  int D.13392;
  int D.13395;
  int D.13396;
  struct MonoThreadHazardPointers * hp;
  struct MonoThreadInfo * info;

  D.13390 = mono_native_thread_id_get ();
  if (D.13390 == tid) goto <D.13388>; else goto <D.13391>;
  <D.13391>:
  D.13392 = mono_threads_core_needs_abort_syscall ();
  if (D.13392 == 0) goto <D.13388>; else goto <D.13389>;
  <D.13388>:
  return;
  <D.13389>:
  hp = mono_hazard_pointer_get ();
  info = mono_thread_info_lookup (tid);
  if (info == 0B) goto <D.13393>; else goto <D.13394>;
  <D.13393>:
  return;
  <D.13394>:
  D.13395 = info->thread_state;
  D.13396 = D.13395 & 15;
  if (D.13396 > 1) goto <D.13397>; else goto <D.13398>;
  <D.13397>:
  if (0 != 0) goto <D.13399>; else goto <D.13400>;
  <D.13399>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 633, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13400>:
  hp->hazard_pointers[1] = 0B;
  return;
  <D.13398>:
  mono_thread_info_suspend_lock ();
  mono_threads_core_abort_syscall (info);
  if (0 != 0) goto <D.13401>; else goto <D.13402>;
  <D.13401>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 641, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13402>:
  hp->hazard_pointers[1] = 0B;
  mono_thread_info_suspend_unlock ();
}


__attribute__((visibility ("hidden")))
mono_thread_info_new_interrupt_enabled ()
{
  gboolean D.13404;

  D.13404 = 0;
  return D.13404;
}


__attribute__((visibility ("hidden")))
mono_thread_info_set_is_async_context (gboolean async_context)
{
  struct MonoThreadInfo * info;

  info = mono_thread_info_current ();
  if (info != 0B) goto <D.13406>; else goto <D.13407>;
  <D.13406>:
  info->is_async_context = async_context;
  <D.13407>:
}


__attribute__((visibility ("hidden")))
mono_thread_info_is_async_context ()
{
  gboolean D.13410;
  struct MonoThreadInfo * info;

  info = mono_thread_info_current ();
  if (info != 0B) goto <D.13408>; else goto <D.13409>;
  <D.13408>:
  D.13410 = info->is_async_context;
  return D.13410;
  <D.13409>:
  D.13410 = 0;
  return D.13410;
}


mono_threads_create_thread (guint32 (*LPTHREAD_START_ROUTINE) (void *) start, void * arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId * out_tid)
{
  long unsigned int real_tid.14;
  void * D.13415;
  void * res;
  gsize real_tid;

  try
    {
      res = CreateThread (0B, stack_size, start, arg, creation_flags, &real_tid);
      if (out_tid != 0B) goto <D.13412>; else goto <D.13413>;
      <D.13412>:
      real_tid.14 = real_tid;
      *out_tid = real_tid.14;
      <D.13413>:
      D.13415 = res;
      return D.13415;
    }
  finally
    {
      real_tid = {CLOBBER};
    }
}


