mono_thread_info_lookup (MonoNativeThreadId id)
{
  int D.12589;
  struct MonoThreadInfo * D.12592;
  struct MonoThreadHazardPointers * hp;

  hp = mono_hazard_pointer_get ();
  D.12589 = mono_lls_find (&thread_list, hp, id);
  if (D.12589 == 0) goto <D.12590>; else goto <D.12591>;
  <D.12590>:
  mono_hazard_pointer_clear_all (hp, -1);
  D.12592 = 0B;
  return D.12592;
  <D.12591>:
  mono_hazard_pointer_clear_all (hp, 1);
  D.12592 = hp->hazard_pointers[1];
  return D.12592;
}


mono_hazard_pointer_clear_all (struct MonoThreadHazardPointers * hp, int retain)
{
  if (retain != 0) goto <D.12594>; else goto <D.12595>;
  <D.12594>:
  if (0 != 0) goto <D.12596>; else goto <D.12597>;
  <D.12596>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 58, "(0) >= 0 && (0) < HAZARD_POINTER_COUNT");
  <D.12597>:
  hp->hazard_pointers[0] = 0B;
  <D.12595>:
  if (retain != 1) goto <D.12598>; else goto <D.12599>;
  <D.12598>:
  if (0 != 0) goto <D.12600>; else goto <D.12601>;
  <D.12600>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 60, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.12601>:
  hp->hazard_pointers[1] = 0B;
  <D.12599>:
  if (retain != 2) goto <D.12602>; else goto <D.12603>;
  <D.12602>:
  if (0 != 0) goto <D.12604>; else goto <D.12605>;
  <D.12604>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 62, "(2) >= 0 && (2) < HAZARD_POINTER_COUNT");
  <D.12605>:
  hp->hazard_pointers[2] = 0B;
  <D.12603>:
}


mono_thread_info_register_small_id ()
{
  int D.12606;
  void * D.12607;
  unsigned int small_id_key.0;
  int D.12609;
  int small_id;

  small_id = mono_thread_small_id_alloc ();
  D.12606 = small_id + 1;
  D.12607 = (void *) D.12606;
  small_id_key.0 = small_id_key;
  mono_native_tls_set_value (small_id_key.0, D.12607);
  D.12609 = small_id;
  return D.12609;
}


mono_native_tls_set_value (pthread_key_t key, void * value)
{
  int D.12611;
  int D.12612;
  _Bool D.12613;

  D.12612 = pthread_setspecific (key, value);
  D.12613 = D.12612 == 0;
  D.12611 = (int) D.12613;
  return D.12611;
}


mono_thread_info_current ()
{
  unsigned int thread_info_key.1;
  struct MonoThreadInfo * D.12618;
  long unsigned int D.12619;
  _Bool D.12620;
  long int D.12621;
  long int D.12622;
  struct MonoThreadHazardPointers * D.12627;
  struct MonoThreadInfo * info;

  thread_info_key.1 = thread_info_key;
  info = pthread_getspecific (thread_info_key.1);
  if (info != 0B) goto <D.12616>; else goto <D.12617>;
  <D.12616>:
  D.12618 = info;
  return D.12618;
  <D.12617>:
  D.12619 = mono_native_thread_id_get ();
  info = mono_thread_info_lookup (D.12619);
  D.12620 = info == 0B;
  D.12621 = (long int) D.12620;
  D.12622 = __builtin_expect (D.12621, 0);
  if (D.12622 != 0) goto <D.12623>; else goto <D.12624>;
  <D.12623>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 242, "info");
  <D.12624>:
  if (0 != 0) goto <D.12625>; else goto <D.12626>;
  <D.12625>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 245, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.12626>:
  D.12627 = mono_hazard_pointer_get ();
  D.12627->hazard_pointers[1] = 0B;
  D.12618 = info;
  return D.12618;
}


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

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


mono_thread_info_list_head ()
{
  struct MonoLinkedListSet * D.12635;

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


mono_thread_info_attach (void * baseptr)
{
  int mono_threads_inited.4;
  struct MonoThreadInfo * D.12640;
  unsigned int thread_info_key.5;
  int thread_info_size.6;
  unsigned int thread_info_size.7;
  void * D.12646;
  void (*<T1b82>) (struct MonoThreadInfo *) D.12650;
  struct MonoThreadInfo * info;

  mono_threads_inited.4 = mono_threads_inited;
  if (mono_threads_inited.4 == 0) goto <D.12638>; else goto <D.12639>;
  <D.12638>:
  D.12640 = 0B;
  return D.12640;
  <D.12639>:
  thread_info_key.5 = thread_info_key;
  info = pthread_getspecific (thread_info_key.5);
  if (info == 0B) goto <D.12642>; else goto <D.12643>;
  <D.12642>:
  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.12646 = register_thread (info, baseptr);
  if (D.12646 == 0B) goto <D.12647>; else goto <D.12648>;
  <D.12647>:
  D.12640 = 0B;
  return D.12640;
  <D.12648>:
  goto <D.12649>;
  <D.12643>:
  D.12650 = threads_callbacks.thread_attach;
  if (D.12650 != 0B) goto <D.12651>; else goto <D.12652>;
  <D.12651>:
  D.12650 = threads_callbacks.thread_attach;
  D.12650 (info);
  <D.12652>:
  <D.12649>:
  D.12640 = info;
  return D.12640;
}


register_thread (struct MonoThreadInfo * info, void * baseptr)
{
  long unsigned int D.12654;
  unsigned int small_id.8;
  union MonoSemType * D.12656;
  union MonoSemType * D.12657;
  union MonoSemType * D.12658;
  unsigned int thread_info_key.9;
  void * (*<T1b7e>) (struct MonoThreadInfo *, void *) D.12660;
  void * D.12663;
  void * D.12666;
  _Bool D.12667;
  long int D.12668;
  long int D.12669;
  int small_id;
  gboolean result;

  small_id = mono_thread_info_register_small_id ();
  D.12654 = mono_native_thread_id_get ();
  info->node.key = D.12654;
  small_id.8 = (unsigned int) small_id;
  info->small_id = small_id.8;
  D.12656 = &info->suspend_semaphore;
  sem_init (D.12656, 0, 1);
  D.12657 = &info->resume_semaphore;
  sem_init (D.12657, 0, 0);
  D.12658 = &info->finish_resume_semaphore;
  sem_init (D.12658, 0, 0);
  thread_info_key.9 = thread_info_key;
  mono_native_tls_set_value (thread_info_key.9, info);
  D.12660 = threads_callbacks.thread_register;
  if (D.12660 != 0B) goto <D.12661>; else goto <D.12662>;
  <D.12661>:
  D.12660 = threads_callbacks.thread_register;
  D.12663 = D.12660 (info, baseptr);
  if (D.12663 == 0B) goto <D.12664>; else goto <D.12665>;
  <D.12664>:
  monoeg_g_log (0B, 16, "thread registation failed\n");
  monoeg_g_free (info);
  D.12666 = 0B;
  return D.12666;
  <D.12665>:
  <D.12662>:
  mono_threads_platform_register (info);
  info->thread_state = 1;
  mono_thread_info_suspend_lock ();
  result = mono_thread_info_insert (info);
  D.12667 = result == 0;
  D.12668 = (long int) D.12667;
  D.12669 = __builtin_expect (D.12668, 0);
  if (D.12669 != 0) goto <D.12670>; else goto <D.12671>;
  <D.12670>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 159, "result");
  <D.12671>:
  mono_thread_info_suspend_unlock ();
  D.12666 = info;
  return D.12666;
}


mono_thread_info_insert (struct MonoThreadInfo * info)
{
  int D.12673;
  gboolean D.12676;
  struct MonoThreadHazardPointers * hp;

  hp = mono_hazard_pointer_get ();
  D.12673 = mono_lls_insert (&thread_list, hp, info);
  if (D.12673 == 0) goto <D.12674>; else goto <D.12675>;
  <D.12674>:
  mono_hazard_pointer_clear_all (hp, -1);
  D.12676 = 0;
  return D.12676;
  <D.12675>:
  mono_hazard_pointer_clear_all (hp, -1);
  D.12676 = 1;
  return D.12676;
}


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.12679>; else goto <D.12680>;
  <D.12679>:
  return;
  <D.12680>:
  thread_info_key.11 = thread_info_key;
  info = pthread_getspecific (thread_info_key.11);
  if (info != 0B) goto <D.12682>; else goto <D.12683>;
  <D.12682>:
  unregister_thread (info);
  thread_info_key.11 = thread_info_key;
  mono_native_tls_set_value (thread_info_key.11, 0B);
  <D.12683>:
}


unregister_thread (void * arg)
{
  unsigned int D.12685;
  _Bool D.12686;
  long int D.12687;
  long int D.12688;
  unsigned int D.12691;
  void * D.12692;
  unsigned int small_id_key.12;
  void (*<T1b82>) (struct MonoThreadInfo *) D.12694;
  void (*<T1b82>) (struct MonoThreadInfo *) D.12697;
  struct MonoThreadInfo * info;
  int small_id;

  info = arg;
  D.12685 = info->small_id;
  small_id = (int) D.12685;
  D.12686 = info == 0B;
  D.12687 = (long int) D.12686;
  D.12688 = __builtin_expect (D.12687, 0);
  if (D.12688 != 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", 169, "info");
  <D.12690>:
  D.12685 = info->small_id;
  D.12691 = D.12685 + 1;
  D.12692 = (void *) D.12691;
  small_id_key.12 = small_id_key;
  mono_native_tls_set_value (small_id_key.12, D.12692);
  info->thread_state = 2;
  D.12694 = threads_callbacks.thread_detach;
  if (D.12694 != 0B) goto <D.12695>; else goto <D.12696>;
  <D.12695>:
  D.12694 = threads_callbacks.thread_detach;
  D.12694 (info);
  <D.12696>:
  mono_thread_info_suspend_lock ();
  D.12697 = threads_callbacks.thread_unregister;
  if (D.12697 != 0B) goto <D.12698>; else goto <D.12699>;
  <D.12698>:
  D.12697 = threads_callbacks.thread_unregister;
  D.12697 (info);
  <D.12699>:
  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.12700;
  union MonoSemType * D.12701;
  union MonoSemType * D.12702;
  struct MonoThreadInfo * info;

  info = mem;
  D.12700 = &info->suspend_semaphore;
  sem_destroy (D.12700);
  D.12701 = &info->resume_semaphore;
  sem_destroy (D.12701);
  D.12702 = &info->finish_resume_semaphore;
  sem_destroy (D.12702);
  mono_threads_platform_free (info);
  monoeg_g_free (info);
}


mono_threads_unregister_current_thread (struct MonoThreadInfo * info)
{
  unsigned int D.12703;
  long unsigned int D.12704;
  _Bool D.12705;
  long int D.12706;
  long int D.12707;
  _Bool D.12710;
  long int D.12711;
  long int D.12712;
  gboolean result;

  D.12703 = info->node.key;
  D.12704 = mono_native_thread_id_get ();
  D.12705 = D.12703 != D.12704;
  D.12706 = (long int) D.12705;
  D.12707 = __builtin_expect (D.12706, 0);
  if (D.12707 != 0) goto <D.12708>; else goto <D.12709>;
  <D.12708>:
  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.12709>:
  result = mono_thread_info_remove (info);
  D.12710 = result == 0;
  D.12711 = (long int) D.12710;
  D.12712 = __builtin_expect (D.12711, 0);
  if (D.12712 != 0) goto <D.12713>; else goto <D.12714>;
  <D.12713>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 220, "result");
  <D.12714>:
}


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


mono_threads_init (struct MonoThreadInfoCallbacks * callbacks, size_t info_size)
{
  int info_size.13;
  _Bool D.12718;
  long int D.12719;
  long int D.12720;
  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.12718 = res == 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", 318, "res");
  <D.12722>:
  res = mono_native_tls_alloc (&small_id_key, 0B);
  D.12718 = res == 0;
  D.12719 = (long int) D.12718;
  D.12720 = __builtin_expect (D.12719, 0);
  if (D.12720 != 0) goto <D.12723>; else goto <D.12724>;
  <D.12723>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 321, "res");
  <D.12724>:
  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.12725>; else goto <D.12726>;
  <D.12725>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 335, "sizeof (MonoNativeThreadId) <= sizeof (uintptr_t)");
  <D.12726>:
}


mono_native_tls_alloc (pthread_key_t * key, void * destructor)
{
  int D.12727;
  void (*<Tbf>) (void *) destructor.14;
  int D.12729;
  _Bool D.12730;

  destructor.14 = (void (*<Tbf>) (void *)) destructor;
  D.12729 = pthread_key_create (key, destructor.14);
  D.12730 = D.12729 == 0;
  D.12727 = (int) D.12730;
  return D.12727;
}


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


mono_threads_get_callbacks ()
{
  struct MonoThreadInfoCallbacks * D.12732;

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


mono_threads_get_runtime_callbacks ()
{
  struct MonoThreadInfoRuntimeCallbacks * D.12734;

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


mono_thread_info_self_suspend ()
{
  union MonoSemType * D.12738;
  int D.12739;
  int D.12740;
  _Bool D.12741;
  long int D.12742;
  long int D.12743;
  int D.12746;
  int D.12747;
  int D.12748;
  struct MonoThreadInfoRuntimeCallbacks * D.12749;
  gboolean (*<T1b9b>) (struct MonoThreadUnwindState *, void *) D.12750;
  struct MonoThreadUnwindState * D.12751;
  _Bool D.12752;
  long int D.12753;
  long int D.12754;
  union MonoSemType * D.12757;
  int D.12758;
  void (*<Tbf>) (void *) D.12759;
  _Bool D.12760;
  long int D.12761;
  long int D.12762;
  union MonoSemType * D.12765;
  gboolean ret;
  struct MonoThreadInfo * info;

  info = mono_thread_info_current ();
  if (info == 0B) goto <D.12736>; else goto <D.12737>;
  <D.12736>:
  return;
  <D.12737>:
  goto <D.12508>;
  <D.12507>:
  <D.12508>:
  D.12738 = &info->suspend_semaphore;
  D.12739 = mono_sem_wait (D.12738, 0);
  if (D.12739 != 0) goto <D.12507>; else goto <D.12509>;
  <D.12509>:
  D.12740 = info->suspend_count;
  D.12741 = D.12740 != 0;
  D.12742 = (long int) D.12741;
  D.12743 = __builtin_expect (D.12742, 0);
  if (D.12743 != 0) goto <D.12744>; else goto <D.12745>;
  <D.12744>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 413, "info->suspend_count == 0");
  <D.12745>:
  D.12740 = info->suspend_count;
  D.12746 = D.12740 + 1;
  info->suspend_count = D.12746;
  D.12747 = info->thread_state;
  D.12748 = D.12747 | 32;
  info->thread_state = D.12748;
  D.12749 = mono_threads_get_runtime_callbacks ();
  D.12750 = D.12749->thread_state_init_from_sigctx;
  D.12751 = &info->suspend_state;
  ret = D.12750 (D.12751, 0B);
  D.12752 = ret == 0;
  D.12753 = (long int) D.12752;
  D.12754 = __builtin_expect (D.12753, 0);
  if (D.12754 != 0) goto <D.12755>; else goto <D.12756>;
  <D.12755>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 419, "ret");
  <D.12756>:
  D.12738 = &info->suspend_semaphore;
  mono_sem_post (D.12738);
  goto <D.12511>;
  <D.12510>:
  <D.12511>:
  D.12757 = &info->resume_semaphore;
  D.12758 = mono_sem_wait (D.12757, 0);
  if (D.12758 != 0) goto <D.12510>; else goto <D.12512>;
  <D.12512>:
  D.12759 = info->async_target;
  D.12760 = D.12759 != 0B;
  D.12761 = (long int) D.12760;
  D.12762 = __builtin_expect (D.12761, 0);
  if (D.12762 != 0) goto <D.12763>; else goto <D.12764>;
  <D.12763>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 425, "!info->async_target");
  <D.12764>:
  D.12765 = &info->finish_resume_semaphore;
  mono_sem_post (D.12765);
}


mono_thread_info_resume (MonoNativeThreadId tid)
{
  gboolean D.12769;
  union MonoSemType * D.12770;
  int D.12771;
  int D.12772;
  unsigned int D.12777;
  _Bool D.12778;
  long int D.12779;
  long int D.12780;
  int D.12783;
  struct MonoThreadInfo * D.12788;
  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.12767>; else goto <D.12768>;
  <D.12767>:
  D.12769 = 0;
  return D.12769;
  <D.12768>:
  goto <D.12527>;
  <D.12526>:
  <D.12527>:
  D.12770 = &info->suspend_semaphore;
  D.12771 = mono_sem_wait (D.12770, 0);
  if (D.12771 != 0) goto <D.12526>; else goto <D.12528>;
  <D.12528>:
  D.12772 = info->suspend_count;
  if (D.12772 <= 0) goto <D.12773>; else goto <D.12774>;
  <D.12773>:
  D.12770 = &info->suspend_semaphore;
  mono_sem_post (D.12770);
  if (0 != 0) goto <D.12775>; else goto <D.12776>;
  <D.12775>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 459, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.12776>:
  hp->hazard_pointers[1] = 0B;
  D.12769 = 0;
  return D.12769;
  <D.12774>:
  D.12777 = info->node.key;
  D.12778 = D.12777 == 0;
  D.12779 = (long int) D.12778;
  D.12780 = __builtin_expect (D.12779, 0);
  if (D.12780 != 0) goto <D.12781>; else goto <D.12782>;
  <D.12781>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 467, "mono_thread_info_get_tid (info)");
  <D.12782>:
  D.12772 = info->suspend_count;
  D.12783 = D.12772 + -1;
  info->suspend_count = D.12783;
  D.12772 = info->suspend_count;
  if (D.12772 == 0) goto <D.12784>; else goto <D.12785>;
  <D.12784>:
  result = mono_thread_info_resume_internal (info);
  <D.12785>:
  D.12770 = &info->suspend_semaphore;
  mono_sem_post (D.12770);
  if (0 != 0) goto <D.12786>; else goto <D.12787>;
  <D.12786>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 473, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.12787>:
  hp->hazard_pointers[1] = 0B;
  D.12788 = mono_thread_info_current ();
  D.12788->inside_critical_region = 0;
  D.12769 = result;
  return D.12769;
}


mono_thread_info_resume_internal (struct MonoThreadInfo * info)
{
  int D.12790;
  int D.12791;
  union MonoSemType * D.12794;
  union MonoSemType * D.12795;
  int D.12796;
  int D.12798;
  gboolean D.12799;
  gboolean result;

  D.12790 = info->thread_state;
  D.12791 = D.12790 & 240;
  if (D.12791 == 32) goto <D.12792>; else goto <D.12793>;
  <D.12792>:
  D.12794 = &info->resume_semaphore;
  mono_sem_post (D.12794);
  goto <D.12518>;
  <D.12517>:
  <D.12518>:
  D.12795 = &info->finish_resume_semaphore;
  D.12796 = mono_sem_wait (D.12795, 0);
  if (D.12796 != 0) goto <D.12517>; else goto <D.12519>;
  <D.12519>:
  result = 1;
  goto <D.12797>;
  <D.12793>:
  result = mono_threads_core_resume (info);
  <D.12797>:
  D.12790 = info->thread_state;
  D.12798 = D.12790 & -241;
  info->thread_state = D.12798;
  D.12799 = result;
  return D.12799;
}


mono_thread_info_finish_suspend ()
{
  struct MonoThreadInfo * D.12801;

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


mono_thread_info_safe_suspend_sync (MonoNativeThreadId id, gboolean interrupt_kernel)
{
  long unsigned int D.12802;
  _Bool D.12803;
  long int D.12804;
  long int D.12805;
  void * id.15;
  struct MonoThreadInfo * D.12811;
  int D.12812;
  int D.12814;
  long unsigned int sleep_duration.16;
  struct MonoThreadInfo * D.12821;
  struct MonoThreadInfo * info;
  int sleep_duration;

  info = 0B;
  sleep_duration = 0;
  D.12802 = mono_native_thread_id_get ();
  D.12803 = D.12802 == id;
  D.12804 = (long int) D.12803;
  D.12805 = __builtin_expect (D.12804, 0);
  if (D.12805 != 0) goto <D.12806>; else goto <D.12807>;
  <D.12806>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 527, "id != mono_native_thread_id_get ()");
  <D.12807>:
  mono_thread_info_suspend_lock ();
  <D.12544>:
  info = mono_thread_info_suspend_sync (id, interrupt_kernel);
  if (info == 0B) goto <D.12808>; else goto <D.12809>;
  <D.12808>:
  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.12811 = 0B;
  return D.12811;
  <D.12809>:
  D.12812 = is_thread_in_critical_region (info);
  if (D.12812 == 0) goto <D.12543>; else goto <D.12813>;
  <D.12813>:
  D.12814 = mono_thread_info_resume (id);
  if (D.12814 == 0) goto <D.12815>; else goto <D.12816>;
  <D.12815>:
  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.12811 = 0B;
  return D.12811;
  <D.12816>:
  if (sleep_duration == 0) goto <D.12817>; else goto <D.12818>;
  <D.12817>:
  sched_yield ();
  goto <D.12819>;
  <D.12818>:
  sleep_duration.16 = (long unsigned int) sleep_duration;
  monoeg_g_usleep (sleep_duration.16);
  <D.12819>:
  sleep_duration = sleep_duration + 10;
  goto <D.12544>;
  <D.12543>:
  D.12821 = mono_thread_info_current ();
  D.12821->inside_critical_region = 1;
  mono_thread_info_suspend_unlock ();
  D.12811 = info;
  return D.12811;
}


mono_thread_info_suspend_sync (MonoNativeThreadId tid, gboolean interrupt_kernel)
{
  struct MonoThreadInfo * D.12825;
  union MonoSemType * D.12826;
  int D.12827;
  int D.12828;
  int D.12829;
  int D.12834;
  int D.12837;
  int D.12840;
  int D.12847;
  struct MonoThreadHazardPointers * hp;
  struct MonoThreadInfo * info;

  hp = mono_hazard_pointer_get ();
  info = mono_thread_info_lookup (tid);
  if (info == 0B) goto <D.12823>; else goto <D.12824>;
  <D.12823>:
  D.12825 = 0B;
  return D.12825;
  <D.12824>:
  goto <D.12500>;
  <D.12499>:
  <D.12500>:
  D.12826 = &info->suspend_semaphore;
  D.12827 = mono_sem_wait (D.12826, 0);
  if (D.12827 != 0) goto <D.12499>; else goto <D.12501>;
  <D.12501>:
  D.12828 = info->thread_state;
  D.12829 = D.12828 & 15;
  if (D.12829 > 1) goto <D.12830>; else goto <D.12831>;
  <D.12830>:
  if (0 != 0) goto <D.12832>; else goto <D.12833>;
  <D.12832>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 371, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.12833>:
  hp->hazard_pointers[1] = 0B;
  D.12825 = 0B;
  return D.12825;
  <D.12831>:
  D.12834 = info->suspend_count;
  if (D.12834 != 0) goto <D.12835>; else goto <D.12836>;
  <D.12835>:
  D.12834 = info->suspend_count;
  D.12837 = D.12834 + 1;
  info->suspend_count = D.12837;
  if (0 != 0) goto <D.12838>; else goto <D.12839>;
  <D.12838>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 379, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.12839>:
  hp->hazard_pointers[1] = 0B;
  D.12826 = &info->suspend_semaphore;
  mono_sem_post (D.12826);
  D.12825 = info;
  return D.12825;
  <D.12836>:
  D.12840 = mono_threads_core_suspend (info);
  if (D.12840 == 0) goto <D.12841>; else goto <D.12842>;
  <D.12841>:
  D.12826 = &info->suspend_semaphore;
  mono_sem_post (D.12826);
  if (0 != 0) goto <D.12843>; else goto <D.12844>;
  <D.12843>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 386, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.12844>:
  hp->hazard_pointers[1] = 0B;
  D.12825 = 0B;
  return D.12825;
  <D.12842>:
  if (interrupt_kernel != 0) goto <D.12845>; else goto <D.12846>;
  <D.12845>:
  mono_threads_core_interrupt (info);
  <D.12846>:
  D.12834 = info->suspend_count;
  D.12837 = D.12834 + 1;
  info->suspend_count = D.12837;
  D.12828 = info->thread_state;
  D.12847 = D.12828 | 16;
  info->thread_state = D.12847;
  D.12826 = &info->suspend_semaphore;
  mono_sem_post (D.12826);
  if (0 != 0) goto <D.12848>; else goto <D.12849>;
  <D.12848>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 396, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.12849>:
  hp->hazard_pointers[1] = 0B;
  D.12825 = info;
  return D.12825;
}


is_thread_in_critical_region (struct MonoThreadInfo * info)
{
  int D.12851;
  gboolean D.12854;
  void * D.12855;
  int D.12858;
  char * D.12859;
  gboolean (*<T1b8a>) (void *) D.12862;
  struct MonoMethod * method;
  struct MonoJitInfo * ji;

  D.12851 = info->inside_critical_region;
  if (D.12851 != 0) goto <D.12852>; else goto <D.12853>;
  <D.12852>:
  D.12854 = 1;
  return D.12854;
  <D.12853>:
  D.12855 = info->suspend_state.unwind_data[0];
  if (D.12855 == 0B) goto <D.12856>; else goto <D.12857>;
  <D.12856>:
  D.12854 = 0;
  return D.12854;
  <D.12857>:
  D.12858 = info->suspend_state.ctx.eip;
  D.12859 = (char *) D.12858;
  D.12855 = info->suspend_state.unwind_data[0];
  ji = mono_jit_info_table_find (D.12855, D.12859);
  if (ji == 0B) goto <D.12860>; else goto <D.12861>;
  <D.12860>:
  D.12854 = 0;
  return D.12854;
  <D.12861>:
  method = mono_jit_info_get_method (ji);
  D.12862 = threads_callbacks.mono_method_is_critical;
  D.12854 = D.12862 (method);
  return D.12854;
}


mono_thread_info_setup_async_call (struct MonoThreadInfo * info, void (*<Tbf>) (void *) target_func, void * user_data)
{
  int D.12864;
  _Bool D.12865;
  long int D.12866;
  long int D.12867;
  void (*<Tbf>) (void *) D.12870;
  _Bool D.12871;
  long int D.12872;
  long int D.12873;

  D.12864 = info->suspend_count;
  D.12865 = D.12864 == 0;
  D.12866 = (long int) D.12865;
  D.12867 = __builtin_expect (D.12866, 0);
  if (D.12867 != 0) goto <D.12868>; else goto <D.12869>;
  <D.12868>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 577, "info->suspend_count");
  <D.12869>:
  D.12870 = info->async_target;
  D.12871 = D.12870 != 0B;
  D.12872 = (long int) D.12871;
  D.12873 = __builtin_expect (D.12872, 0);
  if (D.12873 != 0) goto <D.12874>; else goto <D.12875>;
  <D.12874>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 579, "!info->async_target");
  <D.12875>:
  info->async_target = target_func;
  info->user_data = user_data;
}


mono_thread_info_suspend_lock ()
{
  int D.12876;

  goto <D.12555>;
  <D.12554>:
  <D.12555>:
  D.12876 = mono_sem_wait (&global_suspend_semaphore, 0);
  if (D.12876 != 0) goto <D.12554>; else goto <D.12556>;
  <D.12556>:
}


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.12879;
  int D.12881;
  int D.12884;
  int D.12885;
  struct MonoThreadHazardPointers * hp;
  struct MonoThreadInfo * info;

  D.12879 = mono_native_thread_id_get ();
  if (D.12879 == tid) goto <D.12877>; else goto <D.12880>;
  <D.12880>:
  D.12881 = mono_threads_core_needs_abort_syscall ();
  if (D.12881 == 0) goto <D.12877>; else goto <D.12878>;
  <D.12877>:
  return;
  <D.12878>:
  hp = mono_hazard_pointer_get ();
  info = mono_thread_info_lookup (tid);
  if (info == 0B) goto <D.12882>; else goto <D.12883>;
  <D.12882>:
  return;
  <D.12883>:
  D.12884 = info->thread_state;
  D.12885 = D.12884 & 15;
  if (D.12885 > 1) goto <D.12886>; else goto <D.12887>;
  <D.12886>:
  if (0 != 0) goto <D.12888>; else goto <D.12889>;
  <D.12888>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 633, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.12889>:
  hp->hazard_pointers[1] = 0B;
  return;
  <D.12887>:
  mono_thread_info_suspend_lock ();
  mono_threads_core_abort_syscall (info);
  if (0 != 0) goto <D.12890>; else goto <D.12891>;
  <D.12890>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 641, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.12891>:
  hp->hazard_pointers[1] = 0B;
  mono_thread_info_suspend_unlock ();
}


mono_thread_info_new_interrupt_enabled ()
{
  gboolean D.12893;
  int disable_new_interrupt.17;
  _Bool D.12895;

  disable_new_interrupt.17 = disable_new_interrupt;
  D.12895 = disable_new_interrupt.17 == 0;
  D.12893 = (gboolean) D.12895;
  return D.12893;
  D.12893 = 0;
  return D.12893;
}


mono_thread_info_set_is_async_context (gboolean async_context)
{
  struct MonoThreadInfo * info;

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


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

  info = mono_thread_info_current ();
  if (info != 0B) goto <D.12899>; else goto <D.12900>;
  <D.12899>:
  D.12901 = info->is_async_context;
  return D.12901;
  <D.12900>:
  D.12901 = 0;
  return D.12901;
}


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.18;
  void * D.12906;
  void * res;
  gsize real_tid;

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


