mono_thread_get_tls_key ()
{
  pthread_key_t D.20843;

  D.20843 = current_object_key;
  return D.20843;
}


mono_thread_get_tls_offset ()
{
  gint32 D.20845;
  int offset;

  __asm__("lis	%0,tls_current_object@tprel@ha
addi	%0,%0, tls_current_object@tprel@l
" : "=r" offset);
  D.20845 = offset;
  return D.20845;
}


mono_thread_new_init (intptr_t tid, void * stack_start, void * func)
{
  void (*<T1437>) (intptr_t, void *, void *) mono_thread_start_cb.0;

  mono_thread_start_cb.0 = mono_thread_start_cb;
  if (mono_thread_start_cb.0 != 0B) goto <D.20848>; else goto <D.20849>;
  <D.20848>:
  mono_thread_start_cb.0 = mono_thread_start_cb;
  mono_thread_start_cb.0 (tid, stack_start, func);
  <D.20849>:
}


mono_threads_set_default_stacksize (guint32 stacksize)
{
  default_stacksize = stacksize;
}


mono_threads_get_default_stacksize ()
{
  uint32_t D.20850;

  D.20850 = default_stacksize;
  return D.20850;
}


mono_thread_create_internal (struct MonoDomain * domain, void * func, void * arg, gboolean threadpool_thread, gboolean no_detach, guint32 stack_size)
{
  struct _MonoInternalThread * * D.20852;
  guint32 (*<T3290>) (void *) func.1;
  struct MonoInternalThread * D.20856;
  const char * D.20857;
  struct MonoClass * D.20860;
  struct MonoClassField * D.20861;
  unsigned int D.20862;
  unsigned int D.20863;
  long unsigned int D.20864;
  long unsigned int D.20865;
  struct MonoClassField * D.20866;
  int D.20867;
  _Bool D.20868;
  long int D.20869;
  long int D.20870;
  struct MonoThread * thread;
  struct MonoInternalThread * internal;
  struct StartInfo * start_info;
  gboolean res;

  thread = create_thread_object (domain);
  internal = create_internal_thread ();
  D.20852 = &thread->internal_thread;
  mono_gc_wbarrier_set_field (thread, D.20852, internal);
  start_info = monoeg_malloc0 (32);
  func.1 = (guint32 (*<T3290>) (void *)) func;
  start_info->func = func.1;
  start_info->obj = thread;
  start_info->start_arg = arg;
  res = create_thread (thread, internal, start_info, threadpool_thread, no_detach, stack_size, 1);
  if (res == 0) goto <D.20854>; else goto <D.20855>;
  <D.20854>:
  D.20856 = 0B;
  return D.20856;
  <D.20855>:
  D.20857 = mono_check_corlib_version ();
  if (D.20857 == 0B) goto <D.20858>; else goto <D.20859>;
  <D.20858>:
  D.20860 = mono_defaults.internal_thread_class;
  D.20861 = D.20860->fields;
  D.20860 = mono_defaults.internal_thread_class;
  D.20862 = D.20860->field.count;
  D.20863 = D.20862 + 4294967295;
  D.20864 = (long unsigned int) D.20863;
  D.20865 = D.20864 * 32;
  D.20866 = D.20861 + D.20865;
  D.20867 = D.20866->offset;
  D.20868 = D.20867 != 312;
  D.20869 = (long int) D.20868;
  D.20870 = __builtin_expect (D.20869, 0);
  if (D.20870 != 0) goto <D.20871>; else goto <D.20872>;
  <D.20871>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 850, "((char*)&internal->unused2 - (char*)internal) == mono_defaults.internal_thread_class->fields [mono_defaults.internal_thread_class->field.count - 1].offset");
  <D.20872>:
  <D.20859>:
  D.20856 = internal;
  return D.20856;
}


create_thread_object (struct MonoDomain * domain)
{
  struct MonoClass * D.20874;
  struct MonoThread * D.20875;
  struct MonoVTable * vt;

  D.20874 = mono_defaults.thread_class;
  vt = mono_class_vtable (domain, D.20874);
  D.20875 = mono_gc_alloc_mature (vt);
  return D.20875;
}


create_internal_thread ()
{
  struct MonoDomain * D.20877;
  struct MonoClass * D.20878;
  void * D.20879;
  struct CRITICAL_SECTION * D.20880;
  unsigned int D.20881;
  int D.20882;
  int D.20883;
  void * * D.20886;
  struct MonoInternalThread * D.20887;
  struct MonoInternalThread * thread;
  struct MonoVTable * vt;

  D.20877 = mono_get_root_domain ();
  D.20878 = mono_defaults.internal_thread_class;
  vt = mono_class_vtable (D.20877, D.20878);
  thread = mono_gc_alloc_mature (vt);
  D.20879 = monoeg_malloc0 (48);
  thread->synch_cs = D.20879;
  D.20880 = thread->synch_cs;
  InitializeCriticalSection (D.20880);
  thread->apartment_state = 2;
  D.20881 = get_next_managed_thread_id ();
  D.20882 = (int) D.20881;
  thread->managed_id = D.20882;
  D.20883 = mono_gc_is_moving ();
  if (D.20883 != 0) goto <D.20884>; else goto <D.20885>;
  <D.20884>:
  thread->thread_pinning_ref = thread;
  D.20886 = &thread->thread_pinning_ref;
  mono_gc_register_root (D.20886, 8, 0B);
  <D.20885>:
  D.20887 = thread;
  return D.20887;
}


get_next_managed_thread_id ()
{
  guint32 D.20889;
  int D.20890;

  D.20890 = InterlockedIncrement (&managed_thread_id_counter);
  D.20889 = (guint32) D.20890;
  return D.20889;
}


InterlockedIncrement (volatile gint32 * val)
{
  gint32 D.20892;
  unsigned int D.20893;

  D.20893 = __sync_add_and_fetch_4 (val, 1);
  D.20892 = (gint32) D.20893;
  return D.20892;
}


create_thread (struct MonoThread * thread, struct MonoInternalThread * internal, struct StartInfo * start_info, gboolean threadpool_thread, gboolean no_detach, guint32 stack_size, gboolean throw_on_failure)
{
  _Bool D.20897;
  long int D.20898;
  long int D.20899;
  int shutting_down.2;
  _Bool D.20907;
  long int D.20908;
  long int D.20909;
  gboolean D.20912;
  struct MonoGHashTable * thread_start_args.3;
  int D.20916;
  struct MonoGHashTable * thread_start_args.4;
  void * D.20920;
  struct MonoGHashTable * threads_starting_up.5;
  int D.20924;
  struct MonoGHashTable * threads_starting_up.6;
  _Bool D.20930;
  long int D.20931;
  long int D.20932;
  void * D.20935;
  void * D.20936;
  _Bool D.20941;
  long int D.20942;
  long int D.20943;
  _Bool D.20948;
  long int D.20949;
  long int D.20950;
  unsigned int D.20953;
  guint32 iftmp.7;
  int D.20957;
  _Bool D.20967;
  long int D.20968;
  long int D.20969;
  _Bool D.20974;
  long int D.20975;
  long int D.20976;
  struct MonoException * D.20981;
  unsigned int D.20983;
  long unsigned int tid.8;
  unsigned char D.20985;
  int D.20988;
  void * D.20991;
  void * thread_handle;
  MonoNativeThreadId tid;
  guint32 create_flags;
  static const char __func__[14] = "create_thread";

  try
    {
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.20895>; else goto <D.20896>;
        <D.20895>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.20896>:
        D.20897 = ret != 0;
        D.20898 = (long int) D.20897;
        D.20899 = __builtin_expect (D.20898, 0);
        if (D.20899 != 0) goto <D.20900>; else goto <D.20901>;
        <D.20900>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 705, "ret == 0");
        <D.20901>:
      }
      shutting_down.2 = shutting_down;
      if (shutting_down.2 != 0) goto <D.20903>; else goto <D.20904>;
      <D.20903>:
      monoeg_g_free (start_info);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.20905>; else goto <D.20906>;
        <D.20905>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.20906>:
        D.20907 = ret != 0;
        D.20908 = (long int) D.20907;
        D.20909 = __builtin_expect (D.20908, 0);
        if (D.20909 != 0) goto <D.20910>; else goto <D.20911>;
        <D.20910>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 708, "ret == 0");
        <D.20911>:
      }
      D.20912 = 0;
      return D.20912;
      <D.20904>:
      thread_start_args.3 = thread_start_args;
      if (thread_start_args.3 == 0B) goto <D.20914>; else goto <D.20915>;
      <D.20914>:
      D.20916 = mono_gc_is_moving ();
      if (D.20916 == 0) goto <D.20917>; else goto <D.20918>;
      <D.20917>:
      mono_gc_register_root (&thread_start_args, 8, 0B);
      <D.20918>:
      thread_start_args.4 = mono_g_hash_table_new (0B, 0B);
      thread_start_args = thread_start_args.4;
      <D.20915>:
      thread_start_args.3 = thread_start_args;
      D.20920 = start_info->start_arg;
      mono_g_hash_table_insert (thread_start_args.3, thread, D.20920);
      threads_starting_up.5 = threads_starting_up;
      if (threads_starting_up.5 == 0B) goto <D.20922>; else goto <D.20923>;
      <D.20922>:
      D.20924 = mono_gc_is_moving ();
      if (D.20924 == 0) goto <D.20925>; else goto <D.20926>;
      <D.20925>:
      mono_gc_register_root (&threads_starting_up, 8, 0B);
      <D.20926>:
      threads_starting_up.6 = mono_g_hash_table_new_type (0B, 0B, 3);
      threads_starting_up = threads_starting_up.6;
      <D.20923>:
      threads_starting_up.5 = threads_starting_up;
      mono_g_hash_table_insert (threads_starting_up.5, thread, thread);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.20928>; else goto <D.20929>;
        <D.20928>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.20929>:
        D.20930 = ret != 0;
        D.20931 = (long int) D.20930;
        D.20932 = __builtin_expect (D.20931, 0);
        if (D.20932 != 0) goto <D.20933>; else goto <D.20934>;
        <D.20933>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 727, "ret == 0");
        <D.20934>:
      }
      D.20935 = CreateSemaphore (0B, 0, 2147483647, 0B);
      internal->start_notify = D.20935;
      D.20936 = internal->start_notify;
      if (D.20936 == 0B) goto <D.20937>; else goto <D.20938>;
      <D.20937>:
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.20939>; else goto <D.20940>;
        <D.20939>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.20940>:
        D.20941 = ret != 0;
        D.20942 = (long int) D.20941;
        D.20943 = __builtin_expect (D.20942, 0);
        if (D.20943 != 0) goto <D.20944>; else goto <D.20945>;
        <D.20944>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 731, "ret == 0");
        <D.20945>:
      }
      threads_starting_up.5 = threads_starting_up;
      mono_g_hash_table_remove (threads_starting_up.5, thread);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.20946>; else goto <D.20947>;
        <D.20946>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.20947>:
        D.20948 = ret != 0;
        D.20949 = (long int) D.20948;
        D.20950 = __builtin_expect (D.20949, 0);
        if (D.20950 != 0) goto <D.20951>; else goto <D.20952>;
        <D.20951>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 733, "ret == 0");
        <D.20952>:
      }
      D.20953 = GetLastError ();
      monoeg_g_log (0B, 16, "%s: CreateSemaphore error 0x%x", &__func__, D.20953);
      monoeg_g_free (start_info);
      D.20912 = 0;
      return D.20912;
      <D.20938>:
      if (stack_size == 0) goto <D.20954>; else goto <D.20955>;
      <D.20954>:
      D.20957 = internal->stack_size;
      if (D.20957 != 0) goto <D.20958>; else goto <D.20959>;
      <D.20958>:
      D.20957 = internal->stack_size;
      iftmp.7 = (guint32) D.20957;
      goto <D.20960>;
      <D.20959>:
      iftmp.7 = default_stacksize;
      <D.20960>:
      stack_size = iftmp.7;
      <D.20955>:
      create_flags = 4;
      if (no_detach != 0) goto <D.20961>; else goto <D.20962>;
      <D.20961>:
      create_flags = create_flags | 268435456;
      <D.20962>:
      thread_handle = mono_threads_create_thread (start_wrapper, start_info, stack_size, create_flags, &tid);
      if (thread_handle == 0B) goto <D.20963>; else goto <D.20964>;
      <D.20963>:
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.20965>; else goto <D.20966>;
        <D.20965>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.20966>:
        D.20967 = ret != 0;
        D.20968 = (long int) D.20967;
        D.20969 = __builtin_expect (D.20968, 0);
        if (D.20969 != 0) goto <D.20970>; else goto <D.20971>;
        <D.20970>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 754, "ret == 0");
        <D.20971>:
      }
      threads_starting_up.5 = threads_starting_up;
      mono_g_hash_table_remove (threads_starting_up.5, thread);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.20972>; else goto <D.20973>;
        <D.20972>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.20973>:
        D.20974 = ret != 0;
        D.20975 = (long int) D.20974;
        D.20976 = __builtin_expect (D.20975, 0);
        if (D.20976 != 0) goto <D.20977>; else goto <D.20978>;
        <D.20977>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 756, "ret == 0");
        <D.20978>:
      }
      monoeg_g_free (start_info);
      if (throw_on_failure != 0) goto <D.20979>; else goto <D.20980>;
      <D.20979>:
      D.20981 = mono_get_exception_execution_engine ("Couldn\'t create thread");
      mono_raise_exception (D.20981);
      goto <D.20982>;
      <D.20980>:
      D.20983 = GetLastError ();
      monoeg_g_log (0B, 16, "%s: CreateThread error 0x%x", &__func__, D.20983);
      <D.20982>:
      D.20912 = 0;
      return D.20912;
      <D.20964>:
      internal->handle = thread_handle;
      tid.8 = tid;
      internal->tid = tid.8;
      D.20985 = (unsigned char) threadpool_thread;
      internal->threadpool_thread = D.20985;
      if (threadpool_thread != 0) goto <D.20986>; else goto <D.20987>;
      <D.20986>:
      mono_thread_set_state (internal, 4);
      <D.20987>:
      D.20988 = handle_store (thread, 0);
      if (D.20988 == 0) goto <D.20989>; else goto <D.20990>;
      <D.20989>:
      D.20912 = 0;
      return D.20912;
      <D.20990>:
      D.20991 = internal->handle;
      ResumeThread (D.20991);
      D.20936 = internal->start_notify;
      if (D.20936 != 0B) goto <D.20992>; else goto <D.20993>;
      <D.20992>:
      D.20936 = internal->start_notify;
      WaitForSingleObjectEx (D.20936, 4294967295, 0);
      D.20936 = internal->start_notify;
      CloseHandle (D.20936);
      internal->start_notify = 0B;
      <D.20993>:
      D.20912 = 1;
      return D.20912;
    }
  finally
    {
      tid = {CLOBBER};
    }
}


start_wrapper (void * data)
{
  guint32 D.20996;
  volatile int dummy;

  mono_gc_set_stack_end (&dummy);
  D.20996 = start_wrapper_internal (data);
  return D.20996;
}


start_wrapper_internal (void * data)
{
  struct MonoThread * D.20998;
  struct MonoVTable * D.20999;
  _Bool D.21000;
  long int D.21001;
  long int D.21002;
  long unsigned int tid.9;
  unsigned int current_object_key.10;
  int D.21007;
  guint32 D.21010;
  long unsigned int tid.11;
  long int tid.12;
  unsigned char D.21013;
  void * D.21016;
  _Bool D.21021;
  long int D.21022;
  long int D.21023;
  struct MonoGHashTable * thread_start_args.13;
  _Bool D.21029;
  long int D.21030;
  long int D.21031;
  struct MonoObject * D.21034;
  _Bool D.21038;
  long int D.21039;
  long int D.21040;
  struct MonoThreadInfo * info;
  struct StartInfo * start_info;
  guint32 (*<T3290>) (void *) start_func;
  void * start_arg;
  gsize tid;
  struct MonoInternalThread * internal;
  struct MonoObject * start_delegate;
  struct MonoDomain * domain;

  try
    {
      start_info = data;
      D.20998 = start_info->obj;
      internal = D.20998->internal_thread;
      start_delegate = start_info->delegate;
      D.20998 = start_info->obj;
      D.20999 = D.20998->obj.vtable;
      domain = D.20999->domain;
      info = mono_thread_info_current ();
      D.21000 = info == 0B;
      D.21001 = (long int) D.21000;
      D.21002 = __builtin_expect (D.21001, 0);
      if (D.21002 != 0) goto <D.21003>; else goto <D.21004>;
      <D.21003>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 570, "info");
      <D.21004>:
      internal->thread_info = info;
      tid.9 = internal->tid;
      tid = tid.9;
      tls_current_object = internal;
      current_object_key.10 = current_object_key;
      mono_native_tls_set_value (current_object_key.10, internal);
      mono_monitor_init_tls ();
      mono_thread_push_appdomain_ref (domain);
      D.21007 = mono_domain_set (domain, 0);
      if (D.21007 == 0) goto <D.21008>; else goto <D.21009>;
      <D.21008>:
      mono_thread_pop_appdomain_ref ();
      D.21010 = 0;
      return D.21010;
      <D.21009>:
      start_func = start_info->func;
      start_arg = start_info->start_arg;
      thread_adjust_static_data (internal);
      D.20998 = start_info->obj;
      init_root_domain_thread (internal, D.20998);
      tid.11 = tid;
      tid.12 = (long int) tid.11;
      mono_thread_new_init (tid.12, &tid, start_func);
      internal->stack_ptr = &tid;
      D.21013 = internal->apartment_state;
      if (D.21013 == 2) goto <D.21014>; else goto <D.21015>;
      <D.21014>:
      internal->apartment_state = 1;
      <D.21015>:
      mono_thread_init_apartment_state ();
      D.21016 = internal->start_notify;
      if (D.21016 != 0B) goto <D.21017>; else goto <D.21018>;
      <D.21017>:
      D.21016 = internal->start_notify;
      ReleaseSemaphore (D.21016, 1, 0B);
      <D.21018>:
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.21019>; else goto <D.21020>;
        <D.21019>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.21020>:
        D.21021 = ret != 0;
        D.21022 = (long int) D.21021;
        D.21023 = __builtin_expect (D.21022, 0);
        if (D.21023 != 0) goto <D.21024>; else goto <D.21025>;
        <D.21024>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 623, "ret == 0");
        <D.21025>:
      }
      thread_start_args.13 = thread_start_args;
      D.20998 = start_info->obj;
      mono_g_hash_table_remove (thread_start_args.13, D.20998);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.21027>; else goto <D.21028>;
        <D.21027>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.21028>:
        D.21029 = ret != 0;
        D.21030 = (long int) D.21029;
        D.21031 = __builtin_expect (D.21030, 0);
        if (D.21031 != 0) goto <D.21032>; else goto <D.21033>;
        <D.21032>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 625, "ret == 0");
        <D.21033>:
      }
      D.20998 = start_info->obj;
      D.21034 = D.20998->ec_to_set;
      mono_thread_set_execution_context (D.21034);
      D.20998 = start_info->obj;
      D.20998->ec_to_set = 0B;
      monoeg_g_free (start_info);
      tid.11 = tid;
      mono_profiler_thread_start (tid.11);
      if (start_func != 0B) goto <D.21035>; else goto <D.21036>;
      <D.21035>:
      start_func (start_arg);
      goto <D.21037>;
      <D.21036>:
      {
        void * args[1];

        try
          {
            D.21038 = start_delegate == 0B;
            D.21039 = (long int) D.21038;
            D.21040 = __builtin_expect (D.21039, 0);
            if (D.21040 != 0) goto <D.21041>; else goto <D.21042>;
            <D.21041>:
            monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 646, "start_delegate != NULL");
            <D.21042>:
            args[0] = start_arg;
            mono_runtime_delegate_invoke (start_delegate, &args, 0B);
          }
        finally
          {
            args = {CLOBBER};
          }
      }
      <D.21037>:
      mono_thread_cleanup_apartment_state ();
      thread_cleanup (internal);
      tls_current_object = 0B;
      current_object_key.10 = current_object_key;
      mono_native_tls_set_value (current_object_key.10, 0B);
      D.21010 = 0;
      return D.21010;
    }
  finally
    {
      tid = {CLOBBER};
    }
}


thread_adjust_static_data (struct MonoInternalThread * thread)
{
  _Bool D.21047;
  long int D.21048;
  long int D.21049;
  int D.21054;
  int D.21056;
  int D.21057;
  int D.21058;
  int D.21059;
  void * * * D.21060;
  _Bool D.21063;
  long int D.21064;
  long int D.21065;
  guint32 offset;

  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.21045>; else goto <D.21046>;
    <D.21045>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.21046>:
    D.21047 = ret != 0;
    D.21048 = (long int) D.21047;
    D.21049 = __builtin_expect (D.21048, 0);
    if (D.21049 != 0) goto <D.21050>; else goto <D.21051>;
    <D.21050>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3819, "ret == 0");
    <D.21051>:
  }
  D.21054 = thread_static_info.offset;
  if (D.21054 != 0) goto <D.21052>; else goto <D.21055>;
  <D.21055>:
  D.21056 = thread_static_info.idx;
  if (D.21056 > 0) goto <D.21052>; else goto <D.21053>;
  <D.21052>:
  D.21054 = thread_static_info.offset;
  D.21056 = thread_static_info.idx;
  D.21057 = D.21056 + 1;
  D.21058 = D.21057 << 24;
  D.21059 = D.21054 | D.21058;
  offset = (guint32) D.21059;
  D.21060 = &thread->static_data;
  mono_alloc_static_data (D.21060, offset, 1);
  <D.21053>:
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.21061>; else goto <D.21062>;
    <D.21061>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21062>:
    D.21063 = ret != 0;
    D.21064 = (long int) D.21063;
    D.21065 = __builtin_expect (D.21064, 0);
    if (D.21065 != 0) goto <D.21066>; else goto <D.21067>;
    <D.21066>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3825, "ret == 0");
    <D.21067>:
  }
}


mono_alloc_static_data (void * * * static_data_ptr, guint32 offset, gboolean threadlocal)
{
  unsigned int D.21068;
  int D.21071;
  void * tls_desc.14;
  void * tls_desc.15;
  int D.21078;
  long unsigned int D.21079;
  void * iftmp.16;
  long unsigned int D.21084;
  long unsigned int D.21085;
  void * * D.21086;
  void * D.21087;
  int D.21092;
  int D.21095;
  long unsigned int D.21096;
  void * D.21097;
  long unsigned int D.21098;
  void * D.21099;
  unsigned int i.17;
  guint idx;
  int i;
  void * * static_data;

  D.21068 = offset >> 24;
  idx = D.21068 + 4294967295;
  static_data = *static_data_ptr;
  if (static_data == 0B) goto <D.21069>; else goto <D.21070>;
  <D.21069>:
  {
    static void * tls_desc = 0B;

    D.21071 = mono_gc_user_markers_supported ();
    if (D.21071 != 0) goto <D.21072>; else goto <D.21073>;
    <D.21072>:
    tls_desc.14 = tls_desc;
    if (tls_desc.14 == 0B) goto <D.21075>; else goto <D.21076>;
    <D.21075>:
    tls_desc.15 = mono_gc_make_root_descr_user (mark_tls_slots);
    tls_desc = tls_desc.15;
    <D.21076>:
    <D.21073>:
    D.21078 = 1024;
    D.21079 = (long unsigned int) D.21078;
    if (threadlocal != 0) goto <D.21081>; else goto <D.21082>;
    <D.21081>:
    iftmp.16 = tls_desc;
    goto <D.21083>;
    <D.21082>:
    iftmp.16 = 0B;
    <D.21083>:
    static_data = mono_gc_alloc_fixed (D.21079, iftmp.16);
    *static_data_ptr = static_data;
    *static_data = static_data;
  }
  <D.21070>:
  i = 1;
  goto <D.20519>;
  <D.20518>:
  D.21084 = (long unsigned int) i;
  D.21085 = D.21084 * 8;
  D.21086 = static_data + D.21085;
  D.21087 = *D.21086;
  if (D.21087 != 0B) goto <D.21088>; else goto <D.21089>;
  <D.21088>:
  // predicted unlikely by continue predictor.
  goto <D.20517>;
  <D.21089>:
  D.21092 = mono_gc_user_markers_supported ();
  if (D.21092 != 0) goto <D.21093>; else goto <D.21090>;
  <D.21093>:
  if (threadlocal != 0) goto <D.21094>; else goto <D.21090>;
  <D.21094>:
  D.21084 = (long unsigned int) i;
  D.21085 = D.21084 * 8;
  D.21086 = static_data + D.21085;
  D.21095 = static_data_size[i];
  D.21096 = (long unsigned int) D.21095;
  D.21097 = monoeg_malloc0 (D.21096);
  *D.21086 = D.21097;
  goto <D.21091>;
  <D.21090>:
  D.21084 = (long unsigned int) i;
  D.21085 = D.21084 * 8;
  D.21086 = static_data + D.21085;
  D.21095 = static_data_size[i];
  D.21098 = (long unsigned int) D.21095;
  D.21099 = mono_gc_alloc_fixed (D.21098, 0B);
  *D.21086 = D.21099;
  <D.21091>:
  <D.20517>:
  i = i + 1;
  <D.20519>:
  i.17 = (unsigned int) i;
  if (i.17 <= idx) goto <D.20518>; else goto <D.20520>;
  <D.20520>:
}


mark_tls_slots (void * addr, void (*MonoGCMarkFunc) (void * *) mark_func)
{
  long unsigned int D.21101;
  long unsigned int D.21102;
  void * * D.21103;
  void * D.21104;
  int D.21107;
  long unsigned int D.21108;
  long unsigned int D.21109;
  unsigned int D.21110;
  unsigned int D.21111;
  uintptr_t * D.21112;
  long unsigned int D.21113;
  long unsigned int D.21114;
  uintptr_t * D.21115;
  long unsigned int D.21116;
  void * D.21119;
  int i;
  void * * static_data;

  static_data = addr;
  i = 0;
  goto <D.20506>;
  <D.20505>:
  {
    int j;
    int numwords;
    void * * ptr;

    D.21101 = (long unsigned int) i;
    D.21102 = D.21101 * 8;
    D.21103 = static_data + D.21102;
    D.21104 = *D.21103;
    if (D.21104 == 0B) goto <D.21105>; else goto <D.21106>;
    <D.21105>:
    // predicted unlikely by continue predictor.
    goto <D.20496>;
    <D.21106>:
    D.21107 = static_data_size[i];
    D.21108 = (long unsigned int) D.21107;
    D.21109 = D.21108 / 512;
    D.21110 = (unsigned int) D.21109;
    D.21111 = D.21110 + 1;
    numwords = (int) D.21111;
    D.21101 = (long unsigned int) i;
    D.21102 = D.21101 * 8;
    D.21103 = static_data + D.21102;
    ptr = *D.21103;
    j = 0;
    goto <D.20503>;
    <D.20502>:
    {
      uintptr_t bmap;
      void * * p;

      D.21112 = static_reference_bitmaps[i];
      D.21113 = (long unsigned int) j;
      D.21114 = D.21113 * 8;
      D.21115 = D.21112 + D.21114;
      bmap = *D.21115;
      p = ptr;
      goto <D.20500>;
      <D.20499>:
      D.21116 = bmap & 1;
      if (D.21116 != 0) goto <D.21117>; else goto <D.21118>;
      <D.21117>:
      D.21119 = *p;
      if (D.21119 != 0B) goto <D.21120>; else goto <D.21121>;
      <D.21120>:
      mark_func (p);
      <D.21121>:
      <D.21118>:
      p = p + 8;
      bmap = bmap >> 1;
      <D.20500>:
      if (bmap != 0) goto <D.20499>; else goto <D.20501>;
      <D.20501>:
    }
    j = j + 1;
    ptr = ptr + 512;
    <D.20503>:
    if (j < numwords) goto <D.20502>; else goto <D.20504>;
    <D.20504>:
  }
  <D.20496>:
  i = i + 1;
  <D.20506>:
  if (i <= 7) goto <D.20505>; else goto <D.20507>;
  <D.20507>:
}


init_root_domain_thread (struct MonoInternalThread * thread, struct MonoThread * candidate)
{
  struct MonoVTable * D.21125;
  struct MonoDomain * D.21126;
  struct MonoThread * D.21127;
  _Bool D.21128;
  long int D.21129;
  long int D.21130;
  struct MonoThread * * D.21133;
  struct MonoDomain * domain;

  domain = mono_get_root_domain ();
  if (candidate == 0B) goto <D.21122>; else goto <D.21124>;
  <D.21124>:
  D.21125 = candidate->obj.vtable;
  D.21126 = D.21125->domain;
  if (D.21126 != domain) goto <D.21122>; else goto <D.21123>;
  <D.21122>:
  candidate = new_thread_with_internal (domain, thread);
  <D.21123>:
  set_current_thread_for_domain (domain, thread, candidate);
  D.21127 = thread->root_domain_thread;
  D.21128 = D.21127 != 0B;
  D.21129 = (long int) D.21128;
  D.21130 = __builtin_expect (D.21129, 0);
  if (D.21130 != 0) goto <D.21131>; else goto <D.21132>;
  <D.21131>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 542, "!thread->root_domain_thread");
  <D.21132>:
  D.21133 = &thread->root_domain_thread;
  mono_gc_wbarrier_set_field (thread, D.21133, candidate);
}


new_thread_with_internal (struct MonoDomain * domain, struct MonoInternalThread * internal)
{
  struct _MonoInternalThread * * D.21134;
  struct MonoThread * D.21135;
  struct MonoThread * thread;

  thread = create_thread_object (domain);
  D.21134 = &thread->internal_thread;
  mono_gc_wbarrier_set_field (thread, D.21134, internal);
  D.21135 = thread;
  return D.21135;
}


set_current_thread_for_domain (struct MonoDomain * domain, struct MonoInternalThread * thread, struct MonoThread * current)
{
  struct MonoVTable * D.21137;
  struct MonoDomain * D.21138;
  _Bool D.21139;
  long int D.21140;
  long int D.21141;
  struct MonoThread * D.21144;
  _Bool D.21145;
  long int D.21146;
  long int D.21147;
  struct MonoThread * * current_thread_ptr;

  current_thread_ptr = get_current_thread_ptr_for_domain (domain, thread);
  D.21137 = current->obj.vtable;
  D.21138 = D.21137->domain;
  D.21139 = D.21138 != domain;
  D.21140 = (long int) D.21139;
  D.21141 = __builtin_expect (D.21140, 0);
  if (D.21141 != 0) goto <D.21142>; else goto <D.21143>;
  <D.21142>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 491, "current->obj.vtable->domain == domain");
  <D.21143>:
  D.21144 = *current_thread_ptr;
  D.21145 = D.21144 != 0B;
  D.21146 = (long int) D.21145;
  D.21147 = __builtin_expect (D.21146, 0);
  if (D.21147 != 0) goto <D.21148>; else goto <D.21149>;
  <D.21148>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 493, "!*current_thread_ptr");
  <D.21149>:
  *current_thread_ptr = current;
}


get_current_thread_ptr_for_domain (struct MonoDomain * domain, struct MonoInternalThread * thread)
{
  struct MonoClassField * current_thread_field.18;
  struct MonoClass * D.21153;
  struct MonoClassField * current_thread_field.19;
  _Bool D.21155;
  long int D.21156;
  long int D.21157;
  union mono_mutex_t * D.21160;
  _Bool D.21163;
  long int D.21164;
  long int D.21165;
  struct GHashTable * D.21168;
  void * D.21169;
  long int D.21170;
  _Bool D.21173;
  long int D.21174;
  long int D.21175;
  _Bool D.21178;
  long int D.21179;
  long int D.21180;
  struct MonoThread * * D.21183;
  static struct MonoClassField * current_thread_field = 0B;
  guint32 offset;

  current_thread_field.18 = current_thread_field;
  if (current_thread_field.18 == 0B) goto <D.21151>; else goto <D.21152>;
  <D.21151>:
  D.21153 = mono_defaults.thread_class;
  current_thread_field.19 = mono_class_get_field_from_name (D.21153, "current_thread");
  current_thread_field = current_thread_field.19;
  current_thread_field.18 = current_thread_field;
  D.21155 = current_thread_field.18 == 0B;
  D.21156 = (long int) D.21155;
  D.21157 = __builtin_expect (D.21156, 0);
  if (D.21157 != 0) goto <D.21158>; else goto <D.21159>;
  <D.21158>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 474, "current_thread_field");
  <D.21159>:
  <D.21152>:
  D.21153 = mono_defaults.thread_class;
  mono_class_vtable (domain, D.21153);
  {
    int ret;

    D.21160 = &domain->lock.mutex;
    ret = pthread_mutex_lock (D.21160);
    if (ret != 0) goto <D.21161>; else goto <D.21162>;
    <D.21161>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.21162>:
    D.21163 = ret != 0;
    D.21164 = (long int) D.21163;
    D.21165 = __builtin_expect (D.21164, 0);
    if (D.21165 != 0) goto <D.21166>; else goto <D.21167>;
    <D.21166>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 478, "ret == 0");
    <D.21167>:
  }
  D.21168 = domain->special_static_fields;
  current_thread_field.18 = current_thread_field;
  D.21169 = monoeg_g_hash_table_lookup (D.21168, current_thread_field.18);
  D.21170 = (long int) D.21169;
  offset = (guint32) D.21170;
  {
    int ret;

    D.21160 = &domain->lock.mutex;
    ret = pthread_mutex_unlock (D.21160);
    if (ret != 0) goto <D.21171>; else goto <D.21172>;
    <D.21171>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21172>:
    D.21173 = ret != 0;
    D.21174 = (long int) D.21173;
    D.21175 = __builtin_expect (D.21174, 0);
    if (D.21175 != 0) goto <D.21176>; else goto <D.21177>;
    <D.21176>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 480, "ret == 0");
    <D.21177>:
  }
  D.21178 = offset == 0;
  D.21179 = (long int) D.21178;
  D.21180 = __builtin_expect (D.21179, 0);
  if (D.21180 != 0) goto <D.21181>; else goto <D.21182>;
  <D.21181>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 481, "offset");
  <D.21182>:
  D.21183 = get_thread_static_data (thread, offset);
  return D.21183;
}


get_thread_static_data (struct MonoInternalThread * thread, guint32 offset)
{
  signed int offset.20;
  _Bool D.21186;
  long int D.21187;
  long int D.21188;
  unsigned int D.21191;
  unsigned int D.21192;
  void * D.21193;
  void * * D.21194;
  long unsigned int D.21195;
  long unsigned int D.21196;
  void * * D.21197;
  void * D.21198;
  sizetype D.21199;
  sizetype D.21200;
  int idx;

  offset.20 = (signed int) offset;
  D.21186 = offset.20 < 0;
  D.21187 = (long int) D.21186;
  D.21188 = __builtin_expect (D.21187, 0);
  if (D.21188 != 0) goto <D.21189>; else goto <D.21190>;
  <D.21189>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 459, "(offset & 0x80000000) == 0");
  <D.21190>:
  offset = offset & 2147483647;
  D.21191 = offset >> 24;
  D.21192 = D.21191 + 4294967295;
  idx = (int) D.21192;
  D.21194 = thread->static_data;
  D.21195 = (long unsigned int) idx;
  D.21196 = D.21195 * 8;
  D.21197 = D.21194 + D.21196;
  D.21198 = *D.21197;
  D.21199 = (sizetype) offset;
  D.21200 = D.21199 & 16777215;
  D.21193 = D.21198 + D.21200;
  return D.21193;
}


thread_cleanup (struct MonoInternalThread * thread)
{
  _Bool D.21202;
  long int D.21203;
  long int D.21204;
  int D.21207;
  unsigned int D.21210;
  struct MonoArray * D.21211;
  long unsigned int D.21214;
  struct CRITICAL_SECTION * D.21215;
  int shutting_down.21;
  _Bool D.21220;
  long int D.21221;
  long int D.21222;
  unsigned int D.21225;
  unsigned int D.21226;
  unsigned int D.21227;
  gint32 * D.21230;
  int D.21231;
  int D.21234;
  struct MonoInternalThread * D.21237;
  void (*<T2218>) (struct MonoInternalThread *) mono_thread_cleanup_fn.22;
  long unsigned int D.21243;
  struct MonoInternalThread * D.21244;
  struct MonoInternalThread * D.21247;
  void * * D.21250;
  void * D.21251;
  int D.21254;
  void * * D.21257;

  D.21202 = thread == 0B;
  D.21203 = (long int) D.21202;
  D.21204 = __builtin_expect (D.21203, 0);
  if (D.21204 != 0) goto <D.21205>; else goto <D.21206>;
  <D.21205>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 368, "thread != NULL");
  <D.21206>:
  D.21207 = thread->abort_state_handle;
  if (D.21207 != 0) goto <D.21208>; else goto <D.21209>;
  <D.21208>:
  D.21207 = thread->abort_state_handle;
  D.21210 = (unsigned int) D.21207;
  mono_gchandle_free (D.21210);
  thread->abort_state_handle = 0;
  <D.21209>:
  thread->abort_exc = 0B;
  thread->current_appcontext = 0B;
  D.21211 = thread->cached_culture_info;
  if (D.21211 != 0B) goto <D.21212>; else goto <D.21213>;
  <D.21212>:
  {
    int i;

    i = 0;
    goto <D.19528>;
    <D.19527>:
    {
      struct MonoObject * * __p;

      D.21211 = thread->cached_culture_info;
      D.21214 = (long unsigned int) i;
      __p = mono_array_addr_with_size (D.21211, 8, D.21214);
      *__p = 0B;
    }
    i = i + 1;
    <D.19528>:
    if (i <= 7) goto <D.19527>; else goto <D.19529>;
    <D.19529>:
  }
  <D.21213>:
  D.21215 = thread->synch_cs;
  if (D.21215 != 0B) goto <D.21216>; else goto <D.21217>;
  <D.21216>:
  lock_thread (thread);
  goto <D.21218>;
  <D.21217>:
  shutting_down.21 = shutting_down;
  D.21220 = shutting_down.21 == 0;
  D.21221 = (long int) D.21220;
  D.21222 = __builtin_expect (D.21221, 0);
  if (D.21222 != 0) goto <D.21223>; else goto <D.21224>;
  <D.21223>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 391, "shutting_down");
  <D.21224>:
  <D.21218>:
  D.21225 = thread->state;
  D.21226 = D.21225 | 16;
  thread->state = D.21226;
  D.21225 = thread->state;
  D.21227 = D.21225 & 4294967291;
  thread->state = D.21227;
  D.21215 = thread->synch_cs;
  if (D.21215 != 0B) goto <D.21228>; else goto <D.21229>;
  <D.21228>:
  unlock_thread (thread);
  <D.21229>:
  D.21230 = &thread->interruption_requested;
  D.21231 = InterlockedExchange (D.21230, 0);
  if (D.21231 != 0) goto <D.21232>; else goto <D.21233>;
  <D.21232>:
  InterlockedDecrement (&thread_interruption_requested);
  <D.21233>:
  D.21234 = handle_remove (thread);
  if (D.21234 == 0) goto <D.21235>; else goto <D.21236>;
  <D.21235>:
  D.21237 = mono_thread_internal_current ();
  if (D.21237 == thread) goto <D.21238>; else goto <D.21239>;
  <D.21238>:
  mono_domain_unset ();
  mono_memory_barrier ();
  <D.21239>:
  mono_thread_cleanup_fn.22 = mono_thread_cleanup_fn;
  if (mono_thread_cleanup_fn.22 != 0B) goto <D.21241>; else goto <D.21242>;
  <D.21241>:
  mono_thread_cleanup_fn.22 = mono_thread_cleanup_fn;
  mono_thread_cleanup_fn.22 (thread);
  <D.21242>:
  return;
  <D.21236>:
  mono_release_type_locks (thread);
  D.21243 = thread->tid;
  mono_profiler_thread_end (D.21243);
  D.21244 = mono_thread_internal_current ();
  if (D.21244 == thread) goto <D.21245>; else goto <D.21246>;
  <D.21245>:
  mono_domain_unset ();
  mono_memory_barrier ();
  <D.21246>:
  D.21247 = mono_thread_internal_current ();
  if (D.21247 == thread) goto <D.21248>; else goto <D.21249>;
  <D.21248>:
  mono_thread_pop_appdomain_ref ();
  <D.21249>:
  thread->cached_culture_info = 0B;
  D.21250 = thread->static_data;
  mono_free_static_data (D.21250, 1);
  thread->static_data = 0B;
  D.21251 = thread->appdomain_refs;
  ref_stack_destroy (D.21251);
  thread->appdomain_refs = 0B;
  mono_thread_cleanup_fn.22 = mono_thread_cleanup_fn;
  if (mono_thread_cleanup_fn.22 != 0B) goto <D.21252>; else goto <D.21253>;
  <D.21252>:
  mono_thread_cleanup_fn.22 = mono_thread_cleanup_fn;
  mono_thread_cleanup_fn.22 (thread);
  <D.21253>:
  D.21254 = mono_gc_is_moving ();
  if (D.21254 != 0) goto <D.21255>; else goto <D.21256>;
  <D.21255>:
  D.21257 = &thread->thread_pinning_ref;
  mono_gc_deregister_root (D.21257);
  thread->thread_pinning_ref = 0B;
  <D.21256>:
}


lock_thread (struct MonoInternalThread * thread)
{
  struct CRITICAL_SECTION * D.21259;
  _Bool D.21262;
  long int D.21263;
  long int D.21264;
  union mono_mutex_t * D.21267;
  _Bool D.21270;
  long int D.21271;
  long int D.21272;

  D.21259 = thread->synch_cs;
  if (D.21259 == 0B) goto <D.21260>; else goto <D.21261>;
  <D.21260>:
  ensure_synch_cs_set (thread);
  <D.21261>:
  D.21259 = thread->synch_cs;
  D.21262 = D.21259 == 0B;
  D.21263 = (long int) D.21262;
  D.21264 = __builtin_expect (D.21263, 0);
  if (D.21264 != 0) goto <D.21265>; else goto <D.21266>;
  <D.21265>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 351, "thread->synch_cs");
  <D.21266>:
  {
    int ret;

    D.21259 = thread->synch_cs;
    D.21267 = &D.21259->mutex;
    ret = pthread_mutex_lock (D.21267);
    if (ret != 0) goto <D.21268>; else goto <D.21269>;
    <D.21268>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.21269>:
    D.21270 = ret != 0;
    D.21271 = (long int) D.21270;
    D.21272 = __builtin_expect (D.21271, 0);
    if (D.21272 != 0) goto <D.21273>; else goto <D.21274>;
    <D.21273>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 352, "ret == 0");
    <D.21274>:
  }
}


ensure_synch_cs_set (struct MonoInternalThread * thread)
{
  struct CRITICAL_SECTION * D.21275;
  struct CRITICAL_SECTION * * D.21278;
  void * D.21279;
  struct CRITICAL_SECTION * synch_cs;

  D.21275 = thread->synch_cs;
  if (D.21275 != 0B) goto <D.21276>; else goto <D.21277>;
  <D.21276>:
  return;
  <D.21277>:
  synch_cs = monoeg_malloc0 (48);
  InitializeCriticalSection (synch_cs);
  D.21278 = &thread->synch_cs;
  D.21279 = InterlockedCompareExchangePointer (D.21278, synch_cs, 0B);
  if (D.21279 != 0B) goto <D.21280>; else goto <D.21281>;
  <D.21280>:
  DeleteCriticalSection (synch_cs);
  monoeg_g_free (synch_cs);
  <D.21281>:
}


InterlockedCompareExchangePointer (void * volatile * dest, void * exch, void * comp)
{
  void * D.21283;
  long unsigned int comp.23;
  long unsigned int exch.24;
  long unsigned int D.21286;

  comp.23 = (long unsigned int) comp;
  exch.24 = (long unsigned int) exch;
  D.21286 = __sync_val_compare_and_swap_8 (dest, comp.23, exch.24);
  D.21283 = (void *) D.21286;
  return D.21283;
}


unlock_thread (struct MonoInternalThread * thread)
{
  struct CRITICAL_SECTION * D.21288;
  union mono_mutex_t * D.21289;
  _Bool D.21292;
  long int D.21293;
  long int D.21294;

  {
    int ret;

    D.21288 = thread->synch_cs;
    D.21289 = &D.21288->mutex;
    ret = pthread_mutex_unlock (D.21289);
    if (ret != 0) goto <D.21290>; else goto <D.21291>;
    <D.21290>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21291>:
    D.21292 = ret != 0;
    D.21293 = (long int) D.21292;
    D.21294 = __builtin_expect (D.21293, 0);
    if (D.21294 != 0) goto <D.21295>; else goto <D.21296>;
    <D.21295>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 358, "ret == 0");
    <D.21296>:
  }
}


InterlockedExchange (volatile gint32 * val, gint32 new_val)
{
  unsigned int old_val.25;
  unsigned int new_val.26;
  unsigned int D.21299;
  int D.21300;
  gint32 D.21301;
  gint32 old_val;

  <D.19323>:
  old_val = *val;
  old_val.25 = (unsigned int) old_val;
  new_val.26 = (unsigned int) new_val;
  D.21299 = __sync_val_compare_and_swap_4 (val, old_val.25, new_val.26);
  D.21300 = (int) D.21299;
  if (D.21300 != old_val) goto <D.19323>; else goto <D.19324>;
  <D.19324>:
  D.21301 = old_val;
  return D.21301;
}


InterlockedDecrement (volatile gint32 * val)
{
  gint32 D.21303;
  unsigned int D.21304;

  D.21304 = __sync_sub_and_fetch_4 (val, 1);
  D.21303 = (gint32) D.21304;
  return D.21303;
}


handle_remove (struct MonoInternalThread * thread)
{
  _Bool D.21308;
  long int D.21309;
  long int D.21310;
  struct MonoGHashTable * threads.27;
  const void * tid.28;
  void * D.21317;
  _Bool D.21324;
  long int D.21325;
  long int D.21326;
  gboolean D.21329;
  gboolean ret;
  gsize tid;

  tid = thread->tid;
  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.21306>; else goto <D.21307>;
    <D.21306>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.21307>:
    D.21308 = ret != 0;
    D.21309 = (long int) D.21308;
    D.21310 = __builtin_expect (D.21309, 0);
    if (D.21310 != 0) goto <D.21311>; else goto <D.21312>;
    <D.21311>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 289, "ret == 0");
    <D.21312>:
  }
  threads.27 = threads;
  if (threads.27 != 0B) goto <D.21314>; else goto <D.21315>;
  <D.21314>:
  threads.27 = threads;
  tid.28 = (const void *) tid;
  D.21317 = mono_g_hash_table_lookup (threads.27, tid.28);
  if (D.21317 == thread) goto <D.21318>; else goto <D.21319>;
  <D.21318>:
  threads.27 = threads;
  tid.28 = (const void *) tid;
  mono_g_hash_table_remove (threads.27, tid.28);
  ret = 1;
  goto <D.21320>;
  <D.21319>:
  ret = 0;
  <D.21320>:
  goto <D.21321>;
  <D.21315>:
  ret = 0;
  <D.21321>:
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.21322>; else goto <D.21323>;
    <D.21322>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21323>:
    D.21324 = ret != 0;
    D.21325 = (long int) D.21324;
    D.21326 = __builtin_expect (D.21325, 0);
    if (D.21326 != 0) goto <D.21327>; else goto <D.21328>;
    <D.21327>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 308, "ret == 0");
    <D.21328>:
  }
  D.21329 = ret;
  return D.21329;
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


mono_free_static_data (void * * static_data, gboolean threadlocal)
{
  long unsigned int D.21331;
  long unsigned int D.21332;
  void * * D.21333;
  int D.21338;
  int i;

  i = 1;
  goto <D.20529>;
  <D.20528>:
  {
    void * p;

    D.21331 = (long unsigned int) i;
    D.21332 = D.21331 * 8;
    D.21333 = static_data + D.21332;
    p = *D.21333;
    if (p == 0B) goto <D.21334>; else goto <D.21335>;
    <D.21334>:
    // predicted unlikely by continue predictor.
    goto <D.20527>;
    <D.21335>:
    D.21331 = (long unsigned int) i;
    D.21332 = D.21331 * 8;
    D.21333 = static_data + D.21332;
    *D.21333 = 0B;
    mono_memory_write_barrier ();
    D.21338 = mono_gc_user_markers_supported ();
    if (D.21338 != 0) goto <D.21339>; else goto <D.21336>;
    <D.21339>:
    if (threadlocal != 0) goto <D.21340>; else goto <D.21336>;
    <D.21340>:
    monoeg_g_free (p);
    goto <D.21337>;
    <D.21336>:
    mono_gc_free_fixed (p);
    <D.21337>:
  }
  <D.20527>:
  i = i + 1;
  <D.20529>:
  if (i <= 7) goto <D.20528>; else goto <D.20530>;
  <D.20530>:
  mono_gc_free_fixed (static_data);
}


mono_memory_write_barrier ()
{
  mono_memory_barrier ();
}


ref_stack_destroy (void * ptr)
{
  void * * D.21343;
  struct RefStack * rs;

  rs = ptr;
  if (rs != 0B) goto <D.21341>; else goto <D.21342>;
  <D.21341>:
  D.21343 = rs->refs;
  monoeg_g_free (D.21343);
  monoeg_g_free (rs);
  <D.21342>:
}


mono_native_tls_set_value (pthread_key_t key, void * value)
{
  int D.21344;
  int D.21345;
  _Bool D.21346;

  D.21345 = pthread_setspecific (key, value);
  D.21346 = D.21345 == 0;
  D.21344 = (int) D.21346;
  return D.21344;
}


handle_store (struct MonoThread * thread, gboolean force_attach)
{
  _Bool D.21350;
  long int D.21351;
  long int D.21352;
  struct MonoGHashTable * threads_starting_up.29;
  int shutting_down.30;
  _Bool D.21365;
  long int D.21366;
  long int D.21367;
  gboolean D.21370;
  struct MonoGHashTable * threads.31;
  int D.21374;
  struct MonoGHashTable * threads.32;
  struct _MonoInternalThread * D.21378;
  _Bool D.21379;
  long int D.21380;
  long int D.21381;
  long unsigned int D.21384;
  void * D.21385;
  _Bool D.21388;
  long int D.21389;
  long int D.21390;

  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.21348>; else goto <D.21349>;
    <D.21348>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.21349>:
    D.21350 = ret != 0;
    D.21351 = (long int) D.21350;
    D.21352 = __builtin_expect (D.21351, 0);
    if (D.21352 != 0) goto <D.21353>; else goto <D.21354>;
    <D.21353>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 253, "ret == 0");
    <D.21354>:
  }
  threads_starting_up.29 = threads_starting_up;
  if (threads_starting_up.29 != 0B) goto <D.21356>; else goto <D.21357>;
  <D.21356>:
  threads_starting_up.29 = threads_starting_up;
  mono_g_hash_table_remove (threads_starting_up.29, thread);
  <D.21357>:
  shutting_down.30 = shutting_down;
  if (shutting_down.30 != 0) goto <D.21359>; else goto <D.21360>;
  <D.21359>:
  if (force_attach == 0) goto <D.21361>; else goto <D.21362>;
  <D.21361>:
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.21363>; else goto <D.21364>;
    <D.21363>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21364>:
    D.21365 = ret != 0;
    D.21366 = (long int) D.21365;
    D.21367 = __builtin_expect (D.21366, 0);
    if (D.21367 != 0) goto <D.21368>; else goto <D.21369>;
    <D.21368>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 261, "ret == 0");
    <D.21369>:
  }
  D.21370 = 0;
  return D.21370;
  <D.21362>:
  <D.21360>:
  threads.31 = threads;
  if (threads.31 == 0B) goto <D.21372>; else goto <D.21373>;
  <D.21372>:
  D.21374 = mono_gc_is_moving ();
  if (D.21374 == 0) goto <D.21375>; else goto <D.21376>;
  <D.21375>:
  mono_gc_register_root (&threads, 8, 0B);
  <D.21376>:
  threads.32 = mono_g_hash_table_new_type (0B, 0B, 2);
  threads = threads.32;
  <D.21373>:
  D.21378 = thread->internal_thread;
  D.21379 = D.21378 == 0B;
  D.21380 = (long int) D.21379;
  D.21381 = __builtin_expect (D.21380, 0);
  if (D.21381 != 0) goto <D.21382>; else goto <D.21383>;
  <D.21382>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 273, "thread->internal_thread");
  <D.21383>:
  threads.31 = threads;
  D.21378 = thread->internal_thread;
  D.21384 = D.21378->tid;
  D.21385 = (void *) D.21384;
  D.21378 = thread->internal_thread;
  mono_g_hash_table_insert (threads.31, D.21385, D.21378);
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.21386>; else goto <D.21387>;
    <D.21386>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21387>:
    D.21388 = ret != 0;
    D.21389 = (long int) D.21388;
    D.21390 = __builtin_expect (D.21389, 0);
    if (D.21390 != 0) goto <D.21391>; else goto <D.21392>;
    <D.21391>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 277, "ret == 0");
    <D.21392>:
  }
  D.21370 = 1;
  return D.21370;
}


mono_thread_create (struct MonoDomain * domain, void * func, void * arg)
{
  mono_thread_create_internal (domain, func, arg, 0, 0, 0);
}


mono_thread_get_stack_bounds (guint8 * * staddr, size_t * stsize)
{
  long unsigned int D.21394;
  guint8 * D.21395;
  int iftmp.33;
  long unsigned int D.21403;
  guint8 * D.21404;
  _Bool D.21405;
  long int D.21406;
  long int D.21407;
  long int D.21410;
  int D.21411;
  int D.21412;
  long int D.21413;
  long int D.21414;
  guint8 * D.21415;
  union pthread_attr_t attr;
  guint8 * current;

  try
    {
      current = &attr;
      *staddr = 0B;
      *stsize = 18446744073709551615;
      pthread_attr_init (&attr);
      D.21394 = pthread_self ();
      pthread_getattr_np (D.21394, &attr);
      pthread_attr_getstack (&attr, staddr, stsize);
      pthread_attr_destroy (&attr);
      D.21395 = *staddr;
      if (D.21395 != 0B) goto <D.21396>; else goto <D.21397>;
      <D.21396>:
      D.21395 = *staddr;
      if (D.21395 >= current) goto <D.21399>; else goto <D.21402>;
      <D.21402>:
      D.21395 = *staddr;
      D.21403 = *stsize;
      D.21404 = D.21395 + D.21403;
      if (D.21404 <= current) goto <D.21399>; else goto <D.21400>;
      <D.21399>:
      iftmp.33 = 1;
      goto <D.21401>;
      <D.21400>:
      iftmp.33 = 0;
      <D.21401>:
      D.21405 = iftmp.33 != 0;
      D.21406 = (long int) D.21405;
      D.21407 = __builtin_expect (D.21406, 0);
      if (D.21407 != 0) goto <D.21408>; else goto <D.21409>;
      <D.21408>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 944, "(current > *staddr) && (current < *staddr + *stsize)");
      <D.21409>:
      <D.21397>:
      D.21395 = *staddr;
      D.21410 = (long int) D.21395;
      D.21411 = mono_pagesize ();
      D.21412 = -D.21411;
      D.21413 = (long int) D.21412;
      D.21414 = D.21410 & D.21413;
      D.21415 = (guint8 *) D.21414;
      *staddr = D.21415;
      return;
    }
  finally
    {
      attr = {CLOBBER};
    }
}


mono_thread_attach (struct MonoDomain * domain)
{
  struct MonoThread * D.21418;

  D.21418 = mono_thread_attach_full (domain, 0);
  return D.21418;
}


mono_thread_attach_full (struct MonoDomain * domain, gboolean force_attach)
{
  struct MonoDomain * D.21422;
  struct MonoDomain * domain.34;
  struct MonoThread * D.21426;
  int D.21427;
  long unsigned int D.21430;
  void * thread_handle.35;
  void * thread_handle.36;
  _Bool D.21433;
  long int D.21434;
  long int D.21435;
  long unsigned int tid.37;
  void * D.21439;
  void * D.21440;
  long unsigned int tid.38;
  _Bool D.21442;
  long int D.21443;
  long int D.21444;
  int D.21447;
  unsigned int current_object_key.39;
  struct MonoDomain * D.21451;
  void (*<T143c>) (intptr_t, void *) mono_thread_attach_cb.40;
  guint8 * staddr.41;
  long int tid.42;
  long unsigned int stsize.43;
  void * D.21463;
  struct MonoThreadInfo * info;
  struct MonoInternalThread * thread;
  struct MonoThread * current_thread;
  void * thread_handle;
  gsize tid;

  try
    {
      thread = mono_thread_internal_current ();
      if (thread != 0B) goto <D.21420>; else goto <D.21421>;
      <D.21420>:
      D.21422 = mono_domain_get ();
      domain.34 = domain;
      if (D.21422 != domain.34) goto <D.21424>; else goto <D.21425>;
      <D.21424>:
      domain.34 = domain;
      mono_domain_set (domain.34, 1);
      <D.21425>:
      D.21426 = mono_thread_current ();
      return D.21426;
      <D.21421>:
      D.21427 = mono_gc_register_thread (&domain);
      if (D.21427 == 0) goto <D.21428>; else goto <D.21429>;
      <D.21428>:
      D.21430 = GetCurrentThreadId ();
      monoeg_g_log (0B, 4, "Thread %lu calling into managed code is not registered with the GC. On UNIX, this can be fixed by #include-ing <gc.h> before <pthread.h> in the file containing the thread creation code.", D.21430);
      <D.19653>:
      goto <D.19653>;
      <D.21429>:
      thread = create_internal_thread ();
      thread_handle.35 = GetCurrentThread ();
      thread_handle = thread_handle.35;
      thread_handle.36 = thread_handle;
      D.21433 = thread_handle.36 == 0B;
      D.21434 = (long int) D.21433;
      D.21435 = __builtin_expect (D.21434, 0);
      if (D.21435 != 0) goto <D.21436>; else goto <D.21437>;
      <D.21436>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1028, "thread_handle");
      <D.21437>:
      tid.37 = GetCurrentThreadId ();
      tid = tid.37;
      D.21439 = GetCurrentProcess ();
      thread_handle.36 = thread_handle;
      D.21440 = GetCurrentProcess ();
      DuplicateHandle (D.21439, thread_handle.36, D.21440, &thread_handle, 2032639, 1, 0);
      thread_handle.36 = thread_handle;
      thread->handle = thread_handle.36;
      tid.38 = tid;
      thread->tid = tid.38;
      thread->stack_ptr = &tid;
      info = mono_thread_info_current ();
      D.21442 = info == 0B;
      D.21443 = (long int) D.21442;
      D.21444 = __builtin_expect (D.21443, 0);
      if (D.21444 != 0) goto <D.21445>; else goto <D.21446>;
      <D.21445>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1049, "info");
      <D.21446>:
      thread->thread_info = info;
      domain.34 = domain;
      current_thread = new_thread_with_internal (domain.34, thread);
      D.21447 = handle_store (current_thread, force_attach);
      if (D.21447 == 0) goto <D.21448>; else goto <D.21449>;
      <D.21448>:
      <D.19654>:
      Sleep (10000);
      goto <D.19654>;
      <D.21449>:
      tls_current_object = thread;
      current_object_key.39 = current_object_key;
      mono_native_tls_set_value (current_object_key.39, thread);
      domain.34 = domain;
      mono_domain_set (domain.34, 1);
      mono_monitor_init_tls ();
      thread_adjust_static_data (thread);
      init_root_domain_thread (thread, current_thread);
      D.21451 = mono_get_root_domain ();
      domain.34 = domain;
      if (D.21451 != domain.34) goto <D.21452>; else goto <D.21453>;
      <D.21452>:
      domain.34 = domain;
      set_current_thread_for_domain (domain.34, thread, current_thread);
      <D.21453>:
      mono_thread_attach_cb.40 = mono_thread_attach_cb;
      if (mono_thread_attach_cb.40 != 0B) goto <D.21455>; else goto <D.21456>;
      <D.21455>:
      {
        guint8 * staddr;
        size_t stsize;

        try
          {
            mono_thread_get_stack_bounds (&staddr, &stsize);
            staddr.41 = staddr;
            if (staddr.41 == 0B) goto <D.21458>; else goto <D.21459>;
            <D.21458>:
            mono_thread_attach_cb.40 = mono_thread_attach_cb;
            tid.38 = tid;
            tid.42 = (long int) tid.38;
            mono_thread_attach_cb.40 (tid.42, &tid);
            goto <D.21461>;
            <D.21459>:
            mono_thread_attach_cb.40 = mono_thread_attach_cb;
            tid.38 = tid;
            tid.42 = (long int) tid.38;
            staddr.41 = staddr;
            stsize.43 = stsize;
            D.21463 = staddr.41 + stsize.43;
            mono_thread_attach_cb.40 (tid.42, D.21463);
            <D.21461>:
          }
        finally
          {
            staddr = {CLOBBER};
            stsize = {CLOBBER};
          }
      }
      <D.21456>:
      tid.38 = tid;
      mono_profiler_thread_start (tid.38);
      D.21426 = current_thread;
      return D.21426;
    }
  finally
    {
      thread_handle = {CLOBBER};
      tid = {CLOBBER};
    }
}


mono_thread_detach (struct MonoThread * thread)
{
  struct _MonoInternalThread * D.21468;
  unsigned int current_object_key.44;

  if (thread == 0B) goto <D.21466>; else goto <D.21467>;
  <D.21466>:
  monoeg_g_log (0B, 8, "%s:%d: assertion \'%s\' failed", "threads.c", 1095, "thread != NULL");
  return;
  <D.21467>:
  D.21468 = thread->internal_thread;
  thread_cleanup (D.21468);
  tls_current_object = 0B;
  current_object_key.44 = current_object_key;
  mono_native_tls_set_value (current_object_key.44, 0B);
  mono_domain_unset ();
}


mono_thread_exit ()
{
  unsigned int current_object_key.45;
  struct MonoThread * D.21472;
  struct MonoThread * D.21475;
  struct _MonoInternalThread * D.21476;
  int D.21479;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  thread_cleanup (thread);
  tls_current_object = 0B;
  current_object_key.45 = current_object_key;
  mono_native_tls_set_value (current_object_key.45, 0B);
  mono_domain_unset ();
  D.21472 = mono_thread_get_main ();
  if (D.21472 != 0B) goto <D.21473>; else goto <D.21474>;
  <D.21473>:
  D.21475 = mono_thread_get_main ();
  D.21476 = D.21475->internal_thread;
  if (D.21476 == thread) goto <D.21477>; else goto <D.21478>;
  <D.21477>:
  D.21479 = mono_environment_exitcode_get ();
  exit (D.21479);
  <D.21478>:
  <D.21474>:
  ExitThread (4294967295);
}


ves_icall_System_Threading_Thread_ConstructInternalThread (struct MonoThread * this)
{
  struct _MonoInternalThread * * D.21480;
  struct MonoInternalThread * internal;

  internal = create_internal_thread ();
  internal->state = 8;
  D.21480 = &this->internal_thread;
  InterlockedCompareExchangePointer (D.21480, internal, 0B);
}


ves_icall_System_Threading_Thread_Thread_internal (struct MonoThread * this, struct MonoObject * start)
{
  struct _MonoInternalThread * D.21481;
  unsigned int D.21484;
  unsigned int D.21485;
  struct MonoException * D.21488;
  void * D.21489;
  unsigned int D.21490;
  struct MonoObject * D.21493;
  struct MonoVTable * D.21494;
  struct MonoDomain * D.21495;
  struct MonoDomain * D.21496;
  _Bool D.21497;
  long int D.21498;
  long int D.21499;
  unsigned int D.21504;
  struct StartInfo * start_info;
  struct MonoInternalThread * internal;
  gboolean res;

  D.21481 = this->internal_thread;
  if (D.21481 == 0B) goto <D.21482>; else goto <D.21483>;
  <D.21482>:
  ves_icall_System_Threading_Thread_ConstructInternalThread (this);
  <D.21483>:
  internal = this->internal_thread;
  lock_thread (internal);
  D.21484 = internal->state;
  D.21485 = D.21484 & 8;
  if (D.21485 == 0) goto <D.21486>; else goto <D.21487>;
  <D.21486>:
  unlock_thread (internal);
  D.21488 = mono_get_exception_thread_state ("Thread has already been started.");
  mono_raise_exception (D.21488);
  D.21489 = 0B;
  return D.21489;
  <D.21487>:
  D.21484 = internal->state;
  D.21490 = D.21484 & 256;
  if (D.21490 != 0) goto <D.21491>; else goto <D.21492>;
  <D.21491>:
  unlock_thread (internal);
  D.21489 = this;
  return D.21489;
  <D.21492>:
  start_info = monoeg_malloc0 (32);
  start_info->func = 0B;
  D.21493 = this->start_obj;
  start_info->start_arg = D.21493;
  start_info->delegate = start;
  start_info->obj = this;
  D.21494 = this->obj.vtable;
  D.21495 = D.21494->domain;
  D.21496 = mono_domain_get ();
  D.21497 = D.21495 != D.21496;
  D.21498 = (long int) D.21497;
  D.21499 = __builtin_expect (D.21498, 0);
  if (D.21499 != 0) goto <D.21500>; else goto <D.21501>;
  <D.21500>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1169, "this->obj.vtable->domain == mono_domain_get ()");
  <D.21501>:
  res = create_thread (this, internal, start_info, 0, 0, 0, 0);
  if (res == 0) goto <D.21502>; else goto <D.21503>;
  <D.21502>:
  unlock_thread (internal);
  D.21489 = 0B;
  return D.21489;
  <D.21503>:
  D.21484 = internal->state;
  D.21504 = D.21484 & 4294967287;
  internal->state = D.21504;
  unlock_thread (internal);
  D.21489 = internal->handle;
  return D.21489;
}


ves_icall_System_Threading_InternalThread_Thread_free_internal (struct MonoInternalThread * this, void * thread)
{
  struct CRITICAL_SECTION * D.21508;
  gunichar2 * D.21511;

  if (thread != 0B) goto <D.21506>; else goto <D.21507>;
  <D.21506>:
  CloseHandle (thread);
  <D.21507>:
  D.21508 = this->synch_cs;
  if (D.21508 != 0B) goto <D.21509>; else goto <D.21510>;
  <D.21509>:
  {
    struct CRITICAL_SECTION * synch_cs;

    synch_cs = this->synch_cs;
    this->synch_cs = 0B;
    DeleteCriticalSection (synch_cs);
    monoeg_g_free (synch_cs);
  }
  <D.21510>:
  D.21511 = this->name;
  if (D.21511 != 0B) goto <D.21512>; else goto <D.21513>;
  <D.21512>:
  {
    void * name;

    name = this->name;
    this->name = 0B;
    monoeg_g_free (name);
  }
  <D.21513>:
}


ves_icall_System_Threading_Thread_Sleep_internal (gint32 ms)
{
  unsigned int ms.46;
  guint32 res;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  mono_thread_current_check_pending_interrupt ();
  <D.19687>:
  mono_thread_set_state (thread, 32);
  ms.46 = (unsigned int) ms;
  res = SleepEx (ms.46, 1);
  mono_thread_clr_state (thread, 32);
  if (res == 192) goto <D.21515>; else goto <D.19686>;
  <D.21515>:
  {
    struct MonoException * exc;

    exc = mono_thread_execute_interruption (thread);
    if (exc != 0B) goto <D.21516>; else goto <D.21517>;
    <D.21516>:
    mono_raise_exception (exc);
    goto <D.21518>;
    <D.21517>:
    if (ms != -1) goto <D.19686>; else goto <D.21519>;
    <D.21519>:
    <D.21518>:
  }
  goto <D.19687>;
  <D.19686>:
}


mono_thread_execute_interruption (struct MonoInternalThread * thread)
{
  gint32 * D.21520;
  int D.21521;
  void * D.21524;
  unsigned int D.21525;
  unsigned int D.21526;
  struct MonoException * D.21529;
  struct MonoException * * D.21532;
  struct MonoException * D.21533;
  struct MonoException * D.21534;
  unsigned int D.21535;
  unsigned int D.21538;
  struct MonoException * D.21541;
  unsigned char D.21544;

  lock_thread (thread);
  D.21520 = &thread->interruption_requested;
  D.21521 = InterlockedCompareExchange (D.21520, 0, 1);
  if (D.21521 != 0) goto <D.21522>; else goto <D.21523>;
  <D.21522>:
  D.21524 = GetCurrentThread ();
  WaitForSingleObjectEx (D.21524, 0, 1);
  InterlockedDecrement (&thread_interruption_requested);
  wapi_clear_interruption ();
  <D.21523>:
  D.21525 = thread->state;
  D.21526 = D.21525 & 128;
  if (D.21526 != 0) goto <D.21527>; else goto <D.21528>;
  <D.21527>:
  unlock_thread (thread);
  D.21529 = thread->abort_exc;
  if (D.21529 == 0B) goto <D.21530>; else goto <D.21531>;
  <D.21530>:
  D.21532 = &thread->abort_exc;
  D.21533 = mono_get_exception_thread_abort ();
  mono_gc_wbarrier_set_field (thread, D.21532, D.21533);
  <D.21531>:
  D.21534 = thread->abort_exc;
  return D.21534;
  <D.21528>:
  D.21525 = thread->state;
  D.21535 = D.21525 & 2;
  if (D.21535 != 0) goto <D.21536>; else goto <D.21537>;
  <D.21536>:
  self_suspend_internal (thread);
  D.21534 = 0B;
  return D.21534;
  <D.21537>:
  D.21525 = thread->state;
  D.21538 = D.21525 & 1;
  if (D.21538 != 0) goto <D.21539>; else goto <D.21540>;
  <D.21539>:
  unlock_thread (thread);
  mono_thread_exit ();
  D.21534 = 0B;
  return D.21534;
  <D.21540>:
  D.21541 = thread->pending_exception;
  if (D.21541 != 0B) goto <D.21542>; else goto <D.21543>;
  <D.21542>:
  {
    struct MonoException * exc;

    exc = thread->pending_exception;
    thread->pending_exception = 0B;
    unlock_thread (thread);
    D.21534 = exc;
    return D.21534;
  }
  <D.21543>:
  D.21544 = thread->thread_interrupt_requested;
  if (D.21544 != 0) goto <D.21545>; else goto <D.21546>;
  <D.21545>:
  thread->thread_interrupt_requested = 0;
  unlock_thread (thread);
  D.21534 = mono_get_exception_thread_interrupted ();
  return D.21534;
  <D.21546>:
  unlock_thread (thread);
  D.21534 = 0B;
  return D.21534;
}


InterlockedCompareExchange (volatile gint32 * dest, gint32 exch, gint32 comp)
{
  gint32 D.21548;
  unsigned int comp.47;
  unsigned int exch.48;
  unsigned int D.21551;

  comp.47 = (unsigned int) comp;
  exch.48 = (unsigned int) exch;
  D.21551 = __sync_val_compare_and_swap_4 (dest, comp.47, exch.48);
  D.21548 = (gint32) D.21551;
  return D.21548;
}


self_suspend_internal (struct MonoInternalThread * thread)
{
  int D.21553;
  unsigned int D.21556;
  unsigned int D.21557;
  unsigned int D.21558;
  void * D.21559;
  void * D.21560;
  void * D.21563;
  int shutting_down.49;
  unsigned int D.21569;
  void * D.21570;

  D.21553 = mono_thread_info_new_interrupt_enabled ();
  if (D.21553 == 0) goto <D.21554>; else goto <D.21555>;
  <D.21554>:
  D.21556 = thread->state;
  D.21557 = D.21556 & 4294967293;
  thread->state = D.21557;
  D.21556 = thread->state;
  D.21558 = D.21556 | 64;
  thread->state = D.21558;
  D.21559 = CreateEvent (0B, 1, 0, 0B);
  thread->suspend_event = D.21559;
  D.21560 = thread->suspend_event;
  if (D.21560 == 0B) goto <D.21561>; else goto <D.21562>;
  <D.21561>:
  unlock_thread (thread);
  return;
  <D.21562>:
  D.21563 = thread->suspended_event;
  if (D.21563 != 0B) goto <D.21564>; else goto <D.21565>;
  <D.21564>:
  D.21563 = thread->suspended_event;
  SetEvent (D.21563);
  <D.21565>:
  unlock_thread (thread);
  shutting_down.49 = shutting_down;
  if (shutting_down.49 != 0) goto <D.21567>; else goto <D.21568>;
  <D.21567>:
  <D.20834>:
  Sleep (1000);
  goto <D.20834>;
  <D.21568>:
  D.21560 = thread->suspend_event;
  WaitForSingleObject (D.21560, 4294967295);
  lock_thread (thread);
  D.21560 = thread->suspend_event;
  CloseHandle (D.21560);
  thread->suspend_event = 0B;
  D.21556 = thread->state;
  D.21569 = D.21556 & 4294967231;
  thread->state = D.21569;
  D.21570 = thread->resume_event;
  SetEvent (D.21570);
  unlock_thread (thread);
  return;
  <D.21555>:
  transition_to_suspended (thread);
  mono_thread_info_self_suspend ();
}


transition_to_suspended (struct MonoInternalThread * thread)
{
  unsigned int D.21572;
  unsigned int D.21573;
  long unsigned int D.21578;
  unsigned int D.21580;
  unsigned int D.21581;

  D.21572 = thread->state;
  D.21573 = D.21572 & 2;
  if (D.21573 == 0) goto <D.21574>; else goto <D.21575>;
  <D.21574>:
  if (1 != 0) goto <D.21576>; else goto <D.21577>;
  <D.21576>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4693, "0");
  <D.21577>:
  D.21578 = thread->tid;
  mono_thread_info_resume (D.21578);
  goto <D.21579>;
  <D.21575>:
  D.21572 = thread->state;
  D.21580 = D.21572 & 4294967293;
  thread->state = D.21580;
  D.21572 = thread->state;
  D.21581 = D.21572 | 64;
  thread->state = D.21581;
  mono_thread_info_finish_suspend ();
  <D.21579>:
  unlock_thread (thread);
}


ves_icall_System_Threading_Thread_SpinWait_nop ()
{

}


ves_icall_System_Threading_Thread_GetDomainID ()
{
  gint32 D.21582;
  struct MonoDomain * D.21583;

  D.21583 = mono_domain_get ();
  D.21582 = D.21583->domain_id;
  return D.21582;
}


ves_icall_System_Threading_Thread_Yield ()
{
  gboolean D.21585;
  int D.21586;
  _Bool D.21587;

  D.21586 = sched_yield ();
  D.21587 = D.21586 == 0;
  D.21585 = (gboolean) D.21587;
  return D.21585;
}


mono_thread_get_name (struct MonoInternalThread * this_obj, guint32 * name_len)
{
  gunichar2 * D.21589;
  unsigned int D.21593;
  long unsigned int D.21594;
  long unsigned int D.21595;
  gunichar2 * D.21596;
  gunichar2 * res;

  lock_thread (this_obj);
  D.21589 = this_obj->name;
  if (D.21589 == 0B) goto <D.21590>; else goto <D.21591>;
  <D.21590>:
  *name_len = 0;
  res = 0B;
  goto <D.21592>;
  <D.21591>:
  D.21593 = this_obj->name_len;
  *name_len = D.21593;
  D.21593 = this_obj->name_len;
  D.21594 = (long unsigned int) D.21593;
  D.21595 = D.21594 * 2;
  res = monoeg_malloc (D.21595);
  D.21589 = this_obj->name;
  D.21593 = this_obj->name_len;
  D.21594 = (long unsigned int) D.21593;
  D.21595 = D.21594 * 2;
  memcpy (res, D.21589, D.21595);
  <D.21592>:
  unlock_thread (this_obj);
  D.21596 = res;
  return D.21596;
}


memcpy (void * restrict __dest, const void * restrict __src, size_t __len)
{
  void * D.21598;
  long unsigned int D.21599;

  D.21599 = __builtin_object_size (__dest, 0);
  D.21598 = __builtin___memcpy_chk (__dest, __src, __len, D.21599);
  return D.21598;
}


ves_icall_System_Threading_Thread_GetName_internal (struct MonoInternalThread * this_obj)
{
  gunichar2 * D.21601;
  struct MonoDomain * D.21605;
  unsigned int D.21606;
  int D.21607;
  struct MonoString * D.21608;
  struct MonoString * str;

  lock_thread (this_obj);
  D.21601 = this_obj->name;
  if (D.21601 == 0B) goto <D.21602>; else goto <D.21603>;
  <D.21602>:
  str = 0B;
  goto <D.21604>;
  <D.21603>:
  D.21605 = mono_domain_get ();
  D.21601 = this_obj->name;
  D.21606 = this_obj->name_len;
  D.21607 = (int) D.21606;
  str = mono_string_new_utf16 (D.21605, D.21601, D.21607);
  <D.21604>:
  unlock_thread (this_obj);
  D.21608 = str;
  return D.21608;
}


mono_thread_set_name_internal (struct MonoInternalThread * this_obj, struct MonoString * name, gboolean managed)
{
  long unsigned int D.21610;
  long unsigned int D.21611;
  struct MonoException * D.21614;
  int D.21617;
  long unsigned int D.21618;
  long unsigned int D.21619;
  void * D.21620;
  gunichar2 * D.21621;
  mono_unichar2 * D.21622;
  int D.21623;
  int D.21624;
  long unsigned int D.21625;
  int D.21626;
  unsigned int D.21627;
  long unsigned int D.21631;
  long unsigned int D.21634;

  lock_thread (this_obj);
  D.21610 = this_obj->flags;
  D.21611 = D.21610 & 2;
  if (D.21611 != 0) goto <D.21612>; else goto <D.21613>;
  <D.21612>:
  unlock_thread (this_obj);
  D.21614 = mono_get_exception_invalid_operation ("Thread.Name can only be set once.");
  mono_raise_exception (D.21614);
  return;
  <D.21613>:
  if (name != 0B) goto <D.21615>; else goto <D.21616>;
  <D.21615>:
  D.21617 = mono_string_length (name);
  D.21618 = (long unsigned int) D.21617;
  D.21619 = D.21618 * 2;
  D.21620 = monoeg_malloc (D.21619);
  this_obj->name = D.21620;
  D.21621 = this_obj->name;
  D.21622 = mono_string_chars (name);
  D.21623 = mono_string_length (name);
  D.21624 = D.21623 * 2;
  D.21625 = (long unsigned int) D.21624;
  memcpy (D.21621, D.21622, D.21625);
  D.21626 = mono_string_length (name);
  D.21627 = (unsigned int) D.21626;
  this_obj->name_len = D.21627;
  goto <D.21628>;
  <D.21616>:
  this_obj->name = 0B;
  <D.21628>:
  if (managed != 0) goto <D.21629>; else goto <D.21630>;
  <D.21629>:
  D.21610 = this_obj->flags;
  D.21631 = D.21610 | 2;
  this_obj->flags = D.21631;
  <D.21630>:
  unlock_thread (this_obj);
  D.21621 = this_obj->name;
  if (D.21621 != 0B) goto <D.21632>; else goto <D.21633>;
  <D.21632>:
  {
    char * tname;

    tname = mono_string_to_utf8 (name);
    D.21634 = this_obj->tid;
    mono_profiler_thread_name (D.21634, tname);
    mono_free (tname);
  }
  <D.21633>:
}


ves_icall_System_Threading_Thread_SetName_internal (struct MonoInternalThread * this_obj, struct MonoString * name)
{
  mono_thread_set_name_internal (this_obj, name, 1);
}


ves_icall_System_Threading_Thread_ByteArrayToRootDomain (struct MonoArray * arr)
{
  struct MonoArray * D.21636;
  struct MonoDomain * D.21637;

  D.21637 = mono_get_root_domain ();
  D.21636 = byte_array_to_domain (arr, D.21637);
  return D.21636;
}


byte_array_to_domain (struct MonoArray * arr, struct MonoDomain * domain)
{
  struct MonoArray * D.21641;
  struct MonoVTable * D.21642;
  struct MonoDomain * D.21643;
  struct MonoClass * D.21646;
  unsigned int D.21647;
  long unsigned int D.21648;
  char * D.21649;
  char * D.21650;
  long unsigned int D.21651;
  struct MonoArray * copy;

  if (arr == 0B) goto <D.21639>; else goto <D.21640>;
  <D.21639>:
  D.21641 = 0B;
  return D.21641;
  <D.21640>:
  D.21642 = MEM[(struct MonoObject *)arr].vtable;
  D.21643 = D.21642->domain;
  if (D.21643 == domain) goto <D.21644>; else goto <D.21645>;
  <D.21644>:
  D.21641 = arr;
  return D.21641;
  <D.21645>:
  D.21646 = mono_defaults.byte_class;
  D.21647 = arr->max_length;
  D.21648 = (long unsigned int) D.21647;
  copy = mono_array_new (domain, D.21646, D.21648);
  D.21649 = mono_array_addr_with_size (copy, 1, 0);
  D.21650 = mono_array_addr_with_size (arr, 1, 0);
  D.21647 = arr->max_length;
  D.21651 = (long unsigned int) D.21647;
  memmove (D.21649, D.21650, D.21651);
  D.21641 = copy;
  return D.21641;
}


memmove (void * __dest, const void * __src, size_t __len)
{
  void * D.21653;
  long unsigned int D.21654;

  D.21654 = __builtin_object_size (__dest, 0);
  D.21653 = __builtin___memmove_chk (__dest, __src, __len, D.21654);
  return D.21653;
}


ves_icall_System_Threading_Thread_ByteArrayToCurrentDomain (struct MonoArray * arr)
{
  struct MonoArray * D.21656;
  struct MonoDomain * D.21657;

  D.21657 = mono_domain_get ();
  D.21656 = byte_array_to_domain (arr, D.21657);
  return D.21656;
}


mono_thread_current ()
{
  _Bool D.21659;
  long int D.21660;
  long int D.21661;
  struct MonoThread * D.21664;
  struct MonoDomain * D.21667;
  _Bool D.21668;
  long int D.21669;
  long int D.21670;
  struct MonoThread * D.21673;
  struct MonoThread * D.21674;
  struct MonoDomain * domain;
  struct MonoInternalThread * internal;
  struct MonoThread * * current_thread_ptr;

  domain = mono_domain_get ();
  internal = mono_thread_internal_current ();
  D.21659 = internal == 0B;
  D.21660 = (long int) D.21659;
  D.21661 = __builtin_expect (D.21660, 0);
  if (D.21661 != 0) goto <D.21662>; else goto <D.21663>;
  <D.21662>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1382, "internal");
  <D.21663>:
  current_thread_ptr = get_current_thread_ptr_for_domain (domain, internal);
  D.21664 = *current_thread_ptr;
  if (D.21664 == 0B) goto <D.21665>; else goto <D.21666>;
  <D.21665>:
  D.21667 = mono_get_root_domain ();
  D.21668 = D.21667 == domain;
  D.21669 = (long int) D.21668;
  D.21670 = __builtin_expect (D.21669, 0);
  if (D.21670 != 0) goto <D.21671>; else goto <D.21672>;
  <D.21671>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1386, "domain != mono_get_root_domain ()");
  <D.21672>:
  D.21673 = new_thread_with_internal (domain, internal);
  *current_thread_ptr = D.21673;
  <D.21666>:
  D.21674 = *current_thread_ptr;
  return D.21674;
}


mono_thread_internal_current ()
{
  struct MonoInternalThread * D.21676;
  struct MonoInternalThread * res;

  res = tls_current_object;
  D.21676 = res;
  return D.21676;
}


ves_icall_System_Threading_Thread_Join_internal (struct MonoInternalThread * this, int ms, void * thread)
{
  unsigned int D.21678;
  unsigned int D.21679;
  struct MonoException * D.21682;
  gboolean D.21683;
  unsigned int ms.50;
  unsigned int D.21687;
  struct MonoInternalThread * cur_thread;
  gboolean ret;

  cur_thread = mono_thread_internal_current ();
  mono_thread_current_check_pending_interrupt ();
  lock_thread (this);
  D.21678 = this->state;
  D.21679 = D.21678 & 8;
  if (D.21679 != 0) goto <D.21680>; else goto <D.21681>;
  <D.21680>:
  unlock_thread (this);
  D.21682 = mono_get_exception_thread_state ("Thread has not been started.");
  mono_raise_exception (D.21682);
  D.21683 = 0;
  return D.21683;
  <D.21681>:
  unlock_thread (this);
  if (ms == -1) goto <D.21684>; else goto <D.21685>;
  <D.21684>:
  ms = -1;
  <D.21685>:
  mono_thread_set_state (cur_thread, 32);
  ms.50 = (unsigned int) ms;
  D.21687 = WaitForSingleObjectEx (thread, ms.50, 1);
  ret = (gboolean) D.21687;
  mono_thread_clr_state (cur_thread, 32);
  if (ret == 0) goto <D.21688>; else goto <D.21689>;
  <D.21688>:
  D.21683 = 1;
  return D.21683;
  <D.21689>:
  D.21683 = 0;
  return D.21683;
}


ves_icall_System_Threading_WaitHandle_WaitAll_internal (struct MonoArray * mono_handles, gint32 ms, gboolean exitContext)
{
  long unsigned int D.21691;
  long unsigned int D.21692;
  long unsigned int D.21693;
  long unsigned int D.21694;
  char * D.21695;
  long unsigned int D.21696;
  long unsigned int D.21697;
  void * * D.21698;
  void * D.21699;
  int D.21702;
  gboolean D.21705;
  void * * handles;
  guint32 numhandles;
  guint32 ret;
  guint32 i;
  struct MonoObject * waitHandle;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  mono_thread_current_check_pending_interrupt ();
  D.21691 = mono_array_length (mono_handles);
  numhandles = (guint32) D.21691;
  D.21692 = (long unsigned int) numhandles;
  D.21693 = D.21692 * 8;
  handles = monoeg_malloc0 (D.21693);
  i = 0;
  goto <D.19773>;
  <D.19772>:
  D.21694 = (long unsigned int) i;
  D.21695 = mono_array_addr_with_size (mono_handles, 8, D.21694);
  waitHandle = MEM[(struct MonoObject * *)D.21695];
  D.21696 = (long unsigned int) i;
  D.21697 = D.21696 * 8;
  D.21698 = handles + D.21697;
  D.21699 = mono_wait_handle_get_handle (waitHandle);
  *D.21698 = D.21699;
  i = i + 1;
  <D.19773>:
  if (i < numhandles) goto <D.19772>; else goto <D.19774>;
  <D.19774>:
  if (ms == -1) goto <D.21700>; else goto <D.21701>;
  <D.21700>:
  ms = -1;
  <D.21701>:
  mono_thread_set_state (thread, 32);
  D.21702 = mono_wait_uninterrupted (thread, 1, numhandles, handles, 1, ms, 1);
  ret = (guint32) D.21702;
  mono_thread_clr_state (thread, 32);
  monoeg_g_free (handles);
  if (ret == 4294967295) goto <D.21703>; else goto <D.21704>;
  <D.21703>:
  D.21705 = 0;
  return D.21705;
  <D.21704>:
  if (ret == 258) goto <D.21706>; else goto <D.21707>;
  <D.21706>:
  D.21705 = 0;
  return D.21705;
  <D.21707>:
  D.21705 = 1;
  return D.21705;
}


mono_wait_uninterrupted (struct MonoInternalThread * thread, gboolean multiple, guint32 numhandles, void * * handles, gboolean waitall, gint32 ms, gboolean alertable)
{
  gint64 iftmp.51;
  unsigned int wait.52;
  void * D.21717;
  unsigned int ms.53;
  long int D.21724;
  long int D.21725;
  long int D.21726;
  gint32 D.21729;
  struct MonoException * exc;
  guint32 ret;
  gint64 start;
  gint32 diff_ms;
  gint32 wait;

  wait = ms;
  if (ms != -1) goto <D.21710>; else goto <D.21711>;
  <D.21710>:
  iftmp.51 = mono_100ns_ticks ();
  goto <D.21712>;
  <D.21711>:
  iftmp.51 = 0;
  <D.21712>:
  start = iftmp.51;
  <D.19760>:
  if (multiple != 0) goto <D.21713>; else goto <D.21714>;
  <D.21713>:
  wait.52 = (unsigned int) wait;
  ret = WaitForMultipleObjectsEx (numhandles, handles, waitall, wait.52, alertable);
  goto <D.21716>;
  <D.21714>:
  D.21717 = *handles;
  ms.53 = (unsigned int) ms;
  ret = WaitForSingleObjectEx (D.21717, ms.53, alertable);
  <D.21716>:
  if (ret != 192) goto <D.19758>; else goto <D.21719>;
  <D.21719>:
  exc = mono_thread_execute_interruption (thread);
  if (exc != 0B) goto <D.21720>; else goto <D.21721>;
  <D.21720>:
  mono_raise_exception (exc);
  <D.21721>:
  if (ms == -1) goto <D.21722>; else goto <D.21723>;
  <D.21722>:
  // predicted unlikely by continue predictor.
  goto <D.19759>;
  <D.21723>:
  D.21724 = mono_100ns_ticks ();
  D.21725 = D.21724 - start;
  D.21726 = D.21725 / 10000;
  diff_ms = (gint32) D.21726;
  if (diff_ms >= ms) goto <D.21727>; else goto <D.21728>;
  <D.21727>:
  ret = 258;
  goto <D.19758>;
  <D.21728>:
  wait = ms - diff_ms;
  <D.19759>:
  goto <D.19760>;
  <D.19758>:
  D.21729 = (gint32) ret;
  return D.21729;
}


ves_icall_System_Threading_WaitHandle_WaitAny_internal (struct MonoArray * mono_handles, gint32 ms, gboolean exitContext)
{
  long unsigned int D.21731;
  gint32 D.21734;
  long unsigned int D.21735;
  char * D.21736;
  void * D.21737;
  int D.21740;
  unsigned int D.21741;
  unsigned int D.21746;
  unsigned int D.21748;
  void * handles[64];
  guint32 numhandles;
  guint32 ret;
  guint32 i;
  struct MonoObject * waitHandle;
  struct MonoInternalThread * thread;

  try
    {
      thread = mono_thread_internal_current ();
      mono_thread_current_check_pending_interrupt ();
      D.21731 = mono_array_length (mono_handles);
      numhandles = (guint32) D.21731;
      if (numhandles > 64) goto <D.21732>; else goto <D.21733>;
      <D.21732>:
      D.21734 = -1;
      return D.21734;
      <D.21733>:
      i = 0;
      goto <D.19787>;
      <D.19786>:
      D.21735 = (long unsigned int) i;
      D.21736 = mono_array_addr_with_size (mono_handles, 8, D.21735);
      waitHandle = MEM[(struct MonoObject * *)D.21736];
      D.21737 = mono_wait_handle_get_handle (waitHandle);
      handles[i] = D.21737;
      i = i + 1;
      <D.19787>:
      if (i < numhandles) goto <D.19786>; else goto <D.19788>;
      <D.19788>:
      if (ms == -1) goto <D.21738>; else goto <D.21739>;
      <D.21738>:
      ms = -1;
      <D.21739>:
      mono_thread_set_state (thread, 32);
      D.21740 = mono_wait_uninterrupted (thread, 1, numhandles, &handles, 0, ms, 1);
      ret = (guint32) D.21740;
      mono_thread_clr_state (thread, 32);
      D.21741 = numhandles + 4294967295;
      if (D.21741 >= ret) goto <D.21742>; else goto <D.21743>;
      <D.21742>:
      D.21734 = (gint32) ret;
      return D.21734;
      <D.21743>:
      if (ret > 127) goto <D.21745>; else goto <D.21744>;
      <D.21745>:
      D.21746 = numhandles + 127;
      if (D.21746 >= ret) goto <D.21747>; else goto <D.21744>;
      <D.21747>:
      D.21748 = ret + 4294967168;
      D.21734 = (gint32) D.21748;
      return D.21734;
      <D.21744>:
      D.21734 = (gint32) ret;
      return D.21734;
    }
  finally
    {
      handles = {CLOBBER};
    }
}


ves_icall_System_Threading_WaitHandle_WaitOne_internal (struct MonoObject * this, void * handle, gint32 ms, gboolean exitContext)
{
  int D.21753;
  gboolean D.21756;
  guint32 ret;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  if (ms == -1) goto <D.21751>; else goto <D.21752>;
  <D.21751>:
  ms = -1;
  <D.21752>:
  mono_thread_current_check_pending_interrupt ();
  mono_thread_set_state (thread, 32);
  D.21753 = mono_wait_uninterrupted (thread, 0, 1, &handle, 0, ms, 1);
  ret = (guint32) D.21753;
  mono_thread_clr_state (thread, 32);
  if (ret == 4294967295) goto <D.21754>; else goto <D.21755>;
  <D.21754>:
  D.21756 = 0;
  return D.21756;
  <D.21755>:
  if (ret == 258) goto <D.21757>; else goto <D.21758>;
  <D.21757>:
  D.21756 = 0;
  return D.21756;
  <D.21758>:
  D.21756 = 1;
  return D.21756;
}


ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal (void * toSignal, void * toWait, gint32 ms, gboolean exitContext)
{
  unsigned int ms.54;
  gboolean D.21763;
  int iftmp.55;
  guint32 ret;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  if (ms == -1) goto <D.21760>; else goto <D.21761>;
  <D.21760>:
  ms = -1;
  <D.21761>:
  mono_thread_current_check_pending_interrupt ();
  mono_thread_set_state (thread, 32);
  ms.54 = (unsigned int) ms;
  ret = SignalObjectAndWait (toSignal, toWait, ms.54, 1);
  mono_thread_clr_state (thread, 32);
  if (ret != 258) goto <D.21767>; else goto <D.21765>;
  <D.21767>:
  if (ret != 192) goto <D.21768>; else goto <D.21765>;
  <D.21768>:
  if (ret != 4294967295) goto <D.21769>; else goto <D.21765>;
  <D.21769>:
  iftmp.55 = 1;
  goto <D.21766>;
  <D.21765>:
  iftmp.55 = 0;
  <D.21766>:
  D.21763 = iftmp.55;
  return D.21763;
}


ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, struct MonoString * name, MonoBoolean * created)
{
  int D.21773;
  mono_unichar2 * D.21775;
  unsigned int D.21776;
  void * D.21779;
  void * mutex;

  *created = 1;
  if (name == 0B) goto <D.21771>; else goto <D.21772>;
  <D.21771>:
  D.21773 = (int) owned;
  mutex = CreateMutex (0B, D.21773, 0B);
  goto <D.21774>;
  <D.21772>:
  D.21773 = (int) owned;
  D.21775 = mono_string_chars (name);
  mutex = CreateMutex (0B, D.21773, D.21775);
  D.21776 = GetLastError ();
  if (D.21776 == 183) goto <D.21777>; else goto <D.21778>;
  <D.21777>:
  *created = 0;
  <D.21778>:
  <D.21774>:
  D.21779 = mutex;
  return D.21779;
}


ves_icall_System_Threading_Mutex_ReleaseMutex_internal (void * handle)
{
  MonoBoolean D.21781;
  int D.21782;

  D.21782 = ReleaseMutex (handle);
  D.21781 = (MonoBoolean) D.21782;
  return D.21781;
}


ves_icall_System_Threading_Mutex_OpenMutex_internal (struct MonoString * name, gint32 rights, gint32 * error)
{
  unsigned int rights.56;
  mono_unichar2 * D.21785;
  unsigned int D.21788;
  int D.21789;
  void * D.21790;
  void * ret;

  *error = 0;
  rights.56 = (unsigned int) rights;
  D.21785 = mono_string_chars (name);
  ret = OpenMutex (rights.56, 0, D.21785);
  if (ret == 0B) goto <D.21786>; else goto <D.21787>;
  <D.21786>:
  D.21788 = GetLastError ();
  D.21789 = (int) D.21788;
  *error = D.21789;
  <D.21787>:
  D.21790 = ret;
  return D.21790;
}


ves_icall_System_Threading_Semaphore_CreateSemaphore_internal (gint32 initialCount, gint32 maximumCount, struct MonoString * name, MonoBoolean * created)
{
  mono_unichar2 * D.21795;
  unsigned int D.21796;
  void * D.21799;
  void * sem;

  *created = 1;
  if (name == 0B) goto <D.21792>; else goto <D.21793>;
  <D.21792>:
  sem = CreateSemaphore (0B, initialCount, maximumCount, 0B);
  goto <D.21794>;
  <D.21793>:
  D.21795 = mono_string_chars (name);
  sem = CreateSemaphore (0B, initialCount, maximumCount, D.21795);
  D.21796 = GetLastError ();
  if (D.21796 == 183) goto <D.21797>; else goto <D.21798>;
  <D.21797>:
  *created = 0;
  <D.21798>:
  <D.21794>:
  D.21799 = sem;
  return D.21799;
}


ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (void * handle, gint32 releaseCount, MonoBoolean * fail)
{
  int D.21801;
  _Bool D.21802;
  unsigned char D.21803;
  gint32 D.21804;
  gint32 prevcount;

  try
    {
      D.21801 = ReleaseSemaphore (handle, releaseCount, &prevcount);
      D.21802 = D.21801 == 0;
      D.21803 = (unsigned char) D.21802;
      *fail = D.21803;
      D.21804 = prevcount;
      return D.21804;
    }
  finally
    {
      prevcount = {CLOBBER};
    }
}


ves_icall_System_Threading_Semaphore_OpenSemaphore_internal (struct MonoString * name, gint32 rights, gint32 * error)
{
  unsigned int rights.57;
  mono_unichar2 * D.21808;
  unsigned int D.21811;
  int D.21812;
  void * D.21813;
  void * ret;

  *error = 0;
  rights.57 = (unsigned int) rights;
  D.21808 = mono_string_chars (name);
  ret = OpenSemaphore (rights.57, 0, D.21808);
  if (ret == 0B) goto <D.21809>; else goto <D.21810>;
  <D.21809>:
  D.21811 = GetLastError ();
  D.21812 = (int) D.21811;
  *error = D.21812;
  <D.21810>:
  D.21813 = ret;
  return D.21813;
}


ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, struct MonoString * name, MonoBoolean * created)
{
  int D.21817;
  int D.21818;
  mono_unichar2 * D.21820;
  unsigned int D.21821;
  void * D.21824;
  void * event;

  *created = 1;
  if (name == 0B) goto <D.21815>; else goto <D.21816>;
  <D.21815>:
  D.21817 = (int) manual;
  D.21818 = (int) initial;
  event = CreateEvent (0B, D.21817, D.21818, 0B);
  goto <D.21819>;
  <D.21816>:
  D.21817 = (int) manual;
  D.21818 = (int) initial;
  D.21820 = mono_string_chars (name);
  event = CreateEvent (0B, D.21817, D.21818, D.21820);
  D.21821 = GetLastError ();
  if (D.21821 == 183) goto <D.21822>; else goto <D.21823>;
  <D.21822>:
  *created = 0;
  <D.21823>:
  <D.21819>:
  D.21824 = event;
  return D.21824;
}


ves_icall_System_Threading_Events_SetEvent_internal (void * handle)
{
  gboolean D.21826;

  D.21826 = SetEvent (handle);
  return D.21826;
}


ves_icall_System_Threading_Events_ResetEvent_internal (void * handle)
{
  gboolean D.21828;

  D.21828 = ResetEvent (handle);
  return D.21828;
}


ves_icall_System_Threading_Events_CloseEvent_internal (void * handle)
{
  CloseHandle (handle);
}


ves_icall_System_Threading_Events_OpenEvent_internal (struct MonoString * name, gint32 rights, gint32 * error)
{
  unsigned int rights.58;
  mono_unichar2 * D.21831;
  unsigned int D.21834;
  int D.21835;
  void * D.21836;
  void * ret;

  *error = 0;
  rights.58 = (unsigned int) rights;
  D.21831 = mono_string_chars (name);
  ret = OpenEvent (rights.58, 0, D.21831);
  if (ret == 0B) goto <D.21832>; else goto <D.21833>;
  <D.21832>:
  D.21834 = GetLastError ();
  D.21835 = (int) D.21834;
  *error = D.21835;
  <D.21833>:
  D.21836 = ret;
  return D.21836;
}


ves_icall_System_Threading_Interlocked_Increment_Int (gint32 * location)
{
  gint32 D.21838;

  D.21838 = InterlockedIncrement (location);
  return D.21838;
}


ves_icall_System_Threading_Interlocked_Increment_Long (gint64 * location)
{
  gint64 D.21840;

  D.21840 = InterlockedIncrement64 (location);
  return D.21840;
}


InterlockedIncrement64 (volatile gint64 * val)
{
  gint64 D.21842;
  long unsigned int D.21843;

  D.21843 = __sync_add_and_fetch_8 (val, 1);
  D.21842 = (gint64) D.21843;
  return D.21842;
}


ves_icall_System_Threading_Interlocked_Decrement_Int (gint32 * location)
{
  gint32 D.21845;

  D.21845 = InterlockedDecrement (location);
  return D.21845;
}


ves_icall_System_Threading_Interlocked_Decrement_Long (gint64 * location)
{
  gint64 D.21847;

  D.21847 = InterlockedDecrement64 (location);
  return D.21847;
}


InterlockedDecrement64 (volatile gint64 * val)
{
  gint64 D.21849;
  long unsigned int D.21850;

  D.21850 = __sync_sub_and_fetch_8 (val, 1);
  D.21849 = (gint64) D.21850;
  return D.21849;
}


ves_icall_System_Threading_Interlocked_Exchange_Int (gint32 * location, gint32 value)
{
  gint32 D.21852;

  D.21852 = InterlockedExchange (location, value);
  return D.21852;
}


ves_icall_System_Threading_Interlocked_Exchange_Object (struct MonoObject * * location, struct MonoObject * value)
{
  struct MonoObject * D.21854;
  struct MonoObject * res;

  res = InterlockedExchangePointer (location, value);
  mono_gc_wbarrier_generic_nostore (location);
  D.21854 = res;
  return D.21854;
}


InterlockedExchangePointer (void * volatile * val, void * new_val)
{
  long unsigned int old_val.59;
  long unsigned int new_val.60;
  long unsigned int D.21858;
  void * D.21859;
  void * D.21860;
  void * old_val;

  <D.19330>:
  old_val = *val;
  old_val.59 = (long unsigned int) old_val;
  new_val.60 = (long unsigned int) new_val;
  D.21858 = __sync_val_compare_and_swap_8 (val, old_val.59, new_val.60);
  D.21859 = (void *) D.21858;
  if (D.21859 != old_val) goto <D.19330>; else goto <D.19331>;
  <D.19331>:
  D.21860 = old_val;
  return D.21860;
}


ves_icall_System_Threading_Interlocked_Exchange_IntPtr (void * * location, void * value)
{
  void * D.21862;

  D.21862 = InterlockedExchangePointer (location, value);
  return D.21862;
}


ves_icall_System_Threading_Interlocked_Exchange_Single (gfloat * location, gfloat value)
{
  int D.21864;
  int D.21865;
  gfloat D.21866;
  union IntFloatUnion val;
  union IntFloatUnion ret;

  try
    {
      val.fval = value;
      D.21864 = val.ival;
      D.21865 = InterlockedExchange (location, D.21864);
      ret.ival = D.21865;
      D.21866 = ret.fval;
      return D.21866;
    }
  finally
    {
      val = {CLOBBER};
      ret = {CLOBBER};
    }
}


ves_icall_System_Threading_Interlocked_Exchange_Long (gint64 * location, gint64 value)
{
  gint64 D.21869;

  D.21869 = InterlockedExchange64 (location, value);
  return D.21869;
}


InterlockedExchange64 (volatile gint64 * val, gint64 new_val)
{
  long int D.21871;
  gint64 D.21872;
  gint64 old_val;

  <D.19400>:
  old_val = *val;
  D.21871 = InterlockedCompareExchange64 (val, new_val, old_val);
  if (D.21871 != old_val) goto <D.19400>; else goto <D.19401>;
  <D.19401>:
  D.21872 = old_val;
  return D.21872;
}


InterlockedCompareExchange64 (volatile gint64 * dest, gint64 exch, gint64 comp)
{
  gint64 D.21874;
  long unsigned int comp.61;
  long unsigned int exch.62;
  long unsigned int D.21877;

  comp.61 = (long unsigned int) comp;
  exch.62 = (long unsigned int) exch;
  D.21877 = __sync_val_compare_and_swap_8 (dest, comp.61, exch.62);
  D.21874 = (gint64) D.21877;
  return D.21874;
}


ves_icall_System_Threading_Interlocked_Exchange_Double (gdouble * location, gdouble value)
{
  long int D.21879;
  long int D.21880;
  gdouble D.21881;
  union LongDoubleUnion val;
  union LongDoubleUnion ret;

  try
    {
      val.fval = value;
      D.21879 = val.ival;
      D.21880 = InterlockedExchange64 (location, D.21879);
      ret.ival = D.21880;
      D.21881 = ret.fval;
      return D.21881;
    }
  finally
    {
      val = {CLOBBER};
      ret = {CLOBBER};
    }
}


ves_icall_System_Threading_Interlocked_CompareExchange_Int (gint32 * location, gint32 value, gint32 comparand)
{
  gint32 D.21884;

  D.21884 = InterlockedCompareExchange (location, value, comparand);
  return D.21884;
}


ves_icall_System_Threading_Interlocked_CompareExchange_Object (struct MonoObject * * location, struct MonoObject * value, struct MonoObject * comparand)
{
  struct MonoObject * D.21886;
  struct MonoObject * res;

  res = InterlockedCompareExchangePointer (location, value, comparand);
  mono_gc_wbarrier_generic_nostore (location);
  D.21886 = res;
  return D.21886;
}


ves_icall_System_Threading_Interlocked_CompareExchange_IntPtr (void * * location, void * value, void * comparand)
{
  void * D.21888;

  D.21888 = InterlockedCompareExchangePointer (location, value, comparand);
  return D.21888;
}


ves_icall_System_Threading_Interlocked_CompareExchange_Single (gfloat * location, gfloat value, gfloat comparand)
{
  int D.21890;
  int D.21891;
  int D.21892;
  gfloat D.21893;
  union IntFloatUnion val;
  union IntFloatUnion ret;
  union IntFloatUnion cmp;

  try
    {
      val.fval = value;
      cmp.fval = comparand;
      D.21890 = val.ival;
      D.21891 = cmp.ival;
      D.21892 = InterlockedCompareExchange (location, D.21890, D.21891);
      ret.ival = D.21892;
      D.21893 = ret.fval;
      return D.21893;
    }
  finally
    {
      val = {CLOBBER};
      ret = {CLOBBER};
      cmp = {CLOBBER};
    }
}


ves_icall_System_Threading_Interlocked_CompareExchange_Double (gdouble * location, gdouble value, gdouble comparand)
{
  long int D.21896;
  void * D.21897;
  long int D.21898;
  void * D.21899;
  void * D.21900;
  long int D.21901;
  gdouble D.21902;
  union LongDoubleUnion val;
  union LongDoubleUnion comp;
  union LongDoubleUnion ret;

  try
    {
      val.fval = value;
      comp.fval = comparand;
      D.21896 = val.ival;
      D.21897 = (void *) D.21896;
      D.21898 = comp.ival;
      D.21899 = (void *) D.21898;
      D.21900 = InterlockedCompareExchangePointer (location, D.21897, D.21899);
      D.21901 = (long int) D.21900;
      ret.ival = D.21901;
      D.21902 = ret.fval;
      return D.21902;
    }
  finally
    {
      val = {CLOBBER};
      comp = {CLOBBER};
      ret = {CLOBBER};
    }
}


ves_icall_System_Threading_Interlocked_CompareExchange_Long (gint64 * location, gint64 value, gint64 comparand)
{
  gint64 D.21905;

  D.21905 = InterlockedCompareExchange64 (location, value, comparand);
  return D.21905;
}


ves_icall_System_Threading_Interlocked_CompareExchange_T (struct MonoObject * * location, struct MonoObject * value, struct MonoObject * comparand)
{
  struct MonoObject * D.21907;
  struct MonoObject * res;

  res = InterlockedCompareExchangePointer (location, value, comparand);
  mono_gc_wbarrier_generic_nostore (location);
  D.21907 = res;
  return D.21907;
}


ves_icall_System_Threading_Interlocked_Exchange_T (struct MonoObject * * location, struct MonoObject * value)
{
  struct MonoObject * D.21909;
  struct MonoObject * res;

  res = InterlockedExchangePointer (location, value);
  mono_gc_wbarrier_generic_nostore (location);
  D.21909 = res;
  return D.21909;
}


ves_icall_System_Threading_Interlocked_Add_Int (gint32 * location, gint32 value)
{
  gint32 D.21911;

  D.21911 = InterlockedAdd (location, value);
  return D.21911;
}


InterlockedAdd (volatile gint32 * dest, gint32 add)
{
  gint32 D.21913;
  unsigned int add.63;
  unsigned int D.21915;

  add.63 = (unsigned int) add;
  D.21915 = __sync_add_and_fetch_4 (dest, add.63);
  D.21913 = (gint32) D.21915;
  return D.21913;
}


ves_icall_System_Threading_Interlocked_Add_Long (gint64 * location, gint64 value)
{
  gint64 D.21917;

  D.21917 = InterlockedAdd64 (location, value);
  return D.21917;
}


InterlockedAdd64 (volatile gint64 * dest, gint64 add)
{
  gint64 D.21919;
  long unsigned int add.64;
  long unsigned int D.21921;

  add.64 = (long unsigned int) add;
  D.21921 = __sync_add_and_fetch_8 (dest, add.64);
  D.21919 = (gint64) D.21921;
  return D.21919;
}


ves_icall_System_Threading_Interlocked_Read_Long (gint64 * location)
{
  gint64 D.21923;

  D.21923 = InterlockedRead64 (location);
  return D.21923;
}


InterlockedRead64 (volatile gint64 * src)
{
  gint64 D.21925;
  long unsigned int D.21926;

  D.21926 = __sync_fetch_and_add_8 (src, 0);
  D.21925 = (gint64) D.21926;
  return D.21925;
}


ves_icall_System_Threading_Thread_MemoryBarrier ()
{
  mono_memory_barrier ();
}


ves_icall_System_Threading_Thread_ClrState (struct MonoInternalThread * this, guint32 state)
{
  unsigned int D.21928;
  void * background_change_event.65;

  mono_thread_clr_state (this, state);
  D.21928 = state & 4;
  if (D.21928 != 0) goto <D.21929>; else goto <D.21930>;
  <D.21929>:
  background_change_event.65 = background_change_event;
  SetEvent (background_change_event.65);
  <D.21930>:
}


ves_icall_System_Threading_Thread_SetState (struct MonoInternalThread * this, guint32 state)
{
  unsigned int D.21932;
  void * background_change_event.66;

  mono_thread_set_state (this, state);
  D.21932 = state & 4;
  if (D.21932 != 0) goto <D.21933>; else goto <D.21934>;
  <D.21933>:
  background_change_event.66 = background_change_event;
  SetEvent (background_change_event.66);
  <D.21934>:
}


ves_icall_System_Threading_Thread_GetState (struct MonoInternalThread * this)
{
  guint32 D.21936;
  guint32 state;

  lock_thread (this);
  state = this->state;
  unlock_thread (this);
  D.21936 = state;
  return D.21936;
}


ves_icall_System_Threading_Thread_Interrupt_internal (struct MonoInternalThread * this)
{
  int iftmp.67;
  unsigned int D.21942;
  unsigned int D.21943;
  struct MonoInternalThread * current;
  gboolean throw;

  lock_thread (this);
  current = mono_thread_internal_current ();
  this->thread_interrupt_requested = 1;
  if (current != this) goto <D.21941>; else goto <D.21939>;
  <D.21941>:
  D.21942 = this->state;
  D.21943 = D.21942 & 32;
  if (D.21943 != 0) goto <D.21944>; else goto <D.21939>;
  <D.21944>:
  iftmp.67 = 1;
  goto <D.21940>;
  <D.21939>:
  iftmp.67 = 0;
  <D.21940>:
  throw = iftmp.67;
  unlock_thread (this);
  if (throw != 0) goto <D.21945>; else goto <D.21946>;
  <D.21945>:
  abort_thread_internal (this, 1, 0);
  <D.21946>:
}


abort_thread_internal (struct MonoInternalThread * thread, gboolean can_raise_exception, gboolean install_async_abort)
{
  int D.21947;
  struct MonoInternalThread * D.21950;
  void * D.21955;
  long unsigned int D.21956;
  struct MonoRuntimeExceptionHandlingCallbacks * D.21959;
  gboolean (*<T27a2>) (struct MonoThreadUnwindState *) D.21960;
  struct MonoThreadUnwindState * D.21961;
  int D.21962;
  long unsigned int D.21965;
  gint32 * D.21966;
  int D.21967;
  int iftmp.68;
  struct MonoMethod * D.21974;
  int D.21975;
  long unsigned int D.21977;
  void * D.21978;
  struct MonoJitInfo * ji;
  struct MonoThreadInfo * info;
  gboolean protected_wrapper;
  gboolean running_managed;

  info = 0B;
  D.21947 = mono_thread_info_new_interrupt_enabled ();
  if (D.21947 == 0) goto <D.21948>; else goto <D.21949>;
  <D.21948>:
  signal_thread_state_change (thread);
  return;
  <D.21949>:
  D.21950 = mono_thread_internal_current ();
  if (D.21950 == thread) goto <D.21951>; else goto <D.21952>;
  <D.21951>:
  {
    struct MonoException * exc;

    exc = mono_thread_request_interruption (can_raise_exception);
    if (exc != 0B) goto <D.21953>; else goto <D.21954>;
    <D.21953>:
    mono_raise_exception (exc);
    <D.21954>:
    D.21955 = thread->handle;
    wapi_interrupt_thread (D.21955);
    return;
  }
  <D.21952>:
  D.21956 = thread->tid;
  info = mono_thread_info_safe_suspend_sync (D.21956, 1);
  if (info == 0B) goto <D.21957>; else goto <D.21958>;
  <D.21957>:
  return;
  <D.21958>:
  D.21959 = mono_get_eh_callbacks ();
  D.21960 = D.21959->mono_install_handler_block_guard;
  D.21961 = &info->suspend_state;
  D.21962 = D.21960 (D.21961);
  if (D.21962 != 0) goto <D.21963>; else goto <D.21964>;
  <D.21963>:
  D.21965 = info->node.key;
  mono_thread_info_resume (D.21965);
  return;
  <D.21964>:
  D.21966 = &thread->interruption_requested;
  D.21967 = InterlockedCompareExchange (D.21966, 1, 0);
  if (D.21967 == 1) goto <D.21968>; else goto <D.21969>;
  <D.21968>:
  D.21965 = info->node.key;
  mono_thread_info_resume (D.21965);
  return;
  <D.21969>:
  InterlockedIncrement (&thread_interruption_requested);
  ji = mono_thread_info_get_last_managed (info);
  if (ji != 0B) goto <D.21973>; else goto <D.21971>;
  <D.21973>:
  D.21974 = mono_jit_info_get_method (ji);
  D.21975 = mono_threads_is_critical_method (D.21974);
  if (D.21975 != 0) goto <D.21976>; else goto <D.21971>;
  <D.21976>:
  iftmp.68 = 1;
  goto <D.21972>;
  <D.21971>:
  iftmp.68 = 0;
  <D.21972>:
  protected_wrapper = iftmp.68;
  D.21977 = info->suspend_state.ctx.sc_ir;
  D.21978 = (void *) D.21977;
  running_managed = mono_jit_info_match (ji, D.21978);
  if (protected_wrapper == 0) goto <D.21981>; else goto <D.21979>;
  <D.21981>:
  if (running_managed != 0) goto <D.21982>; else goto <D.21979>;
  <D.21982>:
  if (install_async_abort != 0) goto <D.21983>; else goto <D.21984>;
  <D.21983>:
  mono_thread_info_setup_async_call (info, self_interrupt_thread, 0B);
  <D.21984>:
  D.21965 = info->node.key;
  mono_thread_info_resume (D.21965);
  goto <D.21980>;
  <D.21979>:
  {
    void * interrupt_handle;

    D.21955 = thread->handle;
    interrupt_handle = wapi_prepare_interrupt_thread (D.21955);
    D.21965 = info->node.key;
    mono_thread_info_resume (D.21965);
    wapi_finish_interrupt_thread (interrupt_handle);
  }
  <D.21980>:
}


self_interrupt_thread (void * _unused)
{
  struct MonoInternalThread * D.21986;
  struct MonoContext * D.21989;
  struct MonoThreadInfo * info;
  struct MonoException * exc;

  info = mono_thread_info_current ();
  D.21986 = mono_thread_internal_current ();
  exc = mono_thread_execute_interruption (D.21986);
  if (exc != 0B) goto <D.21987>; else goto <D.21988>;
  <D.21987>:
  D.21989 = &info->suspend_state.ctx;
  mono_raise_exception_with_context (exc, D.21989);
  <D.21988>:
  monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "threads.c", 4585);
}


signal_thread_state_change (struct MonoInternalThread * thread)
{
  struct MonoInternalThread * D.21990;
  int D.21995;
  void * D.21996;

  D.21990 = mono_thread_internal_current ();
  if (D.21990 == thread) goto <D.21991>; else goto <D.21992>;
  <D.21991>:
  {
    struct MonoException * exc;

    exc = mono_thread_request_interruption (0);
    if (exc != 0B) goto <D.21993>; else goto <D.21994>;
    <D.21993>:
    mono_raise_exception (exc);
    <D.21994>:
  }
  <D.21992>:
  D.21995 = mono_thread_get_abort_signal ();
  mono_thread_kill (thread, D.21995);
  D.21996 = thread->handle;
  wapi_interrupt_thread (D.21996);
}


mono_thread_info_get_last_managed (struct MonoThreadInfo * info)
{
  struct MonoJitInfo * D.21999;
  struct MonoRuntimeExceptionHandlingCallbacks * D.22000;
  void (*<T2792>) (gboolean (*MonoInternalStackWalk) (struct MonoStackFrameInfo *, struct MonoContext *, void *), struct MonoThreadUnwindState *, MonoUnwindOptions, void *) D.22001;
  struct MonoThreadUnwindState * D.22002;
  struct MonoJitInfo * ji;

  try
    {
      ji = 0B;
      if (info == 0B) goto <D.21997>; else goto <D.21998>;
      <D.21997>:
      D.21999 = 0B;
      return D.21999;
      <D.21998>:
      D.22000 = mono_get_eh_callbacks ();
      D.22001 = D.22000->mono_walk_stack_with_state;
      D.22002 = &info->suspend_state;
      D.22001 (last_managed, D.22002, 0, &ji);
      D.21999 = ji;
      return D.21999;
    }
  finally
    {
      ji = {CLOBBER};
    }
}


last_managed (struct MonoStackFrameInfo * frame, struct MonoContext * ctx, void * data)
{
  struct MonoJitInfo * D.22005;
  gboolean D.22006;
  struct MonoJitInfo * * dest;

  dest = data;
  D.22005 = frame->ji;
  *dest = D.22005;
  D.22006 = 1;
  return D.22006;
}


mono_threads_is_critical_method (struct MonoMethod * method)
{
  <unnamed-unsigned:5> D.22008;
  int D.22009;
  gboolean D.22010;

  D.22008 = method->wrapper_type;
  D.22009 = (int) D.22008;
  switch (D.22009) <default: <D.22011>, case 4: <D.20035>, case 10: <D.20036>, case 11: <D.20037>>
  <D.20035>:
  <D.20036>:
  <D.20037>:
  D.22010 = 1;
  return D.22010;
  <D.22011>:
  D.22010 = 0;
  return D.22010;
}


mono_jit_info_match (struct MonoJitInfo * ji, void * ip)
{
  gboolean D.22015;
  int iftmp.69;
  void * D.22019;
  int D.22021;
  sizetype D.22022;
  char * D.22023;

  if (ji == 0B) goto <D.22013>; else goto <D.22014>;
  <D.22013>:
  D.22015 = 0;
  return D.22015;
  <D.22014>:
  D.22019 = ji->code_start;
  if (D.22019 <= ip) goto <D.22020>; else goto <D.22017>;
  <D.22020>:
  D.22019 = ji->code_start;
  D.22021 = ji->code_size;
  D.22022 = (sizetype) D.22021;
  D.22023 = D.22019 + D.22022;
  if (D.22023 > ip) goto <D.22024>; else goto <D.22017>;
  <D.22024>:
  iftmp.69 = 1;
  goto <D.22018>;
  <D.22017>:
  iftmp.69 = 0;
  <D.22018>:
  D.22015 = iftmp.69;
  return D.22015;
}


mono_thread_current_check_pending_interrupt ()
{
  unsigned char D.22026;
  struct MonoException * D.22031;
  struct MonoInternalThread * thread;
  gboolean throw;

  thread = mono_thread_internal_current ();
  throw = 0;
  lock_thread (thread);
  D.22026 = thread->thread_interrupt_requested;
  if (D.22026 != 0) goto <D.22027>; else goto <D.22028>;
  <D.22027>:
  throw = 1;
  thread->thread_interrupt_requested = 0;
  <D.22028>:
  unlock_thread (thread);
  if (throw != 0) goto <D.22029>; else goto <D.22030>;
  <D.22029>:
  D.22031 = mono_get_exception_thread_interrupted ();
  mono_raise_exception (D.22031);
  <D.22030>:
}


mono_thread_get_abort_signal ()
{
  int abort_signum.70;
  int D.22035;
  int D.22036;
  void (*<Teee>) (int) D.22037;
  void (*<Tf31>) (int, struct siginfo_t *, void *) D.22040;
  int D.22043;
  static int abort_signum = -1;
  int i;

  abort_signum.70 = abort_signum;
  if (abort_signum.70 != -1) goto <D.22033>; else goto <D.22034>;
  <D.22033>:
  D.22035 = abort_signum;
  return D.22035;
  <D.22034>:
  D.22036 = __libc_current_sigrtmin ();
  i = D.22036 + 1;
  goto <D.19992>;
  <D.19991>:
  {
    struct sigaction sinfo;

    try
      {
        sigaction (i, 0B, &sinfo);
        D.22037 = sinfo.__sigaction_handler.sa_handler;
        if (D.22037 == 0B) goto <D.22038>; else goto <D.22039>;
        <D.22038>:
        D.22040 = sinfo.__sigaction_handler.sa_sigaction;
        if (D.22040 == 0B) goto <D.22041>; else goto <D.22042>;
        <D.22041>:
        abort_signum = i;
        D.22035 = i;
        return D.22035;
        <D.22042>:
        <D.22039>:
      }
    finally
      {
        sinfo = {CLOBBER};
      }
  }
  i = i + 1;
  <D.19992>:
  D.22043 = __libc_current_sigrtmax ();
  if (D.22043 > i) goto <D.19991>; else goto <D.19993>;
  <D.19993>:
  D.22035 = __libc_current_sigrtmin ();
  return D.22035;
}


ves_icall_System_Threading_Thread_Abort (struct MonoInternalThread * thread, struct MonoObject * state)
{
  long unsigned int D.22047;
  long unsigned int D.22048;
  unsigned int D.22051;
  unsigned int D.22052;
  unsigned int D.22055;
  unsigned int D.22056;
  int D.22057;
  unsigned int D.22060;
  unsigned int D.22063;
  int D.22064;
  _Bool D.22065;
  long int D.22066;
  long int D.22067;
  int shutting_down.71;

  lock_thread (thread);
  D.22047 = BIT_FIELD_REF <*thread, 64, 384>;
  D.22048 = D.22047 & 622770257920;
  if (D.22048 != 0) goto <D.22049>; else goto <D.22050>;
  <D.22049>:
  unlock_thread (thread);
  return;
  <D.22050>:
  D.22051 = thread->state;
  D.22052 = D.22051 & 8;
  if (D.22052 != 0) goto <D.22053>; else goto <D.22054>;
  <D.22053>:
  D.22051 = thread->state;
  D.22055 = D.22051 | 256;
  thread->state = D.22055;
  unlock_thread (thread);
  return;
  <D.22054>:
  D.22051 = thread->state;
  D.22056 = D.22051 | 128;
  thread->state = D.22056;
  D.22057 = thread->abort_state_handle;
  if (D.22057 != 0) goto <D.22058>; else goto <D.22059>;
  <D.22058>:
  D.22057 = thread->abort_state_handle;
  D.22060 = (unsigned int) D.22057;
  mono_gchandle_free (D.22060);
  <D.22059>:
  if (state != 0B) goto <D.22061>; else goto <D.22062>;
  <D.22061>:
  D.22063 = mono_gchandle_new (state, 0);
  D.22064 = (int) D.22063;
  thread->abort_state_handle = D.22064;
  D.22057 = thread->abort_state_handle;
  D.22065 = D.22057 == 0;
  D.22066 = (long int) D.22065;
  D.22067 = __builtin_expect (D.22066, 0);
  if (D.22067 != 0) goto <D.22068>; else goto <D.22069>;
  <D.22068>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2156, "thread->abort_state_handle");
  <D.22069>:
  goto <D.22070>;
  <D.22062>:
  thread->abort_state_handle = 0;
  <D.22070>:
  thread->abort_exc = 0B;
  unlock_thread (thread);
  shutting_down.71 = shutting_down;
  if (shutting_down.71 == 0) goto <D.22072>; else goto <D.22073>;
  <D.22072>:
  mono_thread_resume (thread);
  <D.22073>:
  abort_thread_internal (thread, 1, 1);
}


mono_thread_resume (struct MonoInternalThread * thread)
{
  unsigned int D.22075;
  unsigned int D.22076;
  unsigned int D.22079;
  gboolean D.22080;
  long unsigned int D.22081;
  long unsigned int D.22082;

  lock_thread (thread);
  D.22075 = thread->state;
  D.22076 = D.22075 & 2;
  if (D.22076 != 0) goto <D.22077>; else goto <D.22078>;
  <D.22077>:
  D.22075 = thread->state;
  D.22079 = D.22075 & 4294967293;
  thread->state = D.22079;
  unlock_thread (thread);
  D.22080 = 1;
  return D.22080;
  <D.22078>:
  D.22081 = BIT_FIELD_REF <*thread, 64, 384>;
  D.22082 = D.22081 & 1477468749824;
  if (D.22082 != 274877906944) goto <D.22083>; else goto <D.22084>;
  <D.22083>:
  unlock_thread (thread);
  D.22080 = 0;
  return D.22080;
  <D.22084>:
  D.22080 = resume_thread_internal (thread);
  return D.22080;
}


resume_thread_internal (struct MonoInternalThread * thread)
{
  int D.22086;
  void * D.22089;
  void * D.22090;
  gboolean D.22093;
  void * D.22094;
  long unsigned int D.22095;
  int D.22096;
  unsigned int D.22099;
  unsigned int D.22100;

  D.22086 = mono_thread_info_new_interrupt_enabled ();
  if (D.22086 == 0) goto <D.22087>; else goto <D.22088>;
  <D.22087>:
  D.22089 = CreateEvent (0B, 1, 0, 0B);
  thread->resume_event = D.22089;
  D.22090 = thread->resume_event;
  if (D.22090 == 0B) goto <D.22091>; else goto <D.22092>;
  <D.22091>:
  unlock_thread (thread);
  D.22093 = 0;
  return D.22093;
  <D.22092>:
  D.22094 = thread->suspend_event;
  SetEvent (D.22094);
  unlock_thread (thread);
  D.22090 = thread->resume_event;
  WaitForSingleObject (D.22090, 4294967295);
  D.22090 = thread->resume_event;
  CloseHandle (D.22090);
  thread->resume_event = 0B;
  D.22093 = 1;
  return D.22093;
  <D.22088>:
  unlock_thread (thread);
  D.22095 = thread->tid;
  D.22096 = mono_thread_info_resume (D.22095);
  if (D.22096 == 0) goto <D.22097>; else goto <D.22098>;
  <D.22097>:
  D.22093 = 0;
  return D.22093;
  <D.22098>:
  lock_thread (thread);
  D.22099 = thread->state;
  D.22100 = D.22099 & 4294967231;
  thread->state = D.22100;
  unlock_thread (thread);
  D.22093 = 1;
  return D.22093;
}


ves_icall_System_Threading_Thread_ResetAbort ()
{
  unsigned int D.22102;
  int D.22103;
  unsigned int D.22104;
  struct MonoException * D.22107;
  int D.22108;
  unsigned int D.22111;
  struct MonoInternalThread * thread;
  gboolean was_aborting;

  thread = mono_thread_internal_current ();
  lock_thread (thread);
  D.22102 = thread->state;
  D.22103 = (int) D.22102;
  was_aborting = D.22103 & 128;
  D.22102 = thread->state;
  D.22104 = D.22102 & 4294967167;
  thread->state = D.22104;
  unlock_thread (thread);
  if (was_aborting == 0) goto <D.22105>; else goto <D.22106>;
  <D.22105>:
  {
    const char * msg;

    msg = "Unable to reset abort because no abort was requested";
    D.22107 = mono_get_exception_thread_state (msg);
    mono_raise_exception (D.22107);
  }
  <D.22106>:
  thread->abort_exc = 0B;
  D.22108 = thread->abort_state_handle;
  if (D.22108 != 0) goto <D.22109>; else goto <D.22110>;
  <D.22109>:
  D.22108 = thread->abort_state_handle;
  D.22111 = (unsigned int) D.22108;
  mono_gchandle_free (D.22111);
  thread->abort_state_handle = 0;
  <D.22110>:
}


mono_thread_internal_reset_abort (struct MonoInternalThread * thread)
{
  unsigned int D.22112;
  unsigned int D.22113;
  struct MonoException * D.22114;
  int D.22117;
  unsigned int D.22120;

  lock_thread (thread);
  D.22112 = thread->state;
  D.22113 = D.22112 & 4294967167;
  thread->state = D.22113;
  D.22114 = thread->abort_exc;
  if (D.22114 != 0B) goto <D.22115>; else goto <D.22116>;
  <D.22115>:
  thread->abort_exc = 0B;
  D.22117 = thread->abort_state_handle;
  if (D.22117 != 0) goto <D.22118>; else goto <D.22119>;
  <D.22118>:
  D.22117 = thread->abort_state_handle;
  D.22120 = (unsigned int) D.22117;
  mono_gchandle_free (D.22120);
  thread->abort_state_handle = 0;
  <D.22119>:
  <D.22116>:
  unlock_thread (thread);
}


ves_icall_System_Threading_Thread_GetAbortExceptionState (struct MonoThread * this)
{
  int D.22121;
  struct MonoObject * D.22124;
  unsigned int D.22125;
  _Bool D.22126;
  long int D.22127;
  long int D.22128;
  struct MonoVTable * D.22131;
  struct MonoDomain * D.22132;
  struct MonoObject * exc.72;
  struct MonoObject * * D.22140;
  struct MonoInternalThread * thread;
  struct MonoObject * state;
  struct MonoObject * deserialized;
  struct MonoObject * exc;
  struct MonoDomain * domain;

  try
    {
      thread = this->internal_thread;
      deserialized = 0B;
      D.22121 = thread->abort_state_handle;
      if (D.22121 == 0) goto <D.22122>; else goto <D.22123>;
      <D.22122>:
      D.22124 = 0B;
      return D.22124;
      <D.22123>:
      D.22121 = thread->abort_state_handle;
      D.22125 = (unsigned int) D.22121;
      state = mono_gchandle_get_target (D.22125);
      D.22126 = state == 0B;
      D.22127 = (long int) D.22126;
      D.22128 = __builtin_expect (D.22127, 0);
      if (D.22128 != 0) goto <D.22129>; else goto <D.22130>;
      <D.22129>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2237, "state");
      <D.22130>:
      domain = mono_domain_get ();
      D.22131 = state->vtable;
      D.22132 = D.22131->domain;
      if (D.22132 == domain) goto <D.22133>; else goto <D.22134>;
      <D.22133>:
      D.22124 = state;
      return D.22124;
      <D.22134>:
      deserialized = mono_object_xdomain_representation (state, domain, &exc);
      if (deserialized == 0B) goto <D.22135>; else goto <D.22136>;
      <D.22135>:
      {
        struct MonoException * invalid_op_exc;

        invalid_op_exc = mono_get_exception_invalid_operation ("Thread.ExceptionState cannot access an ExceptionState from a different AppDomain");
        exc.72 = exc;
        if (exc.72 != 0B) goto <D.22138>; else goto <D.22139>;
        <D.22138>:
        D.22140 = &invalid_op_exc->inner_ex;
        exc.72 = exc;
        mono_gc_wbarrier_set_field (invalid_op_exc, D.22140, exc.72);
        <D.22139>:
        mono_raise_exception (invalid_op_exc);
      }
      <D.22136>:
      D.22124 = deserialized;
      return D.22124;
    }
  finally
    {
      exc = {CLOBBER};
    }
}


ves_icall_System_Threading_Thread_Suspend (struct MonoInternalThread * thread)
{
  int D.22143;
  struct MonoException * D.22146;

  D.22143 = mono_thread_suspend (thread);
  if (D.22143 == 0) goto <D.22144>; else goto <D.22145>;
  <D.22144>:
  D.22146 = mono_get_exception_thread_state ("Thread has not been started, or is dead.");
  mono_raise_exception (D.22146);
  <D.22145>:
}


mono_thread_suspend (struct MonoInternalThread * thread)
{
  long unsigned int D.22147;
  long unsigned int D.22148;
  gboolean D.22151;
  long unsigned int D.22152;
  unsigned int D.22155;
  unsigned int D.22156;

  lock_thread (thread);
  D.22147 = BIT_FIELD_REF <*thread, 64, 384>;
  D.22148 = D.22147 & 1202590842880;
  if (D.22148 != 0) goto <D.22149>; else goto <D.22150>;
  <D.22149>:
  unlock_thread (thread);
  D.22151 = 0;
  return D.22151;
  <D.22150>:
  D.22147 = BIT_FIELD_REF <*thread, 64, 384>;
  D.22152 = D.22147 & 287762808832;
  if (D.22152 != 0) goto <D.22153>; else goto <D.22154>;
  <D.22153>:
  unlock_thread (thread);
  D.22151 = 1;
  return D.22151;
  <D.22154>:
  D.22155 = thread->state;
  D.22156 = D.22155 | 2;
  thread->state = D.22156;
  unlock_thread (thread);
  suspend_thread_internal (thread, 0);
  D.22151 = 1;
  return D.22151;
}


suspend_thread_internal (struct MonoInternalThread * thread, gboolean interrupt)
{
  int D.22158;
  struct MonoInternalThread * D.22161;
  long unsigned int D.22165;
  int iftmp.73;
  struct MonoMethod * D.22172;
  int D.22173;
  long unsigned int D.22175;
  void * D.22176;
  gint32 * D.22181;
  int D.22182;
  void * D.22187;
  long unsigned int D.22188;

  D.22158 = mono_thread_info_new_interrupt_enabled ();
  if (D.22158 == 0) goto <D.22159>; else goto <D.22160>;
  <D.22159>:
  signal_thread_state_change (thread);
  return;
  <D.22160>:
  lock_thread (thread);
  D.22161 = mono_thread_internal_current ();
  if (D.22161 == thread) goto <D.22162>; else goto <D.22163>;
  <D.22162>:
  transition_to_suspended (thread);
  mono_thread_info_self_suspend ();
  goto <D.22164>;
  <D.22163>:
  {
    struct MonoThreadInfo * info;
    struct MonoJitInfo * ji;
    gboolean protected_wrapper;
    gboolean running_managed;

    D.22165 = thread->tid;
    info = mono_thread_info_safe_suspend_sync (D.22165, interrupt);
    if (info == 0B) goto <D.22166>; else goto <D.22167>;
    <D.22166>:
    unlock_thread (thread);
    return;
    <D.22167>:
    ji = mono_thread_info_get_last_managed (info);
    if (ji != 0B) goto <D.22171>; else goto <D.22169>;
    <D.22171>:
    D.22172 = mono_jit_info_get_method (ji);
    D.22173 = mono_threads_is_critical_method (D.22172);
    if (D.22173 != 0) goto <D.22174>; else goto <D.22169>;
    <D.22174>:
    iftmp.73 = 1;
    goto <D.22170>;
    <D.22169>:
    iftmp.73 = 0;
    <D.22170>:
    protected_wrapper = iftmp.73;
    D.22175 = info->suspend_state.ctx.sc_ir;
    D.22176 = (void *) D.22175;
    running_managed = mono_jit_info_match (ji, D.22176);
    if (running_managed != 0) goto <D.22179>; else goto <D.22177>;
    <D.22179>:
    if (protected_wrapper == 0) goto <D.22180>; else goto <D.22177>;
    <D.22180>:
    transition_to_suspended (thread);
    goto <D.22178>;
    <D.22177>:
    {
      void * interrupt_handle;

      D.22181 = &thread->interruption_requested;
      D.22182 = InterlockedCompareExchange (D.22181, 1, 0);
      if (D.22182 == 0) goto <D.22183>; else goto <D.22184>;
      <D.22183>:
      InterlockedIncrement (&thread_interruption_requested);
      <D.22184>:
      if (interrupt != 0) goto <D.22185>; else goto <D.22186>;
      <D.22185>:
      D.22187 = thread->handle;
      interrupt_handle = wapi_prepare_interrupt_thread (D.22187);
      <D.22186>:
      D.22188 = info->node.key;
      mono_thread_info_resume (D.22188);
      if (interrupt != 0) goto <D.22189>; else goto <D.22190>;
      <D.22189>:
      wapi_finish_interrupt_thread (interrupt_handle);
      <D.22190>:
      unlock_thread (thread);
    }
    <D.22178>:
  }
  <D.22164>:
}


ves_icall_System_Threading_Thread_Resume (struct MonoThread * thread)
{
  struct _MonoInternalThread * D.22194;
  int D.22196;
  struct MonoException * D.22197;

  D.22194 = thread->internal_thread;
  if (D.22194 == 0B) goto <D.22192>; else goto <D.22195>;
  <D.22195>:
  D.22194 = thread->internal_thread;
  D.22196 = mono_thread_resume (D.22194);
  if (D.22196 == 0) goto <D.22192>; else goto <D.22193>;
  <D.22192>:
  D.22197 = mono_get_exception_thread_state ("Thread has not been started, or is dead.");
  mono_raise_exception (D.22197);
  <D.22193>:
}


mono_thread_internal_stop (struct MonoInternalThread * thread)
{
  long unsigned int D.22198;
  long unsigned int D.22199;
  unsigned int D.22202;
  unsigned int D.22203;
  unsigned int D.22204;

  lock_thread (thread);
  D.22198 = BIT_FIELD_REF <*thread, 64, 384>;
  D.22199 = D.22198 & 73014444032;
  if (D.22199 != 0) goto <D.22200>; else goto <D.22201>;
  <D.22200>:
  unlock_thread (thread);
  return;
  <D.22201>:
  mono_thread_resume (thread);
  D.22202 = thread->state;
  D.22203 = D.22202 | 1;
  thread->state = D.22203;
  D.22202 = thread->state;
  D.22204 = D.22202 & 4294967167;
  thread->state = D.22204;
  unlock_thread (thread);
  abort_thread_internal (thread, 1, 1);
}


mono_thread_stop (struct MonoThread * thread)
{
  struct _MonoInternalThread * D.22206;

  D.22206 = thread->internal_thread;
  mono_thread_internal_stop (D.22206);
}


ves_icall_System_Threading_Thread_VolatileRead1 (void * ptr)
{
  gint8 D.22207;
  gint8 tmp;

  {
    gint8 __tmp;

    __tmp = MEM[(volatile gint8 *)ptr];
    mono_memory_barrier ();
    tmp = __tmp;
  }
  D.22207 = tmp;
  return D.22207;
}


ves_icall_System_Threading_Thread_VolatileRead2 (void * ptr)
{
  gint16 D.22209;
  gint16 tmp;

  {
    gint16 __tmp;

    __tmp = MEM[(volatile gint16 *)ptr];
    mono_memory_barrier ();
    tmp = __tmp;
  }
  D.22209 = tmp;
  return D.22209;
}


ves_icall_System_Threading_Thread_VolatileRead4 (void * ptr)
{
  gint32 D.22211;
  gint32 tmp;

  {
    gint32 __tmp;

    __tmp = MEM[(volatile gint32 *)ptr];
    mono_memory_barrier ();
    tmp = __tmp;
  }
  D.22211 = tmp;
  return D.22211;
}


ves_icall_System_Threading_Thread_VolatileRead8 (void * ptr)
{
  gint64 D.22213;
  gint64 tmp;

  {
    gint64 __tmp;

    __tmp = MEM[(volatile gint64 *)ptr];
    mono_memory_barrier ();
    tmp = __tmp;
  }
  D.22213 = tmp;
  return D.22213;
}


ves_icall_System_Threading_Thread_VolatileReadIntPtr (void * ptr)
{
  void * D.22215;
  volatile void * tmp;

  {
    volatile void * __tmp;

    __tmp = MEM[(volatile void * *)ptr];
    mono_memory_barrier ();
    tmp = __tmp;
  }
  D.22215 = tmp;
  return D.22215;
}


ves_icall_System_Threading_Thread_VolatileReadObject (void * ptr)
{
  void * D.22217;
  volatile struct MonoObject * tmp;

  {
    volatile struct MonoObject * __tmp;

    __tmp = MEM[(volatile struct MonoObject * *)ptr];
    mono_memory_barrier ();
    tmp = __tmp;
  }
  D.22217 = tmp;
  return D.22217;
}


ves_icall_System_Threading_Thread_VolatileReadDouble (void * ptr)
{
  double D.22219;
  double tmp;

  {
    double __tmp;

    __tmp = MEM[(volatile double *)ptr];
    mono_memory_barrier ();
    tmp = __tmp;
  }
  D.22219 = tmp;
  return D.22219;
}


ves_icall_System_Threading_Thread_VolatileReadFloat (void * ptr)
{
  float D.22221;
  float tmp;

  {
    float __tmp;

    __tmp = MEM[(volatile float *)ptr];
    mono_memory_barrier ();
    tmp = __tmp;
  }
  D.22221 = tmp;
  return D.22221;
}


ves_icall_System_Threading_Volatile_Read1 (void * ptr)
{
  gint8 D.22223;

  D.22223 = InterlockedRead8 (ptr);
  return D.22223;
}


InterlockedRead8 (volatile gint8 * src)
{
  gint8 D.22225;
  unsigned char D.22226;

  D.22226 = __sync_fetch_and_add_1 (src, 0);
  D.22225 = (gint8) D.22226;
  return D.22225;
}


ves_icall_System_Threading_Volatile_Read2 (void * ptr)
{
  gint16 D.22228;

  D.22228 = InterlockedRead16 (ptr);
  return D.22228;
}


InterlockedRead16 (volatile gint16 * src)
{
  gint16 D.22230;
  short unsigned int D.22231;

  D.22231 = __sync_fetch_and_add_2 (src, 0);
  D.22230 = (gint16) D.22231;
  return D.22230;
}


ves_icall_System_Threading_Volatile_Read4 (void * ptr)
{
  gint32 D.22233;

  D.22233 = InterlockedRead (ptr);
  return D.22233;
}


InterlockedRead (volatile gint32 * src)
{
  gint32 D.22235;
  unsigned int D.22236;

  D.22236 = __sync_fetch_and_add_4 (src, 0);
  D.22235 = (gint32) D.22236;
  return D.22235;
}


ves_icall_System_Threading_Volatile_Read8 (void * ptr)
{
  gint64 D.22238;

  D.22238 = InterlockedRead64 (ptr);
  return D.22238;
}


ves_icall_System_Threading_Volatile_ReadIntPtr (void * ptr)
{
  void * D.22240;

  D.22240 = InterlockedReadPointer (ptr);
  return D.22240;
}


InterlockedReadPointer (void * volatile * src)
{
  void * D.22242;

  D.22242 = InterlockedCompareExchangePointer (src, 0B, 0B);
  return D.22242;
}


ves_icall_System_Threading_Volatile_ReadDouble (void * ptr)
{
  long int D.22244;
  double D.22245;
  union LongDoubleUnion u;

  try
    {
      D.22244 = InterlockedRead64 (ptr);
      u.ival = D.22244;
      D.22245 = u.fval;
      return D.22245;
    }
  finally
    {
      u = {CLOBBER};
    }
}


ves_icall_System_Threading_Volatile_ReadFloat (void * ptr)
{
  int D.22248;
  float D.22249;
  union IntFloatUnion u;

  try
    {
      D.22248 = InterlockedRead (ptr);
      u.ival = D.22248;
      D.22249 = u.fval;
      return D.22249;
    }
  finally
    {
      u = {CLOBBER};
    }
}


ves_icall_System_Threading_Volatile_Read_T (void * ptr)
{
  struct MonoObject * D.22252;

  D.22252 = InterlockedReadPointer (ptr);
  return D.22252;
}


ves_icall_System_Threading_Thread_VolatileWrite1 (void * ptr, gint8 value)
{
  mono_memory_barrier ();
  MEM[(volatile gint8 *)ptr] = value;
}


ves_icall_System_Threading_Thread_VolatileWrite2 (void * ptr, gint16 value)
{
  mono_memory_barrier ();
  MEM[(volatile gint16 *)ptr] = value;
}


ves_icall_System_Threading_Thread_VolatileWrite4 (void * ptr, gint32 value)
{
  mono_memory_barrier ();
  MEM[(volatile gint32 *)ptr] = value;
}


ves_icall_System_Threading_Thread_VolatileWrite8 (void * ptr, gint64 value)
{
  mono_memory_barrier ();
  MEM[(volatile gint64 *)ptr] = value;
}


ves_icall_System_Threading_Thread_VolatileWriteIntPtr (void * ptr, void * value)
{
  mono_memory_barrier ();
  MEM[(volatile void * *)ptr] = value;
}


ves_icall_System_Threading_Thread_VolatileWriteObject (void * ptr, struct MonoObject * value)
{
  mono_gc_wbarrier_generic_store_atomic (ptr, value);
}


ves_icall_System_Threading_Thread_VolatileWriteDouble (void * ptr, double value)
{
  mono_memory_barrier ();
  MEM[(volatile double *)ptr] = value;
}


ves_icall_System_Threading_Thread_VolatileWriteFloat (void * ptr, float value)
{
  mono_memory_barrier ();
  MEM[(volatile float *)ptr] = value;
}


ves_icall_System_Threading_Volatile_Write1 (void * ptr, gint8 value)
{
  InterlockedWrite8 (ptr, value);
}


InterlockedWrite8 (volatile gint8 * dst, gint8 val)
{
  unsigned char old_val.74;
  unsigned char val.75;
  unsigned char D.22256;
  signed char D.22257;
  gint8 old_val;

  <D.19350>:
  old_val = *dst;
  old_val.74 = (unsigned char) old_val;
  val.75 = (unsigned char) val;
  D.22256 = __sync_val_compare_and_swap_1 (dst, old_val.74, val.75);
  D.22257 = (signed char) D.22256;
  if (D.22257 != old_val) goto <D.19350>; else goto <D.19351>;
  <D.19351>:
}


ves_icall_System_Threading_Volatile_Write2 (void * ptr, gint16 value)
{
  InterlockedWrite16 (ptr, value);
}


InterlockedWrite16 (volatile gint16 * dst, gint16 val)
{
  short unsigned int old_val.76;
  short unsigned int val.77;
  short unsigned int D.22260;
  short int D.22261;
  gint16 old_val;

  <D.19357>:
  old_val = *dst;
  old_val.76 = (short unsigned int) old_val;
  val.77 = (short unsigned int) val;
  D.22260 = __sync_val_compare_and_swap_2 (dst, old_val.76, val.77);
  D.22261 = (short int) D.22260;
  if (D.22261 != old_val) goto <D.19357>; else goto <D.19358>;
  <D.19358>:
}


ves_icall_System_Threading_Volatile_Write4 (void * ptr, gint32 value)
{
  InterlockedWrite (ptr, value);
}


InterlockedWrite (volatile gint32 * dst, gint32 val)
{
  unsigned int old_val.78;
  unsigned int val.79;
  unsigned int D.22264;
  int D.22265;
  gint32 old_val;

  <D.19364>:
  old_val = *dst;
  old_val.78 = (unsigned int) old_val;
  val.79 = (unsigned int) val;
  D.22264 = __sync_val_compare_and_swap_4 (dst, old_val.78, val.79);
  D.22265 = (int) D.22264;
  if (D.22265 != old_val) goto <D.19364>; else goto <D.19365>;
  <D.19365>:
}


ves_icall_System_Threading_Volatile_Write8 (void * ptr, gint64 value)
{
  InterlockedWrite64 (ptr, value);
}


InterlockedWrite64 (volatile gint64 * dst, gint64 val)
{
  InterlockedExchange64 (dst, val);
}


ves_icall_System_Threading_Volatile_WriteIntPtr (void * ptr, void * value)
{
  InterlockedWritePointer (ptr, value);
}


InterlockedWritePointer (void * volatile * dst, void * val)
{
  InterlockedExchangePointer (dst, val);
}


ves_icall_System_Threading_Volatile_WriteDouble (void * ptr, double value)
{
  long int D.22266;
  union LongDoubleUnion u;

  try
    {
      u.fval = value;
      D.22266 = u.ival;
      InterlockedWrite64 (ptr, D.22266);
    }
  finally
    {
      u = {CLOBBER};
    }
}


ves_icall_System_Threading_Volatile_WriteFloat (void * ptr, float value)
{
  int D.22267;
  union IntFloatUnion u;

  try
    {
      u.fval = value;
      D.22267 = u.ival;
      InterlockedWrite (ptr, D.22267);
    }
  finally
    {
      u = {CLOBBER};
    }
}


ves_icall_System_Threading_Volatile_Write_T (void * ptr, struct MonoObject * value)
{
  mono_gc_wbarrier_generic_store_atomic (ptr, value);
}


mono_thread_init_tls ()
{
  mono_native_tls_alloc (&current_object_key, 0B);
}


mono_native_tls_alloc (pthread_key_t * key, void * destructor)
{
  int D.22268;
  void (*<Tbf>) (void *) destructor.80;
  int D.22270;
  _Bool D.22271;

  destructor.80 = (void (*<Tbf>) (void *)) destructor;
  D.22270 = pthread_key_create (key, destructor.80);
  D.22271 = D.22270 == 0;
  D.22268 = (int) D.22271;
  return D.22268;
}


mono_thread_init (void (*MonoThreadStartCB) (intptr_t, void *, void *) start_cb, void (*MonoThreadAttachCB) (intptr_t, void *) attach_cb)
{
  void * background_change_event.81;
  void * background_change_event.82;
  _Bool D.22275;
  long int D.22276;
  long int D.22277;

  InitializeCriticalSection (&threads_mutex);
  InitializeCriticalSection (&interlocked_mutex);
  InitializeCriticalSection (&contexts_mutex);
  background_change_event.81 = CreateEvent (0B, 1, 0, 0B);
  background_change_event = background_change_event.81;
  background_change_event.82 = background_change_event;
  D.22275 = background_change_event.82 == 0B;
  D.22276 = (long int) D.22275;
  D.22277 = __builtin_expect (D.22276, 0);
  if (D.22277 != 0) goto <D.22278>; else goto <D.22279>;
  <D.22278>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2657, "background_change_event != NULL");
  <D.22279>:
  mono_init_static_data_info (&thread_static_info);
  mono_init_static_data_info (&context_static_info);
  mono_thread_start_cb = start_cb;
  mono_thread_attach_cb = attach_cb;
  GetCurrentProcess ();
}


mono_init_static_data_info (struct StaticDataInfo * static_data)
{
  static_data->idx = 0;
  static_data->offset = 0;
  static_data->freelist = 0B;
}


mono_thread_cleanup ()
{
  int D.22280;
  unsigned int D.22281;
  unsigned int current_object_key.83;

  D.22280 = mono_environment_exitcode_get ();
  D.22281 = (unsigned int) D.22280;
  _wapi_thread_signal_self (D.22281);
  current_object_key.83 = current_object_key;
  mono_native_tls_free (current_object_key.83);
}


mono_native_tls_free (pthread_key_t key)
{
  pthread_key_delete (key);
}


mono_threads_install_cleanup (void (*MonoThreadCleanupFunc) (struct MonoInternalThread *) func)
{
  mono_thread_cleanup_fn = func;
}


mono_thread_set_manage_callback (struct MonoThread * thread, mono_bool (*MonoThreadManageCallback) (struct MonoThread *) func)
{
  struct _MonoInternalThread * D.22283;

  D.22283 = thread->internal_thread;
  D.22283->manage_callback = func;
}


mono_threads_install_notify_pending_exc (void (*MonoThreadNotifyPendingExcFunc) (void) func)
{
  mono_thread_notify_pending_exc_fn = func;
}


mono_threads_set_shutting_down ()
{
  _Bool D.22286;
  long int D.22287;
  long int D.22288;
  int shutting_down.84;
  _Bool D.22296;
  long int D.22297;
  long int D.22298;
  long unsigned int D.22301;
  long unsigned int D.22302;
  unsigned int D.22306;
  unsigned int D.22307;
  void * background_change_event.85;
  _Bool D.22311;
  long int D.22312;
  long int D.22313;
  struct MonoInternalThread * current_thread;

  current_thread = mono_thread_internal_current ();
  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22284>; else goto <D.22285>;
    <D.22284>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.22285>:
    D.22286 = ret != 0;
    D.22287 = (long int) D.22286;
    D.22288 = __builtin_expect (D.22287, 0);
    if (D.22288 != 0) goto <D.22289>; else goto <D.22290>;
    <D.22289>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2934, "ret == 0");
    <D.22290>:
  }
  shutting_down.84 = shutting_down;
  if (shutting_down.84 != 0) goto <D.22292>; else goto <D.22293>;
  <D.22292>:
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22294>; else goto <D.22295>;
    <D.22294>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.22295>:
    D.22296 = ret != 0;
    D.22297 = (long int) D.22296;
    D.22298 = __builtin_expect (D.22297, 0);
    if (D.22298 != 0) goto <D.22299>; else goto <D.22300>;
    <D.22299>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2937, "ret == 0");
    <D.22300>:
  }
  lock_thread (current_thread);
  D.22301 = BIT_FIELD_REF <*current_thread, 64, 384>;
  D.22302 = D.22301 & 562640715776;
  if (D.22302 != 0) goto <D.22303>; else goto <D.22304>;
  <D.22303>:
  unlock_thread (current_thread);
  mono_thread_execute_interruption (current_thread);
  goto <D.22305>;
  <D.22304>:
  D.22306 = current_thread->state;
  D.22307 = D.22306 | 16;
  current_thread->state = D.22307;
  unlock_thread (current_thread);
  <D.22305>:
  mono_domain_unset ();
  ExitThread (0);
  <D.22293>:
  shutting_down = 1;
  background_change_event.85 = background_change_event;
  SetEvent (background_change_event.85);
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22309>; else goto <D.22310>;
    <D.22309>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.22310>:
    D.22311 = ret != 0;
    D.22312 = (long int) D.22311;
    D.22313 = __builtin_expect (D.22312, 0);
    if (D.22313 != 0) goto <D.22314>; else goto <D.22315>;
    <D.22314>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2967, "ret == 0");
    <D.22315>:
  }
}


mono_thread_manage ()
{
  _Bool D.22318;
  long int D.22319;
  long int D.22320;
  struct MonoGHashTable * threads.86;
  _Bool D.22328;
  long int D.22329;
  long int D.22330;
  _Bool D.22335;
  long int D.22336;
  long int D.22337;
  _Bool D.22342;
  long int D.22343;
  long int D.22344;
  int shutting_down.87;
  _Bool D.22352;
  long int D.22353;
  long int D.22354;
  void * background_change_event.88;
  struct MonoInternalThread *[64] * D.22358;
  _Bool D.22361;
  long int D.22362;
  long int D.22363;
  unsigned int D.22366;
  int D.22369;
  struct MonoInternalThread * D.22372;
  struct MonoInternalThread * D.22373;
  _Bool D.22376;
  long int D.22377;
  long int D.22378;
  _Bool D.22383;
  long int D.22384;
  long int D.22385;
  struct wait_data wait_data;
  struct wait_data * wait;

  try
    {
      wait = &wait_data;
      memset (wait, 0, 1032);
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22316>; else goto <D.22317>;
        <D.22316>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.22317>:
        D.22318 = ret != 0;
        D.22319 = (long int) D.22318;
        D.22320 = __builtin_expect (D.22319, 0);
        if (D.22320 != 0) goto <D.22321>; else goto <D.22322>;
        <D.22321>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2980, "ret == 0");
        <D.22322>:
      }
      threads.86 = threads;
      if (threads.86 == 0B) goto <D.22324>; else goto <D.22325>;
      <D.22324>:
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22326>; else goto <D.22327>;
        <D.22326>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.22327>:
        D.22328 = ret != 0;
        D.22329 = (long int) D.22328;
        D.22330 = __builtin_expect (D.22329, 0);
        if (D.22330 != 0) goto <D.22331>; else goto <D.22332>;
        <D.22331>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2983, "ret == 0");
        <D.22332>:
      }
      return;
      <D.22325>:
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22333>; else goto <D.22334>;
        <D.22333>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.22334>:
        D.22335 = ret != 0;
        D.22336 = (long int) D.22335;
        D.22337 = __builtin_expect (D.22336, 0);
        if (D.22337 != 0) goto <D.22338>; else goto <D.22339>;
        <D.22338>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2986, "ret == 0");
        <D.22339>:
      }
      <D.20282>:
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22340>; else goto <D.22341>;
        <D.22340>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.22341>:
        D.22342 = ret != 0;
        D.22343 = (long int) D.22342;
        D.22344 = __builtin_expect (D.22343, 0);
        if (D.22344 != 0) goto <D.22345>; else goto <D.22346>;
        <D.22345>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2989, "ret == 0");
        <D.22346>:
      }
      shutting_down.87 = shutting_down;
      if (shutting_down.87 != 0) goto <D.22348>; else goto <D.22349>;
      <D.22348>:
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22350>; else goto <D.22351>;
        <D.22350>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.22351>:
        D.22352 = ret != 0;
        D.22353 = (long int) D.22352;
        D.22354 = __builtin_expect (D.22353, 0);
        if (D.22354 != 0) goto <D.22355>; else goto <D.22356>;
        <D.22355>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2992, "ret == 0");
        <D.22356>:
      }
      goto <D.20280>;
      <D.22349>:
      background_change_event.88 = background_change_event;
      ResetEvent (background_change_event.88);
      wait->num = 0;
      D.22358 = &wait->threads;
      memset (D.22358, 0, 512);
      threads.86 = threads;
      mono_g_hash_table_foreach (threads.86, build_wait_tids, wait);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22359>; else goto <D.22360>;
        <D.22359>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.22360>:
        D.22361 = ret != 0;
        D.22362 = (long int) D.22361;
        D.22363 = __builtin_expect (D.22362, 0);
        if (D.22363 != 0) goto <D.22364>; else goto <D.22365>;
        <D.22364>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3003, "ret == 0");
        <D.22365>:
      }
      D.22366 = wait->num;
      if (D.22366 != 0) goto <D.22367>; else goto <D.22368>;
      <D.22367>:
      wait_for_tids_or_state_change (wait, 4294967295);
      <D.22368>:
      D.22366 = wait->num;
      if (D.22366 != 0) goto <D.20282>; else goto <D.20280>;
      <D.20280>:
      D.22369 = mono_runtime_try_shutdown ();
      if (D.22369 == 0) goto <D.22370>; else goto <D.22371>;
      <D.22370>:
      D.22372 = mono_thread_internal_current ();
      mono_thread_suspend (D.22372);
      D.22373 = mono_thread_internal_current ();
      mono_thread_execute_interruption (D.22373);
      <D.22371>:
      <D.20285>:
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22374>; else goto <D.22375>;
        <D.22374>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.22375>:
        D.22376 = ret != 0;
        D.22377 = (long int) D.22376;
        D.22378 = __builtin_expect (D.22377, 0);
        if (D.22378 != 0) goto <D.22379>; else goto <D.22380>;
        <D.22379>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3023, "ret == 0");
        <D.22380>:
      }
      wait->num = 0;
      D.22358 = &wait->threads;
      memset (D.22358, 0, 512);
      threads.86 = threads;
      mono_g_hash_table_foreach_remove (threads.86, remove_and_abort_threads, wait);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22381>; else goto <D.22382>;
        <D.22381>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.22382>:
        D.22383 = ret != 0;
        D.22384 = (long int) D.22383;
        D.22385 = __builtin_expect (D.22384, 0);
        if (D.22385 != 0) goto <D.22386>; else goto <D.22387>;
        <D.22386>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3030, "ret == 0");
        <D.22387>:
      }
      D.22366 = wait->num;
      if (D.22366 != 0) goto <D.22388>; else goto <D.22389>;
      <D.22388>:
      wait_for_tids (wait, 4294967295);
      <D.22389>:
      D.22366 = wait->num;
      if (D.22366 != 0) goto <D.20285>; else goto <D.20286>;
      <D.20286>:
      sched_yield ();
    }
  finally
    {
      wait_data = {CLOBBER};
    }
}


remove_and_abort_threads (void * key, void * value, void * user)
{
  unsigned int D.22393;
  gboolean D.22396;
  long unsigned int D.22397;
  unsigned int D.22400;
  unsigned int D.22401;
  long unsigned int D.22404;
  long unsigned int D.22405;
  void * D.22410;
  unsigned int D.22411;
  int iftmp.89;
  int D.22416;
  struct wait_data * wait;
  gsize self;
  struct MonoInternalThread * thread;
  void * handle;

  wait = user;
  self = GetCurrentThreadId ();
  thread = value;
  D.22393 = wait->num;
  if (D.22393 > 63) goto <D.22394>; else goto <D.22395>;
  <D.22394>:
  D.22396 = 0;
  return D.22396;
  <D.22395>:
  D.22397 = thread->tid;
  if (D.22397 != self) goto <D.22398>; else goto <D.22399>;
  <D.22398>:
  D.22400 = thread->state;
  D.22401 = D.22400 & 4;
  if (D.22401 != 0) goto <D.22402>; else goto <D.22403>;
  <D.22402>:
  D.22404 = thread->flags;
  D.22405 = D.22404 & 1;
  if (D.22405 == 0) goto <D.22406>; else goto <D.22407>;
  <D.22406>:
  D.22397 = thread->tid;
  handle = OpenThread (2032639, 1, D.22397);
  if (handle == 0B) goto <D.22408>; else goto <D.22409>;
  <D.22408>:
  D.22396 = 0;
  return D.22396;
  <D.22409>:
  D.22393 = wait->num;
  D.22410 = thread->handle;
  wait->handles[D.22393] = D.22410;
  D.22393 = wait->num;
  wait->threads[D.22393] = thread;
  D.22393 = wait->num;
  D.22411 = D.22393 + 1;
  wait->num = D.22411;
  mono_thread_internal_stop (thread);
  D.22396 = 1;
  return D.22396;
  <D.22407>:
  <D.22403>:
  <D.22399>:
  D.22397 = thread->tid;
  if (D.22397 != self) goto <D.22415>; else goto <D.22413>;
  <D.22415>:
  D.22416 = mono_gc_is_finalizer_internal_thread (thread);
  if (D.22416 == 0) goto <D.22417>; else goto <D.22413>;
  <D.22417>:
  iftmp.89 = 1;
  goto <D.22414>;
  <D.22413>:
  iftmp.89 = 0;
  <D.22414>:
  D.22396 = iftmp.89;
  return D.22396;
}


build_wait_tids (void * key, void * value, void * user)
{
  unsigned int D.22419;
  unsigned int D.22422;
  unsigned int D.22423;
  int D.22426;
  struct MonoInternalThread * D.22429;
  struct MonoThread * D.22432;
  struct MonoThread * D.22435;
  struct _MonoInternalThread * D.22436;
  long unsigned int D.22439;
  long unsigned int D.22440;
  long unsigned int D.22443;
  mono_bool (*<T1d3c>) (struct MonoThread *) D.22448;
  struct MonoThread * D.22450;
  int D.22451;
  unsigned int D.22452;
  struct wait_data * wait;

  wait = user;
  D.22419 = wait->num;
  if (D.22419 <= 63) goto <D.22420>; else goto <D.22421>;
  <D.22420>:
  {
    void * handle;
    struct MonoInternalThread * thread;

    thread = value;
    D.22422 = thread->state;
    D.22423 = D.22422 & 4;
    if (D.22423 != 0) goto <D.22424>; else goto <D.22425>;
    <D.22424>:
    return;
    <D.22425>:
    D.22426 = mono_gc_is_finalizer_internal_thread (thread);
    if (D.22426 != 0) goto <D.22427>; else goto <D.22428>;
    <D.22427>:
    return;
    <D.22428>:
    D.22429 = mono_thread_internal_current ();
    if (D.22429 == thread) goto <D.22430>; else goto <D.22431>;
    <D.22430>:
    return;
    <D.22431>:
    D.22432 = mono_thread_get_main ();
    if (D.22432 != 0B) goto <D.22433>; else goto <D.22434>;
    <D.22433>:
    D.22435 = mono_thread_get_main ();
    D.22436 = D.22435->internal_thread;
    if (D.22436 == thread) goto <D.22437>; else goto <D.22438>;
    <D.22437>:
    return;
    <D.22438>:
    <D.22434>:
    D.22439 = thread->flags;
    D.22440 = D.22439 & 1;
    if (D.22440 != 0) goto <D.22441>; else goto <D.22442>;
    <D.22441>:
    return;
    <D.22442>:
    D.22443 = thread->tid;
    handle = OpenThread (2032639, 1, D.22443);
    if (handle == 0B) goto <D.22444>; else goto <D.22445>;
    <D.22444>:
    return;
    <D.22445>:
    D.22448 = thread->manage_callback;
    if (D.22448 == 0B) goto <D.22446>; else goto <D.22449>;
    <D.22449>:
    D.22448 = thread->manage_callback;
    D.22450 = thread->root_domain_thread;
    D.22451 = D.22448 (D.22450);
    if (D.22451 == 1) goto <D.22446>; else goto <D.22447>;
    <D.22446>:
    D.22419 = wait->num;
    wait->handles[D.22419] = handle;
    D.22419 = wait->num;
    wait->threads[D.22419] = thread;
    D.22419 = wait->num;
    D.22452 = D.22419 + 1;
    wait->num = D.22452;
    <D.22447>:
  }
  goto <D.22453>;
  <D.22421>:
  <D.22453>:
}


wait_for_tids_or_state_change (struct wait_data * wait, guint32 timeout)
{
  void * background_change_event.90;
  void *[64] * D.22458;
  void * D.22461;
  unsigned int D.22462;
  struct MonoInternalThread * D.22467;
  _Bool D.22470;
  long int D.22471;
  long int D.22472;
  struct MonoGHashTable * threads.91;
  const void * tid.92;
  void * D.22477;
  _Bool D.22482;
  long int D.22483;
  long int D.22484;
  _Bool D.22490;
  long int D.22491;
  long int D.22492;
  guint32 i;
  guint32 ret;
  guint32 count;

  count = wait->num;
  if (count <= 63) goto <D.22455>; else goto <D.22456>;
  <D.22455>:
  background_change_event.90 = background_change_event;
  wait->handles[count] = background_change_event.90;
  count = count + 1;
  <D.22456>:
  D.22458 = &wait->handles;
  ret = WaitForMultipleObjectsEx (count, D.22458, 0, timeout, 1);
  if (ret == 4294967295) goto <D.22459>; else goto <D.22460>;
  <D.22459>:
  return;
  <D.22460>:
  i = 0;
  goto <D.20240>;
  <D.20239>:
  D.22461 = wait->handles[i];
  CloseHandle (D.22461);
  i = i + 1;
  <D.20240>:
  D.22462 = wait->num;
  if (D.22462 > i) goto <D.20239>; else goto <D.20241>;
  <D.20241>:
  if (ret == 258) goto <D.22463>; else goto <D.22464>;
  <D.22463>:
  return;
  <D.22464>:
  D.22462 = wait->num;
  if (D.22462 > ret) goto <D.22465>; else goto <D.22466>;
  <D.22465>:
  {
    gsize tid;

    D.22467 = wait->threads[ret];
    tid = D.22467->tid;
    {
      int ret;

      ret = pthread_mutex_lock (&threads_mutex.mutex);
      if (ret != 0) goto <D.22468>; else goto <D.22469>;
      <D.22468>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
      <D.22469>:
      D.22470 = ret != 0;
      D.22471 = (long int) D.22470;
      D.22472 = __builtin_expect (D.22471, 0);
      if (D.22472 != 0) goto <D.22473>; else goto <D.22474>;
      <D.22473>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2819, "ret == 0");
      <D.22474>:
    }
    threads.91 = threads;
    tid.92 = (const void *) tid;
    D.22477 = mono_g_hash_table_lookup (threads.91, tid.92);
    if (D.22477 != 0B) goto <D.22478>; else goto <D.22479>;
    <D.22478>:
    {
      int ret;

      ret = pthread_mutex_unlock (&threads_mutex.mutex);
      if (ret != 0) goto <D.22480>; else goto <D.22481>;
      <D.22480>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.22481>:
      D.22482 = ret != 0;
      D.22483 = (long int) D.22482;
      D.22484 = __builtin_expect (D.22483, 0);
      if (D.22484 != 0) goto <D.22485>; else goto <D.22486>;
      <D.22485>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2822, "ret == 0");
      <D.22486>:
    }
    D.22467 = wait->threads[ret];
    thread_cleanup (D.22467);
    goto <D.22487>;
    <D.22479>:
    {
      int ret;

      ret = pthread_mutex_unlock (&threads_mutex.mutex);
      if (ret != 0) goto <D.22488>; else goto <D.22489>;
      <D.22488>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.22489>:
      D.22490 = ret != 0;
      D.22491 = (long int) D.22490;
      D.22492 = __builtin_expect (D.22491, 0);
      if (D.22492 != 0) goto <D.22493>; else goto <D.22494>;
      <D.22493>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2826, "ret == 0");
      <D.22494>:
    }
    <D.22487>:
  }
  <D.22466>:
}


memset (void * __dest, int __ch, size_t __len)
{
  int D.22498;
  int D.22503;
  void * D.22505;
  long unsigned int D.22506;

  D.22498 = __builtin_constant_p (__len);
  if (D.22498 != 0) goto <D.22499>; else goto <D.22500>;
  <D.22499>:
  if (__len == 0) goto <D.22501>; else goto <D.22502>;
  <D.22501>:
  D.22503 = __builtin_constant_p (__ch);
  if (D.22503 == 0) goto <D.22496>; else goto <D.22504>;
  <D.22504>:
  if (__ch != 0) goto <D.22496>; else goto <D.22497>;
  <D.22496>:
  __warn_memset_zero_len ();
  D.22505 = __dest;
  return D.22505;
  <D.22497>:
  <D.22502>:
  <D.22500>:
  D.22506 = __builtin_object_size (__dest, 0);
  D.22505 = __builtin___memset_chk (__dest, __ch, __len, D.22506);
  return D.22505;
}


wait_for_tids (struct wait_data * wait, guint32 timeout)
{
  unsigned int D.22508;
  void *[64] * D.22509;
  void * D.22512;
  struct MonoInternalThread * D.22515;
  _Bool D.22518;
  long int D.22519;
  long int D.22520;
  struct MonoGHashTable * threads.93;
  const void * tid.94;
  void * D.22525;
  _Bool D.22530;
  long int D.22531;
  long int D.22532;
  _Bool D.22538;
  long int D.22539;
  long int D.22540;
  guint32 i;
  guint32 ret;

  D.22508 = wait->num;
  D.22509 = &wait->handles;
  ret = WaitForMultipleObjectsEx (D.22508, D.22509, 1, timeout, 1);
  if (ret == 4294967295) goto <D.22510>; else goto <D.22511>;
  <D.22510>:
  return;
  <D.22511>:
  i = 0;
  goto <D.20223>;
  <D.20222>:
  D.22512 = wait->handles[i];
  CloseHandle (D.22512);
  i = i + 1;
  <D.20223>:
  D.22508 = wait->num;
  if (D.22508 > i) goto <D.20222>; else goto <D.20224>;
  <D.20224>:
  if (ret == 258) goto <D.22513>; else goto <D.22514>;
  <D.22513>:
  return;
  <D.22514>:
  i = 0;
  goto <D.20230>;
  <D.20229>:
  {
    gsize tid;

    D.22515 = wait->threads[i];
    tid = D.22515->tid;
    {
      int ret;

      ret = pthread_mutex_lock (&threads_mutex.mutex);
      if (ret != 0) goto <D.22516>; else goto <D.22517>;
      <D.22516>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
      <D.22517>:
      D.22518 = ret != 0;
      D.22519 = (long int) D.22518;
      D.22520 = __builtin_expect (D.22519, 0);
      if (D.22520 != 0) goto <D.22521>; else goto <D.22522>;
      <D.22521>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2766, "ret == 0");
      <D.22522>:
    }
    threads.93 = threads;
    tid.94 = (const void *) tid;
    D.22525 = mono_g_hash_table_lookup (threads.93, tid.94);
    if (D.22525 != 0B) goto <D.22526>; else goto <D.22527>;
    <D.22526>:
    {
      int ret;

      ret = pthread_mutex_unlock (&threads_mutex.mutex);
      if (ret != 0) goto <D.22528>; else goto <D.22529>;
      <D.22528>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.22529>:
      D.22530 = ret != 0;
      D.22531 = (long int) D.22530;
      D.22532 = __builtin_expect (D.22531, 0);
      if (D.22532 != 0) goto <D.22533>; else goto <D.22534>;
      <D.22533>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2779, "ret == 0");
      <D.22534>:
    }
    D.22515 = wait->threads[i];
    thread_cleanup (D.22515);
    goto <D.22535>;
    <D.22527>:
    {
      int ret;

      ret = pthread_mutex_unlock (&threads_mutex.mutex);
      if (ret != 0) goto <D.22536>; else goto <D.22537>;
      <D.22536>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.22537>:
      D.22538 = ret != 0;
      D.22539 = (long int) D.22538;
      D.22540 = __builtin_expect (D.22539, 0);
      if (D.22540 != 0) goto <D.22541>; else goto <D.22542>;
      <D.22541>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2783, "ret == 0");
      <D.22542>:
    }
    <D.22535>:
  }
  i = i + 1;
  <D.20230>:
  D.22508 = wait->num;
  if (D.22508 > i) goto <D.20229>; else goto <D.20231>;
  <D.20231>:
}


mono_thread_abort_all_other_threads ()
{
  _Bool D.22546;
  long int D.22547;
  long int D.22548;
  struct MonoGHashTable * threads.95;
  void * self.96;
  _Bool D.22555;
  long int D.22556;
  long int D.22557;
  gsize self;

  self = GetCurrentThreadId ();
  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22544>; else goto <D.22545>;
    <D.22544>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.22545>:
    D.22546 = ret != 0;
    D.22547 = (long int) D.22546;
    D.22548 = __builtin_expect (D.22547, 0);
    if (D.22548 != 0) goto <D.22549>; else goto <D.22550>;
    <D.22549>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3062, "ret == 0");
    <D.22550>:
  }
  threads.95 = threads;
  self.96 = (void *) self;
  mono_g_hash_table_foreach (threads.95, terminate_thread, self.96);
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22553>; else goto <D.22554>;
    <D.22553>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.22554>:
    D.22555 = ret != 0;
    D.22556 = (long int) D.22555;
    D.22557 = __builtin_expect (D.22556, 0);
    if (D.22557 != 0) goto <D.22558>; else goto <D.22559>;
    <D.22558>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3069, "ret == 0");
    <D.22559>:
  }
}


terminate_thread (void * key, void * value, void * user)
{
  long unsigned int D.22560;
  long unsigned int user.97;
  struct MonoInternalThread * thread;

  thread = value;
  D.22560 = thread->tid;
  user.97 = (long unsigned int) user;
  if (D.22560 != user.97) goto <D.22562>; else goto <D.22563>;
  <D.22562>:
  <D.22563>:
}


mono_thread_suspend_all_other_threads ()
{
  int shutting_down.98;
  _Bool D.22565;
  long int D.22566;
  long int D.22567;
  struct MonoInternalThread *[64] * D.22570;
  _Bool D.22573;
  long int D.22574;
  long int D.22575;
  struct MonoGHashTable * threads.99;
  _Bool D.22581;
  long int D.22582;
  long int D.22583;
  unsigned int D.22586;
  long unsigned int D.22587;
  long unsigned int D.22588;
  long unsigned int D.22591;
  int D.22593;
  long unsigned int D.22595;
  long unsigned int D.22596;
  void * D.22597;
  void * D.22600;
  long unsigned int D.22603;
  long unsigned int D.22604;
  void * D.22607;
  unsigned int D.22608;
  unsigned int D.22609;
  unsigned int eventidx.100;
  long unsigned int D.22613;
  long unsigned int D.22614;
  void * * D.22615;
  unsigned int D.22616;
  unsigned int D.22619;
  unsigned int D.22620;
  int D.22621;
  unsigned int i.101;
  int D.22630;
  unsigned int D.22635;
  unsigned int D.22636;
  void * D.22639;
  _Bool D.22644;
  long int D.22645;
  long int D.22646;
  struct MonoGHashTable * threads_starting_up.102;
  unsigned int D.22652;
  _Bool D.22653;
  _Bool D.22657;
  long int D.22658;
  long int D.22659;
  struct wait_data wait_data;
  struct wait_data * wait;
  int i;
  gsize self;
  void * * events;
  guint32 eventidx;
  gboolean starting;
  gboolean finished;

  try
    {
      wait = &wait_data;
      self = GetCurrentThreadId ();
      eventidx = 0;
      memset (wait, 0, 1032);
      shutting_down.98 = shutting_down;
      D.22565 = shutting_down.98 == 0;
      D.22566 = (long int) D.22565;
      D.22567 = __builtin_expect (D.22566, 0);
      if (D.22567 != 0) goto <D.22568>; else goto <D.22569>;
      <D.22568>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3128, "shutting_down");
      <D.22569>:
      finished = 0;
      goto <D.20334>;
      <D.20333>:
      wait->num = 0;
      D.22570 = &wait->threads;
      memset (D.22570, 0, 512);
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22571>; else goto <D.22572>;
        <D.22571>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.22572>:
        D.22573 = ret != 0;
        D.22574 = (long int) D.22573;
        D.22575 = __builtin_expect (D.22574, 0);
        if (D.22575 != 0) goto <D.22576>; else goto <D.22577>;
        <D.22576>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3144, "ret == 0");
        <D.22577>:
      }
      threads.99 = threads;
      mono_g_hash_table_foreach (threads.99, collect_threads_for_suspend, wait);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22579>; else goto <D.22580>;
        <D.22579>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.22580>:
        D.22581 = ret != 0;
        D.22582 = (long int) D.22581;
        D.22583 = __builtin_expect (D.22582, 0);
        if (D.22583 != 0) goto <D.22584>; else goto <D.22585>;
        <D.22584>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3146, "ret == 0");
        <D.22585>:
      }
      D.22586 = wait->num;
      D.22587 = (long unsigned int) D.22586;
      D.22588 = D.22587 * 8;
      events = monoeg_malloc0 (D.22588);
      eventidx = 0;
      i = 0;
      goto <D.20324>;
      <D.20323>:
      {
        struct MonoInternalThread * thread;
        gboolean signal_suspend;

        thread = wait->threads[i];
        signal_suspend = 0;
        D.22591 = thread->tid;
        if (D.22591 == self) goto <D.22589>; else goto <D.22592>;
        <D.22592>:
        D.22593 = mono_gc_is_finalizer_internal_thread (thread);
        if (D.22593 != 0) goto <D.22589>; else goto <D.22594>;
        <D.22594>:
        D.22595 = thread->flags;
        D.22596 = D.22595 & 1;
        if (D.22596 != 0) goto <D.22589>; else goto <D.22590>;
        <D.22589>:
        wait->threads[i] = 0B;
        // predicted unlikely by continue predictor.
        goto <D.20322>;
        <D.22590>:
        lock_thread (thread);
        D.22597 = thread->suspended_event;
        if (D.22597 == 0B) goto <D.22598>; else goto <D.22599>;
        <D.22598>:
        D.22600 = CreateEvent (0B, 1, 0, 0B);
        thread->suspended_event = D.22600;
        D.22597 = thread->suspended_event;
        if (D.22597 == 0B) goto <D.22601>; else goto <D.22602>;
        <D.22601>:
        unlock_thread (thread);
        // predicted unlikely by continue predictor.
        goto <D.20322>;
        <D.22602>:
        <D.22599>:
        D.22603 = BIT_FIELD_REF <*thread, 64, 384>;
        D.22604 = D.22603 & 347892350976;
        if (D.22604 != 0) goto <D.22605>; else goto <D.22606>;
        <D.22605>:
        unlock_thread (thread);
        D.22607 = wait->handles[i];
        CloseHandle (D.22607);
        wait->threads[i] = 0B;
        // predicted unlikely by continue predictor.
        goto <D.20322>;
        <D.22606>:
        D.22608 = thread->state;
        D.22609 = D.22608 & 2;
        if (D.22609 == 0) goto <D.22610>; else goto <D.22611>;
        <D.22610>:
        signal_suspend = 1;
        <D.22611>:
        eventidx.100 = eventidx;
        eventidx = eventidx.100 + 1;
        D.22613 = (long unsigned int) eventidx.100;
        D.22614 = D.22613 * 8;
        D.22615 = events + D.22614;
        D.22597 = thread->suspended_event;
        *D.22615 = D.22597;
        D.22608 = thread->state;
        D.22616 = D.22608 & 128;
        if (D.22616 != 0) goto <D.22617>; else goto <D.22618>;
        <D.22617>:
        D.22608 = thread->state;
        D.22619 = D.22608 & 4294967167;
        thread->state = D.22619;
        <D.22618>:
        D.22608 = thread->state;
        D.22620 = D.22608 | 2;
        thread->state = D.22620;
        unlock_thread (thread);
        D.22621 = mono_thread_info_new_interrupt_enabled ();
        if (D.22621 != 0) goto <D.22622>; else goto <D.22623>;
        <D.22622>:
        suspend_thread_internal (thread, 1);
        goto <D.22624>;
        <D.22623>:
        if (signal_suspend != 0) goto <D.22625>; else goto <D.22626>;
        <D.22625>:
        signal_thread_state_change (thread);
        <D.22626>:
        <D.22624>:
      }
      <D.20322>:
      i = i + 1;
      <D.20324>:
      i.101 = (unsigned int) i;
      D.22586 = wait->num;
      if (i.101 < D.22586) goto <D.20323>; else goto <D.20325>;
      <D.20325>:
      if (eventidx != 0) goto <D.22628>; else goto <D.22629>;
      <D.22628>:
      D.22630 = mono_thread_info_new_interrupt_enabled ();
      if (D.22630 == 0) goto <D.22631>; else goto <D.22632>;
      <D.22631>:
      WaitForMultipleObjectsEx (eventidx, events, 1, 100, 0);
      i = 0;
      goto <D.20329>;
      <D.20328>:
      {
        struct MonoInternalThread * thread;

        thread = wait->threads[i];
        if (thread == 0B) goto <D.22633>; else goto <D.22634>;
        <D.22633>:
        // predicted unlikely by continue predictor.
        goto <D.20327>;
        <D.22634>:
        lock_thread (thread);
        D.22635 = thread->state;
        D.22636 = D.22635 & 64;
        if (D.22636 != 0) goto <D.22637>; else goto <D.22638>;
        <D.22637>:
        D.22639 = thread->suspended_event;
        CloseHandle (D.22639);
        thread->suspended_event = 0B;
        <D.22638>:
        unlock_thread (thread);
      }
      <D.20327>:
      i = i + 1;
      <D.20329>:
      i.101 = (unsigned int) i;
      D.22586 = wait->num;
      if (i.101 < D.22586) goto <D.20328>; else goto <D.20330>;
      <D.20330>:
      <D.22632>:
      <D.22629>:
      if (eventidx == 0) goto <D.22640>; else goto <D.22641>;
      <D.22640>:
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22642>; else goto <D.22643>;
        <D.22642>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.22643>:
        D.22644 = ret != 0;
        D.22645 = (long int) D.22644;
        D.22646 = __builtin_expect (D.22645, 0);
        if (D.22646 != 0) goto <D.22647>; else goto <D.22648>;
        <D.22647>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3227, "ret == 0");
        <D.22648>:
      }
      threads_starting_up.102 = threads_starting_up;
      if (threads_starting_up.102 != 0B) goto <D.22650>; else goto <D.22651>;
      <D.22650>:
      threads_starting_up.102 = threads_starting_up;
      D.22652 = mono_g_hash_table_size (threads_starting_up.102);
      D.22653 = D.22652 != 0;
      starting = (gboolean) D.22653;
      goto <D.22654>;
      <D.22651>:
      starting = 0;
      <D.22654>:
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22655>; else goto <D.22656>;
        <D.22655>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.22656>:
        D.22657 = ret != 0;
        D.22658 = (long int) D.22657;
        D.22659 = __builtin_expect (D.22658, 0);
        if (D.22659 != 0) goto <D.22660>; else goto <D.22661>;
        <D.22660>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3232, "ret == 0");
        <D.22661>:
      }
      if (starting != 0) goto <D.22662>; else goto <D.22663>;
      <D.22662>:
      Sleep (100);
      goto <D.22664>;
      <D.22663>:
      finished = 1;
      <D.22664>:
      <D.22641>:
      monoeg_g_free (events);
      <D.20334>:
      if (finished == 0) goto <D.20333>; else goto <D.20335>;
      <D.20335>:
    }
  finally
    {
      wait_data = {CLOBBER};
    }
}


collect_threads_for_suspend (void * key, void * value, void * user_data)
{
  long unsigned int D.22665;
  long unsigned int D.22666;
  unsigned int D.22669;
  long unsigned int D.22672;
  unsigned int D.22675;
  struct MonoInternalThread * thread;
  struct wait_data * wait;
  void * handle;

  thread = value;
  wait = user_data;
  D.22665 = BIT_FIELD_REF <*thread, 64, 384>;
  D.22666 = D.22665 & 343597383680;
  if (D.22666 != 0) goto <D.22667>; else goto <D.22668>;
  <D.22667>:
  return;
  <D.22668>:
  D.22669 = wait->num;
  if (D.22669 <= 63) goto <D.22670>; else goto <D.22671>;
  <D.22670>:
  D.22672 = thread->tid;
  handle = OpenThread (2032639, 1, D.22672);
  if (handle == 0B) goto <D.22673>; else goto <D.22674>;
  <D.22673>:
  return;
  <D.22674>:
  D.22669 = wait->num;
  wait->handles[D.22669] = handle;
  D.22669 = wait->num;
  wait->threads[D.22669] = thread;
  D.22669 = wait->num;
  D.22675 = D.22669 + 1;
  wait->num = D.22675;
  <D.22671>:
}


mono_threads_perform_thread_dump ()
{
  int thread_dump_requested.103;
  _Bool D.22682;
  long int D.22683;
  long int D.22684;
  struct MonoGHashTable * threads.104;
  _Bool D.22690;
  long int D.22691;
  long int D.22692;

  thread_dump_requested.103 = thread_dump_requested;
  if (thread_dump_requested.103 == 0) goto <D.22678>; else goto <D.22679>;
  <D.22678>:
  return;
  <D.22679>:
  printf ("Full thread dump:\n");
  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22680>; else goto <D.22681>;
    <D.22680>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.22681>:
    D.22682 = ret != 0;
    D.22683 = (long int) D.22682;
    D.22684 = __builtin_expect (D.22683, 0);
    if (D.22684 != 0) goto <D.22685>; else goto <D.22686>;
    <D.22685>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3357, "ret == 0");
    <D.22686>:
  }
  threads.104 = threads;
  mono_g_hash_table_foreach (threads.104, dump_thread, 0B);
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22688>; else goto <D.22689>;
    <D.22688>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.22689>:
    D.22690 = ret != 0;
    D.22691 = (long int) D.22690;
    D.22692 = __builtin_expect (D.22691, 0);
    if (D.22692 != 0) goto <D.22693>; else goto <D.22694>;
    <D.22693>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3359, "ret == 0");
    <D.22694>:
  }
  thread_dump_requested = 0;
}


dump_thread (void * key, void * value, void * user)
{
  struct MonoInternalThread * D.22696;
  long unsigned int D.22699;
  struct MonoInternalThread * thread;
  struct MonoThreadInfo * info;

  thread = value;
  D.22696 = mono_thread_internal_current ();
  if (D.22696 == thread) goto <D.22697>; else goto <D.22698>;
  <D.22697>:
  return;
  <D.22698>:
  D.22699 = thread->tid;
  info = mono_thread_info_safe_suspend_sync (D.22699, 0);
  if (info == 0B) goto <D.22700>; else goto <D.22701>;
  <D.22700>:
  return;
  <D.22701>:
  print_thread_dump (thread, info);
}


print_thread_dump (struct MonoInternalThread * thread, struct MonoThreadInfo * info)
{
  gunichar2 * D.22703;
  unsigned int D.22706;
  long int D.22707;
  struct GError * error.105;
  _Bool D.22709;
  long int D.22710;
  long int D.22711;
  unsigned char D.22715;
  struct MonoRuntimeExceptionHandlingCallbacks * D.22719;
  void (*<T2792>) (gboolean (*MonoInternalStackWalk) (struct MonoStackFrameInfo *, struct MonoContext *, void *), struct MonoThreadUnwindState *, MonoUnwindOptions, void *) D.22720;
  struct MonoThreadUnwindState * D.22721;
  long unsigned int D.22722;
  struct _IO_FILE * stdout.106;
  char * D.22724;
  struct GString * text;
  char * name;
  struct GError * error;

  try
    {
      text = monoeg_g_string_new (0B);
      error = 0B;
      D.22703 = thread->name;
      if (D.22703 != 0B) goto <D.22704>; else goto <D.22705>;
      <D.22704>:
      D.22703 = thread->name;
      D.22706 = thread->name_len;
      D.22707 = (long int) D.22706;
      name = monoeg_g_utf16_to_utf8 (D.22703, D.22707, 0B, 0B, &error);
      error.105 = error;
      D.22709 = error.105 != 0B;
      D.22710 = (long int) D.22709;
      D.22711 = __builtin_expect (D.22710, 0);
      if (D.22711 != 0) goto <D.22712>; else goto <D.22713>;
      <D.22712>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3290, "!error");
      <D.22713>:
      monoeg_g_string_append_printf (text, "\n\"%s\"", name);
      monoeg_g_free (name);
      goto <D.22714>;
      <D.22705>:
      D.22715 = thread->threadpool_thread;
      if (D.22715 != 0) goto <D.22716>; else goto <D.22717>;
      <D.22716>:
      monoeg_g_string_append (text, "\n\"<threadpool thread>\"");
      goto <D.22718>;
      <D.22717>:
      monoeg_g_string_append (text, "\n\"<unnamed thread>\"");
      <D.22718>:
      <D.22714>:
      D.22719 = mono_get_eh_callbacks ();
      D.22720 = D.22719->mono_walk_stack_with_state;
      D.22721 = &info->suspend_state;
      D.22720 (print_stack_frame_to_string, D.22721, 0, text);
      D.22722 = info->node.key;
      mono_thread_info_resume (D.22722);
      stdout.106 = stdout;
      D.22724 = text->str;
      fprintf (stdout.106, "%s", D.22724);
      monoeg_g_string_free (text, 1);
      stdout.106 = stdout;
      fflush (stdout.106);
    }
  finally
    {
      error = {CLOBBER};
    }
}


print_stack_frame_to_string (struct MonoStackFrameInfo * frame, struct MonoContext * ctx, void * data)
{
  struct MonoJitInfo * D.22725;
  int D.22730;
  unsigned int D.22731;
  struct MonoDomain * D.22732;
  gboolean D.22734;
  struct GString * p;
  struct MonoMethod * method;

  p = data;
  method = 0B;
  D.22725 = frame->ji;
  if (D.22725 != 0B) goto <D.22726>; else goto <D.22727>;
  <D.22726>:
  D.22725 = frame->ji;
  method = mono_jit_info_get_method (D.22725);
  <D.22727>:
  if (method != 0B) goto <D.22728>; else goto <D.22729>;
  <D.22728>:
  {
    gchar * location;

    D.22730 = frame->native_offset;
    D.22731 = (unsigned int) D.22730;
    D.22732 = frame->domain;
    location = mono_debug_print_stack_frame (method, D.22731, D.22732);
    monoeg_g_string_append_printf (p, "  %s\n", location);
    monoeg_g_free (location);
  }
  goto <D.22733>;
  <D.22729>:
  D.22730 = frame->native_offset;
  monoeg_g_string_append_printf (p, "  at <unknown> <0x%05x>\n", D.22730);
  <D.22733>:
  D.22734 = 0;
  return D.22734;
}


fprintf (struct FILE * restrict __stream, const char * restrict __fmt)
{
  int D.22736;

  D.22736 = __fprintf_chk (__stream, 1, __fmt, __builtin_va_arg_pack ());
  return D.22736;
}


printf (const char * restrict __fmt)
{
  int D.22738;

  D.22738 = __printf_chk (1, __fmt, __builtin_va_arg_pack ());
  return D.22738;
}


mono_threads_request_thread_dump ()
{
  int D.22740;
  _Bool D.22745;
  long int D.22746;
  long int D.22747;
  struct MonoGHashTable * threads.107;
  _Bool D.22753;
  long int D.22754;
  long int D.22755;
  int D.22758;
  struct MonoInternalThread * D.22761;
  unsigned char D.22764;
  void * D.22767;
  unsigned int i.108;
  unsigned int D.22769;
  struct wait_data wait_data;
  struct wait_data * wait;
  int i;

  try
    {
      wait = &wait_data;
      D.22740 = mono_thread_info_new_interrupt_enabled ();
      if (D.22740 != 0) goto <D.22741>; else goto <D.22742>;
      <D.22741>:
      thread_dump_requested = 1;
      mono_gc_finalize_notify ();
      return;
      <D.22742>:
      memset (wait, 0, 1032);
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22743>; else goto <D.22744>;
        <D.22743>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.22744>:
        D.22745 = ret != 0;
        D.22746 = (long int) D.22745;
        D.22747 = __builtin_expect (D.22746, 0);
        if (D.22747 != 0) goto <D.22748>; else goto <D.22749>;
        <D.22748>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3390, "ret == 0");
        <D.22749>:
      }
      threads.107 = threads;
      mono_g_hash_table_foreach (threads.107, collect_threads, wait);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22751>; else goto <D.22752>;
        <D.22751>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.22752>:
        D.22753 = ret != 0;
        D.22754 = (long int) D.22753;
        D.22755 = __builtin_expect (D.22754, 0);
        if (D.22755 != 0) goto <D.22756>; else goto <D.22757>;
        <D.22756>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3392, "ret == 0");
        <D.22757>:
      }
      i = 0;
      goto <D.20382>;
      <D.20381>:
      {
        struct MonoInternalThread * thread;

        thread = wait->threads[i];
        D.22758 = mono_gc_is_finalizer_internal_thread (thread);
        if (D.22758 == 0) goto <D.22759>; else goto <D.22760>;
        <D.22759>:
        D.22761 = mono_thread_internal_current ();
        if (D.22761 != thread) goto <D.22762>; else goto <D.22763>;
        <D.22762>:
        D.22764 = thread->thread_dump_requested;
        if (D.22764 == 0) goto <D.22765>; else goto <D.22766>;
        <D.22765>:
        thread->thread_dump_requested = 1;
        signal_thread_state_change (thread);
        <D.22766>:
        <D.22763>:
        <D.22760>:
        D.22767 = wait->handles[i];
        CloseHandle (D.22767);
      }
      i = i + 1;
      <D.20382>:
      i.108 = (unsigned int) i;
      D.22769 = wait->num;
      if (i.108 < D.22769) goto <D.20381>; else goto <D.20383>;
      <D.20383>:
    }
  finally
    {
      wait_data = {CLOBBER};
    }
}


collect_threads (void * key, void * value, void * user_data)
{
  unsigned int D.22773;
  long unsigned int D.22776;
  unsigned int D.22779;
  struct MonoInternalThread * thread;
  struct wait_data * wait;
  void * handle;

  thread = value;
  wait = user_data;
  D.22773 = wait->num;
  if (D.22773 <= 63) goto <D.22774>; else goto <D.22775>;
  <D.22774>:
  D.22776 = thread->tid;
  handle = OpenThread (2032639, 1, D.22776);
  if (handle == 0B) goto <D.22777>; else goto <D.22778>;
  <D.22777>:
  return;
  <D.22778>:
  D.22773 = wait->num;
  wait->handles[D.22773] = handle;
  D.22773 = wait->num;
  wait->threads[D.22773] = thread;
  D.22773 = wait->num;
  D.22779 = D.22773 + 1;
  wait->num = D.22779;
  <D.22775>:
}


mono_thread_push_appdomain_ref (struct MonoDomain * domain)
{
  volatile int * D.22783;
  int D.22784;
  void * D.22786;
  struct RefStack * D.22789;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  if (thread != 0B) goto <D.22781>; else goto <D.22782>;
  <D.22781>:
  <D.20417>:
  D.22783 = &thread->lock_thread_id;
  D.22784 = InterlockedCompareExchange (D.22783, 1, 0);
  if (D.22784 == 0) goto <D.20416>; else goto <D.22785>;
  <D.22785>:
  goto <D.20417>;
  <D.20416>:
  D.22786 = thread->appdomain_refs;
  if (D.22786 == 0B) goto <D.22787>; else goto <D.22788>;
  <D.22787>:
  D.22789 = ref_stack_new (16);
  thread->appdomain_refs = D.22789;
  <D.22788>:
  D.22786 = thread->appdomain_refs;
  ref_stack_push (D.22786, domain);
  thread->lock_thread_id = 0;
  <D.22782>:
}


ref_stack_new (gint initial_size)
{
  int D.22790;
  long unsigned int D.22791;
  long unsigned int D.22792;
  void * D.22793;
  struct RefStack * D.22794;
  struct RefStack * rs;

  D.22790 = MAX_EXPR <initial_size, 16>;
  initial_size = D.22790 + 1;
  rs = monoeg_malloc0 (16);
  D.22791 = (long unsigned int) initial_size;
  D.22792 = D.22791 * 8;
  D.22793 = monoeg_malloc0 (D.22792);
  rs->refs = D.22793;
  rs->allocated = initial_size;
  D.22794 = rs;
  return D.22794;
}


ref_stack_push (struct RefStack * rs, void * ptr)
{
  _Bool D.22796;
  long int D.22797;
  long int D.22798;
  int D.22801;
  int D.22802;
  void * * D.22805;
  int D.22806;
  long unsigned int D.22807;
  long unsigned int D.22808;
  long unsigned int D.22809;
  void * D.22810;
  int D.22811;
  long unsigned int D.22812;
  long unsigned int D.22813;
  void * * D.22814;
  int D.22815;
  int D.22816;
  long unsigned int D.22817;
  long unsigned int D.22818;
  void * * D.22819;

  D.22796 = rs == 0B;
  D.22797 = (long int) D.22796;
  D.22798 = __builtin_expect (D.22797, 0);
  if (D.22798 != 0) goto <D.22799>; else goto <D.22800>;
  <D.22799>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3443, "rs != NULL");
  <D.22800>:
  D.22801 = rs->bottom;
  D.22802 = rs->allocated;
  if (D.22801 >= D.22802) goto <D.22803>; else goto <D.22804>;
  <D.22803>:
  D.22805 = rs->refs;
  D.22802 = rs->allocated;
  D.22806 = D.22802 * 2;
  D.22807 = (long unsigned int) D.22806;
  D.22808 = D.22807 * 8;
  D.22809 = D.22808 + 1;
  D.22810 = monoeg_realloc (D.22805, D.22809);
  rs->refs = D.22810;
  D.22802 = rs->allocated;
  D.22811 = D.22802 << 1;
  rs->allocated = D.22811;
  D.22805 = rs->refs;
  D.22802 = rs->allocated;
  D.22812 = (long unsigned int) D.22802;
  D.22813 = D.22812 * 8;
  D.22814 = D.22805 + D.22813;
  *D.22814 = 0B;
  <D.22804>:
  D.22805 = rs->refs;
  D.22801 = rs->bottom;
  D.22815 = D.22801;
  D.22816 = D.22815 + 1;
  rs->bottom = D.22816;
  D.22817 = (long unsigned int) D.22815;
  D.22818 = D.22817 * 8;
  D.22819 = D.22805 + D.22818;
  *D.22819 = ptr;
}


mono_thread_pop_appdomain_ref ()
{
  volatile int * D.22822;
  int D.22823;
  void * D.22825;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  if (thread != 0B) goto <D.22820>; else goto <D.22821>;
  <D.22820>:
  <D.20423>:
  D.22822 = &thread->lock_thread_id;
  D.22823 = InterlockedCompareExchange (D.22822, 1, 0);
  if (D.22823 == 0) goto <D.20422>; else goto <D.22824>;
  <D.22824>:
  goto <D.20423>;
  <D.20422>:
  D.22825 = thread->appdomain_refs;
  ref_stack_pop (D.22825);
  thread->lock_thread_id = 0;
  <D.22821>:
}


ref_stack_pop (struct RefStack * rs)
{
  int D.22829;
  int D.22830;
  void * * D.22831;
  long unsigned int D.22832;
  long unsigned int D.22833;
  void * * D.22834;

  if (rs == 0B) goto <D.22826>; else goto <D.22828>;
  <D.22828>:
  D.22829 = rs->bottom;
  if (D.22829 == 0) goto <D.22826>; else goto <D.22827>;
  <D.22826>:
  return;
  <D.22827>:
  D.22829 = rs->bottom;
  D.22830 = D.22829 + -1;
  rs->bottom = D.22830;
  D.22831 = rs->refs;
  D.22829 = rs->bottom;
  D.22832 = (long unsigned int) D.22829;
  D.22833 = D.22832 * 8;
  D.22834 = D.22831 + D.22833;
  *D.22834 = 0B;
}


mono_thread_internal_has_appdomain_ref (struct MonoInternalThread * thread, struct MonoDomain * domain)
{
  volatile int * D.22836;
  int D.22837;
  void * D.22839;
  gboolean D.22840;
  gboolean res;

  <D.20430>:
  D.22836 = &thread->lock_thread_id;
  D.22837 = InterlockedCompareExchange (D.22836, 1, 0);
  if (D.22837 == 0) goto <D.20429>; else goto <D.22838>;
  <D.22838>:
  goto <D.20430>;
  <D.20429>:
  D.22839 = thread->appdomain_refs;
  res = ref_stack_find (D.22839, domain);
  thread->lock_thread_id = 0;
  D.22840 = res;
  return D.22840;
}


ref_stack_find (struct RefStack * rs, void * ptr)
{
  gboolean D.22844;
  void * D.22845;
  void * * refs;

  if (rs == 0B) goto <D.22842>; else goto <D.22843>;
  <D.22842>:
  D.22844 = 0;
  return D.22844;
  <D.22843>:
  refs = rs->refs;
  goto <D.20410>;
  <D.20409>:
  D.22845 = *refs;
  if (D.22845 == ptr) goto <D.22846>; else goto <D.22847>;
  <D.22846>:
  D.22844 = 1;
  return D.22844;
  <D.22847>:
  refs = refs + 8;
  <D.20410>:
  if (refs != 0B) goto <D.22848>; else goto <D.20411>;
  <D.22848>:
  D.22845 = *refs;
  if (D.22845 != 0B) goto <D.20409>; else goto <D.20411>;
  <D.20411>:
  D.22844 = 0;
  return D.22844;
}


mono_thread_has_appdomain_ref (struct MonoThread * thread, struct MonoDomain * domain)
{
  gboolean D.22850;
  struct _MonoInternalThread * D.22851;

  D.22851 = thread->internal_thread;
  D.22850 = mono_thread_internal_has_appdomain_ref (D.22851, domain);
  return D.22850;
}


mono_threads_abort_appdomain_threads (struct MonoDomain * domain, int timeout)
{
  _Bool D.22855;
  long int D.22856;
  long int D.22857;
  struct MonoGHashTable * threads.109;
  _Bool D.22863;
  long int D.22864;
  long int D.22865;
  unsigned int D.22868;
  struct MonoInternalThread * D.22871;
  unsigned int i.110;
  unsigned int D.22873;
  unsigned int D.22874;
  unsigned int timeout.111;
  unsigned int D.22876;
  gboolean D.22881;
  struct abort_appdomain_data user_data;
  guint32 start_time;
  int orig_timeout;
  int i;

  try
    {
      orig_timeout = timeout;
      start_time = mono_msec_ticks ();
      <D.20461>:
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22853>; else goto <D.22854>;
        <D.22853>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.22854>:
        D.22855 = ret != 0;
        D.22856 = (long int) D.22855;
        D.22857 = __builtin_expect (D.22856, 0);
        if (D.22857 != 0) goto <D.22858>; else goto <D.22859>;
        <D.22858>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3580, "ret == 0");
        <D.22859>:
      }
      user_data.domain = domain;
      user_data.wait.num = 0;
      threads.109 = threads;
      mono_g_hash_table_foreach (threads.109, collect_appdomain_thread, &user_data);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22861>; else goto <D.22862>;
        <D.22861>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.22862>:
        D.22863 = ret != 0;
        D.22864 = (long int) D.22863;
        D.22865 = __builtin_expect (D.22864, 0);
        if (D.22865 != 0) goto <D.22866>; else goto <D.22867>;
        <D.22866>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3586, "ret == 0");
        <D.22867>:
      }
      D.22868 = user_data.wait.num;
      if (D.22868 != 0) goto <D.22869>; else goto <D.22870>;
      <D.22869>:
      i = 0;
      goto <D.20459>;
      <D.20458>:
      D.22871 = user_data.wait.threads[i];
      ves_icall_System_Threading_Thread_Abort (D.22871, 0B);
      i = i + 1;
      <D.20459>:
      i.110 = (unsigned int) i;
      D.22868 = user_data.wait.num;
      if (i.110 < D.22868) goto <D.20458>; else goto <D.20460>;
      <D.20460>:
      wait_for_tids (&user_data.wait, 100);
      <D.22870>:
      D.22873 = mono_msec_ticks ();
      D.22874 = D.22873 - start_time;
      timeout.111 = (unsigned int) timeout;
      D.22876 = timeout.111 - D.22874;
      timeout = (int) D.22876;
      start_time = mono_msec_ticks ();
      if (orig_timeout != -1) goto <D.22877>; else goto <D.22878>;
      <D.22877>:
      if (timeout < 0) goto <D.22879>; else goto <D.22880>;
      <D.22879>:
      D.22881 = 0;
      return D.22881;
      <D.22880>:
      <D.22878>:
      D.22868 = user_data.wait.num;
      if (D.22868 != 0) goto <D.20461>; else goto <D.20462>;
      <D.20462>:
      D.22881 = 1;
      return D.22881;
    }
  finally
    {
      user_data = {CLOBBER};
    }
}


collect_appdomain_thread (void * key, void * value, void * user_data)
{
  int D.22884;
  unsigned int D.22887;
  long unsigned int D.22890;
  unsigned int D.22893;
  struct MonoInternalThread * thread;
  struct abort_appdomain_data * data;
  struct MonoDomain * domain;

  thread = value;
  data = user_data;
  domain = data->domain;
  D.22884 = mono_thread_internal_has_appdomain_ref (thread, domain);
  if (D.22884 != 0) goto <D.22885>; else goto <D.22886>;
  <D.22885>:
  D.22887 = data->wait.num;
  if (D.22887 <= 63) goto <D.22888>; else goto <D.22889>;
  <D.22888>:
  {
    void * handle;

    D.22890 = thread->tid;
    handle = OpenThread (2032639, 1, D.22890);
    if (handle == 0B) goto <D.22891>; else goto <D.22892>;
    <D.22891>:
    return;
    <D.22892>:
    D.22887 = data->wait.num;
    data->wait.handles[D.22887] = handle;
    D.22887 = data->wait.num;
    data->wait.threads[D.22887] = thread;
    D.22887 = data->wait.num;
    D.22893 = D.22887 + 1;
    data->wait.num = D.22893;
  }
  goto <D.22894>;
  <D.22889>:
  <D.22894>:
  <D.22886>:
}


mono_threads_clear_cached_culture (struct MonoDomain * domain)
{
  _Bool D.22898;
  long int D.22899;
  long int D.22900;
  struct MonoGHashTable * threads.112;
  _Bool D.22906;
  long int D.22907;
  long int D.22908;

  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22896>; else goto <D.22897>;
    <D.22896>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.22897>:
    D.22898 = ret != 0;
    D.22899 = (long int) D.22898;
    D.22900 = __builtin_expect (D.22899, 0);
    if (D.22900 != 0) goto <D.22901>; else goto <D.22902>;
    <D.22901>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3642, "ret == 0");
    <D.22902>:
  }
  threads.112 = threads;
  mono_g_hash_table_foreach (threads.112, clear_cached_culture, domain);
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22904>; else goto <D.22905>;
    <D.22904>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.22905>:
    D.22906 = ret != 0;
    D.22907 = (long int) D.22906;
    D.22908 = __builtin_expect (D.22907, 0);
    if (D.22908 != 0) goto <D.22909>; else goto <D.22910>;
    <D.22909>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3644, "ret == 0");
    <D.22910>:
  }
}


clear_cached_culture (void * key, void * value, void * user_data)
{
  struct MonoArray * D.22911;
  long unsigned int D.22914;
  char * D.22915;
  struct MonoVTable * D.22918;
  struct MonoDomain * D.22919;
  struct MonoInternalThread * thread;
  struct MonoDomain * domain;
  int i;

  thread = value;
  domain = user_data;
  D.22911 = thread->cached_culture_info;
  if (D.22911 != 0B) goto <D.22912>; else goto <D.22913>;
  <D.22912>:
  i = 0;
  goto <D.20474>;
  <D.20473>:
  {
    struct MonoObject * obj;

    D.22911 = thread->cached_culture_info;
    D.22914 = (long unsigned int) i;
    D.22915 = mono_array_addr_with_size (D.22911, 8, D.22914);
    obj = MEM[(struct MonoObject * *)D.22915];
    if (obj != 0B) goto <D.22916>; else goto <D.22917>;
    <D.22916>:
    D.22918 = obj->vtable;
    D.22919 = D.22918->domain;
    if (D.22919 == domain) goto <D.22920>; else goto <D.22921>;
    <D.22920>:
    {
      struct MonoObject * * __p;

      D.22911 = thread->cached_culture_info;
      D.22914 = (long unsigned int) i;
      __p = mono_array_addr_with_size (D.22911, 8, D.22914);
      *__p = 0B;
    }
    <D.22921>:
    <D.22917>:
  }
  i = i + 1;
  <D.20474>:
  if (i <= 7) goto <D.20473>; else goto <D.20475>;
  <D.20475>:
  <D.22913>:
}


mono_thread_get_undeniable_exception ()
{
  struct MonoException * D.22924;
  int D.22927;
  struct MonoException * D.22930;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  if (thread != 0B) goto <D.22922>; else goto <D.22923>;
  <D.22922>:
  D.22924 = thread->abort_exc;
  if (D.22924 != 0B) goto <D.22925>; else goto <D.22926>;
  <D.22925>:
  D.22927 = is_running_protected_wrapper ();
  if (D.22927 == 0) goto <D.22928>; else goto <D.22929>;
  <D.22928>:
  D.22924 = thread->abort_exc;
  D.22924->trace_ips = 0B;
  D.22924 = thread->abort_exc;
  D.22924->stack_trace = 0B;
  D.22930 = thread->abort_exc;
  return D.22930;
  <D.22929>:
  <D.22926>:
  <D.22923>:
  D.22930 = 0B;
  return D.22930;
}


is_running_protected_wrapper ()
{
  gboolean D.22932;
  gboolean found;

  try
    {
      found = 0;
      mono_stack_walk (find_wrapper, &found);
      D.22932 = found;
      return D.22932;
    }
  finally
    {
      found = {CLOBBER};
    }
}


find_wrapper (struct MonoMethod * m, gint no, gint ilo, gboolean managed, void * data)
{
  gboolean D.22937;
  int D.22938;

  if (managed != 0) goto <D.22935>; else goto <D.22936>;
  <D.22935>:
  D.22937 = 1;
  return D.22937;
  <D.22936>:
  D.22938 = mono_threads_is_critical_method (m);
  if (D.22938 != 0) goto <D.22939>; else goto <D.22940>;
  <D.22939>:
  MEM[(gboolean *)data] = 1;
  D.22937 = 1;
  return D.22937;
  <D.22940>:
  D.22937 = 0;
  return D.22937;
}


mono_alloc_special_static_data (guint32 static_type, guint32 size, guint32 align, uintptr_t * bitmap, int numbits)
{
  _Bool D.22946;
  long int D.22947;
  long int D.22948;
  struct MonoGHashTable * threads.113;
  long unsigned int D.22957;
  void * D.22958;
  _Bool D.22961;
  long int D.22962;
  long int D.22963;
  _Bool D.22967;
  long int D.22968;
  long int D.22969;
  _Bool D.22974;
  long int D.22975;
  long int D.22976;
  _Bool D.22981;
  long int D.22982;
  long int D.22983;
  uint32_t D.22986;
  guint32 offset;

  if (static_type == 1) goto <D.22942>; else goto <D.22943>;
  <D.22942>:
  {
    struct MonoThreadDomainTls * item;

    {
      int ret;

      ret = pthread_mutex_lock (&threads_mutex.mutex);
      if (ret != 0) goto <D.22944>; else goto <D.22945>;
      <D.22944>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
      <D.22945>:
      D.22946 = ret != 0;
      D.22947 = (long int) D.22946;
      D.22948 = __builtin_expect (D.22947, 0);
      if (D.22948 != 0) goto <D.22949>; else goto <D.22950>;
      <D.22949>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3902, "ret == 0");
      <D.22950>:
    }
    item = search_tls_slot_in_freelist (&thread_static_info, size, align);
    if (item != 0B) goto <D.22951>; else goto <D.22952>;
    <D.22951>:
    offset = item->offset;
    monoeg_g_free (item);
    goto <D.22953>;
    <D.22952>:
    offset = mono_alloc_static_data_slot (&thread_static_info, size, align);
    <D.22953>:
    update_tls_reference_bitmap (offset, bitmap, numbits);
    threads.113 = threads;
    if (threads.113 != 0B) goto <D.22955>; else goto <D.22956>;
    <D.22955>:
    threads.113 = threads;
    D.22957 = (long unsigned int) offset;
    D.22958 = (void *) D.22957;
    mono_g_hash_table_foreach (threads.113, alloc_thread_static_data_helper, D.22958);
    <D.22956>:
    {
      int ret;

      ret = pthread_mutex_unlock (&threads_mutex.mutex);
      if (ret != 0) goto <D.22959>; else goto <D.22960>;
      <D.22959>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.22960>:
      D.22961 = ret != 0;
      D.22962 = (long int) D.22961;
      D.22963 = __builtin_expect (D.22962, 0);
      if (D.22963 != 0) goto <D.22964>; else goto <D.22965>;
      <D.22964>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3915, "ret == 0");
      <D.22965>:
    }
  }
  goto <D.22966>;
  <D.22943>:
  D.22967 = static_type != 2;
  D.22968 = (long int) D.22967;
  D.22969 = __builtin_expect (D.22968, 0);
  if (D.22969 != 0) goto <D.22970>; else goto <D.22971>;
  <D.22970>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3917, "static_type == SPECIAL_STATIC_CONTEXT");
  <D.22971>:
  {
    int ret;

    ret = pthread_mutex_lock (&contexts_mutex.mutex);
    if (ret != 0) goto <D.22972>; else goto <D.22973>;
    <D.22972>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.22973>:
    D.22974 = ret != 0;
    D.22975 = (long int) D.22974;
    D.22976 = __builtin_expect (D.22975, 0);
    if (D.22976 != 0) goto <D.22977>; else goto <D.22978>;
    <D.22977>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3918, "ret == 0");
    <D.22978>:
  }
  offset = mono_alloc_static_data_slot (&context_static_info, size, align);
  {
    int ret;

    ret = pthread_mutex_unlock (&contexts_mutex.mutex);
    if (ret != 0) goto <D.22979>; else goto <D.22980>;
    <D.22979>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.22980>:
    D.22981 = ret != 0;
    D.22982 = (long int) D.22981;
    D.22983 = __builtin_expect (D.22982, 0);
    if (D.22983 != 0) goto <D.22984>; else goto <D.22985>;
    <D.22984>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3920, "ret == 0");
    <D.22985>:
  }
  offset = offset | 2147483648;
  <D.22966>:
  D.22986 = offset;
  return D.22986;
}


alloc_thread_static_data_helper (void * key, void * value, void * user)
{
  long int user.114;
  void * * * D.22989;
  struct MonoInternalThread * thread;
  guint32 offset;

  thread = value;
  user.114 = (long int) user;
  offset = (guint32) user.114;
  D.22989 = &thread->static_data;
  mono_alloc_static_data (D.22989, offset, 1);
}


search_tls_slot_in_freelist (struct StaticDataInfo * static_data, guint32 size, guint32 align)
{
  unsigned int D.22990;
  struct MonoThreadDomainTls * D.22995;
  struct MonoThreadDomainTls * D.22997;
  struct MonoThreadDomainTls * prev;
  struct MonoThreadDomainTls * tmp;

  prev = 0B;
  tmp = static_data->freelist;
  goto <D.20561>;
  <D.20560>:
  D.22990 = tmp->size;
  if (D.22990 == size) goto <D.22991>; else goto <D.22992>;
  <D.22991>:
  if (prev != 0B) goto <D.22993>; else goto <D.22994>;
  <D.22993>:
  D.22995 = tmp->next;
  prev->next = D.22995;
  goto <D.22996>;
  <D.22994>:
  D.22995 = tmp->next;
  static_data->freelist = D.22995;
  <D.22996>:
  D.22997 = tmp;
  return D.22997;
  <D.22992>:
  tmp = tmp->next;
  <D.20561>:
  if (tmp != 0B) goto <D.20560>; else goto <D.20562>;
  <D.20562>:
  D.22997 = 0B;
  return D.22997;
}


update_tls_reference_bitmap (guint32 offset, uintptr_t * bitmap, int numbits)
{
  unsigned int D.22999;
  unsigned int D.23000;
  uintptr_t * D.23001;
  int D.23004;
  long unsigned int D.23005;
  long unsigned int D.23006;
  long unsigned int D.23007;
  long unsigned int D.23008;
  void * D.23009;
  long unsigned int D.23010;
  long unsigned int D.23011;
  long unsigned int D.23012;
  uintptr_t * D.23013;
  long unsigned int D.23014;
  int D.23015;
  long int D.23016;
  long unsigned int D.23017;
  long unsigned int D.23018;
  unsigned int i.115;
  unsigned int D.23022;
  unsigned int D.23023;
  long unsigned int D.23024;
  long unsigned int D.23025;
  uintptr_t * D.23026;
  long unsigned int D.23027;
  int D.23028;
  int D.23029;
  long int D.23030;
  long unsigned int D.23031;
  long unsigned int D.23032;
  int i;
  int idx;
  uintptr_t * rb;

  D.22999 = offset >> 24;
  D.23000 = D.22999 + 4294967295;
  idx = (int) D.23000;
  D.23001 = static_reference_bitmaps[idx];
  if (D.23001 == 0B) goto <D.23002>; else goto <D.23003>;
  <D.23002>:
  D.23004 = static_data_size[idx];
  D.23005 = (long unsigned int) D.23004;
  D.23006 = D.23005 / 512;
  D.23007 = D.23006 + 1;
  D.23008 = D.23007 * 8;
  D.23009 = monoeg_malloc0 (D.23008);
  static_reference_bitmaps[idx] = D.23009;
  <D.23003>:
  rb = static_reference_bitmaps[idx];
  offset = offset & 16777215;
  offset = offset / 8;
  i = 0;
  goto <D.20572>;
  <D.20571>:
  D.23010 = (long unsigned int) i;
  D.23011 = D.23010 / 8;
  D.23012 = D.23011 * 8;
  D.23013 = bitmap + D.23012;
  D.23014 = *D.23013;
  D.23015 = i & 63;
  D.23016 = 1 << D.23015;
  D.23017 = (long unsigned int) D.23016;
  D.23018 = D.23014 & D.23017;
  if (D.23018 != 0) goto <D.23019>; else goto <D.23020>;
  <D.23019>:
  i.115 = (unsigned int) i;
  D.23022 = offset + i.115;
  D.23023 = D.23022 / 64;
  D.23024 = (long unsigned int) D.23023;
  D.23025 = D.23024 * 8;
  D.23026 = rb + D.23025;
  D.23024 = (long unsigned int) D.23023;
  D.23025 = D.23024 * 8;
  D.23026 = rb + D.23025;
  D.23027 = *D.23026;
  i.115 = (unsigned int) i;
  D.23022 = offset + i.115;
  D.23028 = (int) D.23022;
  D.23029 = D.23028 & 63;
  D.23030 = 1 << D.23029;
  D.23031 = (long unsigned int) D.23030;
  D.23032 = D.23027 | D.23031;
  *D.23026 = D.23032;
  <D.23020>:
  i = i + 1;
  <D.20572>:
  if (i < numbits) goto <D.20571>; else goto <D.20573>;
  <D.20573>:
}


mono_alloc_static_data_slot (struct StaticDataInfo * static_data, guint32 size, guint32 align)
{
  signed long D.23033;
  long unsigned int D.23034;
  long unsigned int D.23035;
  int D.23038;
  unsigned int D.23039;
  unsigned int D.23040;
  unsigned int D.23041;
  int D.23042;
  unsigned int D.23043;
  unsigned int D.23044;
  int D.23045;
  unsigned int D.23046;
  int D.23047;
  int D.23048;
  unsigned int D.23049;
  int D.23052;
  _Bool D.23053;
  long int D.23054;
  long int D.23055;
  _Bool D.23058;
  long int D.23059;
  long int D.23060;
  int D.23063;
  int D.23064;
  int D.23065;
  guint32 D.23066;
  guint32 offset;

  D.23033 = BIT_FIELD_REF <*static_data, 64, 0>;
  D.23034 = (long unsigned int) D.23033;
  D.23035 = D.23034;
  if (D.23035 == 0) goto <D.23036>; else goto <D.23037>;
  <D.23036>:
  static_data->offset = 64;
  <D.23037>:
  D.23038 = static_data->offset;
  D.23039 = (unsigned int) D.23038;
  D.23040 = D.23039 + align;
  D.23041 = D.23040 + 4294967295;
  D.23042 = (int) D.23041;
  static_data->offset = D.23042;
  D.23038 = static_data->offset;
  D.23039 = (unsigned int) D.23038;
  D.23043 = -align;
  D.23044 = D.23039 & D.23043;
  D.23045 = (int) D.23044;
  static_data->offset = D.23045;
  D.23038 = static_data->offset;
  D.23039 = (unsigned int) D.23038;
  D.23046 = D.23039 + size;
  D.23047 = static_data->idx;
  D.23048 = static_data_size[D.23047];
  D.23049 = (unsigned int) D.23048;
  if (D.23046 >= D.23049) goto <D.23050>; else goto <D.23051>;
  <D.23050>:
  D.23047 = static_data->idx;
  D.23052 = D.23047 + 1;
  static_data->idx = D.23052;
  D.23047 = static_data->idx;
  D.23048 = static_data_size[D.23047];
  D.23049 = (unsigned int) D.23048;
  D.23053 = D.23049 < size;
  D.23054 = (long int) D.23053;
  D.23055 = __builtin_expect (D.23054, 0);
  if (D.23055 != 0) goto <D.23056>; else goto <D.23057>;
  <D.23056>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3801, "size <= static_data_size [static_data->idx]");
  <D.23057>:
  D.23047 = static_data->idx;
  D.23058 = D.23047 > 7;
  D.23059 = (long int) D.23058;
  D.23060 = __builtin_expect (D.23059, 0);
  if (D.23060 != 0) goto <D.23061>; else goto <D.23062>;
  <D.23061>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3802, "static_data->idx < NUM_STATIC_DATA_IDX");
  <D.23062>:
  static_data->offset = 0;
  <D.23051>:
  D.23038 = static_data->offset;
  D.23047 = static_data->idx;
  D.23052 = D.23047 + 1;
  D.23063 = D.23052 << 24;
  D.23064 = D.23038 | D.23063;
  offset = (guint32) D.23064;
  D.23038 = static_data->offset;
  D.23039 = (unsigned int) D.23038;
  D.23046 = D.23039 + size;
  D.23065 = (int) D.23046;
  static_data->offset = D.23065;
  D.23066 = offset;
  return D.23066;
}


mono_get_special_static_data_for_thread (struct MonoInternalThread * thread, guint32 offset)
{
  unsigned int D.23068;
  unsigned int D.23069;
  void * D.23072;
  void * * D.23075;
  long unsigned int D.23077;
  long unsigned int D.23078;
  void * * D.23079;
  void * D.23080;
  _Bool D.23083;
  long int D.23084;
  long int D.23085;
  void * * * D.23088;
  _Bool D.23091;
  long int D.23092;
  long int D.23093;
  sizetype D.23096;
  sizetype D.23097;
  guint32 static_type;
  int idx;

  static_type = offset & 2147483648;
  offset = offset & 2147483647;
  D.23068 = offset >> 24;
  D.23069 = D.23068 + 4294967295;
  idx = (int) D.23069;
  if (static_type == 0) goto <D.23070>; else goto <D.23071>;
  <D.23070>:
  D.23072 = get_thread_static_data (thread, offset);
  return D.23072;
  <D.23071>:
  {
    struct MonoAppContext * context;

    context = mono_context_get ();
    D.23075 = context->static_data;
    if (D.23075 == 0B) goto <D.23073>; else goto <D.23076>;
    <D.23076>:
    D.23075 = context->static_data;
    D.23077 = (long unsigned int) idx;
    D.23078 = D.23077 * 8;
    D.23079 = D.23075 + D.23078;
    D.23080 = *D.23079;
    if (D.23080 == 0B) goto <D.23073>; else goto <D.23074>;
    <D.23073>:
    {
      int ret;

      ret = pthread_mutex_lock (&contexts_mutex.mutex);
      if (ret != 0) goto <D.23081>; else goto <D.23082>;
      <D.23081>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
      <D.23082>:
      D.23083 = ret != 0;
      D.23084 = (long int) D.23083;
      D.23085 = __builtin_expect (D.23084, 0);
      if (D.23085 != 0) goto <D.23086>; else goto <D.23087>;
      <D.23086>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3945, "ret == 0");
      <D.23087>:
    }
    D.23088 = &context->static_data;
    mono_alloc_static_data (D.23088, offset, 0);
    {
      int ret;

      ret = pthread_mutex_unlock (&contexts_mutex.mutex);
      if (ret != 0) goto <D.23089>; else goto <D.23090>;
      <D.23089>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.23090>:
      D.23091 = ret != 0;
      D.23092 = (long int) D.23091;
      D.23093 = __builtin_expect (D.23092, 0);
      if (D.23093 != 0) goto <D.23094>; else goto <D.23095>;
      <D.23094>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3947, "ret == 0");
      <D.23095>:
    }
    <D.23074>:
    D.23075 = context->static_data;
    D.23077 = (long unsigned int) idx;
    D.23078 = D.23077 * 8;
    D.23079 = D.23075 + D.23078;
    D.23080 = *D.23079;
    D.23096 = (sizetype) offset;
    D.23097 = D.23096 & 16777215;
    D.23072 = D.23080 + D.23097;
    return D.23072;
  }
}


mono_get_special_static_data (guint32 offset)
{
  void * D.23099;
  struct MonoInternalThread * D.23100;

  D.23100 = mono_thread_internal_current ();
  D.23099 = mono_get_special_static_data_for_thread (D.23100, offset);
  return D.23099;
}


mono_alloc_special_static_data_free (struct GHashTable * special_static_fields)
{
  _Bool D.23104;
  long int D.23105;
  long int D.23106;
  _Bool D.23111;
  long int D.23112;
  long int D.23113;

  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.23102>; else goto <D.23103>;
    <D.23102>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.23103>:
    D.23104 = ret != 0;
    D.23105 = (long int) D.23104;
    D.23106 = __builtin_expect (D.23105, 0);
    if (D.23106 != 0) goto <D.23107>; else goto <D.23108>;
    <D.23107>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4020, "ret == 0");
    <D.23108>:
  }
  monoeg_g_hash_table_foreach (special_static_fields, do_free_special, 0B);
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.23109>; else goto <D.23110>;
    <D.23109>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.23110>:
    D.23111 = ret != 0;
    D.23112 = (long int) D.23111;
    D.23113 = __builtin_expect (D.23112, 0);
    if (D.23113 != 0) goto <D.23114>; else goto <D.23115>;
    <D.23114>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4022, "ret == 0");
    <D.23115>:
  }
}


do_free_special (void * key, void * value, void * data)
{
  long int value.116;
  struct MonoType * D.23117;
  int D.23118;
  struct MonoClassField * field;
  guint32 offset;
  gint32 align;
  guint32 size;

  try
    {
      field = key;
      value.116 = (long int) value;
      offset = (guint32) value.116;
      D.23117 = field->type;
      D.23118 = mono_type_size (D.23117, &align);
      size = (guint32) D.23118;
      do_free_special_slot (offset, size);
    }
  finally
    {
      align = {CLOBBER};
    }
}


do_free_special_slot (guint32 offset, guint32 size)
{
  unsigned int D.23121;
  unsigned int D.23122;
  unsigned int D.23123;
  struct MonoGHashTable * threads.117;
  int D.23127;
  struct MonoThreadDomainTls * D.23130;
  guint32 static_type;

  static_type = offset & 2147483648;
  if (static_type == 0) goto <D.23119>; else goto <D.23120>;
  <D.23119>:
  {
    struct TlsOffsetSize data;
    struct MonoThreadDomainTls * item;

    try
      {
        item = monoeg_malloc0 (16);
        D.23121 = offset & 2147483647;
        data.offset = D.23121;
        data.size = size;
        D.23122 = data.offset;
        D.23123 = data.size;
        clear_reference_bitmap (D.23122, D.23123);
        threads.117 = threads;
        if (threads.117 != 0B) goto <D.23125>; else goto <D.23126>;
        <D.23125>:
        threads.117 = threads;
        mono_g_hash_table_foreach (threads.117, free_thread_static_data_helper, &data);
        <D.23126>:
        item->offset = offset;
        item->size = size;
        D.23127 = mono_runtime_is_shutting_down ();
        if (D.23127 == 0) goto <D.23128>; else goto <D.23129>;
        <D.23128>:
        D.23130 = thread_static_info.freelist;
        item->next = D.23130;
        thread_static_info.freelist = item;
        goto <D.23131>;
        <D.23129>:
        monoeg_g_free (item);
        <D.23131>:
      }
    finally
      {
        data = {CLOBBER};
      }
  }
  goto <D.23132>;
  <D.23120>:
  <D.23132>:
}


free_thread_static_data_helper (void * key, void * value, void * user)
{
  unsigned int D.23133;
  unsigned int D.23134;
  unsigned int D.23135;
  void * * D.23138;
  long unsigned int D.23140;
  long unsigned int D.23141;
  void * * D.23142;
  void * D.23143;
  sizetype D.23144;
  sizetype D.23145;
  unsigned int D.23146;
  long unsigned int D.23147;
  struct MonoInternalThread * thread;
  struct TlsOffsetSize * data;
  int idx;
  char * ptr;

  thread = value;
  data = user;
  D.23133 = data->offset;
  D.23134 = D.23133 >> 24;
  D.23135 = D.23134 + 4294967295;
  idx = (int) D.23135;
  D.23138 = thread->static_data;
  if (D.23138 == 0B) goto <D.23136>; else goto <D.23139>;
  <D.23139>:
  D.23138 = thread->static_data;
  D.23140 = (long unsigned int) idx;
  D.23141 = D.23140 * 8;
  D.23142 = D.23138 + D.23141;
  D.23143 = *D.23142;
  if (D.23143 == 0B) goto <D.23136>; else goto <D.23137>;
  <D.23136>:
  return;
  <D.23137>:
  D.23138 = thread->static_data;
  D.23140 = (long unsigned int) idx;
  D.23141 = D.23140 * 8;
  D.23142 = D.23138 + D.23141;
  D.23143 = *D.23142;
  D.23133 = data->offset;
  D.23144 = (sizetype) D.23133;
  D.23145 = D.23144 & 16777215;
  ptr = D.23143 + D.23145;
  D.23146 = data->size;
  D.23147 = (long unsigned int) D.23146;
  mono_gc_bzero_atomic (ptr, D.23147);
}


clear_reference_bitmap (guint32 offset, guint32 size)
{
  unsigned int D.23149;
  unsigned int D.23150;
  unsigned int D.23151;
  long unsigned int D.23152;
  long unsigned int D.23153;
  uintptr_t * D.23154;
  long unsigned int D.23155;
  int offset.118;
  int D.23157;
  long int D.23158;
  long int D.23159;
  long unsigned int D.23160;
  long unsigned int D.23161;
  int idx;
  uintptr_t * rb;

  D.23149 = offset >> 24;
  D.23150 = D.23149 + 4294967295;
  idx = (int) D.23150;
  rb = static_reference_bitmaps[idx];
  offset = offset & 16777215;
  offset = offset / 8;
  size = size / 8;
  size = size + offset;
  goto <D.20581>;
  <D.20580>:
  D.23151 = offset / 64;
  D.23152 = (long unsigned int) D.23151;
  D.23153 = D.23152 * 8;
  D.23154 = rb + D.23153;
  D.23152 = (long unsigned int) D.23151;
  D.23153 = D.23152 * 8;
  D.23154 = rb + D.23153;
  D.23155 = *D.23154;
  offset.118 = (int) offset;
  D.23157 = offset.118 & 63;
  D.23158 = 1 << D.23157;
  D.23159 = ~D.23158;
  D.23160 = (long unsigned int) D.23159;
  D.23161 = D.23155 & D.23160;
  *D.23154 = D.23161;
  offset = offset + 1;
  <D.20581>:
  if (offset < size) goto <D.20580>; else goto <D.20582>;
  <D.20582>:
}


mono_special_static_data_free_slot (guint32 offset, guint32 size)
{
  _Bool D.23164;
  long int D.23165;
  long int D.23166;
  _Bool D.23171;
  long int D.23172;
  long int D.23173;

  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.23162>; else goto <D.23163>;
    <D.23162>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.23163>:
    D.23164 = ret != 0;
    D.23165 = (long int) D.23164;
    D.23166 = __builtin_expect (D.23165, 0);
    if (D.23166 != 0) goto <D.23167>; else goto <D.23168>;
    <D.23167>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4028, "ret == 0");
    <D.23168>:
  }
  do_free_special_slot (offset, size);
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.23169>; else goto <D.23170>;
    <D.23169>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.23170>:
    D.23171 = ret != 0;
    D.23172 = (long int) D.23171;
    D.23173 = __builtin_expect (D.23172, 0);
    if (D.23173 != 0) goto <D.23174>; else goto <D.23175>;
    <D.23174>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4030, "ret == 0");
    <D.23175>:
  }
}


mono_thread_alloc_tls (struct MonoReflectionType * type)
{
  struct MonoType * D.23176;
  int D.23177;
  int align.119;
  unsigned int align.120;
  int max_set.121;
  int D.23181;
  union mono_mutex_t * D.23184;
  _Bool D.23187;
  long int D.23188;
  long int D.23189;
  struct MonoTlsDataRecord * D.23192;
  _Bool D.23195;
  long int D.23196;
  long int D.23197;
  uint32_t D.23200;
  struct MonoDomain * domain;
  struct MonoClass * klass;
  struct MonoTlsDataRecord * tlsrec;
  int max_set;
  gsize * bitmap;
  gsize default_bitmap[4];
  uint32_t tls_offset;
  guint32 size;
  gint32 align;

  try
    {
      domain = mono_domain_get ();
      max_set = 0;
      default_bitmap = {};
      D.23176 = type->type;
      klass = mono_class_from_mono_type (D.23176);
      bitmap = mono_class_compute_bitmap (klass, &default_bitmap, 256, -2, &max_set, 0);
      D.23176 = type->type;
      D.23177 = mono_type_size (D.23176, &align);
      size = (guint32) D.23177;
      align.119 = align;
      align.120 = (unsigned int) align.119;
      max_set.121 = max_set;
      D.23181 = max_set.121 + 1;
      tls_offset = mono_alloc_special_static_data (1, size, align.120, bitmap, D.23181);
      if (&default_bitmap != bitmap) goto <D.23182>; else goto <D.23183>;
      <D.23182>:
      monoeg_g_free (bitmap);
      <D.23183>:
      tlsrec = monoeg_malloc0 (16);
      tlsrec->tls_offset = tls_offset;
      tlsrec->size = size;
      {
        int ret;

        D.23184 = &domain->lock.mutex;
        ret = pthread_mutex_lock (D.23184);
        if (ret != 0) goto <D.23185>; else goto <D.23186>;
        <D.23185>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.23186>:
        D.23187 = ret != 0;
        D.23188 = (long int) D.23187;
        D.23189 = __builtin_expect (D.23188, 0);
        if (D.23189 != 0) goto <D.23190>; else goto <D.23191>;
        <D.23190>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4060, "ret == 0");
        <D.23191>:
      }
      D.23192 = domain->tlsrec_list;
      tlsrec->next = D.23192;
      domain->tlsrec_list = tlsrec;
      {
        int ret;

        D.23184 = &domain->lock.mutex;
        ret = pthread_mutex_unlock (D.23184);
        if (ret != 0) goto <D.23193>; else goto <D.23194>;
        <D.23193>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.23194>:
        D.23195 = ret != 0;
        D.23196 = (long int) D.23195;
        D.23197 = __builtin_expect (D.23196, 0);
        if (D.23197 != 0) goto <D.23198>; else goto <D.23199>;
        <D.23198>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4063, "ret == 0");
        <D.23199>:
      }
      D.23200 = tls_offset;
      return D.23200;
    }
  finally
    {
      max_set = {CLOBBER};
      default_bitmap = {CLOBBER};
      align = {CLOBBER};
    }
}


mono_thread_destroy_tls (uint32_t tls_offset)
{
  union mono_mutex_t * D.23203;
  _Bool D.23206;
  long int D.23207;
  long int D.23208;
  unsigned int D.23211;
  struct MonoTlsDataRecord * D.23216;
  _Bool D.23220;
  long int D.23221;
  long int D.23222;
  struct MonoTlsDataRecord * prev;
  struct MonoTlsDataRecord * cur;
  guint32 size;
  struct MonoDomain * domain;

  prev = 0B;
  size = 0;
  domain = mono_domain_get ();
  {
    int ret;

    D.23203 = &domain->lock.mutex;
    ret = pthread_mutex_lock (D.23203);
    if (ret != 0) goto <D.23204>; else goto <D.23205>;
    <D.23204>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.23205>:
    D.23206 = ret != 0;
    D.23207 = (long int) D.23206;
    D.23208 = __builtin_expect (D.23207, 0);
    if (D.23208 != 0) goto <D.23209>; else goto <D.23210>;
    <D.23209>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4074, "ret == 0");
    <D.23210>:
  }
  cur = domain->tlsrec_list;
  goto <D.20672>;
  <D.20671>:
  D.23211 = cur->tls_offset;
  if (D.23211 == tls_offset) goto <D.23212>; else goto <D.23213>;
  <D.23212>:
  if (prev != 0B) goto <D.23214>; else goto <D.23215>;
  <D.23214>:
  D.23216 = cur->next;
  prev->next = D.23216;
  goto <D.23217>;
  <D.23215>:
  D.23216 = cur->next;
  domain->tlsrec_list = D.23216;
  <D.23217>:
  size = cur->size;
  monoeg_g_free (cur);
  goto <D.20670>;
  <D.23213>:
  prev = cur;
  cur = cur->next;
  <D.20672>:
  if (cur != 0B) goto <D.20671>; else goto <D.20670>;
  <D.20670>:
  {
    int ret;

    D.23203 = &domain->lock.mutex;
    ret = pthread_mutex_unlock (D.23203);
    if (ret != 0) goto <D.23218>; else goto <D.23219>;
    <D.23218>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.23219>:
    D.23220 = ret != 0;
    D.23221 = (long int) D.23220;
    D.23222 = __builtin_expect (D.23221, 0);
    if (D.23222 != 0) goto <D.23223>; else goto <D.23224>;
    <D.23223>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4089, "ret == 0");
    <D.23224>:
  }
  if (size != 0) goto <D.23225>; else goto <D.23226>;
  <D.23225>:
  mono_special_static_data_free_slot (tls_offset, size);
  <D.23226>:
}


mono_thread_destroy_domain_tls (struct MonoDomain * domain)
{
  struct MonoTlsDataRecord * D.23227;
  unsigned int D.23228;

  goto <D.20678>;
  <D.20677>:
  D.23227 = domain->tlsrec_list;
  D.23228 = D.23227->tls_offset;
  mono_thread_destroy_tls (D.23228);
  <D.20678>:
  D.23227 = domain->tlsrec_list;
  if (D.23227 != 0B) goto <D.20677>; else goto <D.20679>;
  <D.20679>:
}


mono_thread_free_local_slot_values (int slot, MonoBoolean thread_local)
{
  struct MonoClassField * local_slots.122;
  struct MonoClass * D.23234;
  struct MonoClassField * local_slots.123;
  union mono_mutex_t * D.23238;
  _Bool D.23241;
  long int D.23242;
  long int D.23243;
  struct GHashTable * D.23246;
  _Bool D.23251;
  long int D.23252;
  long int D.23253;
  long int addr.124;
  unsigned int D.23259;
  unsigned int D.23260;
  unsigned int D.23261;
  unsigned int D.23262;
  unsigned int D.23263;
  int D.23264;
  _Bool D.23267;
  long int D.23268;
  long int D.23269;
  struct MonoGHashTable * threads.125;
  _Bool D.23275;
  long int D.23276;
  long int D.23277;
  struct MonoDomain * domain;
  struct LocalSlotID sid;

  try
    {
      sid.slot = slot;
      if (thread_local != 0) goto <D.23229>; else goto <D.23230>;
      <D.23229>:
      {
        void * addr;

        addr = 0B;
        local_slots.122 = local_slots;
        if (local_slots.122 == 0B) goto <D.23232>; else goto <D.23233>;
        <D.23232>:
        D.23234 = mono_defaults.thread_class;
        local_slots.123 = mono_class_get_field_from_name (D.23234, "local_slots");
        local_slots = local_slots.123;
        local_slots.122 = local_slots;
        if (local_slots.122 == 0B) goto <D.23236>; else goto <D.23237>;
        <D.23236>:
        monoeg_g_log (0B, 16, "local_slots field not found in Thread class");
        return;
        <D.23237>:
        <D.23233>:
        domain = mono_domain_get ();
        {
          int ret;

          D.23238 = &domain->lock.mutex;
          ret = pthread_mutex_lock (D.23238);
          if (ret != 0) goto <D.23239>; else goto <D.23240>;
          <D.23239>:
          monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
          <D.23240>:
          D.23241 = ret != 0;
          D.23242 = (long int) D.23241;
          D.23243 = __builtin_expect (D.23242, 0);
          if (D.23243 != 0) goto <D.23244>; else goto <D.23245>;
          <D.23244>:
          monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4150, "ret == 0");
          <D.23245>:
        }
        D.23246 = domain->special_static_fields;
        if (D.23246 != 0B) goto <D.23247>; else goto <D.23248>;
        <D.23247>:
        D.23246 = domain->special_static_fields;
        local_slots.122 = local_slots;
        addr = monoeg_g_hash_table_lookup (D.23246, local_slots.122);
        <D.23248>:
        {
          int ret;

          D.23238 = &domain->lock.mutex;
          ret = pthread_mutex_unlock (D.23238);
          if (ret != 0) goto <D.23249>; else goto <D.23250>;
          <D.23249>:
          monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
          <D.23250>:
          D.23251 = ret != 0;
          D.23252 = (long int) D.23251;
          D.23253 = __builtin_expect (D.23252, 0);
          if (D.23253 != 0) goto <D.23254>; else goto <D.23255>;
          <D.23254>:
          monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4153, "ret == 0");
          <D.23255>:
        }
        if (addr == 0B) goto <D.23256>; else goto <D.23257>;
        <D.23256>:
        return;
        <D.23257>:
        addr.124 = (long int) addr;
        D.23259 = (unsigned int) addr.124;
        sid.offset = D.23259;
        D.23260 = sid.offset;
        D.23261 = D.23260 & 2147483647;
        sid.offset = D.23261;
        D.23260 = sid.offset;
        D.23262 = D.23260 >> 24;
        D.23263 = D.23262 + 4294967295;
        D.23264 = (int) D.23263;
        sid.idx = D.23264;
        {
          int ret;

          ret = pthread_mutex_lock (&threads_mutex.mutex);
          if (ret != 0) goto <D.23265>; else goto <D.23266>;
          <D.23265>:
          monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
          <D.23266>:
          D.23267 = ret != 0;
          D.23268 = (long int) D.23267;
          D.23269 = __builtin_expect (D.23268, 0);
          if (D.23269 != 0) goto <D.23270>; else goto <D.23271>;
          <D.23270>:
          monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4160, "ret == 0");
          <D.23271>:
        }
        threads.125 = threads;
        mono_g_hash_table_foreach (threads.125, clear_local_slot, &sid);
        {
          int ret;

          ret = pthread_mutex_unlock (&threads_mutex.mutex);
          if (ret != 0) goto <D.23273>; else goto <D.23274>;
          <D.23273>:
          monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
          <D.23274>:
          D.23275 = ret != 0;
          D.23276 = (long int) D.23275;
          D.23277 = __builtin_expect (D.23276, 0);
          if (D.23277 != 0) goto <D.23278>; else goto <D.23279>;
          <D.23278>:
          monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4162, "ret == 0");
          <D.23279>:
        }
      }
      goto <D.23280>;
      <D.23230>:
      <D.23280>:
    }
  finally
    {
      sid = {CLOBBER};
    }
}


clear_local_slot (void * key, void * value, void * user_data)
{
  void * * D.23286;
  int D.23288;
  long unsigned int D.23289;
  long unsigned int D.23290;
  void * * D.23291;
  void * D.23292;
  unsigned int D.23293;
  sizetype D.23294;
  sizetype D.23295;
  struct MonoArray * * D.23296;
  int D.23300;
  long unsigned int D.23301;
  long unsigned int D.23302;
  struct LocalSlotID * sid;
  struct MonoInternalThread * thread;
  struct MonoArray * slots_array;

  sid = user_data;
  thread = value;
  D.23286 = thread->static_data;
  if (D.23286 == 0B) goto <D.23284>; else goto <D.23287>;
  <D.23287>:
  D.23286 = thread->static_data;
  D.23288 = sid->idx;
  D.23289 = (long unsigned int) D.23288;
  D.23290 = D.23289 * 8;
  D.23291 = D.23286 + D.23290;
  D.23292 = *D.23291;
  if (D.23292 == 0B) goto <D.23284>; else goto <D.23285>;
  <D.23284>:
  return;
  <D.23285>:
  D.23286 = thread->static_data;
  D.23288 = sid->idx;
  D.23289 = (long unsigned int) D.23288;
  D.23290 = D.23289 * 8;
  D.23291 = D.23286 + D.23290;
  D.23292 = *D.23291;
  D.23293 = sid->offset;
  D.23294 = (sizetype) D.23293;
  D.23295 = D.23294 & 16777215;
  D.23296 = D.23292 + D.23295;
  slots_array = *D.23296;
  if (slots_array == 0B) goto <D.23297>; else goto <D.23299>;
  <D.23299>:
  D.23300 = sid->slot;
  D.23301 = (long unsigned int) D.23300;
  D.23302 = mono_array_length (slots_array);
  if (D.23301 >= D.23302) goto <D.23297>; else goto <D.23298>;
  <D.23297>:
  return;
  <D.23298>:
  {
    struct MonoObject * * __p;

    D.23300 = sid->slot;
    D.23301 = (long unsigned int) D.23300;
    __p = mono_array_addr_with_size (slots_array, 8, D.23301);
    *__p = 0B;
  }
}


mono_thread_request_interruption (gboolean running_managed)
{
  struct MonoException * D.23306;
  gint32 * D.23307;
  int D.23308;
  int D.23314;
  void (*<T553>) (void) mono_thread_notify_pending_exc_fn.126;
  void * D.23320;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  if (thread == 0B) goto <D.23304>; else goto <D.23305>;
  <D.23304>:
  D.23306 = 0B;
  return D.23306;
  <D.23305>:
  D.23307 = &thread->interruption_requested;
  D.23308 = InterlockedCompareExchange (D.23307, 1, 0);
  if (D.23308 == 1) goto <D.23309>; else goto <D.23310>;
  <D.23309>:
  D.23306 = 0B;
  return D.23306;
  <D.23310>:
  InterlockedIncrement (&thread_interruption_requested);
  if (running_managed == 0) goto <D.23311>; else goto <D.23313>;
  <D.23313>:
  D.23314 = is_running_protected_wrapper ();
  if (D.23314 != 0) goto <D.23311>; else goto <D.23312>;
  <D.23311>:
  mono_thread_notify_pending_exc_fn.126 = mono_thread_notify_pending_exc_fn;
  if (mono_thread_notify_pending_exc_fn.126 != 0B) goto <D.23316>; else goto <D.23317>;
  <D.23316>:
  if (running_managed == 0) goto <D.23318>; else goto <D.23319>;
  <D.23318>:
  mono_thread_notify_pending_exc_fn.126 = mono_thread_notify_pending_exc_fn;
  mono_thread_notify_pending_exc_fn.126 ();
  <D.23319>:
  <D.23317>:
  D.23320 = thread->handle;
  QueueUserAPC (dummy_apc, D.23320, 0B);
  D.23306 = 0B;
  return D.23306;
  <D.23312>:
  D.23306 = mono_thread_execute_interruption (thread);
  return D.23306;
}


dummy_apc (void * param)
{
  guint32 D.23322;

  D.23322 = 0;
  return D.23322;
}


mono_thread_resume_interruption ()
{
  struct MonoException * D.23326;
  unsigned int D.23327;
  unsigned int D.23328;
  _Bool D.23329;
  gint32 * D.23332;
  int D.23333;
  struct MonoInternalThread * thread;
  gboolean still_aborting;

  thread = mono_thread_internal_current ();
  if (thread == 0B) goto <D.23324>; else goto <D.23325>;
  <D.23324>:
  D.23326 = 0B;
  return D.23326;
  <D.23325>:
  lock_thread (thread);
  D.23327 = thread->state;
  D.23328 = D.23327 & 128;
  D.23329 = D.23328 != 0;
  still_aborting = (gboolean) D.23329;
  unlock_thread (thread);
  if (still_aborting == 0) goto <D.23330>; else goto <D.23331>;
  <D.23330>:
  D.23326 = 0B;
  return D.23326;
  <D.23331>:
  D.23332 = &thread->interruption_requested;
  D.23333 = InterlockedCompareExchange (D.23332, 1, 0);
  if (D.23333 == 1) goto <D.23334>; else goto <D.23335>;
  <D.23334>:
  D.23326 = 0B;
  return D.23326;
  <D.23335>:
  InterlockedIncrement (&thread_interruption_requested);
  wapi_self_interrupt ();
  D.23326 = mono_thread_execute_interruption (thread);
  return D.23326;
}


mono_thread_interruption_requested ()
{
  int thread_interruption_requested.127;
  gboolean D.23342;

  thread_interruption_requested.127 = thread_interruption_requested;
  if (thread_interruption_requested.127 != 0) goto <D.23338>; else goto <D.23339>;
  <D.23338>:
  {
    struct MonoInternalThread * thread;

    thread = mono_thread_internal_current ();
    if (thread != 0B) goto <D.23340>; else goto <D.23341>;
    <D.23340>:
    D.23342 = thread->interruption_requested;
    return D.23342;
    <D.23341>:
  }
  <D.23339>:
  D.23342 = 0;
  return D.23342;
}


mono_thread_interruption_checkpoint ()
{
  mono_thread_interruption_checkpoint_request (0);
}


mono_thread_interruption_checkpoint_request (gboolean bypass_abort_protection)
{
  int D.23348;
  int D.23352;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  if (thread == 0B) goto <D.23344>; else goto <D.23345>;
  <D.23344>:
  return;
  <D.23345>:
  D.23348 = thread->interruption_requested;
  if (D.23348 != 0) goto <D.23349>; else goto <D.23350>;
  <D.23349>:
  if (bypass_abort_protection != 0) goto <D.23346>; else goto <D.23351>;
  <D.23351>:
  D.23352 = is_running_protected_wrapper ();
  if (D.23352 == 0) goto <D.23346>; else goto <D.23347>;
  <D.23346>:
  {
    struct MonoException * exc;

    exc = mono_thread_execute_interruption (thread);
    if (exc != 0B) goto <D.23353>; else goto <D.23354>;
    <D.23353>:
    mono_raise_exception (exc);
    <D.23354>:
  }
  <D.23347>:
  <D.23350>:
}


mono_thread_force_interruption_checkpoint ()
{
  mono_thread_interruption_checkpoint_request (1);
}


mono_thread_get_and_clear_pending_exception ()
{
  struct MonoException * D.23358;
  int D.23359;
  int D.23362;
  struct MonoException * D.23365;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  if (thread == 0B) goto <D.23356>; else goto <D.23357>;
  <D.23356>:
  D.23358 = 0B;
  return D.23358;
  <D.23357>:
  D.23359 = thread->interruption_requested;
  if (D.23359 != 0) goto <D.23360>; else goto <D.23361>;
  <D.23360>:
  D.23362 = is_running_protected_wrapper ();
  if (D.23362 == 0) goto <D.23363>; else goto <D.23364>;
  <D.23363>:
  D.23358 = mono_thread_execute_interruption (thread);
  return D.23358;
  <D.23364>:
  <D.23361>:
  D.23365 = thread->pending_exception;
  if (D.23365 != 0B) goto <D.23366>; else goto <D.23367>;
  <D.23366>:
  {
    struct MonoException * exc;

    exc = thread->pending_exception;
    thread->pending_exception = 0B;
    D.23358 = exc;
    return D.23358;
  }
  <D.23367>:
  D.23358 = 0B;
  return D.23358;
}


mono_set_pending_exception (struct MonoException * exc)
{
  struct MonoException * * D.23371;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  if (thread == 0B) goto <D.23369>; else goto <D.23370>;
  <D.23369>:
  return;
  <D.23370>:
  D.23371 = &thread->pending_exception;
  mono_gc_wbarrier_set_field (thread, D.23371, exc);
  mono_thread_request_interruption (0);
}


mono_thread_interruption_request_flag ()
{
  gint32 * D.23373;

  D.23373 = &thread_interruption_requested;
  return D.23373;
}


mono_thread_init_apartment_state ()
{

}


mono_thread_cleanup_apartment_state ()
{

}


mono_thread_set_state (struct MonoInternalThread * thread, MonoThreadState state)
{
  unsigned int D.23375;
  unsigned int D.23376;

  lock_thread (thread);
  D.23375 = thread->state;
  D.23376 = D.23375 | state;
  thread->state = D.23376;
  unlock_thread (thread);
}


mono_thread_clr_state (struct MonoInternalThread * thread, MonoThreadState state)
{
  unsigned int D.23377;
  unsigned int D.23378;
  unsigned int D.23379;

  lock_thread (thread);
  D.23377 = thread->state;
  D.23378 = ~state;
  D.23379 = D.23377 & D.23378;
  thread->state = D.23379;
  unlock_thread (thread);
}


mono_thread_test_state (struct MonoInternalThread * thread, MonoThreadState test)
{
  unsigned int D.23380;
  unsigned int D.23381;
  gboolean D.23384;
  gboolean ret;

  ret = 0;
  lock_thread (thread);
  D.23380 = thread->state;
  D.23381 = D.23380 & test;
  if (D.23381 != 0) goto <D.23382>; else goto <D.23383>;
  <D.23382>:
  ret = 1;
  <D.23383>:
  unlock_thread (thread);
  D.23384 = ret;
  return D.23384;
}


mono_thread_get_execution_context ()
{
  struct MonoObject * D.23386;
  struct MonoObject * * D.23387;

  D.23387 = get_execution_context_addr ();
  D.23386 = *D.23387;
  return D.23386;
}


get_execution_context_addr ()
{
  struct MonoClass * D.23391;
  _Bool D.23392;
  long int D.23393;
  long int D.23394;
  struct MonoClass * D.23397;
  struct MonoVTable * D.23398;
  _Bool D.23399;
  long int D.23400;
  long int D.23401;
  union mono_mutex_t * D.23404;
  _Bool D.23407;
  long int D.23408;
  long int D.23409;
  struct GHashTable * D.23412;
  void * D.23413;
  long int D.23414;
  _Bool D.23417;
  long int D.23418;
  long int D.23419;
  _Bool D.23422;
  long int D.23423;
  long int D.23424;
  struct MonoObject * * D.23427;
  struct MonoDomain * domain;
  guint32 offset;

  domain = mono_domain_get ();
  offset = domain->execution_context_field_offset;
  if (offset == 0) goto <D.23389>; else goto <D.23390>;
  <D.23389>:
  {
    struct MonoClassField * field;

    D.23391 = mono_defaults.thread_class;
    field = mono_class_get_field_from_name (D.23391, "_ec");
    D.23392 = field == 0B;
    D.23393 = (long int) D.23392;
    D.23394 = __builtin_expect (D.23393, 0);
    if (D.23394 != 0) goto <D.23395>; else goto <D.23396>;
    <D.23395>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4501, "field");
    <D.23396>:
    D.23397 = mono_defaults.appdomain_class;
    D.23398 = mono_class_try_get_vtable (domain, D.23397);
    D.23399 = D.23398 == 0B;
    D.23400 = (long int) D.23399;
    D.23401 = __builtin_expect (D.23400, 0);
    if (D.23401 != 0) goto <D.23402>; else goto <D.23403>;
    <D.23402>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4503, "mono_class_try_get_vtable (domain, mono_defaults.appdomain_class)");
    <D.23403>:
    {
      int ret;

      D.23404 = &domain->lock.mutex;
      ret = pthread_mutex_lock (D.23404);
      if (ret != 0) goto <D.23405>; else goto <D.23406>;
      <D.23405>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
      <D.23406>:
      D.23407 = ret != 0;
      D.23408 = (long int) D.23407;
      D.23409 = __builtin_expect (D.23408, 0);
      if (D.23409 != 0) goto <D.23410>; else goto <D.23411>;
      <D.23410>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4505, "ret == 0");
      <D.23411>:
    }
    D.23412 = domain->special_static_fields;
    D.23413 = monoeg_g_hash_table_lookup (D.23412, field);
    D.23414 = (long int) D.23413;
    offset = (guint32) D.23414;
    {
      int ret;

      D.23404 = &domain->lock.mutex;
      ret = pthread_mutex_unlock (D.23404);
      if (ret != 0) goto <D.23415>; else goto <D.23416>;
      <D.23415>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.23416>:
      D.23417 = ret != 0;
      D.23418 = (long int) D.23417;
      D.23419 = __builtin_expect (D.23418, 0);
      if (D.23419 != 0) goto <D.23420>; else goto <D.23421>;
      <D.23420>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4507, "ret == 0");
      <D.23421>:
    }
    D.23422 = offset == 0;
    D.23423 = (long int) D.23422;
    D.23424 = __builtin_expect (D.23423, 0);
    if (D.23424 != 0) goto <D.23425>; else goto <D.23426>;
    <D.23425>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4508, "offset");
    <D.23426>:
    domain->execution_context_field_offset = offset;
  }
  <D.23390>:
  D.23427 = mono_get_special_static_data (offset);
  return D.23427;
}


mono_thread_set_execution_context (struct MonoObject * ec)
{
  struct MonoObject * * D.23429;

  D.23429 = get_execution_context_addr ();
  *D.23429 = ec;
}


mono_runtime_set_has_tls_get (gboolean val)
{
  has_tls_get = val;
}


mono_runtime_has_tls_get ()
{
  gboolean D.23430;

  D.23430 = has_tls_get;
  return D.23430;
}


mono_thread_kill (struct MonoInternalThread * thread, int signal)
{
  int D.23432;
  long unsigned int D.23433;
  int D.23434;

  D.23433 = thread->tid;
  D.23434 = mono_thread_get_abort_signal ();
  D.23432 = pthread_kill (D.23433, D.23434);
  return D.23432;
}


mono_thread_is_foreign (struct MonoThread * thread)
{
  struct _MonoInternalThread * D.23436;
  mono_bool D.23437;
  int D.23438;
  _Bool D.23439;
  struct MonoThreadInfo * info;

  D.23436 = thread->internal_thread;
  info = D.23436->thread_info;
  D.23438 = info->runtime_thread;
  D.23439 = D.23438 == 0;
  D.23437 = (mono_bool) D.23439;
  return D.23437;
}


