mono_thread_info_lookup (MonoNativeThreadId id)
{
  int D.13483;
  struct MonoThreadInfo * D.13486;
  struct MonoThreadHazardPointers * hp;

  hp = mono_hazard_pointer_get ();
  D.13483 = mono_lls_find (&thread_list, hp, id);
  if (D.13483 == 0) goto <D.13484>; else goto <D.13485>;
  <D.13484>:
  mono_hazard_pointer_clear_all (hp, -1);
  D.13486 = 0B;
  return D.13486;
  <D.13485>:
  mono_hazard_pointer_clear_all (hp, 1);
  D.13486 = hp->hazard_pointers[1];
  return D.13486;
}


mono_hazard_pointer_clear_all (struct MonoThreadHazardPointers * hp, int retain)
{
  if (retain != 0) goto <D.13488>; else goto <D.13489>;
  <D.13488>:
  if (0 != 0) goto <D.13490>; else goto <D.13491>;
  <D.13490>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 58, "(0) >= 0 && (0) < HAZARD_POINTER_COUNT");
  <D.13491>:
  hp->hazard_pointers[0] = 0B;
  <D.13489>:
  if (retain != 1) goto <D.13492>; else goto <D.13493>;
  <D.13492>:
  if (0 != 0) goto <D.13494>; else goto <D.13495>;
  <D.13494>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 60, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13495>:
  hp->hazard_pointers[1] = 0B;
  <D.13493>:
  if (retain != 2) goto <D.13496>; else goto <D.13497>;
  <D.13496>:
  if (0 != 0) goto <D.13498>; else goto <D.13499>;
  <D.13498>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 62, "(2) >= 0 && (2) < HAZARD_POINTER_COUNT");
  <D.13499>:
  hp->hazard_pointers[2] = 0B;
  <D.13497>:
}


mono_thread_info_register_small_id ()
{
  unsigned int small_id_key.0;
  int D.13501;
  long unsigned int D.13502;
  void * D.13503;
  int D.13504;
  int small_id;

  small_id = mono_thread_small_id_alloc ();
  small_id_key.0 = small_id_key;
  D.13501 = small_id + 1;
  D.13502 = (long unsigned int) D.13501;
  D.13503 = (void *) D.13502;
  mono_native_tls_set_value (small_id_key.0, D.13503);
  D.13504 = small_id;
  return D.13504;
}


mono_native_tls_set_value (pthread_key_t key, void * value)
{
  int D.13506;
  int D.13507;
  _Bool D.13508;

  D.13507 = pthread_setspecific (key, value);
  D.13508 = D.13507 == 0;
  D.13506 = (int) D.13508;
  return D.13506;
}


mono_thread_info_current ()
{
  unsigned int thread_info_key.1;
  struct MonoThreadInfo * D.13513;
  long unsigned int D.13514;
  _Bool D.13515;
  long int D.13516;
  long int D.13517;
  struct MonoThreadHazardPointers * D.13522;
  struct MonoThreadInfo * info;

  thread_info_key.1 = thread_info_key;
  info = pthread_getspecific (thread_info_key.1);
  if (info != 0B) goto <D.13511>; else goto <D.13512>;
  <D.13511>:
  D.13513 = info;
  return D.13513;
  <D.13512>:
  D.13514 = mono_native_thread_id_get ();
  info = mono_thread_info_lookup (D.13514);
  D.13515 = info == 0B;
  D.13516 = (long int) D.13515;
  D.13517 = __builtin_expect (D.13516, 0);
  if (D.13517 != 0) goto <D.13518>; else goto <D.13519>;
  <D.13518>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 242, "info");
  <D.13519>:
  if (0 != 0) goto <D.13520>; else goto <D.13521>;
  <D.13520>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 245, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13521>:
  D.13522 = mono_hazard_pointer_get ();
  D.13522->hazard_pointers[1] = 0B;
  D.13513 = info;
  return D.13513;
}


mono_thread_info_get_small_id ()
{
  unsigned int small_id_key.2;
  int D.13527;
  long int val.3;
  int D.13529;
  void * val;

  small_id_key.2 = small_id_key;
  val = pthread_getspecific (small_id_key.2);
  if (val == 0B) goto <D.13525>; else goto <D.13526>;
  <D.13525>:
  D.13527 = -1;
  return D.13527;
  <D.13526>:
  val.3 = (long int) val;
  D.13529 = (int) val.3;
  D.13527 = D.13529 + -1;
  return D.13527;
}


mono_thread_info_list_head ()
{
  struct MonoLinkedListSet * D.13531;

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


mono_thread_info_attach (void * baseptr)
{
  int mono_threads_inited.4;
  struct MonoThreadInfo * D.13536;
  unsigned int thread_info_key.5;
  int thread_info_size.6;
  long unsigned int D.13541;
  void * D.13542;
  void (*<T1cb6>) (struct MonoThreadInfo *) D.13546;
  struct MonoThreadInfo * info;

  mono_threads_inited.4 = mono_threads_inited;
  if (mono_threads_inited.4 == 0) goto <D.13534>; else goto <D.13535>;
  <D.13534>:
  D.13536 = 0B;
  return D.13536;
  <D.13535>:
  thread_info_key.5 = thread_info_key;
  info = pthread_getspecific (thread_info_key.5);
  if (info == 0B) goto <D.13538>; else goto <D.13539>;
  <D.13538>:
  thread_info_size.6 = thread_info_size;
  D.13541 = (long unsigned int) thread_info_size.6;
  info = monoeg_malloc0 (D.13541);
  D.13542 = register_thread (info, baseptr);
  if (D.13542 == 0B) goto <D.13543>; else goto <D.13544>;
  <D.13543>:
  D.13536 = 0B;
  return D.13536;
  <D.13544>:
  goto <D.13545>;
  <D.13539>:
  D.13546 = threads_callbacks.thread_attach;
  if (D.13546 != 0B) goto <D.13547>; else goto <D.13548>;
  <D.13547>:
  D.13546 = threads_callbacks.thread_attach;
  D.13546 (info);
  <D.13548>:
  <D.13545>:
  D.13536 = info;
  return D.13536;
}


register_thread (struct MonoThreadInfo * info, void * baseptr)
{
  long unsigned int D.13550;
  unsigned int small_id.7;
  union MonoSemType * D.13552;
  union MonoSemType * D.13553;
  union MonoSemType * D.13554;
  unsigned int thread_info_key.8;
  void * (*<T1cb2>) (struct MonoThreadInfo *, void *) D.13556;
  void * D.13559;
  void * D.13562;
  _Bool D.13563;
  long int D.13564;
  long int D.13565;
  int small_id;
  gboolean result;

  small_id = mono_thread_info_register_small_id ();
  D.13550 = mono_native_thread_id_get ();
  info->node.key = D.13550;
  small_id.7 = (unsigned int) small_id;
  info->small_id = small_id.7;
  D.13552 = &info->suspend_semaphore;
  sem_init (D.13552, 0, 1);
  D.13553 = &info->resume_semaphore;
  sem_init (D.13553, 0, 0);
  D.13554 = &info->finish_resume_semaphore;
  sem_init (D.13554, 0, 0);
  thread_info_key.8 = thread_info_key;
  mono_native_tls_set_value (thread_info_key.8, info);
  D.13556 = threads_callbacks.thread_register;
  if (D.13556 != 0B) goto <D.13557>; else goto <D.13558>;
  <D.13557>:
  D.13556 = threads_callbacks.thread_register;
  D.13559 = D.13556 (info, baseptr);
  if (D.13559 == 0B) goto <D.13560>; else goto <D.13561>;
  <D.13560>:
  monoeg_g_log (0B, 16, "thread registation failed\n");
  monoeg_g_free (info);
  D.13562 = 0B;
  return D.13562;
  <D.13561>:
  <D.13558>:
  mono_threads_platform_register (info);
  info->thread_state = 1;
  mono_thread_info_suspend_lock ();
  result = mono_thread_info_insert (info);
  D.13563 = result == 0;
  D.13564 = (long int) D.13563;
  D.13565 = __builtin_expect (D.13564, 0);
  if (D.13565 != 0) goto <D.13566>; else goto <D.13567>;
  <D.13566>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 159, "result");
  <D.13567>:
  mono_thread_info_suspend_unlock ();
  D.13562 = info;
  return D.13562;
}


mono_thread_info_insert (struct MonoThreadInfo * info)
{
  int D.13569;
  gboolean D.13572;
  struct MonoThreadHazardPointers * hp;

  hp = mono_hazard_pointer_get ();
  D.13569 = mono_lls_insert (&thread_list, hp, info);
  if (D.13569 == 0) goto <D.13570>; else goto <D.13571>;
  <D.13570>:
  mono_hazard_pointer_clear_all (hp, -1);
  D.13572 = 0;
  return D.13572;
  <D.13571>:
  mono_hazard_pointer_clear_all (hp, -1);
  D.13572 = 1;
  return D.13572;
}


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.13575>; else goto <D.13576>;
  <D.13575>:
  return;
  <D.13576>:
  thread_info_key.10 = thread_info_key;
  info = pthread_getspecific (thread_info_key.10);
  if (info != 0B) goto <D.13578>; else goto <D.13579>;
  <D.13578>:
  unregister_thread (info);
  thread_info_key.10 = thread_info_key;
  mono_native_tls_set_value (thread_info_key.10, 0B);
  <D.13579>:
}


unregister_thread (void * arg)
{
  unsigned int D.13581;
  _Bool D.13582;
  long int D.13583;
  long int D.13584;
  unsigned int small_id_key.11;
  unsigned int D.13588;
  long unsigned int D.13589;
  void * D.13590;
  void (*<T1cb6>) (struct MonoThreadInfo *) D.13591;
  void (*<T1cb6>) (struct MonoThreadInfo *) D.13594;
  struct MonoThreadInfo * info;
  int small_id;

  info = arg;
  D.13581 = info->small_id;
  small_id = (int) D.13581;
  D.13582 = info == 0B;
  D.13583 = (long int) D.13582;
  D.13584 = __builtin_expect (D.13583, 0);
  if (D.13584 != 0) goto <D.13585>; else goto <D.13586>;
  <D.13585>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 169, "info");
  <D.13586>:
  small_id_key.11 = small_id_key;
  D.13581 = info->small_id;
  D.13588 = D.13581 + 1;
  D.13589 = (long unsigned int) D.13588;
  D.13590 = (void *) D.13589;
  mono_native_tls_set_value (small_id_key.11, D.13590);
  info->thread_state = 2;
  D.13591 = threads_callbacks.thread_detach;
  if (D.13591 != 0B) goto <D.13592>; else goto <D.13593>;
  <D.13592>:
  D.13591 = threads_callbacks.thread_detach;
  D.13591 (info);
  <D.13593>:
  mono_thread_info_suspend_lock ();
  D.13594 = threads_callbacks.thread_unregister;
  if (D.13594 != 0B) goto <D.13595>; else goto <D.13596>;
  <D.13595>:
  D.13594 = threads_callbacks.thread_unregister;
  D.13594 (info);
  <D.13596>:
  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.13597;
  union MonoSemType * D.13598;
  union MonoSemType * D.13599;
  struct MonoThreadInfo * info;

  info = mem;
  D.13597 = &info->suspend_semaphore;
  sem_destroy (D.13597);
  D.13598 = &info->resume_semaphore;
  sem_destroy (D.13598);
  D.13599 = &info->finish_resume_semaphore;
  sem_destroy (D.13599);
  mono_threads_platform_free (info);
  monoeg_g_free (info);
}


mono_threads_unregister_current_thread (struct MonoThreadInfo * info)
{
  long unsigned int D.13600;
  long unsigned int D.13601;
  _Bool D.13602;
  long int D.13603;
  long int D.13604;
  _Bool D.13607;
  long int D.13608;
  long int D.13609;
  gboolean result;

  D.13600 = info->node.key;
  D.13601 = mono_native_thread_id_get ();
  D.13602 = D.13600 != D.13601;
  D.13603 = (long int) D.13602;
  D.13604 = __builtin_expect (D.13603, 0);
  if (D.13604 != 0) goto <D.13605>; else goto <D.13606>;
  <D.13605>:
  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.13606>:
  result = mono_thread_info_remove (info);
  D.13607 = result == 0;
  D.13608 = (long int) D.13607;
  D.13609 = __builtin_expect (D.13608, 0);
  if (D.13609 != 0) goto <D.13610>; else goto <D.13611>;
  <D.13610>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 220, "result");
  <D.13611>:
}


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


mono_threads_init (struct MonoThreadInfoCallbacks * callbacks, size_t info_size)
{
  int thread_info_size.12;
  _Bool D.13615;
  long int D.13616;
  long int D.13617;
  gboolean res;

  threads_callbacks = *callbacks;
  thread_info_size.12 = (int) info_size;
  thread_info_size = thread_info_size.12;
  res = mono_native_tls_alloc (&thread_info_key, unregister_thread);
  D.13615 = res == 0;
  D.13616 = (long int) D.13615;
  D.13617 = __builtin_expect (D.13616, 0);
  if (D.13617 != 0) goto <D.13618>; else goto <D.13619>;
  <D.13618>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 318, "res");
  <D.13619>:
  res = mono_native_tls_alloc (&small_id_key, 0B);
  D.13615 = res == 0;
  D.13616 = (long int) D.13615;
  D.13617 = __builtin_expect (D.13616, 0);
  if (D.13617 != 0) goto <D.13620>; else goto <D.13621>;
  <D.13620>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 321, "res");
  <D.13621>:
  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.13622>; else goto <D.13623>;
  <D.13622>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 335, "sizeof (MonoNativeThreadId) <= sizeof (uintptr_t)");
  <D.13623>:
}


mono_native_tls_alloc (pthread_key_t * key, void * destructor)
{
  int D.13624;
  void (*<Tbf>) (void *) destructor.13;
  int D.13626;
  _Bool D.13627;

  destructor.13 = (void (*<Tbf>) (void *)) destructor;
  D.13626 = pthread_key_create (key, destructor.13);
  D.13627 = D.13626 == 0;
  D.13624 = (int) D.13627;
  return D.13624;
}


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


mono_threads_get_callbacks ()
{
  struct MonoThreadInfoCallbacks * D.13629;

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


mono_threads_get_runtime_callbacks ()
{
  struct MonoThreadInfoRuntimeCallbacks * D.13631;

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


mono_thread_info_self_suspend ()
{
  union MonoSemType * D.13635;
  int D.13636;
  int D.13637;
  _Bool D.13638;
  long int D.13639;
  long int D.13640;
  int D.13643;
  int D.13644;
  int D.13645;
  struct MonoThreadInfoRuntimeCallbacks * D.13646;
  gboolean (*<T1ccf>) (struct MonoThreadUnwindState *, void *) D.13647;
  struct MonoThreadUnwindState * D.13648;
  _Bool D.13649;
  long int D.13650;
  long int D.13651;
  union MonoSemType * D.13654;
  int D.13655;
  void (*<Tbf>) (void *) D.13656;
  _Bool D.13657;
  long int D.13658;
  long int D.13659;
  union MonoSemType * D.13662;
  gboolean ret;
  struct MonoThreadInfo * info;

  info = mono_thread_info_current ();
  if (info == 0B) goto <D.13633>; else goto <D.13634>;
  <D.13633>:
  return;
  <D.13634>:
  goto <D.13402>;
  <D.13401>:
  <D.13402>:
  D.13635 = &info->suspend_semaphore;
  D.13636 = mono_sem_wait (D.13635, 0);
  if (D.13636 != 0) goto <D.13401>; else goto <D.13403>;
  <D.13403>:
  D.13637 = info->suspend_count;
  D.13638 = D.13637 != 0;
  D.13639 = (long int) D.13638;
  D.13640 = __builtin_expect (D.13639, 0);
  if (D.13640 != 0) goto <D.13641>; else goto <D.13642>;
  <D.13641>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 413, "info->suspend_count == 0");
  <D.13642>:
  D.13637 = info->suspend_count;
  D.13643 = D.13637 + 1;
  info->suspend_count = D.13643;
  D.13644 = info->thread_state;
  D.13645 = D.13644 | 32;
  info->thread_state = D.13645;
  D.13646 = mono_threads_get_runtime_callbacks ();
  D.13647 = D.13646->thread_state_init_from_sigctx;
  D.13648 = &info->suspend_state;
  ret = D.13647 (D.13648, 0B);
  D.13649 = ret == 0;
  D.13650 = (long int) D.13649;
  D.13651 = __builtin_expect (D.13650, 0);
  if (D.13651 != 0) goto <D.13652>; else goto <D.13653>;
  <D.13652>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 419, "ret");
  <D.13653>:
  D.13635 = &info->suspend_semaphore;
  mono_sem_post (D.13635);
  goto <D.13405>;
  <D.13404>:
  <D.13405>:
  D.13654 = &info->resume_semaphore;
  D.13655 = mono_sem_wait (D.13654, 0);
  if (D.13655 != 0) goto <D.13404>; else goto <D.13406>;
  <D.13406>:
  D.13656 = info->async_target;
  D.13657 = D.13656 != 0B;
  D.13658 = (long int) D.13657;
  D.13659 = __builtin_expect (D.13658, 0);
  if (D.13659 != 0) goto <D.13660>; else goto <D.13661>;
  <D.13660>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 425, "!info->async_target");
  <D.13661>:
  D.13662 = &info->finish_resume_semaphore;
  mono_sem_post (D.13662);
}


mono_thread_info_resume (MonoNativeThreadId tid)
{
  gboolean D.13666;
  union MonoSemType * D.13667;
  int D.13668;
  int D.13669;
  long unsigned int D.13674;
  _Bool D.13675;
  long int D.13676;
  long int D.13677;
  int D.13680;
  struct MonoThreadInfo * D.13685;
  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.13664>; else goto <D.13665>;
  <D.13664>:
  D.13666 = 0;
  return D.13666;
  <D.13665>:
  goto <D.13421>;
  <D.13420>:
  <D.13421>:
  D.13667 = &info->suspend_semaphore;
  D.13668 = mono_sem_wait (D.13667, 0);
  if (D.13668 != 0) goto <D.13420>; else goto <D.13422>;
  <D.13422>:
  D.13669 = info->suspend_count;
  if (D.13669 <= 0) goto <D.13670>; else goto <D.13671>;
  <D.13670>:
  D.13667 = &info->suspend_semaphore;
  mono_sem_post (D.13667);
  if (0 != 0) goto <D.13672>; else goto <D.13673>;
  <D.13672>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 459, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13673>:
  hp->hazard_pointers[1] = 0B;
  D.13666 = 0;
  return D.13666;
  <D.13671>:
  D.13674 = info->node.key;
  D.13675 = D.13674 == 0;
  D.13676 = (long int) D.13675;
  D.13677 = __builtin_expect (D.13676, 0);
  if (D.13677 != 0) goto <D.13678>; else goto <D.13679>;
  <D.13678>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 467, "mono_thread_info_get_tid (info)");
  <D.13679>:
  D.13669 = info->suspend_count;
  D.13680 = D.13669 + -1;
  info->suspend_count = D.13680;
  D.13669 = info->suspend_count;
  if (D.13669 == 0) goto <D.13681>; else goto <D.13682>;
  <D.13681>:
  result = mono_thread_info_resume_internal (info);
  <D.13682>:
  D.13667 = &info->suspend_semaphore;
  mono_sem_post (D.13667);
  if (0 != 0) goto <D.13683>; else goto <D.13684>;
  <D.13683>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 473, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13684>:
  hp->hazard_pointers[1] = 0B;
  mono_memory_barrier ();
  D.13685 = mono_thread_info_current ();
  D.13685->inside_critical_region = 0;
  D.13666 = result;
  return D.13666;
}


mono_thread_info_resume_internal (struct MonoThreadInfo * info)
{
  int D.13687;
  int D.13688;
  union MonoSemType * D.13691;
  union MonoSemType * D.13692;
  int D.13693;
  int D.13695;
  gboolean D.13696;
  gboolean result;

  D.13687 = info->thread_state;
  D.13688 = D.13687 & 240;
  if (D.13688 == 32) goto <D.13689>; else goto <D.13690>;
  <D.13689>:
  D.13691 = &info->resume_semaphore;
  mono_sem_post (D.13691);
  goto <D.13412>;
  <D.13411>:
  <D.13412>:
  D.13692 = &info->finish_resume_semaphore;
  D.13693 = mono_sem_wait (D.13692, 0);
  if (D.13693 != 0) goto <D.13411>; else goto <D.13413>;
  <D.13413>:
  result = 1;
  goto <D.13694>;
  <D.13690>:
  result = mono_threads_core_resume (info);
  <D.13694>:
  D.13687 = info->thread_state;
  D.13695 = D.13687 & -241;
  info->thread_state = D.13695;
  D.13696 = result;
  return D.13696;
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


mono_thread_info_finish_suspend ()
{
  struct MonoThreadInfo * D.13698;

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


mono_thread_info_safe_suspend_sync (MonoNativeThreadId id, gboolean interrupt_kernel)
{
  long unsigned int D.13699;
  _Bool D.13700;
  long int D.13701;
  long int D.13702;
  void * id.14;
  struct MonoThreadInfo * D.13708;
  int D.13709;
  int D.13711;
  long unsigned int D.13717;
  struct MonoThreadInfo * D.13718;
  struct MonoThreadInfo * info;
  int sleep_duration;

  info = 0B;
  sleep_duration = 0;
  D.13699 = mono_native_thread_id_get ();
  D.13700 = D.13699 == id;
  D.13701 = (long int) D.13700;
  D.13702 = __builtin_expect (D.13701, 0);
  if (D.13702 != 0) goto <D.13703>; else goto <D.13704>;
  <D.13703>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 527, "id != mono_native_thread_id_get ()");
  <D.13704>:
  mono_thread_info_suspend_lock ();
  <D.13438>:
  info = mono_thread_info_suspend_sync (id, interrupt_kernel);
  if (info == 0B) goto <D.13705>; else goto <D.13706>;
  <D.13705>:
  id.14 = (void *) id;
  monoeg_g_log (0B, 16, "failed to suspend thread %p, hopefully it is dead", id.14);
  mono_thread_info_suspend_unlock ();
  D.13708 = 0B;
  return D.13708;
  <D.13706>:
  D.13709 = is_thread_in_critical_region (info);
  if (D.13709 == 0) goto <D.13437>; else goto <D.13710>;
  <D.13710>:
  D.13711 = mono_thread_info_resume (id);
  if (D.13711 == 0) goto <D.13712>; else goto <D.13713>;
  <D.13712>:
  id.14 = (void *) id;
  monoeg_g_log (0B, 16, "failed to result thread %p, hopefully it is dead", id.14);
  mono_thread_info_suspend_unlock ();
  D.13708 = 0B;
  return D.13708;
  <D.13713>:
  if (sleep_duration == 0) goto <D.13714>; else goto <D.13715>;
  <D.13714>:
  sched_yield ();
  goto <D.13716>;
  <D.13715>:
  D.13717 = (long unsigned int) sleep_duration;
  monoeg_g_usleep (D.13717);
  <D.13716>:
  sleep_duration = sleep_duration + 10;
  goto <D.13438>;
  <D.13437>:
  mono_memory_barrier ();
  D.13718 = mono_thread_info_current ();
  D.13718->inside_critical_region = 1;
  mono_thread_info_suspend_unlock ();
  D.13708 = info;
  return D.13708;
}


mono_thread_info_suspend_sync (MonoNativeThreadId tid, gboolean interrupt_kernel)
{
  struct MonoThreadInfo * D.13722;
  union MonoSemType * D.13723;
  int D.13724;
  int D.13725;
  int D.13726;
  int D.13731;
  int D.13734;
  int D.13737;
  int D.13744;
  struct MonoThreadHazardPointers * hp;
  struct MonoThreadInfo * info;

  hp = mono_hazard_pointer_get ();
  info = mono_thread_info_lookup (tid);
  if (info == 0B) goto <D.13720>; else goto <D.13721>;
  <D.13720>:
  D.13722 = 0B;
  return D.13722;
  <D.13721>:
  goto <D.13394>;
  <D.13393>:
  <D.13394>:
  D.13723 = &info->suspend_semaphore;
  D.13724 = mono_sem_wait (D.13723, 0);
  if (D.13724 != 0) goto <D.13393>; else goto <D.13395>;
  <D.13395>:
  D.13725 = info->thread_state;
  D.13726 = D.13725 & 15;
  if (D.13726 > 1) goto <D.13727>; else goto <D.13728>;
  <D.13727>:
  if (0 != 0) goto <D.13729>; else goto <D.13730>;
  <D.13729>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 371, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13730>:
  hp->hazard_pointers[1] = 0B;
  D.13722 = 0B;
  return D.13722;
  <D.13728>:
  D.13731 = info->suspend_count;
  if (D.13731 != 0) goto <D.13732>; else goto <D.13733>;
  <D.13732>:
  D.13731 = info->suspend_count;
  D.13734 = D.13731 + 1;
  info->suspend_count = D.13734;
  if (0 != 0) goto <D.13735>; else goto <D.13736>;
  <D.13735>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 379, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13736>:
  hp->hazard_pointers[1] = 0B;
  D.13723 = &info->suspend_semaphore;
  mono_sem_post (D.13723);
  D.13722 = info;
  return D.13722;
  <D.13733>:
  D.13737 = mono_threads_core_suspend (info);
  if (D.13737 == 0) goto <D.13738>; else goto <D.13739>;
  <D.13738>:
  D.13723 = &info->suspend_semaphore;
  mono_sem_post (D.13723);
  if (0 != 0) goto <D.13740>; else goto <D.13741>;
  <D.13740>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 386, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13741>:
  hp->hazard_pointers[1] = 0B;
  D.13722 = 0B;
  return D.13722;
  <D.13739>:
  if (interrupt_kernel != 0) goto <D.13742>; else goto <D.13743>;
  <D.13742>:
  mono_threads_core_interrupt (info);
  <D.13743>:
  D.13731 = info->suspend_count;
  D.13734 = D.13731 + 1;
  info->suspend_count = D.13734;
  D.13725 = info->thread_state;
  D.13744 = D.13725 | 16;
  info->thread_state = D.13744;
  D.13723 = &info->suspend_semaphore;
  mono_sem_post (D.13723);
  if (0 != 0) goto <D.13745>; else goto <D.13746>;
  <D.13745>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 396, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13746>:
  hp->hazard_pointers[1] = 0B;
  D.13722 = info;
  return D.13722;
}


is_thread_in_critical_region (struct MonoThreadInfo * info)
{
  int D.13748;
  gboolean D.13751;
  void * D.13752;
  long unsigned int D.13755;
  char * D.13756;
  gboolean (*<T1cbe>) (void *) D.13759;
  struct MonoMethod * method;
  struct MonoJitInfo * ji;

  D.13748 = info->inside_critical_region;
  if (D.13748 != 0) goto <D.13749>; else goto <D.13750>;
  <D.13749>:
  D.13751 = 1;
  return D.13751;
  <D.13750>:
  D.13752 = info->suspend_state.unwind_data[0];
  if (D.13752 == 0B) goto <D.13753>; else goto <D.13754>;
  <D.13753>:
  D.13751 = 0;
  return D.13751;
  <D.13754>:
  D.13752 = info->suspend_state.unwind_data[0];
  D.13755 = info->suspend_state.ctx.sc_ir;
  D.13756 = (char *) D.13755;
  ji = mono_jit_info_table_find (D.13752, D.13756);
  if (ji == 0B) goto <D.13757>; else goto <D.13758>;
  <D.13757>:
  D.13751 = 0;
  return D.13751;
  <D.13758>:
  method = mono_jit_info_get_method (ji);
  D.13759 = threads_callbacks.mono_method_is_critical;
  D.13751 = D.13759 (method);
  return D.13751;
}


mono_thread_info_setup_async_call (struct MonoThreadInfo * info, void (*<Tbf>) (void *) target_func, void * user_data)
{
  int D.13761;
  _Bool D.13762;
  long int D.13763;
  long int D.13764;
  void (*<Tbf>) (void *) D.13767;
  _Bool D.13768;
  long int D.13769;
  long int D.13770;

  D.13761 = info->suspend_count;
  D.13762 = D.13761 == 0;
  D.13763 = (long int) D.13762;
  D.13764 = __builtin_expect (D.13763, 0);
  if (D.13764 != 0) goto <D.13765>; else goto <D.13766>;
  <D.13765>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 577, "info->suspend_count");
  <D.13766>:
  D.13767 = info->async_target;
  D.13768 = D.13767 != 0B;
  D.13769 = (long int) D.13768;
  D.13770 = __builtin_expect (D.13769, 0);
  if (D.13770 != 0) goto <D.13771>; else goto <D.13772>;
  <D.13771>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 579, "!info->async_target");
  <D.13772>:
  info->async_target = target_func;
  info->user_data = user_data;
}


mono_thread_info_suspend_lock ()
{
  int D.13773;

  goto <D.13449>;
  <D.13448>:
  <D.13449>:
  D.13773 = mono_sem_wait (&global_suspend_semaphore, 0);
  if (D.13773 != 0) goto <D.13448>; else goto <D.13450>;
  <D.13450>:
}


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.13776;
  int D.13778;
  int D.13781;
  int D.13782;
  struct MonoThreadHazardPointers * hp;
  struct MonoThreadInfo * info;

  D.13776 = mono_native_thread_id_get ();
  if (D.13776 == tid) goto <D.13774>; else goto <D.13777>;
  <D.13777>:
  D.13778 = mono_threads_core_needs_abort_syscall ();
  if (D.13778 == 0) goto <D.13774>; else goto <D.13775>;
  <D.13774>:
  return;
  <D.13775>:
  hp = mono_hazard_pointer_get ();
  info = mono_thread_info_lookup (tid);
  if (info == 0B) goto <D.13779>; else goto <D.13780>;
  <D.13779>:
  return;
  <D.13780>:
  D.13781 = info->thread_state;
  D.13782 = D.13781 & 15;
  if (D.13782 > 1) goto <D.13783>; else goto <D.13784>;
  <D.13783>:
  if (0 != 0) goto <D.13785>; else goto <D.13786>;
  <D.13785>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 633, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13786>:
  hp->hazard_pointers[1] = 0B;
  return;
  <D.13784>:
  mono_thread_info_suspend_lock ();
  mono_threads_core_abort_syscall (info);
  if (0 != 0) goto <D.13787>; else goto <D.13788>;
  <D.13787>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 641, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13788>:
  hp->hazard_pointers[1] = 0B;
  mono_thread_info_suspend_unlock ();
}


mono_thread_info_new_interrupt_enabled ()
{
  gboolean D.13790;

  D.13790 = 0;
  return D.13790;
}


mono_thread_info_set_is_async_context (gboolean async_context)
{
  struct MonoThreadInfo * info;

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


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

  info = mono_thread_info_current ();
  if (info != 0B) goto <D.13794>; else goto <D.13795>;
  <D.13794>:
  D.13796 = info->is_async_context;
  return D.13796;
  <D.13795>:
  D.13796 = 0;
  return D.13796;
}


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

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


