mono_thread_info_lookup (MonoNativeThreadId id)
{
  int D.12953;
  struct MonoThreadInfo * D.12956;
  struct MonoThreadHazardPointers * hp;

  hp = mono_hazard_pointer_get ();
  D.12953 = mono_lls_find (&thread_list, hp, id);
  if (D.12953 == 0) goto <D.12954>; else goto <D.12955>;
  <D.12954>:
  mono_hazard_pointer_clear_all (hp, -1);
  D.12956 = 0B;
  return D.12956;
  <D.12955>:
  mono_hazard_pointer_clear_all (hp, 1);
  D.12956 = hp->hazard_pointers[1];
  return D.12956;
}


mono_hazard_pointer_clear_all (struct MonoThreadHazardPointers * hp, int retain)
{
  if (retain != 0) goto <D.12958>; else goto <D.12959>;
  <D.12958>:
  if (0 != 0) goto <D.12960>; else goto <D.12961>;
  <D.12960>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 58, "(0) >= 0 && (0) < HAZARD_POINTER_COUNT");
  <D.12961>:
  hp->hazard_pointers[0] = 0B;
  <D.12959>:
  if (retain != 1) goto <D.12962>; else goto <D.12963>;
  <D.12962>:
  if (0 != 0) goto <D.12964>; else goto <D.12965>;
  <D.12964>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 60, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.12965>:
  hp->hazard_pointers[1] = 0B;
  <D.12963>:
  if (retain != 2) goto <D.12966>; else goto <D.12967>;
  <D.12966>:
  if (0 != 0) goto <D.12968>; else goto <D.12969>;
  <D.12968>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 62, "(2) >= 0 && (2) < HAZARD_POINTER_COUNT");
  <D.12969>:
  hp->hazard_pointers[2] = 0B;
  <D.12967>:
}


mono_thread_info_register_small_id ()
{
  int D.12970;
  long unsigned int D.12971;
  void * D.12972;
  unsigned int small_id_key.0;
  int D.12974;
  int small_id;

  small_id = mono_thread_small_id_alloc ();
  D.12970 = small_id + 1;
  D.12971 = (long unsigned int) D.12970;
  D.12972 = (void *) D.12971;
  small_id_key.0 = small_id_key;
  mono_native_tls_set_value (small_id_key.0, D.12972);
  D.12974 = small_id;
  return D.12974;
}


mono_native_tls_set_value (pthread_key_t key, void * value)
{
  int D.12976;
  int D.12977;
  _Bool D.12978;

  D.12977 = pthread_setspecific (key, value);
  D.12978 = D.12977 == 0;
  D.12976 = (int) D.12978;
  return D.12976;
}


mono_thread_info_current ()
{
  unsigned int thread_info_key.1;
  struct MonoThreadInfo * D.12983;
  long unsigned int D.12984;
  _Bool D.12985;
  long int D.12986;
  long int D.12987;
  struct MonoThreadHazardPointers * D.12992;
  struct MonoThreadInfo * info;

  thread_info_key.1 = thread_info_key;
  info = pthread_getspecific (thread_info_key.1);
  if (info != 0B) goto <D.12981>; else goto <D.12982>;
  <D.12981>:
  D.12983 = info;
  return D.12983;
  <D.12982>:
  D.12984 = mono_native_thread_id_get ();
  info = mono_thread_info_lookup (D.12984);
  D.12985 = info == 0B;
  D.12986 = (long int) D.12985;
  D.12987 = __builtin_expect (D.12986, 0);
  if (D.12987 != 0) goto <D.12988>; else goto <D.12989>;
  <D.12988>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 242, "info");
  <D.12989>:
  if (0 != 0) goto <D.12990>; else goto <D.12991>;
  <D.12990>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 245, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.12991>:
  D.12992 = mono_hazard_pointer_get ();
  D.12992->hazard_pointers[1] = 0B;
  D.12983 = info;
  return D.12983;
}


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

  small_id_key.2 = small_id_key;
  val = pthread_getspecific (small_id_key.2);
  if (val == 0B) goto <D.12995>; else goto <D.12996>;
  <D.12995>:
  D.12997 = -1;
  return D.12997;
  <D.12996>:
  val.3 = (long int) val;
  D.12999 = (int) val.3;
  D.12997 = D.12999 + -1;
  return D.12997;
}


mono_thread_info_list_head ()
{
  struct MonoLinkedListSet * D.13001;

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


mono_thread_info_attach (void * baseptr)
{
  int mono_threads_inited.4;
  struct MonoThreadInfo * D.13006;
  unsigned int thread_info_key.5;
  int thread_info_size.6;
  long unsigned int D.13011;
  void * D.13012;
  void (*<T1c2e>) (struct MonoThreadInfo *) D.13016;
  struct MonoThreadInfo * info;

  mono_threads_inited.4 = mono_threads_inited;
  if (mono_threads_inited.4 == 0) goto <D.13004>; else goto <D.13005>;
  <D.13004>:
  D.13006 = 0B;
  return D.13006;
  <D.13005>:
  thread_info_key.5 = thread_info_key;
  info = pthread_getspecific (thread_info_key.5);
  if (info == 0B) goto <D.13008>; else goto <D.13009>;
  <D.13008>:
  thread_info_size.6 = thread_info_size;
  D.13011 = (long unsigned int) thread_info_size.6;
  info = monoeg_malloc0 (D.13011);
  D.13012 = register_thread (info, baseptr);
  if (D.13012 == 0B) goto <D.13013>; else goto <D.13014>;
  <D.13013>:
  D.13006 = 0B;
  return D.13006;
  <D.13014>:
  goto <D.13015>;
  <D.13009>:
  D.13016 = threads_callbacks.thread_attach;
  if (D.13016 != 0B) goto <D.13017>; else goto <D.13018>;
  <D.13017>:
  D.13016 = threads_callbacks.thread_attach;
  D.13016 (info);
  <D.13018>:
  <D.13015>:
  D.13006 = info;
  return D.13006;
}


register_thread (struct MonoThreadInfo * info, void * baseptr)
{
  long unsigned int D.13020;
  unsigned int small_id.7;
  union MonoSemType * D.13022;
  union MonoSemType * D.13023;
  union MonoSemType * D.13024;
  unsigned int thread_info_key.8;
  void * (*<T1c2a>) (struct MonoThreadInfo *, void *) D.13026;
  void * D.13029;
  void * D.13032;
  _Bool D.13033;
  long int D.13034;
  long int D.13035;
  int small_id;
  gboolean result;

  small_id = mono_thread_info_register_small_id ();
  D.13020 = mono_native_thread_id_get ();
  info->node.key = D.13020;
  small_id.7 = (unsigned int) small_id;
  info->small_id = small_id.7;
  D.13022 = &info->suspend_semaphore;
  sem_init (D.13022, 0, 1);
  D.13023 = &info->resume_semaphore;
  sem_init (D.13023, 0, 0);
  D.13024 = &info->finish_resume_semaphore;
  sem_init (D.13024, 0, 0);
  thread_info_key.8 = thread_info_key;
  mono_native_tls_set_value (thread_info_key.8, info);
  D.13026 = threads_callbacks.thread_register;
  if (D.13026 != 0B) goto <D.13027>; else goto <D.13028>;
  <D.13027>:
  D.13026 = threads_callbacks.thread_register;
  D.13029 = D.13026 (info, baseptr);
  if (D.13029 == 0B) goto <D.13030>; else goto <D.13031>;
  <D.13030>:
  monoeg_g_log (0B, 16, "thread registation failed\n");
  monoeg_g_free (info);
  D.13032 = 0B;
  return D.13032;
  <D.13031>:
  <D.13028>:
  mono_threads_platform_register (info);
  info->thread_state = 1;
  mono_thread_info_suspend_lock ();
  result = mono_thread_info_insert (info);
  D.13033 = result == 0;
  D.13034 = (long int) D.13033;
  D.13035 = __builtin_expect (D.13034, 0);
  if (D.13035 != 0) goto <D.13036>; else goto <D.13037>;
  <D.13036>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 159, "result");
  <D.13037>:
  mono_thread_info_suspend_unlock ();
  D.13032 = info;
  return D.13032;
}


mono_thread_info_insert (struct MonoThreadInfo * info)
{
  int D.13039;
  gboolean D.13042;
  struct MonoThreadHazardPointers * hp;

  hp = mono_hazard_pointer_get ();
  D.13039 = mono_lls_insert (&thread_list, hp, info);
  if (D.13039 == 0) goto <D.13040>; else goto <D.13041>;
  <D.13040>:
  mono_hazard_pointer_clear_all (hp, -1);
  D.13042 = 0;
  return D.13042;
  <D.13041>:
  mono_hazard_pointer_clear_all (hp, -1);
  D.13042 = 1;
  return D.13042;
}


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.13045>; else goto <D.13046>;
  <D.13045>:
  return;
  <D.13046>:
  thread_info_key.10 = thread_info_key;
  info = pthread_getspecific (thread_info_key.10);
  if (info != 0B) goto <D.13048>; else goto <D.13049>;
  <D.13048>:
  unregister_thread (info);
  thread_info_key.10 = thread_info_key;
  mono_native_tls_set_value (thread_info_key.10, 0B);
  <D.13049>:
}


unregister_thread (void * arg)
{
  unsigned int D.13051;
  _Bool D.13052;
  long int D.13053;
  long int D.13054;
  unsigned int D.13057;
  long unsigned int D.13058;
  void * D.13059;
  unsigned int small_id_key.11;
  void (*<T1c2e>) (struct MonoThreadInfo *) D.13061;
  void (*<T1c2e>) (struct MonoThreadInfo *) D.13064;
  struct MonoThreadInfo * info;
  int small_id;

  info = arg;
  D.13051 = info->small_id;
  small_id = (int) D.13051;
  D.13052 = info == 0B;
  D.13053 = (long int) D.13052;
  D.13054 = __builtin_expect (D.13053, 0);
  if (D.13054 != 0) goto <D.13055>; else goto <D.13056>;
  <D.13055>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 169, "info");
  <D.13056>:
  D.13051 = info->small_id;
  D.13057 = D.13051 + 1;
  D.13058 = (long unsigned int) D.13057;
  D.13059 = (void *) D.13058;
  small_id_key.11 = small_id_key;
  mono_native_tls_set_value (small_id_key.11, D.13059);
  info->thread_state = 2;
  D.13061 = threads_callbacks.thread_detach;
  if (D.13061 != 0B) goto <D.13062>; else goto <D.13063>;
  <D.13062>:
  D.13061 = threads_callbacks.thread_detach;
  D.13061 (info);
  <D.13063>:
  mono_thread_info_suspend_lock ();
  D.13064 = threads_callbacks.thread_unregister;
  if (D.13064 != 0B) goto <D.13065>; else goto <D.13066>;
  <D.13065>:
  D.13064 = threads_callbacks.thread_unregister;
  D.13064 (info);
  <D.13066>:
  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.13067;
  union MonoSemType * D.13068;
  union MonoSemType * D.13069;
  struct MonoThreadInfo * info;

  info = mem;
  D.13067 = &info->suspend_semaphore;
  sem_destroy (D.13067);
  D.13068 = &info->resume_semaphore;
  sem_destroy (D.13068);
  D.13069 = &info->finish_resume_semaphore;
  sem_destroy (D.13069);
  mono_threads_platform_free (info);
  monoeg_g_free (info);
}


mono_threads_unregister_current_thread (struct MonoThreadInfo * info)
{
  long unsigned int D.13070;
  long unsigned int D.13071;
  _Bool D.13072;
  long int D.13073;
  long int D.13074;
  _Bool D.13077;
  long int D.13078;
  long int D.13079;
  gboolean result;

  D.13070 = info->node.key;
  D.13071 = mono_native_thread_id_get ();
  D.13072 = D.13070 != D.13071;
  D.13073 = (long int) D.13072;
  D.13074 = __builtin_expect (D.13073, 0);
  if (D.13074 != 0) goto <D.13075>; else goto <D.13076>;
  <D.13075>:
  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.13076>:
  result = mono_thread_info_remove (info);
  D.13077 = result == 0;
  D.13078 = (long int) D.13077;
  D.13079 = __builtin_expect (D.13078, 0);
  if (D.13079 != 0) goto <D.13080>; else goto <D.13081>;
  <D.13080>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 220, "result");
  <D.13081>:
}


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


mono_threads_init (struct MonoThreadInfoCallbacks * callbacks, size_t info_size)
{
  int thread_info_size.12;
  _Bool D.13085;
  long int D.13086;
  long int D.13087;
  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.13085 = res == 0;
  D.13086 = (long int) D.13085;
  D.13087 = __builtin_expect (D.13086, 0);
  if (D.13087 != 0) goto <D.13088>; else goto <D.13089>;
  <D.13088>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 318, "res");
  <D.13089>:
  res = mono_native_tls_alloc (&small_id_key, 0B);
  D.13085 = res == 0;
  D.13086 = (long int) D.13085;
  D.13087 = __builtin_expect (D.13086, 0);
  if (D.13087 != 0) goto <D.13090>; else goto <D.13091>;
  <D.13090>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 321, "res");
  <D.13091>:
  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.13092>; else goto <D.13093>;
  <D.13092>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 335, "sizeof (MonoNativeThreadId) <= sizeof (uintptr_t)");
  <D.13093>:
}


mono_native_tls_alloc (pthread_key_t * key, void * destructor)
{
  int D.13094;
  void (*<Tc2>) (void *) destructor.13;
  int D.13096;
  _Bool D.13097;

  destructor.13 = (void (*<Tc2>) (void *)) destructor;
  D.13096 = pthread_key_create (key, destructor.13);
  D.13097 = D.13096 == 0;
  D.13094 = (int) D.13097;
  return D.13094;
}


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


mono_threads_get_callbacks ()
{
  struct MonoThreadInfoCallbacks * D.13099;

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


mono_threads_get_runtime_callbacks ()
{
  struct MonoThreadInfoRuntimeCallbacks * D.13101;

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


mono_thread_info_self_suspend ()
{
  union MonoSemType * D.13105;
  int D.13106;
  int D.13107;
  _Bool D.13108;
  long int D.13109;
  long int D.13110;
  int D.13113;
  int D.13114;
  int D.13115;
  struct MonoThreadInfoRuntimeCallbacks * D.13116;
  gboolean (*<T1c47>) (struct MonoThreadUnwindState *, void *) D.13117;
  struct MonoThreadUnwindState * D.13118;
  _Bool D.13119;
  long int D.13120;
  long int D.13121;
  union MonoSemType * D.13124;
  int D.13125;
  void (*<Tc2>) (void *) D.13126;
  _Bool D.13127;
  long int D.13128;
  long int D.13129;
  union MonoSemType * D.13132;
  gboolean ret;
  struct MonoThreadInfo * info;

  info = mono_thread_info_current ();
  if (info == 0B) goto <D.13103>; else goto <D.13104>;
  <D.13103>:
  return;
  <D.13104>:
  goto <D.12872>;
  <D.12871>:
  <D.12872>:
  D.13105 = &info->suspend_semaphore;
  D.13106 = mono_sem_wait (D.13105, 0);
  if (D.13106 != 0) goto <D.12871>; else goto <D.12873>;
  <D.12873>:
  D.13107 = info->suspend_count;
  D.13108 = D.13107 != 0;
  D.13109 = (long int) D.13108;
  D.13110 = __builtin_expect (D.13109, 0);
  if (D.13110 != 0) goto <D.13111>; else goto <D.13112>;
  <D.13111>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 413, "info->suspend_count == 0");
  <D.13112>:
  D.13107 = info->suspend_count;
  D.13113 = D.13107 + 1;
  info->suspend_count = D.13113;
  D.13114 = info->thread_state;
  D.13115 = D.13114 | 32;
  info->thread_state = D.13115;
  D.13116 = mono_threads_get_runtime_callbacks ();
  D.13117 = D.13116->thread_state_init_from_sigctx;
  D.13118 = &info->suspend_state;
  ret = D.13117 (D.13118, 0B);
  D.13119 = ret == 0;
  D.13120 = (long int) D.13119;
  D.13121 = __builtin_expect (D.13120, 0);
  if (D.13121 != 0) goto <D.13122>; else goto <D.13123>;
  <D.13122>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 419, "ret");
  <D.13123>:
  D.13105 = &info->suspend_semaphore;
  mono_sem_post (D.13105);
  goto <D.12875>;
  <D.12874>:
  <D.12875>:
  D.13124 = &info->resume_semaphore;
  D.13125 = mono_sem_wait (D.13124, 0);
  if (D.13125 != 0) goto <D.12874>; else goto <D.12876>;
  <D.12876>:
  D.13126 = info->async_target;
  D.13127 = D.13126 != 0B;
  D.13128 = (long int) D.13127;
  D.13129 = __builtin_expect (D.13128, 0);
  if (D.13129 != 0) goto <D.13130>; else goto <D.13131>;
  <D.13130>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 425, "!info->async_target");
  <D.13131>:
  D.13132 = &info->finish_resume_semaphore;
  mono_sem_post (D.13132);
}


mono_thread_info_resume (MonoNativeThreadId tid)
{
  gboolean D.13136;
  union MonoSemType * D.13137;
  int D.13138;
  int D.13139;
  long unsigned int D.13144;
  _Bool D.13145;
  long int D.13146;
  long int D.13147;
  int D.13150;
  struct MonoThreadInfo * D.13155;
  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.13134>; else goto <D.13135>;
  <D.13134>:
  D.13136 = 0;
  return D.13136;
  <D.13135>:
  goto <D.12891>;
  <D.12890>:
  <D.12891>:
  D.13137 = &info->suspend_semaphore;
  D.13138 = mono_sem_wait (D.13137, 0);
  if (D.13138 != 0) goto <D.12890>; else goto <D.12892>;
  <D.12892>:
  D.13139 = info->suspend_count;
  if (D.13139 <= 0) goto <D.13140>; else goto <D.13141>;
  <D.13140>:
  D.13137 = &info->suspend_semaphore;
  mono_sem_post (D.13137);
  if (0 != 0) goto <D.13142>; else goto <D.13143>;
  <D.13142>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 459, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13143>:
  hp->hazard_pointers[1] = 0B;
  D.13136 = 0;
  return D.13136;
  <D.13141>:
  D.13144 = info->node.key;
  D.13145 = D.13144 == 0;
  D.13146 = (long int) D.13145;
  D.13147 = __builtin_expect (D.13146, 0);
  if (D.13147 != 0) goto <D.13148>; else goto <D.13149>;
  <D.13148>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 467, "mono_thread_info_get_tid (info)");
  <D.13149>:
  D.13139 = info->suspend_count;
  D.13150 = D.13139 + -1;
  info->suspend_count = D.13150;
  D.13139 = info->suspend_count;
  if (D.13139 == 0) goto <D.13151>; else goto <D.13152>;
  <D.13151>:
  result = mono_thread_info_resume_internal (info);
  <D.13152>:
  D.13137 = &info->suspend_semaphore;
  mono_sem_post (D.13137);
  if (0 != 0) goto <D.13153>; else goto <D.13154>;
  <D.13153>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 473, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13154>:
  hp->hazard_pointers[1] = 0B;
  D.13155 = mono_thread_info_current ();
  D.13155->inside_critical_region = 0;
  D.13136 = result;
  return D.13136;
}


mono_thread_info_resume_internal (struct MonoThreadInfo * info)
{
  int D.13157;
  int D.13158;
  union MonoSemType * D.13161;
  union MonoSemType * D.13162;
  int D.13163;
  int D.13165;
  gboolean D.13166;
  gboolean result;

  D.13157 = info->thread_state;
  D.13158 = D.13157 & 240;
  if (D.13158 == 32) goto <D.13159>; else goto <D.13160>;
  <D.13159>:
  D.13161 = &info->resume_semaphore;
  mono_sem_post (D.13161);
  goto <D.12882>;
  <D.12881>:
  <D.12882>:
  D.13162 = &info->finish_resume_semaphore;
  D.13163 = mono_sem_wait (D.13162, 0);
  if (D.13163 != 0) goto <D.12881>; else goto <D.12883>;
  <D.12883>:
  result = 1;
  goto <D.13164>;
  <D.13160>:
  result = mono_threads_core_resume (info);
  <D.13164>:
  D.13157 = info->thread_state;
  D.13165 = D.13157 & -241;
  info->thread_state = D.13165;
  D.13166 = result;
  return D.13166;
}


mono_thread_info_finish_suspend ()
{
  struct MonoThreadInfo * D.13168;

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


mono_thread_info_safe_suspend_sync (MonoNativeThreadId id, gboolean interrupt_kernel)
{
  long unsigned int D.13169;
  _Bool D.13170;
  long int D.13171;
  long int D.13172;
  void * id.14;
  struct MonoThreadInfo * D.13178;
  int D.13179;
  int D.13181;
  long unsigned int D.13187;
  struct MonoThreadInfo * D.13188;
  struct MonoThreadInfo * info;
  int sleep_duration;

  info = 0B;
  sleep_duration = 0;
  D.13169 = mono_native_thread_id_get ();
  D.13170 = D.13169 == id;
  D.13171 = (long int) D.13170;
  D.13172 = __builtin_expect (D.13171, 0);
  if (D.13172 != 0) goto <D.13173>; else goto <D.13174>;
  <D.13173>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 527, "id != mono_native_thread_id_get ()");
  <D.13174>:
  mono_thread_info_suspend_lock ();
  <D.12908>:
  info = mono_thread_info_suspend_sync (id, interrupt_kernel);
  if (info == 0B) goto <D.13175>; else goto <D.13176>;
  <D.13175>:
  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.13178 = 0B;
  return D.13178;
  <D.13176>:
  D.13179 = is_thread_in_critical_region (info);
  if (D.13179 == 0) goto <D.12907>; else goto <D.13180>;
  <D.13180>:
  D.13181 = mono_thread_info_resume (id);
  if (D.13181 == 0) goto <D.13182>; else goto <D.13183>;
  <D.13182>:
  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.13178 = 0B;
  return D.13178;
  <D.13183>:
  if (sleep_duration == 0) goto <D.13184>; else goto <D.13185>;
  <D.13184>:
  sched_yield ();
  goto <D.13186>;
  <D.13185>:
  D.13187 = (long unsigned int) sleep_duration;
  monoeg_g_usleep (D.13187);
  <D.13186>:
  sleep_duration = sleep_duration + 10;
  goto <D.12908>;
  <D.12907>:
  D.13188 = mono_thread_info_current ();
  D.13188->inside_critical_region = 1;
  mono_thread_info_suspend_unlock ();
  D.13178 = info;
  return D.13178;
}


mono_thread_info_suspend_sync (MonoNativeThreadId tid, gboolean interrupt_kernel)
{
  struct MonoThreadInfo * D.13192;
  union MonoSemType * D.13193;
  int D.13194;
  int D.13195;
  int D.13196;
  int D.13201;
  int D.13204;
  int D.13207;
  int D.13214;
  struct MonoThreadHazardPointers * hp;
  struct MonoThreadInfo * info;

  hp = mono_hazard_pointer_get ();
  info = mono_thread_info_lookup (tid);
  if (info == 0B) goto <D.13190>; else goto <D.13191>;
  <D.13190>:
  D.13192 = 0B;
  return D.13192;
  <D.13191>:
  goto <D.12864>;
  <D.12863>:
  <D.12864>:
  D.13193 = &info->suspend_semaphore;
  D.13194 = mono_sem_wait (D.13193, 0);
  if (D.13194 != 0) goto <D.12863>; else goto <D.12865>;
  <D.12865>:
  D.13195 = info->thread_state;
  D.13196 = D.13195 & 15;
  if (D.13196 > 1) goto <D.13197>; else goto <D.13198>;
  <D.13197>:
  if (0 != 0) goto <D.13199>; else goto <D.13200>;
  <D.13199>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 371, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13200>:
  hp->hazard_pointers[1] = 0B;
  D.13192 = 0B;
  return D.13192;
  <D.13198>:
  D.13201 = info->suspend_count;
  if (D.13201 != 0) goto <D.13202>; else goto <D.13203>;
  <D.13202>:
  D.13201 = info->suspend_count;
  D.13204 = D.13201 + 1;
  info->suspend_count = D.13204;
  if (0 != 0) goto <D.13205>; else goto <D.13206>;
  <D.13205>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 379, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13206>:
  hp->hazard_pointers[1] = 0B;
  D.13193 = &info->suspend_semaphore;
  mono_sem_post (D.13193);
  D.13192 = info;
  return D.13192;
  <D.13203>:
  D.13207 = mono_threads_core_suspend (info);
  if (D.13207 == 0) goto <D.13208>; else goto <D.13209>;
  <D.13208>:
  D.13193 = &info->suspend_semaphore;
  mono_sem_post (D.13193);
  if (0 != 0) goto <D.13210>; else goto <D.13211>;
  <D.13210>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 386, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13211>:
  hp->hazard_pointers[1] = 0B;
  D.13192 = 0B;
  return D.13192;
  <D.13209>:
  if (interrupt_kernel != 0) goto <D.13212>; else goto <D.13213>;
  <D.13212>:
  mono_threads_core_interrupt (info);
  <D.13213>:
  D.13201 = info->suspend_count;
  D.13204 = D.13201 + 1;
  info->suspend_count = D.13204;
  D.13195 = info->thread_state;
  D.13214 = D.13195 | 16;
  info->thread_state = D.13214;
  D.13193 = &info->suspend_semaphore;
  mono_sem_post (D.13193);
  if (0 != 0) goto <D.13215>; else goto <D.13216>;
  <D.13215>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 396, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13216>:
  hp->hazard_pointers[1] = 0B;
  D.13192 = info;
  return D.13192;
}


is_thread_in_critical_region (struct MonoThreadInfo * info)
{
  int D.13218;
  gboolean D.13221;
  void * D.13222;
  long int D.13225;
  char * D.13226;
  gboolean (*<T1c36>) (void *) D.13229;
  struct MonoMethod * method;
  struct MonoJitInfo * ji;

  D.13218 = info->inside_critical_region;
  if (D.13218 != 0) goto <D.13219>; else goto <D.13220>;
  <D.13219>:
  D.13221 = 1;
  return D.13221;
  <D.13220>:
  D.13222 = info->suspend_state.unwind_data[0];
  if (D.13222 == 0B) goto <D.13223>; else goto <D.13224>;
  <D.13223>:
  D.13221 = 0;
  return D.13221;
  <D.13224>:
  D.13225 = info->suspend_state.ctx.rip;
  D.13226 = (char *) D.13225;
  D.13222 = info->suspend_state.unwind_data[0];
  ji = mono_jit_info_table_find (D.13222, D.13226);
  if (ji == 0B) goto <D.13227>; else goto <D.13228>;
  <D.13227>:
  D.13221 = 0;
  return D.13221;
  <D.13228>:
  method = mono_jit_info_get_method (ji);
  D.13229 = threads_callbacks.mono_method_is_critical;
  D.13221 = D.13229 (method);
  return D.13221;
}


mono_thread_info_setup_async_call (struct MonoThreadInfo * info, void (*<Tc2>) (void *) target_func, void * user_data)
{
  int D.13231;
  _Bool D.13232;
  long int D.13233;
  long int D.13234;
  void (*<Tc2>) (void *) D.13237;
  _Bool D.13238;
  long int D.13239;
  long int D.13240;

  D.13231 = info->suspend_count;
  D.13232 = D.13231 == 0;
  D.13233 = (long int) D.13232;
  D.13234 = __builtin_expect (D.13233, 0);
  if (D.13234 != 0) goto <D.13235>; else goto <D.13236>;
  <D.13235>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 577, "info->suspend_count");
  <D.13236>:
  D.13237 = info->async_target;
  D.13238 = D.13237 != 0B;
  D.13239 = (long int) D.13238;
  D.13240 = __builtin_expect (D.13239, 0);
  if (D.13240 != 0) goto <D.13241>; else goto <D.13242>;
  <D.13241>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 579, "!info->async_target");
  <D.13242>:
  info->async_target = target_func;
  info->user_data = user_data;
}


mono_thread_info_suspend_lock ()
{
  int D.13243;

  goto <D.12919>;
  <D.12918>:
  <D.12919>:
  D.13243 = mono_sem_wait (&global_suspend_semaphore, 0);
  if (D.13243 != 0) goto <D.12918>; else goto <D.12920>;
  <D.12920>:
}


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.13246;
  int D.13248;
  int D.13251;
  int D.13252;
  struct MonoThreadHazardPointers * hp;
  struct MonoThreadInfo * info;

  D.13246 = mono_native_thread_id_get ();
  if (D.13246 == tid) goto <D.13244>; else goto <D.13247>;
  <D.13247>:
  D.13248 = mono_threads_core_needs_abort_syscall ();
  if (D.13248 == 0) goto <D.13244>; else goto <D.13245>;
  <D.13244>:
  return;
  <D.13245>:
  hp = mono_hazard_pointer_get ();
  info = mono_thread_info_lookup (tid);
  if (info == 0B) goto <D.13249>; else goto <D.13250>;
  <D.13249>:
  return;
  <D.13250>:
  D.13251 = info->thread_state;
  D.13252 = D.13251 & 15;
  if (D.13252 > 1) goto <D.13253>; else goto <D.13254>;
  <D.13253>:
  if (0 != 0) goto <D.13255>; else goto <D.13256>;
  <D.13255>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 633, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13256>:
  hp->hazard_pointers[1] = 0B;
  return;
  <D.13254>:
  mono_thread_info_suspend_lock ();
  mono_threads_core_abort_syscall (info);
  if (0 != 0) goto <D.13257>; else goto <D.13258>;
  <D.13257>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads.c", 641, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
  <D.13258>:
  hp->hazard_pointers[1] = 0B;
  mono_thread_info_suspend_unlock ();
}


mono_thread_info_new_interrupt_enabled ()
{
  gboolean D.13260;

  D.13260 = 0;
  return D.13260;
}


mono_thread_info_set_is_async_context (gboolean async_context)
{
  struct MonoThreadInfo * info;

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


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

  info = mono_thread_info_current ();
  if (info != 0B) goto <D.13264>; else goto <D.13265>;
  <D.13264>:
  D.13266 = info->is_async_context;
  return D.13266;
  <D.13265>:
  D.13266 = 0;
  return D.13266;
}


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

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


