mono_thread_info_lookup (MonoNativeThreadId id)
{
  int D.12555;
  struct MonoThreadInfo * D.12558;
  struct MonoThreadHazardPointers * hp;

  hp = mono_hazard_pointer_get ();
  D.12555 = mono_lls_find (&thread_list, hp, id);
  if (D.12555 == 0) goto <D.12556>; else goto <D.12557>;
  <D.12556>:
  mono_hazard_pointer_clear_all (hp, -1);
  D.12558 = 0B;
  return D.12558;
  <D.12557>:
  mono_hazard_pointer_clear_all (hp, 1);
  D.12558 = hp->hazard_pointers[1];
  return D.12558;
}


mono_hazard_pointer_clear_all (struct MonoThreadHazardPointers * hp, int retain)
{
  if (retain != 0) goto <D.12560>; else goto <D.12561>;
  <D.12560>:
  if (0 != 0) goto <D.12562>; else goto <D.12563>;
  <D.12562>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 58, "(0) >= 0 && (0) < HAZARD_POINTER_COUNT");
  <D.12563>:
  hp->hazard_pointers[0] = 0B;
  <D.12561>:
  if (retain != 1) goto <D.12564>; else goto <D.12565>;
  <D.12564>:
  if (0 != 0) goto <D.12566>; else goto <D.12567>;
  <D.12566>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 60, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.12567>:
  hp->hazard_pointers[1] = 0B;
  <D.12565>:
  if (retain != 2) goto <D.12568>; else goto <D.12569>;
  <D.12568>:
  if (0 != 0) goto <D.12570>; else goto <D.12571>;
  <D.12570>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 62, "(2) >= 0 && (2) < HAZARD_POINTER_COUNT");
  <D.12571>:
  hp->hazard_pointers[2] = 0B;
  <D.12569>:
}


mono_thread_info_register_small_id ()
{
  unsigned int small_id_key.0;
  int D.12573;
  void * D.12574;
  int D.12575;
  int small_id;

  small_id = mono_thread_small_id_alloc ();
  small_id_key.0 = small_id_key;
  D.12573 = small_id + 1;
  D.12574 = (void *) D.12573;
  mono_native_tls_set_value (small_id_key.0, D.12574);
  D.12575 = small_id;
  return D.12575;
}


mono_native_tls_set_value (pthread_key_t key, void * value)
{
  int D.12577;
  int D.12578;
  _Bool D.12579;

  D.12578 = pthread_setspecific (key, value);
  D.12579 = D.12578 == 0;
  D.12577 = (int) D.12579;
  return D.12577;
}


mono_thread_info_current ()
{
  unsigned int thread_info_key.1;
  struct MonoThreadInfo * D.12584;
  long unsigned int D.12585;
  _Bool D.12586;
  long int D.12587;
  long int D.12588;
  struct MonoThreadHazardPointers * D.12593;
  struct MonoThreadInfo * info;

  thread_info_key.1 = thread_info_key;
  info = pthread_getspecific (thread_info_key.1);
  if (info != 0B) goto <D.12582>; else goto <D.12583>;
  <D.12582>:
  D.12584 = info;
  return D.12584;
  <D.12583>:
  D.12585 = mono_native_thread_id_get ();
  info = mono_thread_info_lookup (D.12585);
  D.12586 = info == 0B;
  D.12587 = (long int) D.12586;
  D.12588 = __builtin_expect (D.12587, 0);
  if (D.12588 != 0) goto <D.12589>; else goto <D.12590>;
  <D.12589>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 242, "info");
  <D.12590>:
  if (0 != 0) goto <D.12591>; else goto <D.12592>;
  <D.12591>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 245, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.12592>:
  D.12593 = mono_hazard_pointer_get ();
  D.12593->hazard_pointers[1] = 0B;
  D.12584 = info;
  return D.12584;
}


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

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


mono_thread_info_list_head ()
{
  struct MonoLinkedListSet * D.12601;

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


mono_thread_info_attach (void * baseptr)
{
  int mono_threads_inited.4;
  struct MonoThreadInfo * D.12606;
  unsigned int thread_info_key.5;
  int thread_info_size.6;
  unsigned int thread_info_size.7;
  void * D.12612;
  void (*<T1b7f>) (struct MonoThreadInfo *) D.12616;
  struct MonoThreadInfo * info;

  mono_threads_inited.4 = mono_threads_inited;
  if (mono_threads_inited.4 == 0) goto <D.12604>; else goto <D.12605>;
  <D.12604>:
  D.12606 = 0B;
  return D.12606;
  <D.12605>:
  thread_info_key.5 = thread_info_key;
  info = pthread_getspecific (thread_info_key.5);
  if (info == 0B) goto <D.12608>; else goto <D.12609>;
  <D.12608>:
  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.12612 = register_thread (info, baseptr);
  if (D.12612 == 0B) goto <D.12613>; else goto <D.12614>;
  <D.12613>:
  D.12606 = 0B;
  return D.12606;
  <D.12614>:
  goto <D.12615>;
  <D.12609>:
  D.12616 = threads_callbacks.thread_attach;
  if (D.12616 != 0B) goto <D.12617>; else goto <D.12618>;
  <D.12617>:
  D.12616 = threads_callbacks.thread_attach;
  D.12616 (info);
  <D.12618>:
  <D.12615>:
  D.12606 = info;
  return D.12606;
}


register_thread (struct MonoThreadInfo * info, void * baseptr)
{
  long unsigned int D.12620;
  unsigned int small_id.8;
  union MonoSemType * D.12622;
  union MonoSemType * D.12623;
  union MonoSemType * D.12624;
  unsigned int thread_info_key.9;
  void * (*<T1b7b>) (struct MonoThreadInfo *, void *) D.12626;
  void * D.12629;
  void * D.12632;
  _Bool D.12633;
  long int D.12634;
  long int D.12635;
  int small_id;
  gboolean result;

  small_id = mono_thread_info_register_small_id ();
  D.12620 = mono_native_thread_id_get ();
  info->node.key = D.12620;
  small_id.8 = (unsigned int) small_id;
  info->small_id = small_id.8;
  D.12622 = &info->suspend_semaphore;
  sem_init (D.12622, 0, 1);
  D.12623 = &info->resume_semaphore;
  sem_init (D.12623, 0, 0);
  D.12624 = &info->finish_resume_semaphore;
  sem_init (D.12624, 0, 0);
  thread_info_key.9 = thread_info_key;
  mono_native_tls_set_value (thread_info_key.9, info);
  D.12626 = threads_callbacks.thread_register;
  if (D.12626 != 0B) goto <D.12627>; else goto <D.12628>;
  <D.12627>:
  D.12626 = threads_callbacks.thread_register;
  D.12629 = D.12626 (info, baseptr);
  if (D.12629 == 0B) goto <D.12630>; else goto <D.12631>;
  <D.12630>:
  monoeg_g_log (0B, 16, "thread registation failed\n");
  monoeg_g_free (info);
  D.12632 = 0B;
  return D.12632;
  <D.12631>:
  <D.12628>:
  mono_threads_platform_register (info);
  info->thread_state = 1;
  mono_thread_info_suspend_lock ();
  result = mono_thread_info_insert (info);
  D.12633 = result == 0;
  D.12634 = (long int) D.12633;
  D.12635 = __builtin_expect (D.12634, 0);
  if (D.12635 != 0) goto <D.12636>; else goto <D.12637>;
  <D.12636>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 159, "result");
  <D.12637>:
  mono_thread_info_suspend_unlock ();
  D.12632 = info;
  return D.12632;
}


mono_thread_info_insert (struct MonoThreadInfo * info)
{
  int D.12639;
  gboolean D.12642;
  struct MonoThreadHazardPointers * hp;

  hp = mono_hazard_pointer_get ();
  D.12639 = mono_lls_insert (&thread_list, hp, info);
  if (D.12639 == 0) goto <D.12640>; else goto <D.12641>;
  <D.12640>:
  mono_hazard_pointer_clear_all (hp, -1);
  D.12642 = 0;
  return D.12642;
  <D.12641>:
  mono_hazard_pointer_clear_all (hp, -1);
  D.12642 = 1;
  return D.12642;
}


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.12645>; else goto <D.12646>;
  <D.12645>:
  return;
  <D.12646>:
  thread_info_key.11 = thread_info_key;
  info = pthread_getspecific (thread_info_key.11);
  if (info != 0B) goto <D.12648>; else goto <D.12649>;
  <D.12648>:
  unregister_thread (info);
  thread_info_key.11 = thread_info_key;
  mono_native_tls_set_value (thread_info_key.11, 0B);
  <D.12649>:
}


unregister_thread (void * arg)
{
  unsigned int D.12651;
  _Bool D.12652;
  long int D.12653;
  long int D.12654;
  unsigned int small_id_key.12;
  unsigned int D.12658;
  void * D.12659;
  void (*<T1b7f>) (struct MonoThreadInfo *) D.12660;
  void (*<T1b7f>) (struct MonoThreadInfo *) D.12663;
  struct MonoThreadInfo * info;
  int small_id;

  info = arg;
  D.12651 = info->small_id;
  small_id = (int) D.12651;
  D.12652 = info == 0B;
  D.12653 = (long int) D.12652;
  D.12654 = __builtin_expect (D.12653, 0);
  if (D.12654 != 0) goto <D.12655>; else goto <D.12656>;
  <D.12655>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 169, "info");
  <D.12656>:
  small_id_key.12 = small_id_key;
  D.12651 = info->small_id;
  D.12658 = D.12651 + 1;
  D.12659 = (void *) D.12658;
  mono_native_tls_set_value (small_id_key.12, D.12659);
  info->thread_state = 2;
  D.12660 = threads_callbacks.thread_detach;
  if (D.12660 != 0B) goto <D.12661>; else goto <D.12662>;
  <D.12661>:
  D.12660 = threads_callbacks.thread_detach;
  D.12660 (info);
  <D.12662>:
  mono_thread_info_suspend_lock ();
  D.12663 = threads_callbacks.thread_unregister;
  if (D.12663 != 0B) goto <D.12664>; else goto <D.12665>;
  <D.12664>:
  D.12663 = threads_callbacks.thread_unregister;
  D.12663 (info);
  <D.12665>:
  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.12666;
  union MonoSemType * D.12667;
  union MonoSemType * D.12668;
  struct MonoThreadInfo * info;

  info = mem;
  D.12666 = &info->suspend_semaphore;
  sem_destroy (D.12666);
  D.12667 = &info->resume_semaphore;
  sem_destroy (D.12667);
  D.12668 = &info->finish_resume_semaphore;
  sem_destroy (D.12668);
  mono_threads_platform_free (info);
  monoeg_g_free (info);
}


mono_threads_unregister_current_thread (struct MonoThreadInfo * info)
{
  unsigned int D.12669;
  long unsigned int D.12670;
  _Bool D.12671;
  long int D.12672;
  long int D.12673;
  _Bool D.12676;
  long int D.12677;
  long int D.12678;
  gboolean result;

  D.12669 = info->node.key;
  D.12670 = mono_native_thread_id_get ();
  D.12671 = D.12669 != D.12670;
  D.12672 = (long int) D.12671;
  D.12673 = __builtin_expect (D.12672, 0);
  if (D.12673 != 0) goto <D.12674>; else goto <D.12675>;
  <D.12674>:
  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.12675>:
  result = mono_thread_info_remove (info);
  D.12676 = result == 0;
  D.12677 = (long int) D.12676;
  D.12678 = __builtin_expect (D.12677, 0);
  if (D.12678 != 0) goto <D.12679>; else goto <D.12680>;
  <D.12679>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 220, "result");
  <D.12680>:
}


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


mono_threads_init (struct MonoThreadInfoCallbacks * callbacks, size_t info_size)
{
  int info_size.13;
  _Bool D.12684;
  long int D.12685;
  long int D.12686;
  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.12684 = res == 0;
  D.12685 = (long int) D.12684;
  D.12686 = __builtin_expect (D.12685, 0);
  if (D.12686 != 0) goto <D.12687>; else goto <D.12688>;
  <D.12687>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 318, "res");
  <D.12688>:
  res = mono_native_tls_alloc (&small_id_key, 0B);
  D.12684 = res == 0;
  D.12685 = (long int) D.12684;
  D.12686 = __builtin_expect (D.12685, 0);
  if (D.12686 != 0) goto <D.12689>; else goto <D.12690>;
  <D.12689>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 321, "res");
  <D.12690>:
  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.12691>; else goto <D.12692>;
  <D.12691>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 335, "sizeof (MonoNativeThreadId) <= sizeof (uintptr_t)");
  <D.12692>:
}


mono_native_tls_alloc (pthread_key_t * key, void * destructor)
{
  int D.12693;
  void (*<Tc3>) (void *) destructor.14;
  int D.12695;
  _Bool D.12696;

  destructor.14 = (void (*<Tc3>) (void *)) destructor;
  D.12695 = pthread_key_create (key, destructor.14);
  D.12696 = D.12695 == 0;
  D.12693 = (int) D.12696;
  return D.12693;
}


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


mono_threads_get_callbacks ()
{
  struct MonoThreadInfoCallbacks * D.12698;

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


mono_threads_get_runtime_callbacks ()
{
  struct MonoThreadInfoRuntimeCallbacks * D.12700;

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


mono_thread_info_self_suspend ()
{
  union MonoSemType * D.12704;
  int D.12705;
  int D.12706;
  _Bool D.12707;
  long int D.12708;
  long int D.12709;
  int D.12712;
  int D.12713;
  int D.12714;
  struct MonoThreadInfoRuntimeCallbacks * D.12715;
  gboolean (*<T1b98>) (struct MonoThreadUnwindState *, void *) D.12716;
  struct MonoThreadUnwindState * D.12717;
  _Bool D.12718;
  long int D.12719;
  long int D.12720;
  union MonoSemType * D.12723;
  int D.12724;
  void (*<Tc3>) (void *) D.12725;
  _Bool D.12726;
  long int D.12727;
  long int D.12728;
  union MonoSemType * D.12731;
  gboolean ret;
  struct MonoThreadInfo * info;

  info = mono_thread_info_current ();
  if (info == 0B) goto <D.12702>; else goto <D.12703>;
  <D.12702>:
  return;
  <D.12703>:
  goto <D.12474>;
  <D.12473>:
  <D.12474>:
  D.12704 = &info->suspend_semaphore;
  D.12705 = mono_sem_wait (D.12704, 0);
  if (D.12705 != 0) goto <D.12473>; else goto <D.12475>;
  <D.12475>:
  D.12706 = info->suspend_count;
  D.12707 = D.12706 != 0;
  D.12708 = (long int) D.12707;
  D.12709 = __builtin_expect (D.12708, 0);
  if (D.12709 != 0) goto <D.12710>; else goto <D.12711>;
  <D.12710>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 413, "info->suspend_count == 0");
  <D.12711>:
  D.12706 = info->suspend_count;
  D.12712 = D.12706 + 1;
  info->suspend_count = D.12712;
  D.12713 = info->thread_state;
  D.12714 = D.12713 | 32;
  info->thread_state = D.12714;
  D.12715 = mono_threads_get_runtime_callbacks ();
  D.12716 = D.12715->thread_state_init_from_sigctx;
  D.12717 = &info->suspend_state;
  ret = D.12716 (D.12717, 0B);
  D.12718 = ret == 0;
  D.12719 = (long int) D.12718;
  D.12720 = __builtin_expect (D.12719, 0);
  if (D.12720 != 0) goto <D.12721>; else goto <D.12722>;
  <D.12721>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 419, "ret");
  <D.12722>:
  D.12704 = &info->suspend_semaphore;
  mono_sem_post (D.12704);
  goto <D.12477>;
  <D.12476>:
  <D.12477>:
  D.12723 = &info->resume_semaphore;
  D.12724 = mono_sem_wait (D.12723, 0);
  if (D.12724 != 0) goto <D.12476>; else goto <D.12478>;
  <D.12478>:
  D.12725 = info->async_target;
  D.12726 = D.12725 != 0B;
  D.12727 = (long int) D.12726;
  D.12728 = __builtin_expect (D.12727, 0);
  if (D.12728 != 0) goto <D.12729>; else goto <D.12730>;
  <D.12729>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 425, "!info->async_target");
  <D.12730>:
  D.12731 = &info->finish_resume_semaphore;
  mono_sem_post (D.12731);
}


mono_thread_info_resume (MonoNativeThreadId tid)
{
  gboolean D.12735;
  union MonoSemType * D.12736;
  int D.12737;
  int D.12738;
  unsigned int D.12743;
  _Bool D.12744;
  long int D.12745;
  long int D.12746;
  int D.12749;
  struct MonoThreadInfo * D.12754;
  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.12733>; else goto <D.12734>;
  <D.12733>:
  D.12735 = 0;
  return D.12735;
  <D.12734>:
  goto <D.12493>;
  <D.12492>:
  <D.12493>:
  D.12736 = &info->suspend_semaphore;
  D.12737 = mono_sem_wait (D.12736, 0);
  if (D.12737 != 0) goto <D.12492>; else goto <D.12494>;
  <D.12494>:
  D.12738 = info->suspend_count;
  if (D.12738 <= 0) goto <D.12739>; else goto <D.12740>;
  <D.12739>:
  D.12736 = &info->suspend_semaphore;
  mono_sem_post (D.12736);
  if (0 != 0) goto <D.12741>; else goto <D.12742>;
  <D.12741>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 459, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.12742>:
  hp->hazard_pointers[1] = 0B;
  D.12735 = 0;
  return D.12735;
  <D.12740>:
  D.12743 = info->node.key;
  D.12744 = D.12743 == 0;
  D.12745 = (long int) D.12744;
  D.12746 = __builtin_expect (D.12745, 0);
  if (D.12746 != 0) goto <D.12747>; else goto <D.12748>;
  <D.12747>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 467, "mono_thread_info_get_tid (info)");
  <D.12748>:
  D.12738 = info->suspend_count;
  D.12749 = D.12738 + -1;
  info->suspend_count = D.12749;
  D.12738 = info->suspend_count;
  if (D.12738 == 0) goto <D.12750>; else goto <D.12751>;
  <D.12750>:
  result = mono_thread_info_resume_internal (info);
  <D.12751>:
  D.12736 = &info->suspend_semaphore;
  mono_sem_post (D.12736);
  if (0 != 0) goto <D.12752>; else goto <D.12753>;
  <D.12752>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 473, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.12753>:
  hp->hazard_pointers[1] = 0B;
  mono_memory_barrier ();
  D.12754 = mono_thread_info_current ();
  D.12754->inside_critical_region = 0;
  D.12735 = result;
  return D.12735;
}


mono_thread_info_resume_internal (struct MonoThreadInfo * info)
{
  int D.12756;
  int D.12757;
  union MonoSemType * D.12760;
  union MonoSemType * D.12761;
  int D.12762;
  int D.12764;
  gboolean D.12765;
  gboolean result;

  D.12756 = info->thread_state;
  D.12757 = D.12756 & 240;
  if (D.12757 == 32) goto <D.12758>; else goto <D.12759>;
  <D.12758>:
  D.12760 = &info->resume_semaphore;
  mono_sem_post (D.12760);
  goto <D.12484>;
  <D.12483>:
  <D.12484>:
  D.12761 = &info->finish_resume_semaphore;
  D.12762 = mono_sem_wait (D.12761, 0);
  if (D.12762 != 0) goto <D.12483>; else goto <D.12485>;
  <D.12485>:
  result = 1;
  goto <D.12763>;
  <D.12759>:
  result = mono_threads_core_resume (info);
  <D.12763>:
  D.12756 = info->thread_state;
  D.12764 = D.12756 & -241;
  info->thread_state = D.12764;
  D.12765 = result;
  return D.12765;
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


mono_thread_info_finish_suspend ()
{
  struct MonoThreadInfo * D.12767;

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


mono_thread_info_safe_suspend_sync (MonoNativeThreadId id, gboolean interrupt_kernel)
{
  long unsigned int D.12768;
  _Bool D.12769;
  long int D.12770;
  long int D.12771;
  void * id.15;
  struct MonoThreadInfo * D.12777;
  int D.12778;
  int D.12780;
  long unsigned int sleep_duration.16;
  struct MonoThreadInfo * D.12787;
  struct MonoThreadInfo * info;
  int sleep_duration;

  info = 0B;
  sleep_duration = 0;
  D.12768 = mono_native_thread_id_get ();
  D.12769 = D.12768 == id;
  D.12770 = (long int) D.12769;
  D.12771 = __builtin_expect (D.12770, 0);
  if (D.12771 != 0) goto <D.12772>; else goto <D.12773>;
  <D.12772>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 527, "id != mono_native_thread_id_get ()");
  <D.12773>:
  mono_thread_info_suspend_lock ();
  <D.12510>:
  info = mono_thread_info_suspend_sync (id, interrupt_kernel);
  if (info == 0B) goto <D.12774>; else goto <D.12775>;
  <D.12774>:
  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.12777 = 0B;
  return D.12777;
  <D.12775>:
  D.12778 = is_thread_in_critical_region (info);
  if (D.12778 == 0) goto <D.12509>; else goto <D.12779>;
  <D.12779>:
  D.12780 = mono_thread_info_resume (id);
  if (D.12780 == 0) goto <D.12781>; else goto <D.12782>;
  <D.12781>:
  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.12777 = 0B;
  return D.12777;
  <D.12782>:
  if (sleep_duration == 0) goto <D.12783>; else goto <D.12784>;
  <D.12783>:
  sched_yield ();
  goto <D.12785>;
  <D.12784>:
  sleep_duration.16 = (long unsigned int) sleep_duration;
  monoeg_g_usleep (sleep_duration.16);
  <D.12785>:
  sleep_duration = sleep_duration + 10;
  goto <D.12510>;
  <D.12509>:
  mono_memory_barrier ();
  D.12787 = mono_thread_info_current ();
  D.12787->inside_critical_region = 1;
  mono_thread_info_suspend_unlock ();
  D.12777 = info;
  return D.12777;
}


mono_thread_info_suspend_sync (MonoNativeThreadId tid, gboolean interrupt_kernel)
{
  struct MonoThreadInfo * D.12791;
  union MonoSemType * D.12792;
  int D.12793;
  int D.12794;
  int D.12795;
  int D.12800;
  int D.12803;
  int D.12806;
  int D.12813;
  struct MonoThreadHazardPointers * hp;
  struct MonoThreadInfo * info;

  hp = mono_hazard_pointer_get ();
  info = mono_thread_info_lookup (tid);
  if (info == 0B) goto <D.12789>; else goto <D.12790>;
  <D.12789>:
  D.12791 = 0B;
  return D.12791;
  <D.12790>:
  goto <D.12466>;
  <D.12465>:
  <D.12466>:
  D.12792 = &info->suspend_semaphore;
  D.12793 = mono_sem_wait (D.12792, 0);
  if (D.12793 != 0) goto <D.12465>; else goto <D.12467>;
  <D.12467>:
  D.12794 = info->thread_state;
  D.12795 = D.12794 & 15;
  if (D.12795 > 1) goto <D.12796>; else goto <D.12797>;
  <D.12796>:
  if (0 != 0) goto <D.12798>; else goto <D.12799>;
  <D.12798>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 371, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.12799>:
  hp->hazard_pointers[1] = 0B;
  D.12791 = 0B;
  return D.12791;
  <D.12797>:
  D.12800 = info->suspend_count;
  if (D.12800 != 0) goto <D.12801>; else goto <D.12802>;
  <D.12801>:
  D.12800 = info->suspend_count;
  D.12803 = D.12800 + 1;
  info->suspend_count = D.12803;
  if (0 != 0) goto <D.12804>; else goto <D.12805>;
  <D.12804>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 379, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.12805>:
  hp->hazard_pointers[1] = 0B;
  D.12792 = &info->suspend_semaphore;
  mono_sem_post (D.12792);
  D.12791 = info;
  return D.12791;
  <D.12802>:
  D.12806 = mono_threads_core_suspend (info);
  if (D.12806 == 0) goto <D.12807>; else goto <D.12808>;
  <D.12807>:
  D.12792 = &info->suspend_semaphore;
  mono_sem_post (D.12792);
  if (0 != 0) goto <D.12809>; else goto <D.12810>;
  <D.12809>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 386, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.12810>:
  hp->hazard_pointers[1] = 0B;
  D.12791 = 0B;
  return D.12791;
  <D.12808>:
  if (interrupt_kernel != 0) goto <D.12811>; else goto <D.12812>;
  <D.12811>:
  mono_threads_core_interrupt (info);
  <D.12812>:
  D.12800 = info->suspend_count;
  D.12803 = D.12800 + 1;
  info->suspend_count = D.12803;
  D.12794 = info->thread_state;
  D.12813 = D.12794 | 16;
  info->thread_state = D.12813;
  D.12792 = &info->suspend_semaphore;
  mono_sem_post (D.12792);
  if (0 != 0) goto <D.12814>; else goto <D.12815>;
  <D.12814>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 396, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.12815>:
  hp->hazard_pointers[1] = 0B;
  D.12791 = info;
  return D.12791;
}


is_thread_in_critical_region (struct MonoThreadInfo * info)
{
  int D.12817;
  gboolean D.12820;
  void * D.12821;
  int D.12824;
  char * D.12825;
  gboolean (*<T1b87>) (void *) D.12828;
  struct MonoMethod * method;
  struct MonoJitInfo * ji;

  D.12817 = info->inside_critical_region;
  if (D.12817 != 0) goto <D.12818>; else goto <D.12819>;
  <D.12818>:
  D.12820 = 1;
  return D.12820;
  <D.12819>:
  D.12821 = info->suspend_state.unwind_data[0];
  if (D.12821 == 0B) goto <D.12822>; else goto <D.12823>;
  <D.12822>:
  D.12820 = 0;
  return D.12820;
  <D.12823>:
  D.12821 = info->suspend_state.unwind_data[0];
  D.12824 = info->suspend_state.ctx.sc_pc;
  D.12825 = (char *) D.12824;
  ji = mono_jit_info_table_find (D.12821, D.12825);
  if (ji == 0B) goto <D.12826>; else goto <D.12827>;
  <D.12826>:
  D.12820 = 0;
  return D.12820;
  <D.12827>:
  method = mono_jit_info_get_method (ji);
  D.12828 = threads_callbacks.mono_method_is_critical;
  D.12820 = D.12828 (method);
  return D.12820;
}


mono_thread_info_setup_async_call (struct MonoThreadInfo * info, void (*<Tc3>) (void *) target_func, void * user_data)
{
  int D.12830;
  _Bool D.12831;
  long int D.12832;
  long int D.12833;
  void (*<Tc3>) (void *) D.12836;
  _Bool D.12837;
  long int D.12838;
  long int D.12839;

  D.12830 = info->suspend_count;
  D.12831 = D.12830 == 0;
  D.12832 = (long int) D.12831;
  D.12833 = __builtin_expect (D.12832, 0);
  if (D.12833 != 0) goto <D.12834>; else goto <D.12835>;
  <D.12834>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 577, "info->suspend_count");
  <D.12835>:
  D.12836 = info->async_target;
  D.12837 = D.12836 != 0B;
  D.12838 = (long int) D.12837;
  D.12839 = __builtin_expect (D.12838, 0);
  if (D.12839 != 0) goto <D.12840>; else goto <D.12841>;
  <D.12840>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 579, "!info->async_target");
  <D.12841>:
  info->async_target = target_func;
  info->user_data = user_data;
}


mono_thread_info_suspend_lock ()
{
  int D.12842;

  goto <D.12521>;
  <D.12520>:
  <D.12521>:
  D.12842 = mono_sem_wait (&global_suspend_semaphore, 0);
  if (D.12842 != 0) goto <D.12520>; else goto <D.12522>;
  <D.12522>:
}


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.12845;
  int D.12847;
  int D.12850;
  int D.12851;
  struct MonoThreadHazardPointers * hp;
  struct MonoThreadInfo * info;

  D.12845 = mono_native_thread_id_get ();
  if (D.12845 == tid) goto <D.12843>; else goto <D.12846>;
  <D.12846>:
  D.12847 = mono_threads_core_needs_abort_syscall ();
  if (D.12847 == 0) goto <D.12843>; else goto <D.12844>;
  <D.12843>:
  return;
  <D.12844>:
  hp = mono_hazard_pointer_get ();
  info = mono_thread_info_lookup (tid);
  if (info == 0B) goto <D.12848>; else goto <D.12849>;
  <D.12848>:
  return;
  <D.12849>:
  D.12850 = info->thread_state;
  D.12851 = D.12850 & 15;
  if (D.12851 > 1) goto <D.12852>; else goto <D.12853>;
  <D.12852>:
  if (0 != 0) goto <D.12854>; else goto <D.12855>;
  <D.12854>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 633, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.12855>:
  hp->hazard_pointers[1] = 0B;
  return;
  <D.12853>:
  mono_thread_info_suspend_lock ();
  mono_threads_core_abort_syscall (info);
  if (0 != 0) goto <D.12856>; else goto <D.12857>;
  <D.12856>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 641, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.12857>:
  hp->hazard_pointers[1] = 0B;
  mono_thread_info_suspend_unlock ();
}


mono_thread_info_new_interrupt_enabled ()
{
  gboolean D.12859;

  D.12859 = 0;
  return D.12859;
}


mono_thread_info_set_is_async_context (gboolean async_context)
{
  struct MonoThreadInfo * info;

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


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

  info = mono_thread_info_current ();
  if (info != 0B) goto <D.12863>; else goto <D.12864>;
  <D.12863>:
  D.12865 = info->is_async_context;
  return D.12865;
  <D.12864>:
  D.12865 = 0;
  return D.12865;
}


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.12870;
  void * res;
  gsize real_tid;

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


