mono_thread_info_lookup (MonoNativeThreadId id)
{
  int D.15140;
  struct MonoThreadInfo * D.15143;
  struct MonoThreadHazardPointers * hp;

  hp = mono_hazard_pointer_get ();
  D.15140 = mono_lls_find (&thread_list, hp, id);
  if (D.15140 == 0) goto <D.15141>; else goto <D.15142>;
  <D.15141>:
  mono_hazard_pointer_clear_all (hp, -1);
  D.15143 = 0B;
  return D.15143;
  <D.15142>:
  mono_hazard_pointer_clear_all (hp, 1);
  D.15143 = hp->hazard_pointers[1];
  return D.15143;
}


mono_hazard_pointer_clear_all (struct MonoThreadHazardPointers * hp, int retain)
{
  if (retain != 0) goto <D.15145>; else goto <D.15146>;
  <D.15145>:
  if (0 != 0) goto <D.15147>; else goto <D.15148>;
  <D.15147>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 58, "(0) >= 0 && (0) < HAZARD_POINTER_COUNT");
  <D.15148>:
  hp->hazard_pointers[0] = 0B;
  <D.15146>:
  if (retain != 1) goto <D.15149>; else goto <D.15150>;
  <D.15149>:
  if (0 != 0) goto <D.15151>; else goto <D.15152>;
  <D.15151>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 60, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.15152>:
  hp->hazard_pointers[1] = 0B;
  <D.15150>:
  if (retain != 2) goto <D.15153>; else goto <D.15154>;
  <D.15153>:
  if (0 != 0) goto <D.15155>; else goto <D.15156>;
  <D.15155>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 62, "(2) >= 0 && (2) < HAZARD_POINTER_COUNT");
  <D.15156>:
  hp->hazard_pointers[2] = 0B;
  <D.15154>:
}


mono_thread_info_register_small_id ()
{
  unsigned int small_id_key.0;
  int D.15158;
  void * D.15159;
  int D.15160;
  int small_id;

  small_id = mono_thread_small_id_alloc ();
  small_id_key.0 = small_id_key;
  D.15158 = small_id + 1;
  D.15159 = (void *) D.15158;
  mono_native_tls_set_value (small_id_key.0, D.15159);
  D.15160 = small_id;
  return D.15160;
}


mono_native_tls_set_value (pthread_key_t key, void * value)
{
  int D.15162;
  int D.15163;
  _Bool D.15164;

  D.15163 = pthread_setspecific (key, value);
  D.15164 = D.15163 == 0;
  D.15162 = (int) D.15164;
  return D.15162;
}


mono_thread_info_current ()
{
  unsigned int thread_info_key.1;
  struct MonoThreadInfo * D.15169;
  long unsigned int D.15170;
  _Bool D.15171;
  long int D.15172;
  long int D.15173;
  struct MonoThreadHazardPointers * D.15178;
  struct MonoThreadInfo * info;

  thread_info_key.1 = thread_info_key;
  info = pthread_getspecific (thread_info_key.1);
  if (info != 0B) goto <D.15167>; else goto <D.15168>;
  <D.15167>:
  D.15169 = info;
  return D.15169;
  <D.15168>:
  D.15170 = mono_native_thread_id_get ();
  info = mono_thread_info_lookup (D.15170);
  D.15171 = info == 0B;
  D.15172 = (long int) D.15171;
  D.15173 = __builtin_expect (D.15172, 0);
  if (D.15173 != 0) goto <D.15174>; else goto <D.15175>;
  <D.15174>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 242, "info");
  <D.15175>:
  if (0 != 0) goto <D.15176>; else goto <D.15177>;
  <D.15176>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 245, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.15177>:
  D.15178 = mono_hazard_pointer_get ();
  D.15178->hazard_pointers[1] = 0B;
  D.15169 = info;
  return D.15169;
}


mono_thread_info_get_small_id ()
{
  unsigned int small_id_key.2;
  int D.15183;
  int val.3;
  void * val;

  small_id_key.2 = small_id_key;
  val = pthread_getspecific (small_id_key.2);
  if (val == 0B) goto <D.15181>; else goto <D.15182>;
  <D.15181>:
  D.15183 = -1;
  return D.15183;
  <D.15182>:
  val.3 = (int) val;
  D.15183 = val.3 + -1;
  return D.15183;
}


mono_thread_info_list_head ()
{
  struct MonoLinkedListSet * D.15186;

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


mono_thread_info_attach (void * baseptr)
{
  int mono_threads_inited.4;
  struct MonoThreadInfo * D.15191;
  unsigned int thread_info_key.5;
  int thread_info_size.6;
  unsigned int thread_info_size.7;
  void * D.15197;
  void (*<T25f0>) (struct MonoThreadInfo *) D.15201;
  struct MonoThreadInfo * info;

  mono_threads_inited.4 = mono_threads_inited;
  if (mono_threads_inited.4 == 0) goto <D.15189>; else goto <D.15190>;
  <D.15189>:
  D.15191 = 0B;
  return D.15191;
  <D.15190>:
  thread_info_key.5 = thread_info_key;
  info = pthread_getspecific (thread_info_key.5);
  if (info == 0B) goto <D.15193>; else goto <D.15194>;
  <D.15193>:
  thread_info_size.6 = thread_info_size;
  thread_info_size.7 = (unsigned int) thread_info_size.6;
  info = monoeg_malloc0 (thread_info_size.7);
  D.15197 = register_thread (info, baseptr);
  if (D.15197 == 0B) goto <D.15198>; else goto <D.15199>;
  <D.15198>:
  D.15191 = 0B;
  return D.15191;
  <D.15199>:
  goto <D.15200>;
  <D.15194>:
  D.15201 = threads_callbacks.thread_attach;
  if (D.15201 != 0B) goto <D.15202>; else goto <D.15203>;
  <D.15202>:
  D.15201 = threads_callbacks.thread_attach;
  D.15201 (info);
  <D.15203>:
  <D.15200>:
  D.15191 = info;
  return D.15191;
}


register_thread (struct MonoThreadInfo * info, void * baseptr)
{
  long unsigned int D.15205;
  unsigned int small_id.8;
  union MonoSemType * D.15207;
  union MonoSemType * D.15208;
  union MonoSemType * D.15209;
  unsigned int thread_info_key.9;
  void * (*<T25ec>) (struct MonoThreadInfo *, void *) D.15211;
  void * D.15214;
  void * D.15217;
  _Bool D.15218;
  long int D.15219;
  long int D.15220;
  int small_id;
  gboolean result;

  small_id = mono_thread_info_register_small_id ();
  D.15205 = mono_native_thread_id_get ();
  info->node.key = D.15205;
  small_id.8 = (unsigned int) small_id;
  info->small_id = small_id.8;
  D.15207 = &info->suspend_semaphore;
  sem_init (D.15207, 0, 1);
  D.15208 = &info->resume_semaphore;
  sem_init (D.15208, 0, 0);
  D.15209 = &info->finish_resume_semaphore;
  sem_init (D.15209, 0, 0);
  thread_info_key.9 = thread_info_key;
  mono_native_tls_set_value (thread_info_key.9, info);
  D.15211 = threads_callbacks.thread_register;
  if (D.15211 != 0B) goto <D.15212>; else goto <D.15213>;
  <D.15212>:
  D.15211 = threads_callbacks.thread_register;
  D.15214 = D.15211 (info, baseptr);
  if (D.15214 == 0B) goto <D.15215>; else goto <D.15216>;
  <D.15215>:
  monoeg_g_log (0B, 16, "thread registation failed\n");
  monoeg_g_free (info);
  D.15217 = 0B;
  return D.15217;
  <D.15216>:
  <D.15213>:
  mono_threads_platform_register (info);
  info->thread_state = 1;
  mono_thread_info_suspend_lock ();
  result = mono_thread_info_insert (info);
  D.15218 = result == 0;
  D.15219 = (long int) D.15218;
  D.15220 = __builtin_expect (D.15219, 0);
  if (D.15220 != 0) goto <D.15221>; else goto <D.15222>;
  <D.15221>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 159, "result");
  <D.15222>:
  mono_thread_info_suspend_unlock ();
  D.15217 = info;
  return D.15217;
}


mono_thread_info_insert (struct MonoThreadInfo * info)
{
  int D.15224;
  gboolean D.15227;
  struct MonoThreadHazardPointers * hp;

  hp = mono_hazard_pointer_get ();
  D.15224 = mono_lls_insert (&thread_list, hp, info);
  if (D.15224 == 0) goto <D.15225>; else goto <D.15226>;
  <D.15225>:
  mono_hazard_pointer_clear_all (hp, -1);
  D.15227 = 0;
  return D.15227;
  <D.15226>:
  mono_hazard_pointer_clear_all (hp, -1);
  D.15227 = 1;
  return D.15227;
}


mono_thread_info_dettach ()
{
  int mono_threads_inited.10;
  unsigned int thread_info_key.11;
  struct MonoThreadInfo * info;

  mono_threads_inited.10 = mono_threads_inited;
  if (mono_threads_inited.10 == 0) goto <D.15230>; else goto <D.15231>;
  <D.15230>:
  return;
  <D.15231>:
  thread_info_key.11 = thread_info_key;
  info = pthread_getspecific (thread_info_key.11);
  if (info != 0B) goto <D.15233>; else goto <D.15234>;
  <D.15233>:
  unregister_thread (info);
  thread_info_key.11 = thread_info_key;
  mono_native_tls_set_value (thread_info_key.11, 0B);
  <D.15234>:
}


unregister_thread (void * arg)
{
  unsigned int D.15236;
  _Bool D.15237;
  long int D.15238;
  long int D.15239;
  unsigned int small_id_key.12;
  unsigned int D.15243;
  void * D.15244;
  void (*<T25f0>) (struct MonoThreadInfo *) D.15245;
  void (*<T25f0>) (struct MonoThreadInfo *) D.15248;
  struct MonoThreadInfo * info;
  int small_id;

  info = arg;
  D.15236 = info->small_id;
  small_id = (int) D.15236;
  D.15237 = info == 0B;
  D.15238 = (long int) D.15237;
  D.15239 = __builtin_expect (D.15238, 0);
  if (D.15239 != 0) goto <D.15240>; else goto <D.15241>;
  <D.15240>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 169, "info");
  <D.15241>:
  small_id_key.12 = small_id_key;
  D.15236 = info->small_id;
  D.15243 = D.15236 + 1;
  D.15244 = (void *) D.15243;
  mono_native_tls_set_value (small_id_key.12, D.15244);
  info->thread_state = 2;
  D.15245 = threads_callbacks.thread_detach;
  if (D.15245 != 0B) goto <D.15246>; else goto <D.15247>;
  <D.15246>:
  D.15245 = threads_callbacks.thread_detach;
  D.15245 (info);
  <D.15247>:
  mono_thread_info_suspend_lock ();
  D.15248 = threads_callbacks.thread_unregister;
  if (D.15248 != 0B) goto <D.15249>; else goto <D.15250>;
  <D.15249>:
  D.15248 = threads_callbacks.thread_unregister;
  D.15248 (info);
  <D.15250>:
  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.15251;
  union MonoSemType * D.15252;
  union MonoSemType * D.15253;
  struct MonoThreadInfo * info;

  info = mem;
  D.15251 = &info->suspend_semaphore;
  sem_destroy (D.15251);
  D.15252 = &info->resume_semaphore;
  sem_destroy (D.15252);
  D.15253 = &info->finish_resume_semaphore;
  sem_destroy (D.15253);
  mono_threads_platform_free (info);
  monoeg_g_free (info);
}


mono_threads_unregister_current_thread (struct MonoThreadInfo * info)
{
  unsigned int D.15254;
  long unsigned int D.15255;
  _Bool D.15256;
  long int D.15257;
  long int D.15258;
  _Bool D.15261;
  long int D.15262;
  long int D.15263;
  gboolean result;

  D.15254 = info->node.key;
  D.15255 = mono_native_thread_id_get ();
  D.15256 = D.15254 != D.15255;
  D.15257 = (long int) D.15256;
  D.15258 = __builtin_expect (D.15257, 0);
  if (D.15258 != 0) goto <D.15259>; else goto <D.15260>;
  <D.15259>:
  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.15260>:
  result = mono_thread_info_remove (info);
  D.15261 = result == 0;
  D.15262 = (long int) D.15261;
  D.15263 = __builtin_expect (D.15262, 0);
  if (D.15263 != 0) goto <D.15264>; else goto <D.15265>;
  <D.15264>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 220, "result");
  <D.15265>:
}


mono_thread_info_remove (struct MonoThreadInfo * info)
{
  gboolean D.15266;
  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.15266 = res;
  return D.15266;
}


mono_threads_init (struct MonoThreadInfoCallbacks * callbacks, size_t info_size)
{
  int info_size.13;
  _Bool D.15269;
  long int D.15270;
  long int D.15271;
  gboolean res;

  threads_callbacks = *callbacks;
  info_size.13 = (int) info_size;
  thread_info_size = info_size.13;
  res = mono_native_tls_alloc (&thread_info_key, unregister_thread);
  D.15269 = res == 0;
  D.15270 = (long int) D.15269;
  D.15271 = __builtin_expect (D.15270, 0);
  if (D.15271 != 0) goto <D.15272>; else goto <D.15273>;
  <D.15272>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 318, "res");
  <D.15273>:
  res = mono_native_tls_alloc (&small_id_key, 0B);
  D.15269 = res == 0;
  D.15270 = (long int) D.15269;
  D.15271 = __builtin_expect (D.15270, 0);
  if (D.15271 != 0) goto <D.15274>; else goto <D.15275>;
  <D.15274>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 321, "res");
  <D.15275>:
  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.15276>; else goto <D.15277>;
  <D.15276>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 335, "sizeof (MonoNativeThreadId) <= sizeof (uintptr_t)");
  <D.15277>:
}


mono_native_tls_alloc (pthread_key_t * key, void * destructor)
{
  int D.15278;
  void (*<Tc1>) (void *) destructor.14;
  int D.15280;
  _Bool D.15281;

  destructor.14 = (void (*<Tc1>) (void *)) destructor;
  D.15280 = pthread_key_create (key, destructor.14);
  D.15281 = D.15280 == 0;
  D.15278 = (int) D.15281;
  return D.15278;
}


mono_threads_runtime_init (struct MonoThreadInfoRuntimeCallbacks * callbacks)
{
  runtime_callbacks = *callbacks;
}


mono_threads_get_callbacks ()
{
  struct MonoThreadInfoCallbacks * D.15283;

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


mono_threads_get_runtime_callbacks ()
{
  struct MonoThreadInfoRuntimeCallbacks * D.15285;

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


mono_thread_info_self_suspend ()
{
  union MonoSemType * D.15289;
  int D.15290;
  int D.15291;
  _Bool D.15292;
  long int D.15293;
  long int D.15294;
  int D.15297;
  int D.15298;
  int D.15299;
  struct MonoThreadInfoRuntimeCallbacks * D.15300;
  gboolean (*<T2609>) (struct MonoThreadUnwindState *, void *) D.15301;
  struct MonoThreadUnwindState * D.15302;
  _Bool D.15303;
  long int D.15304;
  long int D.15305;
  union MonoSemType * D.15308;
  int D.15309;
  void (*<Tc1>) (void *) D.15310;
  _Bool D.15311;
  long int D.15312;
  long int D.15313;
  union MonoSemType * D.15316;
  gboolean ret;
  struct MonoThreadInfo * info;

  info = mono_thread_info_current ();
  if (info == 0B) goto <D.15287>; else goto <D.15288>;
  <D.15287>:
  return;
  <D.15288>:
  goto <D.15057>;
  <D.15056>:
  <D.15057>:
  D.15289 = &info->suspend_semaphore;
  D.15290 = mono_sem_wait (D.15289, 0);
  if (D.15290 != 0) goto <D.15056>; else goto <D.15058>;
  <D.15058>:
  D.15291 = info->suspend_count;
  D.15292 = D.15291 != 0;
  D.15293 = (long int) D.15292;
  D.15294 = __builtin_expect (D.15293, 0);
  if (D.15294 != 0) goto <D.15295>; else goto <D.15296>;
  <D.15295>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 413, "info->suspend_count == 0");
  <D.15296>:
  D.15291 = info->suspend_count;
  D.15297 = D.15291 + 1;
  info->suspend_count = D.15297;
  D.15298 = info->thread_state;
  D.15299 = D.15298 | 32;
  info->thread_state = D.15299;
  D.15300 = mono_threads_get_runtime_callbacks ();
  D.15301 = D.15300->thread_state_init_from_sigctx;
  D.15302 = &info->suspend_state;
  ret = D.15301 (D.15302, 0B);
  D.15303 = ret == 0;
  D.15304 = (long int) D.15303;
  D.15305 = __builtin_expect (D.15304, 0);
  if (D.15305 != 0) goto <D.15306>; else goto <D.15307>;
  <D.15306>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 419, "ret");
  <D.15307>:
  D.15289 = &info->suspend_semaphore;
  mono_sem_post (D.15289);
  goto <D.15060>;
  <D.15059>:
  <D.15060>:
  D.15308 = &info->resume_semaphore;
  D.15309 = mono_sem_wait (D.15308, 0);
  if (D.15309 != 0) goto <D.15059>; else goto <D.15061>;
  <D.15061>:
  D.15310 = info->async_target;
  D.15311 = D.15310 != 0B;
  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", "mono-threads.c", 425, "!info->async_target");
  <D.15315>:
  D.15316 = &info->finish_resume_semaphore;
  mono_sem_post (D.15316);
}


mono_thread_info_resume (MonoNativeThreadId tid)
{
  gboolean D.15320;
  union MonoSemType * D.15321;
  int D.15322;
  int D.15323;
  unsigned int D.15328;
  _Bool D.15329;
  long int D.15330;
  long int D.15331;
  int D.15334;
  struct MonoThreadInfo * D.15339;
  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.15318>; else goto <D.15319>;
  <D.15318>:
  D.15320 = 0;
  return D.15320;
  <D.15319>:
  goto <D.15076>;
  <D.15075>:
  <D.15076>:
  D.15321 = &info->suspend_semaphore;
  D.15322 = mono_sem_wait (D.15321, 0);
  if (D.15322 != 0) goto <D.15075>; else goto <D.15077>;
  <D.15077>:
  D.15323 = info->suspend_count;
  if (D.15323 <= 0) goto <D.15324>; else goto <D.15325>;
  <D.15324>:
  D.15321 = &info->suspend_semaphore;
  mono_sem_post (D.15321);
  if (0 != 0) goto <D.15326>; else goto <D.15327>;
  <D.15326>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 459, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.15327>:
  hp->hazard_pointers[1] = 0B;
  D.15320 = 0;
  return D.15320;
  <D.15325>:
  D.15328 = info->node.key;
  D.15329 = D.15328 == 0;
  D.15330 = (long int) D.15329;
  D.15331 = __builtin_expect (D.15330, 0);
  if (D.15331 != 0) goto <D.15332>; else goto <D.15333>;
  <D.15332>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 467, "mono_thread_info_get_tid (info)");
  <D.15333>:
  D.15323 = info->suspend_count;
  D.15334 = D.15323 + -1;
  info->suspend_count = D.15334;
  D.15323 = info->suspend_count;
  if (D.15323 == 0) goto <D.15335>; else goto <D.15336>;
  <D.15335>:
  result = mono_thread_info_resume_internal (info);
  <D.15336>:
  D.15321 = &info->suspend_semaphore;
  mono_sem_post (D.15321);
  if (0 != 0) goto <D.15337>; else goto <D.15338>;
  <D.15337>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 473, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.15338>:
  hp->hazard_pointers[1] = 0B;
  mono_memory_barrier ();
  D.15339 = mono_thread_info_current ();
  D.15339->inside_critical_region = 0;
  D.15320 = result;
  return D.15320;
}


mono_thread_info_resume_internal (struct MonoThreadInfo * info)
{
  int D.15341;
  int D.15342;
  union MonoSemType * D.15345;
  union MonoSemType * D.15346;
  int D.15347;
  int D.15349;
  gboolean D.15350;
  gboolean result;

  D.15341 = info->thread_state;
  D.15342 = D.15341 & 240;
  if (D.15342 == 32) goto <D.15343>; else goto <D.15344>;
  <D.15343>:
  D.15345 = &info->resume_semaphore;
  mono_sem_post (D.15345);
  goto <D.15067>;
  <D.15066>:
  <D.15067>:
  D.15346 = &info->finish_resume_semaphore;
  D.15347 = mono_sem_wait (D.15346, 0);
  if (D.15347 != 0) goto <D.15066>; else goto <D.15068>;
  <D.15068>:
  result = 1;
  goto <D.15348>;
  <D.15344>:
  result = mono_threads_core_resume (info);
  <D.15348>:
  D.15341 = info->thread_state;
  D.15349 = D.15341 & -241;
  info->thread_state = D.15349;
  D.15350 = result;
  return D.15350;
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


mono_thread_info_finish_suspend ()
{
  struct MonoThreadInfo * D.15352;

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


mono_thread_info_safe_suspend_sync (MonoNativeThreadId id, gboolean interrupt_kernel)
{
  long unsigned int D.15353;
  _Bool D.15354;
  long int D.15355;
  long int D.15356;
  void * id.15;
  struct MonoThreadInfo * D.15362;
  int D.15363;
  int D.15365;
  long unsigned int sleep_duration.16;
  struct MonoThreadInfo * D.15372;
  struct MonoThreadInfo * info;
  int sleep_duration;

  info = 0B;
  sleep_duration = 0;
  D.15353 = mono_native_thread_id_get ();
  D.15354 = D.15353 == id;
  D.15355 = (long int) D.15354;
  D.15356 = __builtin_expect (D.15355, 0);
  if (D.15356 != 0) goto <D.15357>; else goto <D.15358>;
  <D.15357>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 527, "id != mono_native_thread_id_get ()");
  <D.15358>:
  mono_thread_info_suspend_lock ();
  <D.15093>:
  info = mono_thread_info_suspend_sync (id, interrupt_kernel);
  if (info == 0B) goto <D.15359>; else goto <D.15360>;
  <D.15359>:
  id.15 = (void *) id;
  monoeg_g_log (0B, 16, "failed to suspend thread %p, hopefully it is dead", id.15);
  mono_thread_info_suspend_unlock ();
  D.15362 = 0B;
  return D.15362;
  <D.15360>:
  D.15363 = is_thread_in_critical_region (info);
  if (D.15363 == 0) goto <D.15092>; else goto <D.15364>;
  <D.15364>:
  D.15365 = mono_thread_info_resume (id);
  if (D.15365 == 0) goto <D.15366>; else goto <D.15367>;
  <D.15366>:
  id.15 = (void *) id;
  monoeg_g_log (0B, 16, "failed to result thread %p, hopefully it is dead", id.15);
  mono_thread_info_suspend_unlock ();
  D.15362 = 0B;
  return D.15362;
  <D.15367>:
  if (sleep_duration == 0) goto <D.15368>; else goto <D.15369>;
  <D.15368>:
  sched_yield ();
  goto <D.15370>;
  <D.15369>:
  sleep_duration.16 = (long unsigned int) sleep_duration;
  monoeg_g_usleep (sleep_duration.16);
  <D.15370>:
  sleep_duration = sleep_duration + 10;
  goto <D.15093>;
  <D.15092>:
  mono_memory_barrier ();
  D.15372 = mono_thread_info_current ();
  D.15372->inside_critical_region = 1;
  mono_thread_info_suspend_unlock ();
  D.15362 = info;
  return D.15362;
}


mono_thread_info_suspend_sync (MonoNativeThreadId tid, gboolean interrupt_kernel)
{
  struct MonoThreadInfo * D.15376;
  union MonoSemType * D.15377;
  int D.15378;
  int D.15379;
  int D.15380;
  int D.15385;
  int D.15388;
  int D.15391;
  int D.15398;
  struct MonoThreadHazardPointers * hp;
  struct MonoThreadInfo * info;

  hp = mono_hazard_pointer_get ();
  info = mono_thread_info_lookup (tid);
  if (info == 0B) goto <D.15374>; else goto <D.15375>;
  <D.15374>:
  D.15376 = 0B;
  return D.15376;
  <D.15375>:
  goto <D.15049>;
  <D.15048>:
  <D.15049>:
  D.15377 = &info->suspend_semaphore;
  D.15378 = mono_sem_wait (D.15377, 0);
  if (D.15378 != 0) goto <D.15048>; else goto <D.15050>;
  <D.15050>:
  D.15379 = info->thread_state;
  D.15380 = D.15379 & 15;
  if (D.15380 > 1) goto <D.15381>; else goto <D.15382>;
  <D.15381>:
  if (0 != 0) goto <D.15383>; else goto <D.15384>;
  <D.15383>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 371, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.15384>:
  hp->hazard_pointers[1] = 0B;
  D.15376 = 0B;
  return D.15376;
  <D.15382>:
  D.15385 = info->suspend_count;
  if (D.15385 != 0) goto <D.15386>; else goto <D.15387>;
  <D.15386>:
  D.15385 = info->suspend_count;
  D.15388 = D.15385 + 1;
  info->suspend_count = D.15388;
  if (0 != 0) goto <D.15389>; else goto <D.15390>;
  <D.15389>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 379, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.15390>:
  hp->hazard_pointers[1] = 0B;
  D.15377 = &info->suspend_semaphore;
  mono_sem_post (D.15377);
  D.15376 = info;
  return D.15376;
  <D.15387>:
  D.15391 = mono_threads_core_suspend (info);
  if (D.15391 == 0) goto <D.15392>; else goto <D.15393>;
  <D.15392>:
  D.15377 = &info->suspend_semaphore;
  mono_sem_post (D.15377);
  if (0 != 0) goto <D.15394>; else goto <D.15395>;
  <D.15394>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 386, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.15395>:
  hp->hazard_pointers[1] = 0B;
  D.15376 = 0B;
  return D.15376;
  <D.15393>:
  if (interrupt_kernel != 0) goto <D.15396>; else goto <D.15397>;
  <D.15396>:
  mono_threads_core_interrupt (info);
  <D.15397>:
  D.15385 = info->suspend_count;
  D.15388 = D.15385 + 1;
  info->suspend_count = D.15388;
  D.15379 = info->thread_state;
  D.15398 = D.15379 | 16;
  info->thread_state = D.15398;
  D.15377 = &info->suspend_semaphore;
  mono_sem_post (D.15377);
  if (0 != 0) goto <D.15399>; else goto <D.15400>;
  <D.15399>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 396, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.15400>:
  hp->hazard_pointers[1] = 0B;
  D.15376 = info;
  return D.15376;
}


is_thread_in_critical_region (struct MonoThreadInfo * info)
{
  int D.15402;
  gboolean D.15405;
  void * D.15406;
  int D.15409;
  char * D.15410;
  gboolean (*<T25f8>) (void *) D.15413;
  struct MonoMethod * method;
  struct MonoJitInfo * ji;

  D.15402 = info->inside_critical_region;
  if (D.15402 != 0) goto <D.15403>; else goto <D.15404>;
  <D.15403>:
  D.15405 = 1;
  return D.15405;
  <D.15404>:
  D.15406 = info->suspend_state.unwind_data[0];
  if (D.15406 == 0B) goto <D.15407>; else goto <D.15408>;
  <D.15407>:
  D.15405 = 0;
  return D.15405;
  <D.15408>:
  D.15406 = info->suspend_state.unwind_data[0];
  D.15409 = info->suspend_state.ctx.pc;
  D.15410 = (char *) D.15409;
  ji = mono_jit_info_table_find (D.15406, D.15410);
  if (ji == 0B) goto <D.15411>; else goto <D.15412>;
  <D.15411>:
  D.15405 = 0;
  return D.15405;
  <D.15412>:
  method = mono_jit_info_get_method (ji);
  D.15413 = threads_callbacks.mono_method_is_critical;
  D.15405 = D.15413 (method);
  return D.15405;
}


mono_thread_info_setup_async_call (struct MonoThreadInfo * info, void (*<Tc1>) (void *) target_func, void * user_data)
{
  int D.15415;
  _Bool D.15416;
  long int D.15417;
  long int D.15418;
  void (*<Tc1>) (void *) D.15421;
  _Bool D.15422;
  long int D.15423;
  long int D.15424;

  D.15415 = info->suspend_count;
  D.15416 = D.15415 == 0;
  D.15417 = (long int) D.15416;
  D.15418 = __builtin_expect (D.15417, 0);
  if (D.15418 != 0) goto <D.15419>; else goto <D.15420>;
  <D.15419>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 577, "info->suspend_count");
  <D.15420>:
  D.15421 = info->async_target;
  D.15422 = D.15421 != 0B;
  D.15423 = (long int) D.15422;
  D.15424 = __builtin_expect (D.15423, 0);
  if (D.15424 != 0) goto <D.15425>; else goto <D.15426>;
  <D.15425>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 579, "!info->async_target");
  <D.15426>:
  info->async_target = target_func;
  info->user_data = user_data;
}


mono_thread_info_suspend_lock ()
{
  int D.15427;

  goto <D.15104>;
  <D.15103>:
  <D.15104>:
  D.15427 = mono_sem_wait (&global_suspend_semaphore, 0);
  if (D.15427 != 0) goto <D.15103>; else goto <D.15105>;
  <D.15105>:
}


mono_thread_info_suspend_unlock ()
{
  mono_sem_post (&global_suspend_semaphore);
}


mono_thread_info_disable_new_interrupt (gboolean disable)
{
  disable_new_interrupt = disable;
}


mono_thread_info_abort_socket_syscall_for_close (MonoNativeThreadId tid)
{
  long unsigned int D.15430;
  int D.15432;
  int D.15435;
  int D.15436;
  struct MonoThreadHazardPointers * hp;
  struct MonoThreadInfo * info;

  D.15430 = mono_native_thread_id_get ();
  if (D.15430 == tid) goto <D.15428>; else goto <D.15431>;
  <D.15431>:
  D.15432 = mono_threads_core_needs_abort_syscall ();
  if (D.15432 == 0) goto <D.15428>; else goto <D.15429>;
  <D.15428>:
  return;
  <D.15429>:
  hp = mono_hazard_pointer_get ();
  info = mono_thread_info_lookup (tid);
  if (info == 0B) goto <D.15433>; else goto <D.15434>;
  <D.15433>:
  return;
  <D.15434>:
  D.15435 = info->thread_state;
  D.15436 = D.15435 & 15;
  if (D.15436 > 1) goto <D.15437>; else goto <D.15438>;
  <D.15437>:
  if (0 != 0) goto <D.15439>; else goto <D.15440>;
  <D.15439>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 633, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.15440>:
  hp->hazard_pointers[1] = 0B;
  return;
  <D.15438>:
  mono_thread_info_suspend_lock ();
  mono_threads_core_abort_syscall (info);
  if (0 != 0) goto <D.15441>; else goto <D.15442>;
  <D.15441>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 641, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.15442>:
  hp->hazard_pointers[1] = 0B;
  mono_thread_info_suspend_unlock ();
}


mono_thread_info_new_interrupt_enabled ()
{
  gboolean D.15444;

  D.15444 = 0;
  return D.15444;
}


mono_thread_info_set_is_async_context (gboolean async_context)
{
  struct MonoThreadInfo * info;

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


mono_thread_info_is_async_context ()
{
  gboolean D.15450;
  struct MonoThreadInfo * info;

  info = mono_thread_info_current ();
  if (info != 0B) goto <D.15448>; else goto <D.15449>;
  <D.15448>:
  D.15450 = info->is_async_context;
  return D.15450;
  <D.15449>:
  D.15450 = 0;
  return D.15450;
}


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

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


