mono_thread_get_tls_key ()
{
  pthread_key_t D.19977;

  D.19977 = current_object_key;
  return D.19977;
}


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

  __asm__("movl $tls_current_object@ntpoff, %0" : "=r" offset);
  D.19979 = offset;
  return D.19979;
}


mono_thread_new_init (intptr_t tid, void * stack_start, void * func)
{
  void (*<T1310>) (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.19982>; else goto <D.19983>;
  <D.19982>:
  mono_thread_start_cb.0 = mono_thread_start_cb;
  mono_thread_start_cb.0 (tid, stack_start, func);
  <D.19983>:
}


mono_threads_set_default_stacksize (guint32 stacksize)
{
  default_stacksize = stacksize;
}


mono_threads_get_default_stacksize ()
{
  uint32_t D.19984;

  D.19984 = default_stacksize;
  return D.19984;
}


mono_thread_create_internal (struct MonoDomain * domain, void * func, void * arg, gboolean threadpool_thread, gboolean no_detach, guint32 stack_size)
{
  struct _MonoInternalThread * * D.19986;
  guint32 (*<T315b>) (void *) func.1;
  struct MonoInternalThread * D.19990;
  const char * D.19991;
  struct MonoClass * D.19994;
  struct MonoClassField * D.19995;
  unsigned int D.19996;
  sizetype D.19997;
  sizetype D.19998;
  struct MonoClassField * D.19999;
  int D.20000;
  _Bool D.20001;
  long int D.20002;
  long int D.20003;
  struct MonoThread * thread;
  struct MonoInternalThread * internal;
  struct StartInfo * start_info;
  gboolean res;

  thread = create_thread_object (domain);
  internal = create_internal_thread ();
  D.19986 = &thread->internal_thread;
  mono_gc_wbarrier_set_field (thread, D.19986, internal);
  start_info = monoeg_malloc0 (16);
  func.1 = (guint32 (*<T315b>) (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.19988>; else goto <D.19989>;
  <D.19988>:
  D.19990 = 0B;
  return D.19990;
  <D.19989>:
  D.19991 = mono_check_corlib_version ();
  if (D.19991 == 0B) goto <D.19992>; else goto <D.19993>;
  <D.19992>:
  D.19994 = mono_defaults.internal_thread_class;
  D.19995 = D.19994->fields;
  D.19994 = mono_defaults.internal_thread_class;
  D.19996 = D.19994->field.count;
  D.19997 = D.19996 + 268435455;
  D.19998 = D.19997 * 16;
  D.19999 = D.19995 + D.19998;
  D.20000 = D.19999->offset;
  D.20001 = D.20000 != 172;
  D.20002 = (long int) D.20001;
  D.20003 = __builtin_expect (D.20002, 0);
  if (D.20003 != 0) goto <D.20004>; else goto <D.20005>;
  <D.20004>:
  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.20005>:
  <D.19993>:
  D.19990 = internal;
  return D.19990;
}


create_thread_object (struct MonoDomain * domain)
{
  struct MonoClass * D.20007;
  struct MonoThread * D.20008;
  struct MonoVTable * vt;

  D.20007 = mono_defaults.thread_class;
  vt = mono_class_vtable (domain, D.20007);
  D.20008 = mono_gc_alloc_mature (vt);
  return D.20008;
}


create_internal_thread ()
{
  struct MonoClass * D.20010;
  struct MonoDomain * D.20011;
  void * D.20012;
  struct CRITICAL_SECTION * D.20013;
  unsigned int D.20014;
  int D.20015;
  int D.20016;
  void * * D.20019;
  struct MonoInternalThread * D.20020;
  struct MonoInternalThread * thread;
  struct MonoVTable * vt;

  D.20010 = mono_defaults.internal_thread_class;
  D.20011 = mono_get_root_domain ();
  vt = mono_class_vtable (D.20011, D.20010);
  thread = mono_gc_alloc_mature (vt);
  D.20012 = monoeg_malloc0 (28);
  thread->synch_cs = D.20012;
  D.20013 = thread->synch_cs;
  InitializeCriticalSection (D.20013);
  thread->apartment_state = 2;
  D.20014 = get_next_managed_thread_id ();
  D.20015 = (int) D.20014;
  thread->managed_id = D.20015;
  D.20016 = mono_gc_is_moving ();
  if (D.20016 != 0) goto <D.20017>; else goto <D.20018>;
  <D.20017>:
  thread->thread_pinning_ref = thread;
  D.20019 = &thread->thread_pinning_ref;
  mono_gc_register_root (D.20019, 4, 0B);
  <D.20018>:
  D.20020 = thread;
  return D.20020;
}


get_next_managed_thread_id ()
{
  guint32 D.20022;
  int D.20023;

  D.20023 = InterlockedIncrement (&managed_thread_id_counter);
  D.20022 = (guint32) D.20023;
  return D.20022;
}


InterlockedIncrement (volatile gint32 * val)
{
  gint32 D.20025;
  unsigned int D.20026;

  D.20026 = __sync_add_and_fetch_4 (val, 1);
  D.20025 = (gint32) D.20026;
  return D.20025;
}


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.20030;
  long int D.20031;
  long int D.20032;
  int shutting_down.2;
  _Bool D.20040;
  long int D.20041;
  long int D.20042;
  gboolean D.20045;
  struct MonoGHashTable * thread_start_args.3;
  int D.20049;
  struct MonoGHashTable * thread_start_args.4;
  void * D.20053;
  struct MonoGHashTable * threads_starting_up.5;
  int D.20057;
  struct MonoGHashTable * threads_starting_up.6;
  _Bool D.20063;
  long int D.20064;
  long int D.20065;
  void * D.20068;
  void * D.20069;
  _Bool D.20074;
  long int D.20075;
  long int D.20076;
  _Bool D.20081;
  long int D.20082;
  long int D.20083;
  unsigned int D.20086;
  guint32 iftmp.7;
  int D.20090;
  _Bool D.20100;
  long int D.20101;
  long int D.20102;
  _Bool D.20107;
  long int D.20108;
  long int D.20109;
  struct MonoException * D.20114;
  unsigned int D.20116;
  long unsigned int tid.8;
  long long unsigned int D.20118;
  unsigned char D.20119;
  int D.20122;
  void * D.20125;
  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.20028>; else goto <D.20029>;
        <D.20028>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.20029>:
        D.20030 = ret != 0;
        D.20031 = (long int) D.20030;
        D.20032 = __builtin_expect (D.20031, 0);
        if (D.20032 != 0) goto <D.20033>; else goto <D.20034>;
        <D.20033>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 705, "ret == 0");
        <D.20034>:
      }
      shutting_down.2 = shutting_down;
      if (shutting_down.2 != 0) goto <D.20036>; else goto <D.20037>;
      <D.20036>:
      monoeg_g_free (start_info);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.20038>; else goto <D.20039>;
        <D.20038>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.20039>:
        D.20040 = ret != 0;
        D.20041 = (long int) D.20040;
        D.20042 = __builtin_expect (D.20041, 0);
        if (D.20042 != 0) goto <D.20043>; else goto <D.20044>;
        <D.20043>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 708, "ret == 0");
        <D.20044>:
      }
      D.20045 = 0;
      return D.20045;
      <D.20037>:
      thread_start_args.3 = thread_start_args;
      if (thread_start_args.3 == 0B) goto <D.20047>; else goto <D.20048>;
      <D.20047>:
      D.20049 = mono_gc_is_moving ();
      if (D.20049 == 0) goto <D.20050>; else goto <D.20051>;
      <D.20050>:
      mono_gc_register_root (&thread_start_args, 4, 0B);
      <D.20051>:
      thread_start_args.4 = mono_g_hash_table_new (0B, 0B);
      thread_start_args = thread_start_args.4;
      <D.20048>:
      D.20053 = start_info->start_arg;
      thread_start_args.3 = thread_start_args;
      mono_g_hash_table_insert (thread_start_args.3, thread, D.20053);
      threads_starting_up.5 = threads_starting_up;
      if (threads_starting_up.5 == 0B) goto <D.20055>; else goto <D.20056>;
      <D.20055>:
      D.20057 = mono_gc_is_moving ();
      if (D.20057 == 0) goto <D.20058>; else goto <D.20059>;
      <D.20058>:
      mono_gc_register_root (&threads_starting_up, 4, 0B);
      <D.20059>:
      threads_starting_up.6 = mono_g_hash_table_new_type (0B, 0B, 3);
      threads_starting_up = threads_starting_up.6;
      <D.20056>:
      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.20061>; else goto <D.20062>;
        <D.20061>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.20062>:
        D.20063 = ret != 0;
        D.20064 = (long int) D.20063;
        D.20065 = __builtin_expect (D.20064, 0);
        if (D.20065 != 0) goto <D.20066>; else goto <D.20067>;
        <D.20066>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 727, "ret == 0");
        <D.20067>:
      }
      D.20068 = CreateSemaphore (0B, 0, 2147483647, 0B);
      internal->start_notify = D.20068;
      D.20069 = internal->start_notify;
      if (D.20069 == 0B) goto <D.20070>; else goto <D.20071>;
      <D.20070>:
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.20072>; else goto <D.20073>;
        <D.20072>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.20073>:
        D.20074 = ret != 0;
        D.20075 = (long int) D.20074;
        D.20076 = __builtin_expect (D.20075, 0);
        if (D.20076 != 0) goto <D.20077>; else goto <D.20078>;
        <D.20077>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 731, "ret == 0");
        <D.20078>:
      }
      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.20079>; else goto <D.20080>;
        <D.20079>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.20080>:
        D.20081 = ret != 0;
        D.20082 = (long int) D.20081;
        D.20083 = __builtin_expect (D.20082, 0);
        if (D.20083 != 0) goto <D.20084>; else goto <D.20085>;
        <D.20084>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 733, "ret == 0");
        <D.20085>:
      }
      D.20086 = GetLastError ();
      monoeg_g_log (0B, 16, "%s: CreateSemaphore error 0x%x", &__func__, D.20086);
      monoeg_g_free (start_info);
      D.20045 = 0;
      return D.20045;
      <D.20071>:
      if (stack_size == 0) goto <D.20087>; else goto <D.20088>;
      <D.20087>:
      D.20090 = internal->stack_size;
      if (D.20090 != 0) goto <D.20091>; else goto <D.20092>;
      <D.20091>:
      D.20090 = internal->stack_size;
      iftmp.7 = (guint32) D.20090;
      goto <D.20093>;
      <D.20092>:
      iftmp.7 = default_stacksize;
      <D.20093>:
      stack_size = iftmp.7;
      <D.20088>:
      create_flags = 4;
      if (no_detach != 0) goto <D.20094>; else goto <D.20095>;
      <D.20094>:
      create_flags = create_flags | 268435456;
      <D.20095>:
      thread_handle = mono_threads_create_thread (start_wrapper, start_info, stack_size, create_flags, &tid);
      if (thread_handle == 0B) goto <D.20096>; else goto <D.20097>;
      <D.20096>:
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.20098>; else goto <D.20099>;
        <D.20098>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.20099>:
        D.20100 = ret != 0;
        D.20101 = (long int) D.20100;
        D.20102 = __builtin_expect (D.20101, 0);
        if (D.20102 != 0) goto <D.20103>; else goto <D.20104>;
        <D.20103>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 754, "ret == 0");
        <D.20104>:
      }
      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.20105>; else goto <D.20106>;
        <D.20105>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.20106>:
        D.20107 = ret != 0;
        D.20108 = (long int) D.20107;
        D.20109 = __builtin_expect (D.20108, 0);
        if (D.20109 != 0) goto <D.20110>; else goto <D.20111>;
        <D.20110>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 756, "ret == 0");
        <D.20111>:
      }
      monoeg_g_free (start_info);
      if (throw_on_failure != 0) goto <D.20112>; else goto <D.20113>;
      <D.20112>:
      D.20114 = mono_get_exception_execution_engine ("Couldn\'t create thread");
      mono_raise_exception (D.20114);
      goto <D.20115>;
      <D.20113>:
      D.20116 = GetLastError ();
      monoeg_g_log (0B, 16, "%s: CreateThread error 0x%x", &__func__, D.20116);
      <D.20115>:
      D.20045 = 0;
      return D.20045;
      <D.20097>:
      internal->handle = thread_handle;
      tid.8 = tid;
      D.20118 = (long long unsigned int) tid.8;
      internal->tid = D.20118;
      D.20119 = (unsigned char) threadpool_thread;
      internal->threadpool_thread = D.20119;
      if (threadpool_thread != 0) goto <D.20120>; else goto <D.20121>;
      <D.20120>:
      mono_thread_set_state (internal, 4);
      <D.20121>:
      D.20122 = handle_store (thread, 0);
      if (D.20122 == 0) goto <D.20123>; else goto <D.20124>;
      <D.20123>:
      D.20045 = 0;
      return D.20045;
      <D.20124>:
      D.20125 = internal->handle;
      ResumeThread (D.20125);
      D.20069 = internal->start_notify;
      if (D.20069 != 0B) goto <D.20126>; else goto <D.20127>;
      <D.20126>:
      D.20069 = internal->start_notify;
      WaitForSingleObjectEx (D.20069, 4294967295, 0);
      D.20069 = internal->start_notify;
      CloseHandle (D.20069);
      internal->start_notify = 0B;
      <D.20127>:
      D.20045 = 1;
      return D.20045;
    }
  finally
    {
      tid = {CLOBBER};
    }
}


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

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


start_wrapper_internal (void * data)
{
  struct MonoThread * D.20132;
  struct MonoVTable * D.20133;
  _Bool D.20134;
  long int D.20135;
  long int D.20136;
  long long unsigned int D.20139;
  unsigned int tid.9;
  unsigned int current_object_key.10;
  int D.20142;
  guint32 D.20145;
  unsigned int tid.11;
  int tid.12;
  unsigned char D.20148;
  void * D.20151;
  _Bool D.20156;
  long int D.20157;
  long int D.20158;
  struct MonoGHashTable * thread_start_args.13;
  _Bool D.20164;
  long int D.20165;
  long int D.20166;
  struct MonoObject * D.20169;
  _Bool D.20173;
  long int D.20174;
  long int D.20175;
  struct MonoThreadInfo * info;
  struct StartInfo * start_info;
  guint32 (*<T315b>) (void *) start_func;
  void * start_arg;
  gsize tid;
  struct MonoInternalThread * internal;
  struct MonoObject * start_delegate;
  struct MonoDomain * domain;

  try
    {
      start_info = data;
      D.20132 = start_info->obj;
      internal = D.20132->internal_thread;
      start_delegate = start_info->delegate;
      D.20132 = start_info->obj;
      D.20133 = D.20132->obj.vtable;
      domain = D.20133->domain;
      info = mono_thread_info_current ();
      D.20134 = info == 0B;
      D.20135 = (long int) D.20134;
      D.20136 = __builtin_expect (D.20135, 0);
      if (D.20136 != 0) goto <D.20137>; else goto <D.20138>;
      <D.20137>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 570, "info");
      <D.20138>:
      internal->thread_info = info;
      D.20139 = internal->tid;
      tid.9 = (unsigned int) D.20139;
      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.20142 = mono_domain_set (domain, 0);
      if (D.20142 == 0) goto <D.20143>; else goto <D.20144>;
      <D.20143>:
      mono_thread_pop_appdomain_ref ();
      D.20145 = 0;
      return D.20145;
      <D.20144>:
      start_func = start_info->func;
      start_arg = start_info->start_arg;
      thread_adjust_static_data (internal);
      D.20132 = start_info->obj;
      init_root_domain_thread (internal, D.20132);
      tid.11 = tid;
      tid.12 = (int) tid.11;
      mono_thread_new_init (tid.12, &tid, start_func);
      internal->stack_ptr = &tid;
      D.20148 = internal->apartment_state;
      if (D.20148 == 2) goto <D.20149>; else goto <D.20150>;
      <D.20149>:
      internal->apartment_state = 1;
      <D.20150>:
      mono_thread_init_apartment_state ();
      D.20151 = internal->start_notify;
      if (D.20151 != 0B) goto <D.20152>; else goto <D.20153>;
      <D.20152>:
      D.20151 = internal->start_notify;
      ReleaseSemaphore (D.20151, 1, 0B);
      <D.20153>:
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.20154>; else goto <D.20155>;
        <D.20154>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.20155>:
        D.20156 = ret != 0;
        D.20157 = (long int) D.20156;
        D.20158 = __builtin_expect (D.20157, 0);
        if (D.20158 != 0) goto <D.20159>; else goto <D.20160>;
        <D.20159>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 623, "ret == 0");
        <D.20160>:
      }
      D.20132 = start_info->obj;
      thread_start_args.13 = thread_start_args;
      mono_g_hash_table_remove (thread_start_args.13, D.20132);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.20162>; else goto <D.20163>;
        <D.20162>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.20163>:
        D.20164 = ret != 0;
        D.20165 = (long int) D.20164;
        D.20166 = __builtin_expect (D.20165, 0);
        if (D.20166 != 0) goto <D.20167>; else goto <D.20168>;
        <D.20167>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 625, "ret == 0");
        <D.20168>:
      }
      D.20132 = start_info->obj;
      D.20169 = D.20132->ec_to_set;
      mono_thread_set_execution_context (D.20169);
      D.20132 = start_info->obj;
      D.20132->ec_to_set = 0B;
      monoeg_g_free (start_info);
      tid.11 = tid;
      mono_profiler_thread_start (tid.11);
      if (start_func != 0B) goto <D.20170>; else goto <D.20171>;
      <D.20170>:
      start_func (start_arg);
      goto <D.20172>;
      <D.20171>:
      {
        void * args[1];

        try
          {
            D.20173 = start_delegate == 0B;
            D.20174 = (long int) D.20173;
            D.20175 = __builtin_expect (D.20174, 0);
            if (D.20175 != 0) goto <D.20176>; else goto <D.20177>;
            <D.20176>:
            monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 646, "start_delegate != NULL");
            <D.20177>:
            args[0] = start_arg;
            mono_runtime_delegate_invoke (start_delegate, &args, 0B);
          }
        finally
          {
            args = {CLOBBER};
          }
      }
      <D.20172>:
      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.20145 = 0;
      return D.20145;
    }
  finally
    {
      tid = {CLOBBER};
    }
}


thread_adjust_static_data (struct MonoInternalThread * thread)
{
  _Bool D.20182;
  long int D.20183;
  long int D.20184;
  int D.20189;
  int D.20191;
  int D.20192;
  int D.20193;
  int D.20194;
  void * * * D.20195;
  _Bool D.20198;
  long int D.20199;
  long int D.20200;
  guint32 offset;

  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.20180>; else goto <D.20181>;
    <D.20180>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.20181>:
    D.20182 = ret != 0;
    D.20183 = (long int) D.20182;
    D.20184 = __builtin_expect (D.20183, 0);
    if (D.20184 != 0) goto <D.20185>; else goto <D.20186>;
    <D.20185>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3819, "ret == 0");
    <D.20186>:
  }
  D.20189 = thread_static_info.offset;
  if (D.20189 != 0) goto <D.20187>; else goto <D.20190>;
  <D.20190>:
  D.20191 = thread_static_info.idx;
  if (D.20191 > 0) goto <D.20187>; else goto <D.20188>;
  <D.20187>:
  D.20189 = thread_static_info.offset;
  D.20191 = thread_static_info.idx;
  D.20192 = D.20191 + 1;
  D.20193 = D.20192 << 24;
  D.20194 = D.20189 | D.20193;
  offset = (guint32) D.20194;
  D.20195 = &thread->static_data;
  mono_alloc_static_data (D.20195, offset, 1);
  <D.20188>:
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.20196>; else goto <D.20197>;
    <D.20196>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.20197>:
    D.20198 = ret != 0;
    D.20199 = (long int) D.20198;
    D.20200 = __builtin_expect (D.20199, 0);
    if (D.20200 != 0) goto <D.20201>; else goto <D.20202>;
    <D.20201>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3825, "ret == 0");
    <D.20202>:
  }
}


mono_alloc_static_data (void * * * static_data_ptr, guint32 offset, gboolean threadlocal)
{
  unsigned int D.20203;
  int D.20206;
  void * tls_desc.14;
  void * tls_desc.15;
  void * iftmp.16;
  int D.20217;
  unsigned int D.20218;
  unsigned int i.17;
  unsigned int D.20220;
  void * * D.20221;
  void * D.20222;
  int D.20227;
  int D.20230;
  unsigned int D.20231;
  void * D.20232;
  unsigned int D.20233;
  void * D.20234;
  unsigned int i.18;
  guint idx;
  int i;
  void * * static_data;

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

    D.20206 = mono_gc_user_markers_supported ();
    if (D.20206 != 0) goto <D.20207>; else goto <D.20208>;
    <D.20207>:
    tls_desc.14 = tls_desc;
    if (tls_desc.14 == 0B) goto <D.20210>; else goto <D.20211>;
    <D.20210>:
    tls_desc.15 = mono_gc_make_root_descr_user (mark_tls_slots);
    tls_desc = tls_desc.15;
    <D.20211>:
    <D.20208>:
    if (threadlocal != 0) goto <D.20214>; else goto <D.20215>;
    <D.20214>:
    iftmp.16 = tls_desc;
    goto <D.20216>;
    <D.20215>:
    iftmp.16 = 0B;
    <D.20216>:
    D.20217 = 1024;
    D.20218 = (unsigned int) D.20217;
    static_data = mono_gc_alloc_fixed (D.20218, iftmp.16);
    *static_data_ptr = static_data;
    *static_data = static_data;
  }
  <D.20205>:
  i = 1;
  goto <D.19653>;
  <D.19652>:
  i.17 = (unsigned int) i;
  D.20220 = i.17 * 4;
  D.20221 = static_data + D.20220;
  D.20222 = *D.20221;
  if (D.20222 != 0B) goto <D.20223>; else goto <D.20224>;
  <D.20223>:
  // predicted unlikely by continue predictor.
  goto <D.19651>;
  <D.20224>:
  D.20227 = mono_gc_user_markers_supported ();
  if (D.20227 != 0) goto <D.20228>; else goto <D.20225>;
  <D.20228>:
  if (threadlocal != 0) goto <D.20229>; else goto <D.20225>;
  <D.20229>:
  i.17 = (unsigned int) i;
  D.20220 = i.17 * 4;
  D.20221 = static_data + D.20220;
  D.20230 = static_data_size[i];
  D.20231 = (unsigned int) D.20230;
  D.20232 = monoeg_malloc0 (D.20231);
  *D.20221 = D.20232;
  goto <D.20226>;
  <D.20225>:
  i.17 = (unsigned int) i;
  D.20220 = i.17 * 4;
  D.20221 = static_data + D.20220;
  D.20230 = static_data_size[i];
  D.20233 = (unsigned int) D.20230;
  D.20234 = mono_gc_alloc_fixed (D.20233, 0B);
  *D.20221 = D.20234;
  <D.20226>:
  <D.19651>:
  i = i + 1;
  <D.19653>:
  i.18 = (unsigned int) i;
  if (i.18 <= idx) goto <D.19652>; else goto <D.19654>;
  <D.19654>:
}


mark_tls_slots (void * addr, void (*MonoGCMarkFunc) (void * *) mark_func)
{
  unsigned int i.19;
  unsigned int D.20237;
  void * * D.20238;
  void * D.20239;
  int D.20242;
  unsigned int D.20243;
  unsigned int D.20244;
  unsigned int D.20245;
  uintptr_t * D.20246;
  unsigned int j.20;
  unsigned int D.20248;
  uintptr_t * D.20249;
  unsigned int D.20250;
  void * D.20253;
  int i;
  void * * static_data;

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

    i.19 = (unsigned int) i;
    D.20237 = i.19 * 4;
    D.20238 = static_data + D.20237;
    D.20239 = *D.20238;
    if (D.20239 == 0B) goto <D.20240>; else goto <D.20241>;
    <D.20240>:
    // predicted unlikely by continue predictor.
    goto <D.19630>;
    <D.20241>:
    D.20242 = static_data_size[i];
    D.20243 = (unsigned int) D.20242;
    D.20244 = D.20243 / 128;
    D.20245 = D.20244 + 1;
    numwords = (int) D.20245;
    i.19 = (unsigned int) i;
    D.20237 = i.19 * 4;
    D.20238 = static_data + D.20237;
    ptr = *D.20238;
    j = 0;
    goto <D.19637>;
    <D.19636>:
    {
      uintptr_t bmap;
      void * * p;

      D.20246 = static_reference_bitmaps[i];
      j.20 = (unsigned int) j;
      D.20248 = j.20 * 4;
      D.20249 = D.20246 + D.20248;
      bmap = *D.20249;
      p = ptr;
      goto <D.19634>;
      <D.19633>:
      D.20250 = bmap & 1;
      if (D.20250 != 0) goto <D.20251>; else goto <D.20252>;
      <D.20251>:
      D.20253 = *p;
      if (D.20253 != 0B) goto <D.20254>; else goto <D.20255>;
      <D.20254>:
      mark_func (p);
      <D.20255>:
      <D.20252>:
      p = p + 4;
      bmap = bmap >> 1;
      <D.19634>:
      if (bmap != 0) goto <D.19633>; else goto <D.19635>;
      <D.19635>:
    }
    j = j + 1;
    ptr = ptr + 128;
    <D.19637>:
    if (j < numwords) goto <D.19636>; else goto <D.19638>;
    <D.19638>:
  }
  <D.19630>:
  i = i + 1;
  <D.19640>:
  if (i <= 7) goto <D.19639>; else goto <D.19641>;
  <D.19641>:
}


init_root_domain_thread (struct MonoInternalThread * thread, struct MonoThread * candidate)
{
  struct MonoVTable * D.20259;
  struct MonoDomain * D.20260;
  struct MonoThread * D.20261;
  _Bool D.20262;
  long int D.20263;
  long int D.20264;
  struct MonoThread * * D.20267;
  struct MonoDomain * domain;

  domain = mono_get_root_domain ();
  if (candidate == 0B) goto <D.20256>; else goto <D.20258>;
  <D.20258>:
  D.20259 = candidate->obj.vtable;
  D.20260 = D.20259->domain;
  if (D.20260 != domain) goto <D.20256>; else goto <D.20257>;
  <D.20256>:
  candidate = new_thread_with_internal (domain, thread);
  <D.20257>:
  set_current_thread_for_domain (domain, thread, candidate);
  D.20261 = thread->root_domain_thread;
  D.20262 = D.20261 != 0B;
  D.20263 = (long int) D.20262;
  D.20264 = __builtin_expect (D.20263, 0);
  if (D.20264 != 0) goto <D.20265>; else goto <D.20266>;
  <D.20265>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 542, "!thread->root_domain_thread");
  <D.20266>:
  D.20267 = &thread->root_domain_thread;
  mono_gc_wbarrier_set_field (thread, D.20267, candidate);
}


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

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


set_current_thread_for_domain (struct MonoDomain * domain, struct MonoInternalThread * thread, struct MonoThread * current)
{
  struct MonoVTable * D.20271;
  struct MonoDomain * D.20272;
  _Bool D.20273;
  long int D.20274;
  long int D.20275;
  struct MonoThread * D.20278;
  _Bool D.20279;
  long int D.20280;
  long int D.20281;
  struct MonoThread * * current_thread_ptr;

  current_thread_ptr = get_current_thread_ptr_for_domain (domain, thread);
  D.20271 = current->obj.vtable;
  D.20272 = D.20271->domain;
  D.20273 = D.20272 != domain;
  D.20274 = (long int) D.20273;
  D.20275 = __builtin_expect (D.20274, 0);
  if (D.20275 != 0) goto <D.20276>; else goto <D.20277>;
  <D.20276>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 491, "current->obj.vtable->domain == domain");
  <D.20277>:
  D.20278 = *current_thread_ptr;
  D.20279 = D.20278 != 0B;
  D.20280 = (long int) D.20279;
  D.20281 = __builtin_expect (D.20280, 0);
  if (D.20281 != 0) goto <D.20282>; else goto <D.20283>;
  <D.20282>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 493, "!*current_thread_ptr");
  <D.20283>:
  *current_thread_ptr = current;
}


get_current_thread_ptr_for_domain (struct MonoDomain * domain, struct MonoInternalThread * thread)
{
  struct MonoClassField * current_thread_field.21;
  struct MonoClass * D.20287;
  struct MonoClassField * current_thread_field.22;
  _Bool D.20289;
  long int D.20290;
  long int D.20291;
  union mono_mutex_t * D.20294;
  _Bool D.20297;
  long int D.20298;
  long int D.20299;
  struct GHashTable * D.20302;
  void * D.20303;
  _Bool D.20306;
  long int D.20307;
  long int D.20308;
  _Bool D.20311;
  long int D.20312;
  long int D.20313;
  struct MonoThread * * D.20316;
  static struct MonoClassField * current_thread_field = 0B;
  guint32 offset;

  current_thread_field.21 = current_thread_field;
  if (current_thread_field.21 == 0B) goto <D.20285>; else goto <D.20286>;
  <D.20285>:
  D.20287 = mono_defaults.thread_class;
  current_thread_field.22 = mono_class_get_field_from_name (D.20287, "current_thread");
  current_thread_field = current_thread_field.22;
  current_thread_field.21 = current_thread_field;
  D.20289 = current_thread_field.21 == 0B;
  D.20290 = (long int) D.20289;
  D.20291 = __builtin_expect (D.20290, 0);
  if (D.20291 != 0) goto <D.20292>; else goto <D.20293>;
  <D.20292>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 474, "current_thread_field");
  <D.20293>:
  <D.20286>:
  D.20287 = mono_defaults.thread_class;
  mono_class_vtable (domain, D.20287);
  {
    int ret;

    D.20294 = &domain->lock.mutex;
    ret = pthread_mutex_lock (D.20294);
    if (ret != 0) goto <D.20295>; else goto <D.20296>;
    <D.20295>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.20296>:
    D.20297 = ret != 0;
    D.20298 = (long int) D.20297;
    D.20299 = __builtin_expect (D.20298, 0);
    if (D.20299 != 0) goto <D.20300>; else goto <D.20301>;
    <D.20300>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 478, "ret == 0");
    <D.20301>:
  }
  current_thread_field.21 = current_thread_field;
  D.20302 = domain->special_static_fields;
  D.20303 = monoeg_g_hash_table_lookup (D.20302, current_thread_field.21);
  offset = (guint32) D.20303;
  {
    int ret;

    D.20294 = &domain->lock.mutex;
    ret = pthread_mutex_unlock (D.20294);
    if (ret != 0) goto <D.20304>; else goto <D.20305>;
    <D.20304>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.20305>:
    D.20306 = ret != 0;
    D.20307 = (long int) D.20306;
    D.20308 = __builtin_expect (D.20307, 0);
    if (D.20308 != 0) goto <D.20309>; else goto <D.20310>;
    <D.20309>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 480, "ret == 0");
    <D.20310>:
  }
  D.20311 = offset == 0;
  D.20312 = (long int) D.20311;
  D.20313 = __builtin_expect (D.20312, 0);
  if (D.20313 != 0) goto <D.20314>; else goto <D.20315>;
  <D.20314>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 481, "offset");
  <D.20315>:
  D.20316 = get_thread_static_data (thread, offset);
  return D.20316;
}


get_thread_static_data (struct MonoInternalThread * thread, guint32 offset)
{
  signed int offset.23;
  _Bool D.20319;
  long int D.20320;
  long int D.20321;
  unsigned int D.20324;
  unsigned int D.20325;
  void * D.20326;
  void * * D.20327;
  unsigned int idx.24;
  unsigned int D.20329;
  void * * D.20330;
  void * D.20331;
  sizetype D.20332;
  int idx;

  offset.23 = (signed int) offset;
  D.20319 = offset.23 < 0;
  D.20320 = (long int) D.20319;
  D.20321 = __builtin_expect (D.20320, 0);
  if (D.20321 != 0) goto <D.20322>; else goto <D.20323>;
  <D.20322>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 459, "(offset & 0x80000000) == 0");
  <D.20323>:
  offset = offset & 2147483647;
  D.20324 = offset >> 24;
  D.20325 = D.20324 + 4294967295;
  idx = (int) D.20325;
  D.20327 = thread->static_data;
  idx.24 = (unsigned int) idx;
  D.20329 = idx.24 * 4;
  D.20330 = D.20327 + D.20329;
  D.20331 = *D.20330;
  D.20332 = offset & 16777215;
  D.20326 = D.20331 + D.20332;
  return D.20326;
}


thread_cleanup (struct MonoInternalThread * thread)
{
  _Bool D.20334;
  long int D.20335;
  long int D.20336;
  int D.20339;
  unsigned int D.20342;
  struct MonoArray * D.20343;
  unsigned int i.25;
  struct CRITICAL_SECTION * D.20347;
  int shutting_down.26;
  _Bool D.20352;
  long int D.20353;
  long int D.20354;
  unsigned int D.20357;
  unsigned int D.20358;
  unsigned int D.20359;
  gint32 * D.20362;
  int D.20363;
  int D.20366;
  struct MonoInternalThread * D.20369;
  void (*<T20f3>) (struct MonoInternalThread *) mono_thread_cleanup_fn.27;
  long long unsigned int D.20375;
  unsigned int D.20376;
  struct MonoInternalThread * D.20377;
  struct MonoInternalThread * D.20380;
  void * * D.20383;
  void * D.20384;
  int D.20387;
  void * * D.20390;

  D.20334 = thread == 0B;
  D.20335 = (long int) D.20334;
  D.20336 = __builtin_expect (D.20335, 0);
  if (D.20336 != 0) goto <D.20337>; else goto <D.20338>;
  <D.20337>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 368, "thread != NULL");
  <D.20338>:
  D.20339 = thread->abort_state_handle;
  if (D.20339 != 0) goto <D.20340>; else goto <D.20341>;
  <D.20340>:
  D.20339 = thread->abort_state_handle;
  D.20342 = (unsigned int) D.20339;
  mono_gchandle_free (D.20342);
  thread->abort_state_handle = 0;
  <D.20341>:
  thread->abort_exc = 0B;
  thread->current_appcontext = 0B;
  D.20343 = thread->cached_culture_info;
  if (D.20343 != 0B) goto <D.20344>; else goto <D.20345>;
  <D.20344>:
  {
    int i;

    i = 0;
    goto <D.18634>;
    <D.18633>:
    {
      struct MonoObject * * __p;

      i.25 = (unsigned int) i;
      D.20343 = thread->cached_culture_info;
      __p = mono_array_addr_with_size (D.20343, 4, i.25);
      *__p = 0B;
    }
    i = i + 1;
    <D.18634>:
    if (i <= 7) goto <D.18633>; else goto <D.18635>;
    <D.18635>:
  }
  <D.20345>:
  D.20347 = thread->synch_cs;
  if (D.20347 != 0B) goto <D.20348>; else goto <D.20349>;
  <D.20348>:
  lock_thread (thread);
  goto <D.20350>;
  <D.20349>:
  shutting_down.26 = shutting_down;
  D.20352 = shutting_down.26 == 0;
  D.20353 = (long int) D.20352;
  D.20354 = __builtin_expect (D.20353, 0);
  if (D.20354 != 0) goto <D.20355>; else goto <D.20356>;
  <D.20355>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 391, "shutting_down");
  <D.20356>:
  <D.20350>:
  D.20357 = thread->state;
  D.20358 = D.20357 | 16;
  thread->state = D.20358;
  D.20357 = thread->state;
  D.20359 = D.20357 & 4294967291;
  thread->state = D.20359;
  D.20347 = thread->synch_cs;
  if (D.20347 != 0B) goto <D.20360>; else goto <D.20361>;
  <D.20360>:
  unlock_thread (thread);
  <D.20361>:
  D.20362 = &thread->interruption_requested;
  D.20363 = InterlockedExchange (D.20362, 0);
  if (D.20363 != 0) goto <D.20364>; else goto <D.20365>;
  <D.20364>:
  InterlockedDecrement (&thread_interruption_requested);
  <D.20365>:
  D.20366 = handle_remove (thread);
  if (D.20366 == 0) goto <D.20367>; else goto <D.20368>;
  <D.20367>:
  D.20369 = mono_thread_internal_current ();
  if (D.20369 == thread) goto <D.20370>; else goto <D.20371>;
  <D.20370>:
  mono_domain_unset ();
  mono_memory_barrier ();
  <D.20371>:
  mono_thread_cleanup_fn.27 = mono_thread_cleanup_fn;
  if (mono_thread_cleanup_fn.27 != 0B) goto <D.20373>; else goto <D.20374>;
  <D.20373>:
  mono_thread_cleanup_fn.27 = mono_thread_cleanup_fn;
  mono_thread_cleanup_fn.27 (thread);
  <D.20374>:
  return;
  <D.20368>:
  mono_release_type_locks (thread);
  D.20375 = thread->tid;
  D.20376 = (unsigned int) D.20375;
  mono_profiler_thread_end (D.20376);
  D.20377 = mono_thread_internal_current ();
  if (D.20377 == thread) goto <D.20378>; else goto <D.20379>;
  <D.20378>:
  mono_domain_unset ();
  mono_memory_barrier ();
  <D.20379>:
  D.20380 = mono_thread_internal_current ();
  if (D.20380 == thread) goto <D.20381>; else goto <D.20382>;
  <D.20381>:
  mono_thread_pop_appdomain_ref ();
  <D.20382>:
  thread->cached_culture_info = 0B;
  D.20383 = thread->static_data;
  mono_free_static_data (D.20383, 1);
  thread->static_data = 0B;
  D.20384 = thread->appdomain_refs;
  ref_stack_destroy (D.20384);
  thread->appdomain_refs = 0B;
  mono_thread_cleanup_fn.27 = mono_thread_cleanup_fn;
  if (mono_thread_cleanup_fn.27 != 0B) goto <D.20385>; else goto <D.20386>;
  <D.20385>:
  mono_thread_cleanup_fn.27 = mono_thread_cleanup_fn;
  mono_thread_cleanup_fn.27 (thread);
  <D.20386>:
  D.20387 = mono_gc_is_moving ();
  if (D.20387 != 0) goto <D.20388>; else goto <D.20389>;
  <D.20388>:
  D.20390 = &thread->thread_pinning_ref;
  mono_gc_deregister_root (D.20390);
  thread->thread_pinning_ref = 0B;
  <D.20389>:
}


lock_thread (struct MonoInternalThread * thread)
{
  struct CRITICAL_SECTION * D.20392;
  _Bool D.20395;
  long int D.20396;
  long int D.20397;
  union mono_mutex_t * D.20400;
  _Bool D.20403;
  long int D.20404;
  long int D.20405;

  D.20392 = thread->synch_cs;
  if (D.20392 == 0B) goto <D.20393>; else goto <D.20394>;
  <D.20393>:
  ensure_synch_cs_set (thread);
  <D.20394>:
  D.20392 = thread->synch_cs;
  D.20395 = D.20392 == 0B;
  D.20396 = (long int) D.20395;
  D.20397 = __builtin_expect (D.20396, 0);
  if (D.20397 != 0) goto <D.20398>; else goto <D.20399>;
  <D.20398>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 351, "thread->synch_cs");
  <D.20399>:
  {
    int ret;

    D.20392 = thread->synch_cs;
    D.20400 = &D.20392->mutex;
    ret = pthread_mutex_lock (D.20400);
    if (ret != 0) goto <D.20401>; else goto <D.20402>;
    <D.20401>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.20402>:
    D.20403 = ret != 0;
    D.20404 = (long int) D.20403;
    D.20405 = __builtin_expect (D.20404, 0);
    if (D.20405 != 0) goto <D.20406>; else goto <D.20407>;
    <D.20406>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 352, "ret == 0");
    <D.20407>:
  }
}


ensure_synch_cs_set (struct MonoInternalThread * thread)
{
  struct CRITICAL_SECTION * D.20408;
  struct CRITICAL_SECTION * * D.20411;
  void * D.20412;
  struct CRITICAL_SECTION * synch_cs;

  D.20408 = thread->synch_cs;
  if (D.20408 != 0B) goto <D.20409>; else goto <D.20410>;
  <D.20409>:
  return;
  <D.20410>:
  synch_cs = monoeg_malloc0 (28);
  InitializeCriticalSection (synch_cs);
  D.20411 = &thread->synch_cs;
  D.20412 = InterlockedCompareExchangePointer (D.20411, synch_cs, 0B);
  if (D.20412 != 0B) goto <D.20413>; else goto <D.20414>;
  <D.20413>:
  DeleteCriticalSection (synch_cs);
  monoeg_g_free (synch_cs);
  <D.20414>:
}


InterlockedCompareExchangePointer (void * volatile * dest, void * exch, void * comp)
{
  void * D.20416;
  unsigned int exch.28;
  unsigned int comp.29;
  unsigned int D.20419;

  exch.28 = (unsigned int) exch;
  comp.29 = (unsigned int) comp;
  D.20419 = __sync_val_compare_and_swap_4 (dest, comp.29, exch.28);
  D.20416 = (void *) D.20419;
  return D.20416;
}


unlock_thread (struct MonoInternalThread * thread)
{
  struct CRITICAL_SECTION * D.20421;
  union mono_mutex_t * D.20422;
  _Bool D.20425;
  long int D.20426;
  long int D.20427;

  {
    int ret;

    D.20421 = thread->synch_cs;
    D.20422 = &D.20421->mutex;
    ret = pthread_mutex_unlock (D.20422);
    if (ret != 0) goto <D.20423>; else goto <D.20424>;
    <D.20423>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.20424>:
    D.20425 = ret != 0;
    D.20426 = (long int) D.20425;
    D.20427 = __builtin_expect (D.20426, 0);
    if (D.20427 != 0) goto <D.20428>; else goto <D.20429>;
    <D.20428>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 358, "ret == 0");
    <D.20429>:
  }
}


InterlockedExchange (volatile gint32 * val, gint32 new_val)
{
  unsigned int new_val.30;
  unsigned int old_val.31;
  unsigned int D.20432;
  int D.20433;
  gint32 D.20434;
  gint32 old_val;

  <D.18429>:
  old_val = *val;
  new_val.30 = (unsigned int) new_val;
  old_val.31 = (unsigned int) old_val;
  D.20432 = __sync_val_compare_and_swap_4 (val, old_val.31, new_val.30);
  D.20433 = (int) D.20432;
  if (D.20433 != old_val) goto <D.18429>; else goto <D.18430>;
  <D.18430>:
  D.20434 = old_val;
  return D.20434;
}


InterlockedDecrement (volatile gint32 * val)
{
  gint32 D.20436;
  unsigned int D.20437;

  D.20437 = __sync_sub_and_fetch_4 (val, 1);
  D.20436 = (gint32) D.20437;
  return D.20436;
}


handle_remove (struct MonoInternalThread * thread)
{
  long long unsigned int D.20439;
  _Bool D.20442;
  long int D.20443;
  long int D.20444;
  struct MonoGHashTable * threads.32;
  const void * tid.33;
  void * D.20451;
  _Bool D.20458;
  long int D.20459;
  long int D.20460;
  gboolean D.20463;
  gboolean ret;
  gsize tid;

  D.20439 = thread->tid;
  tid = (gsize) D.20439;
  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.20440>; else goto <D.20441>;
    <D.20440>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.20441>:
    D.20442 = ret != 0;
    D.20443 = (long int) D.20442;
    D.20444 = __builtin_expect (D.20443, 0);
    if (D.20444 != 0) goto <D.20445>; else goto <D.20446>;
    <D.20445>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 289, "ret == 0");
    <D.20446>:
  }
  threads.32 = threads;
  if (threads.32 != 0B) goto <D.20448>; else goto <D.20449>;
  <D.20448>:
  tid.33 = (const void *) tid;
  threads.32 = threads;
  D.20451 = mono_g_hash_table_lookup (threads.32, tid.33);
  if (D.20451 == thread) goto <D.20452>; else goto <D.20453>;
  <D.20452>:
  tid.33 = (const void *) tid;
  threads.32 = threads;
  mono_g_hash_table_remove (threads.32, tid.33);
  ret = 1;
  goto <D.20454>;
  <D.20453>:
  ret = 0;
  <D.20454>:
  goto <D.20455>;
  <D.20449>:
  ret = 0;
  <D.20455>:
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.20456>; else goto <D.20457>;
    <D.20456>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.20457>:
    D.20458 = ret != 0;
    D.20459 = (long int) D.20458;
    D.20460 = __builtin_expect (D.20459, 0);
    if (D.20460 != 0) goto <D.20461>; else goto <D.20462>;
    <D.20461>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 308, "ret == 0");
    <D.20462>:
  }
  D.20463 = ret;
  return D.20463;
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


mono_free_static_data (void * * static_data, gboolean threadlocal)
{
  unsigned int i.34;
  unsigned int D.20466;
  void * * D.20467;
  int D.20472;
  int i;

  i = 1;
  goto <D.19663>;
  <D.19662>:
  {
    void * p;

    i.34 = (unsigned int) i;
    D.20466 = i.34 * 4;
    D.20467 = static_data + D.20466;
    p = *D.20467;
    if (p == 0B) goto <D.20468>; else goto <D.20469>;
    <D.20468>:
    // predicted unlikely by continue predictor.
    goto <D.19661>;
    <D.20469>:
    i.34 = (unsigned int) i;
    D.20466 = i.34 * 4;
    D.20467 = static_data + D.20466;
    *D.20467 = 0B;
    mono_memory_write_barrier ();
    D.20472 = mono_gc_user_markers_supported ();
    if (D.20472 != 0) goto <D.20473>; else goto <D.20470>;
    <D.20473>:
    if (threadlocal != 0) goto <D.20474>; else goto <D.20470>;
    <D.20474>:
    monoeg_g_free (p);
    goto <D.20471>;
    <D.20470>:
    mono_gc_free_fixed (p);
    <D.20471>:
  }
  <D.19661>:
  i = i + 1;
  <D.19663>:
  if (i <= 7) goto <D.19662>; else goto <D.19664>;
  <D.19664>:
  mono_gc_free_fixed (static_data);
}


mono_memory_write_barrier ()
{
  mono_memory_barrier ();
}


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

  rs = ptr;
  if (rs != 0B) goto <D.20475>; else goto <D.20476>;
  <D.20475>:
  D.20477 = rs->refs;
  monoeg_g_free (D.20477);
  monoeg_g_free (rs);
  <D.20476>:
}


mono_native_tls_set_value (pthread_key_t key, void * value)
{
  int D.20478;
  int D.20479;
  _Bool D.20480;

  D.20479 = pthread_setspecific (key, value);
  D.20480 = D.20479 == 0;
  D.20478 = (int) D.20480;
  return D.20478;
}


handle_store (struct MonoThread * thread, gboolean force_attach)
{
  _Bool D.20484;
  long int D.20485;
  long int D.20486;
  struct MonoGHashTable * threads_starting_up.35;
  int shutting_down.36;
  _Bool D.20499;
  long int D.20500;
  long int D.20501;
  gboolean D.20504;
  struct MonoGHashTable * threads.37;
  int D.20508;
  struct MonoGHashTable * threads.38;
  struct _MonoInternalThread * D.20512;
  _Bool D.20513;
  long int D.20514;
  long int D.20515;
  long long unsigned int D.20518;
  unsigned int D.20519;
  void * D.20520;
  _Bool D.20523;
  long int D.20524;
  long int D.20525;

  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.20482>; else goto <D.20483>;
    <D.20482>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.20483>:
    D.20484 = ret != 0;
    D.20485 = (long int) D.20484;
    D.20486 = __builtin_expect (D.20485, 0);
    if (D.20486 != 0) goto <D.20487>; else goto <D.20488>;
    <D.20487>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 253, "ret == 0");
    <D.20488>:
  }
  threads_starting_up.35 = threads_starting_up;
  if (threads_starting_up.35 != 0B) goto <D.20490>; else goto <D.20491>;
  <D.20490>:
  threads_starting_up.35 = threads_starting_up;
  mono_g_hash_table_remove (threads_starting_up.35, thread);
  <D.20491>:
  shutting_down.36 = shutting_down;
  if (shutting_down.36 != 0) goto <D.20493>; else goto <D.20494>;
  <D.20493>:
  if (force_attach == 0) goto <D.20495>; else goto <D.20496>;
  <D.20495>:
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.20497>; else goto <D.20498>;
    <D.20497>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.20498>:
    D.20499 = ret != 0;
    D.20500 = (long int) D.20499;
    D.20501 = __builtin_expect (D.20500, 0);
    if (D.20501 != 0) goto <D.20502>; else goto <D.20503>;
    <D.20502>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 261, "ret == 0");
    <D.20503>:
  }
  D.20504 = 0;
  return D.20504;
  <D.20496>:
  <D.20494>:
  threads.37 = threads;
  if (threads.37 == 0B) goto <D.20506>; else goto <D.20507>;
  <D.20506>:
  D.20508 = mono_gc_is_moving ();
  if (D.20508 == 0) goto <D.20509>; else goto <D.20510>;
  <D.20509>:
  mono_gc_register_root (&threads, 4, 0B);
  <D.20510>:
  threads.38 = mono_g_hash_table_new_type (0B, 0B, 2);
  threads = threads.38;
  <D.20507>:
  D.20512 = thread->internal_thread;
  D.20513 = D.20512 == 0B;
  D.20514 = (long int) D.20513;
  D.20515 = __builtin_expect (D.20514, 0);
  if (D.20515 != 0) goto <D.20516>; else goto <D.20517>;
  <D.20516>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 273, "thread->internal_thread");
  <D.20517>:
  D.20512 = thread->internal_thread;
  D.20512 = thread->internal_thread;
  D.20518 = D.20512->tid;
  D.20519 = (unsigned int) D.20518;
  D.20520 = (void *) D.20519;
  threads.37 = threads;
  mono_g_hash_table_insert (threads.37, D.20520, D.20512);
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.20521>; else goto <D.20522>;
    <D.20521>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.20522>:
    D.20523 = ret != 0;
    D.20524 = (long int) D.20523;
    D.20525 = __builtin_expect (D.20524, 0);
    if (D.20525 != 0) goto <D.20526>; else goto <D.20527>;
    <D.20526>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 277, "ret == 0");
    <D.20527>:
  }
  D.20504 = 1;
  return D.20504;
}


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.20529;
  guint8 * D.20530;
  int iftmp.39;
  unsigned int D.20538;
  guint8 * D.20539;
  _Bool D.20540;
  long int D.20541;
  long int D.20542;
  int D.20545;
  int D.20546;
  int D.20547;
  int D.20548;
  guint8 * D.20549;
  union pthread_attr_t attr;
  guint8 * current;

  try
    {
      current = &attr;
      *staddr = 0B;
      *stsize = 4294967295;
      pthread_attr_init (&attr);
      D.20529 = pthread_self ();
      pthread_getattr_np (D.20529, &attr);
      pthread_attr_getstack (&attr, staddr, stsize);
      pthread_attr_destroy (&attr);
      D.20530 = *staddr;
      if (D.20530 != 0B) goto <D.20531>; else goto <D.20532>;
      <D.20531>:
      D.20530 = *staddr;
      if (D.20530 >= current) goto <D.20534>; else goto <D.20537>;
      <D.20537>:
      D.20530 = *staddr;
      D.20538 = *stsize;
      D.20539 = D.20530 + D.20538;
      if (D.20539 <= current) goto <D.20534>; else goto <D.20535>;
      <D.20534>:
      iftmp.39 = 1;
      goto <D.20536>;
      <D.20535>:
      iftmp.39 = 0;
      <D.20536>:
      D.20540 = iftmp.39 != 0;
      D.20541 = (long int) D.20540;
      D.20542 = __builtin_expect (D.20541, 0);
      if (D.20542 != 0) goto <D.20543>; else goto <D.20544>;
      <D.20543>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 944, "(current > *staddr) && (current < *staddr + *stsize)");
      <D.20544>:
      <D.20532>:
      D.20530 = *staddr;
      D.20545 = (int) D.20530;
      D.20546 = mono_pagesize ();
      D.20547 = -D.20546;
      D.20548 = D.20545 & D.20547;
      D.20549 = (guint8 *) D.20548;
      *staddr = D.20549;
      return;
    }
  finally
    {
      attr = {CLOBBER};
    }
}


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

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


mono_thread_attach_full (struct MonoDomain * domain, gboolean force_attach)
{
  struct MonoDomain * D.20556;
  struct MonoDomain * domain.40;
  struct MonoThread * D.20560;
  int D.20561;
  unsigned int D.20564;
  void * thread_handle.41;
  void * thread_handle.42;
  _Bool D.20567;
  long int D.20568;
  long int D.20569;
  unsigned int tid.43;
  void * D.20573;
  void * D.20574;
  unsigned int tid.44;
  long long unsigned int D.20576;
  _Bool D.20577;
  long int D.20578;
  long int D.20579;
  int D.20582;
  unsigned int current_object_key.45;
  struct MonoDomain * D.20586;
  void (*<T1315>) (intptr_t, void *) mono_thread_attach_cb.46;
  guint8 * staddr.47;
  int tid.48;
  unsigned int stsize.49;
  void * D.20598;
  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.20554>; else goto <D.20555>;
      <D.20554>:
      D.20556 = mono_domain_get ();
      domain.40 = domain;
      if (D.20556 != domain.40) goto <D.20558>; else goto <D.20559>;
      <D.20558>:
      domain.40 = domain;
      mono_domain_set (domain.40, 1);
      <D.20559>:
      D.20560 = mono_thread_current ();
      return D.20560;
      <D.20555>:
      D.20561 = mono_gc_register_thread (&domain);
      if (D.20561 == 0) goto <D.20562>; else goto <D.20563>;
      <D.20562>:
      D.20564 = GetCurrentThreadId ();
      monoeg_g_log (0B, 4, "Thread %u 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.20564);
      <D.18759>:
      goto <D.18759>;
      <D.20563>:
      thread = create_internal_thread ();
      thread_handle.41 = GetCurrentThread ();
      thread_handle = thread_handle.41;
      thread_handle.42 = thread_handle;
      D.20567 = thread_handle.42 == 0B;
      D.20568 = (long int) D.20567;
      D.20569 = __builtin_expect (D.20568, 0);
      if (D.20569 != 0) goto <D.20570>; else goto <D.20571>;
      <D.20570>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1028, "thread_handle");
      <D.20571>:
      tid.43 = GetCurrentThreadId ();
      tid = tid.43;
      D.20573 = GetCurrentProcess ();
      thread_handle.42 = thread_handle;
      D.20574 = GetCurrentProcess ();
      DuplicateHandle (D.20574, thread_handle.42, D.20573, &thread_handle, 2032639, 1, 0);
      thread_handle.42 = thread_handle;
      thread->handle = thread_handle.42;
      tid.44 = tid;
      D.20576 = (long long unsigned int) tid.44;
      thread->tid = D.20576;
      thread->stack_ptr = &tid;
      info = mono_thread_info_current ();
      D.20577 = info == 0B;
      D.20578 = (long int) D.20577;
      D.20579 = __builtin_expect (D.20578, 0);
      if (D.20579 != 0) goto <D.20580>; else goto <D.20581>;
      <D.20580>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1049, "info");
      <D.20581>:
      thread->thread_info = info;
      domain.40 = domain;
      current_thread = new_thread_with_internal (domain.40, thread);
      D.20582 = handle_store (current_thread, force_attach);
      if (D.20582 == 0) goto <D.20583>; else goto <D.20584>;
      <D.20583>:
      <D.18760>:
      Sleep (10000);
      goto <D.18760>;
      <D.20584>:
      tls_current_object = thread;
      current_object_key.45 = current_object_key;
      mono_native_tls_set_value (current_object_key.45, thread);
      domain.40 = domain;
      mono_domain_set (domain.40, 1);
      mono_monitor_init_tls ();
      thread_adjust_static_data (thread);
      init_root_domain_thread (thread, current_thread);
      D.20586 = mono_get_root_domain ();
      domain.40 = domain;
      if (D.20586 != domain.40) goto <D.20587>; else goto <D.20588>;
      <D.20587>:
      domain.40 = domain;
      set_current_thread_for_domain (domain.40, thread, current_thread);
      <D.20588>:
      mono_thread_attach_cb.46 = mono_thread_attach_cb;
      if (mono_thread_attach_cb.46 != 0B) goto <D.20590>; else goto <D.20591>;
      <D.20590>:
      {
        guint8 * staddr;
        size_t stsize;

        try
          {
            mono_thread_get_stack_bounds (&staddr, &stsize);
            staddr.47 = staddr;
            if (staddr.47 == 0B) goto <D.20593>; else goto <D.20594>;
            <D.20593>:
            mono_thread_attach_cb.46 = mono_thread_attach_cb;
            tid.44 = tid;
            tid.48 = (int) tid.44;
            mono_thread_attach_cb.46 (tid.48, &tid);
            goto <D.20596>;
            <D.20594>:
            mono_thread_attach_cb.46 = mono_thread_attach_cb;
            staddr.47 = staddr;
            stsize.49 = stsize;
            D.20598 = staddr.47 + stsize.49;
            tid.44 = tid;
            tid.48 = (int) tid.44;
            mono_thread_attach_cb.46 (tid.48, D.20598);
            <D.20596>:
          }
        finally
          {
            staddr = {CLOBBER};
            stsize = {CLOBBER};
          }
      }
      <D.20591>:
      tid.44 = tid;
      mono_profiler_thread_start (tid.44);
      D.20560 = current_thread;
      return D.20560;
    }
  finally
    {
      thread_handle = {CLOBBER};
      tid = {CLOBBER};
    }
}


mono_thread_detach (struct MonoThread * thread)
{
  struct _MonoInternalThread * D.20603;
  unsigned int current_object_key.50;

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


mono_thread_exit ()
{
  unsigned int current_object_key.51;
  struct MonoThread * D.20607;
  struct MonoThread * D.20610;
  struct _MonoInternalThread * D.20611;
  int D.20614;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  thread_cleanup (thread);
  tls_current_object = 0B;
  current_object_key.51 = current_object_key;
  mono_native_tls_set_value (current_object_key.51, 0B);
  mono_domain_unset ();
  D.20607 = mono_thread_get_main ();
  if (D.20607 != 0B) goto <D.20608>; else goto <D.20609>;
  <D.20608>:
  D.20610 = mono_thread_get_main ();
  D.20611 = D.20610->internal_thread;
  if (D.20611 == thread) goto <D.20612>; else goto <D.20613>;
  <D.20612>:
  D.20614 = mono_environment_exitcode_get ();
  exit (D.20614);
  <D.20613>:
  <D.20609>:
  ExitThread (4294967295);
}


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

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


ves_icall_System_Threading_Thread_Thread_internal (struct MonoThread * this, struct MonoObject * start)
{
  struct _MonoInternalThread * D.20616;
  unsigned int D.20619;
  unsigned int D.20620;
  struct MonoException * D.20623;
  void * D.20624;
  unsigned int D.20625;
  struct MonoObject * D.20628;
  struct MonoVTable * D.20629;
  struct MonoDomain * D.20630;
  struct MonoDomain * D.20631;
  _Bool D.20632;
  long int D.20633;
  long int D.20634;
  unsigned int D.20639;
  struct StartInfo * start_info;
  struct MonoInternalThread * internal;
  gboolean res;

  D.20616 = this->internal_thread;
  if (D.20616 == 0B) goto <D.20617>; else goto <D.20618>;
  <D.20617>:
  ves_icall_System_Threading_Thread_ConstructInternalThread (this);
  <D.20618>:
  internal = this->internal_thread;
  lock_thread (internal);
  D.20619 = internal->state;
  D.20620 = D.20619 & 8;
  if (D.20620 == 0) goto <D.20621>; else goto <D.20622>;
  <D.20621>:
  unlock_thread (internal);
  D.20623 = mono_get_exception_thread_state ("Thread has already been started.");
  mono_raise_exception (D.20623);
  D.20624 = 0B;
  return D.20624;
  <D.20622>:
  D.20619 = internal->state;
  D.20625 = D.20619 & 256;
  if (D.20625 != 0) goto <D.20626>; else goto <D.20627>;
  <D.20626>:
  unlock_thread (internal);
  D.20624 = this;
  return D.20624;
  <D.20627>:
  start_info = monoeg_malloc0 (16);
  start_info->func = 0B;
  D.20628 = this->start_obj;
  start_info->start_arg = D.20628;
  start_info->delegate = start;
  start_info->obj = this;
  D.20629 = this->obj.vtable;
  D.20630 = D.20629->domain;
  D.20631 = mono_domain_get ();
  D.20632 = D.20630 != D.20631;
  D.20633 = (long int) D.20632;
  D.20634 = __builtin_expect (D.20633, 0);
  if (D.20634 != 0) goto <D.20635>; else goto <D.20636>;
  <D.20635>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1169, "this->obj.vtable->domain == mono_domain_get ()");
  <D.20636>:
  res = create_thread (this, internal, start_info, 0, 0, 0, 0);
  if (res == 0) goto <D.20637>; else goto <D.20638>;
  <D.20637>:
  unlock_thread (internal);
  D.20624 = 0B;
  return D.20624;
  <D.20638>:
  D.20619 = internal->state;
  D.20639 = D.20619 & 4294967287;
  internal->state = D.20639;
  unlock_thread (internal);
  D.20624 = internal->handle;
  return D.20624;
}


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

  if (thread != 0B) goto <D.20641>; else goto <D.20642>;
  <D.20641>:
  CloseHandle (thread);
  <D.20642>:
  D.20643 = this->synch_cs;
  if (D.20643 != 0B) goto <D.20644>; else goto <D.20645>;
  <D.20644>:
  {
    struct CRITICAL_SECTION * synch_cs;

    synch_cs = this->synch_cs;
    this->synch_cs = 0B;
    DeleteCriticalSection (synch_cs);
    monoeg_g_free (synch_cs);
  }
  <D.20645>:
  D.20646 = this->name;
  if (D.20646 != 0B) goto <D.20647>; else goto <D.20648>;
  <D.20647>:
  {
    void * name;

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


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

  thread = mono_thread_internal_current ();
  mono_thread_current_check_pending_interrupt ();
  <D.18793>:
  mono_thread_set_state (thread, 32);
  ms.52 = (unsigned int) ms;
  res = SleepEx (ms.52, 1);
  mono_thread_clr_state (thread, 32);
  if (res == 192) goto <D.20650>; else goto <D.18792>;
  <D.20650>:
  {
    struct MonoException * exc;

    exc = mono_thread_execute_interruption (thread);
    if (exc != 0B) goto <D.20651>; else goto <D.20652>;
    <D.20651>:
    mono_raise_exception (exc);
    goto <D.20653>;
    <D.20652>:
    if (ms != -1) goto <D.18792>; else goto <D.20654>;
    <D.20654>:
    <D.20653>:
  }
  goto <D.18793>;
  <D.18792>:
}


mono_thread_execute_interruption (struct MonoInternalThread * thread)
{
  gint32 * D.20655;
  int D.20656;
  void * D.20659;
  unsigned int D.20660;
  unsigned int D.20661;
  struct MonoException * D.20664;
  struct MonoException * D.20667;
  struct MonoException * * D.20668;
  struct MonoException * D.20669;
  unsigned int D.20670;
  unsigned int D.20673;
  struct MonoException * D.20676;
  unsigned char D.20679;

  lock_thread (thread);
  D.20655 = &thread->interruption_requested;
  D.20656 = InterlockedCompareExchange (D.20655, 0, 1);
  if (D.20656 != 0) goto <D.20657>; else goto <D.20658>;
  <D.20657>:
  D.20659 = GetCurrentThread ();
  WaitForSingleObjectEx (D.20659, 0, 1);
  InterlockedDecrement (&thread_interruption_requested);
  wapi_clear_interruption ();
  <D.20658>:
  D.20660 = thread->state;
  D.20661 = D.20660 & 128;
  if (D.20661 != 0) goto <D.20662>; else goto <D.20663>;
  <D.20662>:
  unlock_thread (thread);
  D.20664 = thread->abort_exc;
  if (D.20664 == 0B) goto <D.20665>; else goto <D.20666>;
  <D.20665>:
  D.20667 = mono_get_exception_thread_abort ();
  D.20668 = &thread->abort_exc;
  mono_gc_wbarrier_set_field (thread, D.20668, D.20667);
  <D.20666>:
  D.20669 = thread->abort_exc;
  return D.20669;
  <D.20663>:
  D.20660 = thread->state;
  D.20670 = D.20660 & 2;
  if (D.20670 != 0) goto <D.20671>; else goto <D.20672>;
  <D.20671>:
  self_suspend_internal (thread);
  D.20669 = 0B;
  return D.20669;
  <D.20672>:
  D.20660 = thread->state;
  D.20673 = D.20660 & 1;
  if (D.20673 != 0) goto <D.20674>; else goto <D.20675>;
  <D.20674>:
  unlock_thread (thread);
  mono_thread_exit ();
  D.20669 = 0B;
  return D.20669;
  <D.20675>:
  D.20676 = thread->pending_exception;
  if (D.20676 != 0B) goto <D.20677>; else goto <D.20678>;
  <D.20677>:
  {
    struct MonoException * exc;

    exc = thread->pending_exception;
    thread->pending_exception = 0B;
    unlock_thread (thread);
    D.20669 = exc;
    return D.20669;
  }
  <D.20678>:
  D.20679 = thread->thread_interrupt_requested;
  if (D.20679 != 0) goto <D.20680>; else goto <D.20681>;
  <D.20680>:
  thread->thread_interrupt_requested = 0;
  unlock_thread (thread);
  D.20669 = mono_get_exception_thread_interrupted ();
  return D.20669;
  <D.20681>:
  unlock_thread (thread);
  D.20669 = 0B;
  return D.20669;
}


InterlockedCompareExchange (volatile gint32 * dest, gint32 exch, gint32 comp)
{
  gint32 D.20683;
  unsigned int exch.53;
  unsigned int comp.54;
  unsigned int D.20686;

  exch.53 = (unsigned int) exch;
  comp.54 = (unsigned int) comp;
  D.20686 = __sync_val_compare_and_swap_4 (dest, comp.54, exch.53);
  D.20683 = (gint32) D.20686;
  return D.20683;
}


self_suspend_internal (struct MonoInternalThread * thread)
{
  int D.20688;
  unsigned int D.20691;
  unsigned int D.20692;
  unsigned int D.20693;
  void * D.20694;
  void * D.20695;
  void * D.20698;
  int shutting_down.55;
  unsigned int D.20704;
  void * D.20705;

  D.20688 = mono_thread_info_new_interrupt_enabled ();
  if (D.20688 == 0) goto <D.20689>; else goto <D.20690>;
  <D.20689>:
  D.20691 = thread->state;
  D.20692 = D.20691 & 4294967293;
  thread->state = D.20692;
  D.20691 = thread->state;
  D.20693 = D.20691 | 64;
  thread->state = D.20693;
  D.20694 = CreateEvent (0B, 1, 0, 0B);
  thread->suspend_event = D.20694;
  D.20695 = thread->suspend_event;
  if (D.20695 == 0B) goto <D.20696>; else goto <D.20697>;
  <D.20696>:
  unlock_thread (thread);
  return;
  <D.20697>:
  D.20698 = thread->suspended_event;
  if (D.20698 != 0B) goto <D.20699>; else goto <D.20700>;
  <D.20699>:
  D.20698 = thread->suspended_event;
  SetEvent (D.20698);
  <D.20700>:
  unlock_thread (thread);
  shutting_down.55 = shutting_down;
  if (shutting_down.55 != 0) goto <D.20702>; else goto <D.20703>;
  <D.20702>:
  <D.19968>:
  Sleep (1000);
  goto <D.19968>;
  <D.20703>:
  D.20695 = thread->suspend_event;
  WaitForSingleObject (D.20695, 4294967295);
  lock_thread (thread);
  D.20695 = thread->suspend_event;
  CloseHandle (D.20695);
  thread->suspend_event = 0B;
  D.20691 = thread->state;
  D.20704 = D.20691 & 4294967231;
  thread->state = D.20704;
  D.20705 = thread->resume_event;
  SetEvent (D.20705);
  unlock_thread (thread);
  return;
  <D.20690>:
  transition_to_suspended (thread);
  mono_thread_info_self_suspend ();
}


transition_to_suspended (struct MonoInternalThread * thread)
{
  unsigned int D.20707;
  unsigned int D.20708;
  long long unsigned int D.20713;
  long unsigned int D.20714;
  unsigned int D.20716;
  unsigned int D.20717;

  D.20707 = thread->state;
  D.20708 = D.20707 & 2;
  if (D.20708 == 0) goto <D.20709>; else goto <D.20710>;
  <D.20709>:
  if (1 != 0) goto <D.20711>; else goto <D.20712>;
  <D.20711>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4693, "0");
  <D.20712>:
  D.20713 = thread->tid;
  D.20714 = (long unsigned int) D.20713;
  mono_thread_info_resume (D.20714);
  goto <D.20715>;
  <D.20710>:
  D.20707 = thread->state;
  D.20716 = D.20707 & 4294967293;
  thread->state = D.20716;
  D.20707 = thread->state;
  D.20717 = D.20707 | 64;
  thread->state = D.20717;
  mono_thread_info_finish_suspend ();
  <D.20715>:
  unlock_thread (thread);
}


ves_icall_System_Threading_Thread_SpinWait_nop ()
{

}


ves_icall_System_Threading_Thread_GetDomainID ()
{
  gint32 D.20718;
  struct MonoDomain * D.20719;

  D.20719 = mono_domain_get ();
  D.20718 = D.20719->domain_id;
  return D.20718;
}


ves_icall_System_Threading_Thread_Yield ()
{
  gboolean D.20721;
  int D.20722;
  _Bool D.20723;

  D.20722 = sched_yield ();
  D.20723 = D.20722 == 0;
  D.20721 = (gboolean) D.20723;
  return D.20721;
}


mono_thread_get_name (struct MonoInternalThread * this_obj, guint32 * name_len)
{
  gunichar2 * D.20725;
  unsigned int D.20729;
  unsigned int D.20730;
  gunichar2 * D.20731;
  gunichar2 * res;

  lock_thread (this_obj);
  D.20725 = this_obj->name;
  if (D.20725 == 0B) goto <D.20726>; else goto <D.20727>;
  <D.20726>:
  *name_len = 0;
  res = 0B;
  goto <D.20728>;
  <D.20727>:
  D.20729 = this_obj->name_len;
  *name_len = D.20729;
  D.20729 = this_obj->name_len;
  D.20730 = D.20729 * 2;
  res = monoeg_malloc (D.20730);
  D.20729 = this_obj->name_len;
  D.20730 = D.20729 * 2;
  D.20725 = this_obj->name;
  memcpy (res, D.20725, D.20730);
  <D.20728>:
  unlock_thread (this_obj);
  D.20731 = res;
  return D.20731;
}


memcpy (void * restrict __dest, const void * restrict __src, size_t __len)
{
  void * D.20733;
  unsigned int D.20734;

  D.20734 = __builtin_object_size (__dest, 0);
  D.20733 = __builtin___memcpy_chk (__dest, __src, __len, D.20734);
  return D.20733;
}


ves_icall_System_Threading_Thread_GetName_internal (struct MonoInternalThread * this_obj)
{
  gunichar2 * D.20736;
  unsigned int D.20740;
  int D.20741;
  struct MonoDomain * D.20742;
  struct MonoString * D.20743;
  struct MonoString * str;

  lock_thread (this_obj);
  D.20736 = this_obj->name;
  if (D.20736 == 0B) goto <D.20737>; else goto <D.20738>;
  <D.20737>:
  str = 0B;
  goto <D.20739>;
  <D.20738>:
  D.20740 = this_obj->name_len;
  D.20741 = (int) D.20740;
  D.20736 = this_obj->name;
  D.20742 = mono_domain_get ();
  str = mono_string_new_utf16 (D.20742, D.20736, D.20741);
  <D.20739>:
  unlock_thread (this_obj);
  D.20743 = str;
  return D.20743;
}


mono_thread_set_name_internal (struct MonoInternalThread * this_obj, struct MonoString * name, gboolean managed)
{
  unsigned int D.20745;
  unsigned int D.20746;
  struct MonoException * D.20749;
  int D.20752;
  unsigned int D.20753;
  unsigned int D.20754;
  void * D.20755;
  int D.20756;
  int D.20757;
  unsigned int D.20758;
  mono_unichar2 * D.20759;
  gunichar2 * D.20760;
  int D.20761;
  unsigned int D.20762;
  unsigned int D.20766;
  long long unsigned int D.20769;
  unsigned int D.20770;

  lock_thread (this_obj);
  D.20745 = this_obj->flags;
  D.20746 = D.20745 & 2;
  if (D.20746 != 0) goto <D.20747>; else goto <D.20748>;
  <D.20747>:
  unlock_thread (this_obj);
  D.20749 = mono_get_exception_invalid_operation ("Thread.Name can only be set once.");
  mono_raise_exception (D.20749);
  return;
  <D.20748>:
  if (name != 0B) goto <D.20750>; else goto <D.20751>;
  <D.20750>:
  D.20752 = mono_string_length (name);
  D.20753 = (unsigned int) D.20752;
  D.20754 = D.20753 * 2;
  D.20755 = monoeg_malloc (D.20754);
  this_obj->name = D.20755;
  D.20756 = mono_string_length (name);
  D.20757 = D.20756 * 2;
  D.20758 = (unsigned int) D.20757;
  D.20759 = mono_string_chars (name);
  D.20760 = this_obj->name;
  memcpy (D.20760, D.20759, D.20758);
  D.20761 = mono_string_length (name);
  D.20762 = (unsigned int) D.20761;
  this_obj->name_len = D.20762;
  goto <D.20763>;
  <D.20751>:
  this_obj->name = 0B;
  <D.20763>:
  if (managed != 0) goto <D.20764>; else goto <D.20765>;
  <D.20764>:
  D.20745 = this_obj->flags;
  D.20766 = D.20745 | 2;
  this_obj->flags = D.20766;
  <D.20765>:
  unlock_thread (this_obj);
  D.20760 = this_obj->name;
  if (D.20760 != 0B) goto <D.20767>; else goto <D.20768>;
  <D.20767>:
  {
    char * tname;

    tname = mono_string_to_utf8 (name);
    D.20769 = this_obj->tid;
    D.20770 = (unsigned int) D.20769;
    mono_profiler_thread_name (D.20770, tname);
    mono_free (tname);
  }
  <D.20768>:
}


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.20772;
  struct MonoDomain * D.20773;

  D.20773 = mono_get_root_domain ();
  D.20772 = byte_array_to_domain (arr, D.20773);
  return D.20772;
}


byte_array_to_domain (struct MonoArray * arr, struct MonoDomain * domain)
{
  struct MonoArray * D.20777;
  struct MonoVTable * D.20778;
  struct MonoDomain * D.20779;
  unsigned int D.20782;
  struct MonoClass * D.20783;
  char * D.20784;
  char * D.20785;
  struct MonoArray * copy;

  if (arr == 0B) goto <D.20775>; else goto <D.20776>;
  <D.20775>:
  D.20777 = 0B;
  return D.20777;
  <D.20776>:
  D.20778 = MEM[(struct MonoObject *)arr].vtable;
  D.20779 = D.20778->domain;
  if (D.20779 == domain) goto <D.20780>; else goto <D.20781>;
  <D.20780>:
  D.20777 = arr;
  return D.20777;
  <D.20781>:
  D.20782 = arr->max_length;
  D.20783 = mono_defaults.byte_class;
  copy = mono_array_new (domain, D.20783, D.20782);
  D.20782 = arr->max_length;
  D.20784 = mono_array_addr_with_size (arr, 1, 0);
  D.20785 = mono_array_addr_with_size (copy, 1, 0);
  memmove (D.20785, D.20784, D.20782);
  D.20777 = copy;
  return D.20777;
}


memmove (void * __dest, const void * __src, size_t __len)
{
  void * D.20787;
  unsigned int D.20788;

  D.20788 = __builtin_object_size (__dest, 0);
  D.20787 = __builtin___memmove_chk (__dest, __src, __len, D.20788);
  return D.20787;
}


ves_icall_System_Threading_Thread_ByteArrayToCurrentDomain (struct MonoArray * arr)
{
  struct MonoArray * D.20790;
  struct MonoDomain * D.20791;

  D.20791 = mono_domain_get ();
  D.20790 = byte_array_to_domain (arr, D.20791);
  return D.20790;
}


mono_thread_current ()
{
  _Bool D.20793;
  long int D.20794;
  long int D.20795;
  struct MonoThread * D.20798;
  struct MonoDomain * D.20801;
  _Bool D.20802;
  long int D.20803;
  long int D.20804;
  struct MonoThread * D.20807;
  struct MonoThread * D.20808;
  struct MonoDomain * domain;
  struct MonoInternalThread * internal;
  struct MonoThread * * current_thread_ptr;

  domain = mono_domain_get ();
  internal = mono_thread_internal_current ();
  D.20793 = internal == 0B;
  D.20794 = (long int) D.20793;
  D.20795 = __builtin_expect (D.20794, 0);
  if (D.20795 != 0) goto <D.20796>; else goto <D.20797>;
  <D.20796>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1382, "internal");
  <D.20797>:
  current_thread_ptr = get_current_thread_ptr_for_domain (domain, internal);
  D.20798 = *current_thread_ptr;
  if (D.20798 == 0B) goto <D.20799>; else goto <D.20800>;
  <D.20799>:
  D.20801 = mono_get_root_domain ();
  D.20802 = D.20801 == domain;
  D.20803 = (long int) D.20802;
  D.20804 = __builtin_expect (D.20803, 0);
  if (D.20804 != 0) goto <D.20805>; else goto <D.20806>;
  <D.20805>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1386, "domain != mono_get_root_domain ()");
  <D.20806>:
  D.20807 = new_thread_with_internal (domain, internal);
  *current_thread_ptr = D.20807;
  <D.20800>:
  D.20808 = *current_thread_ptr;
  return D.20808;
}


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

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


ves_icall_System_Threading_Thread_Join_internal (struct MonoInternalThread * this, int ms, void * thread)
{
  unsigned int D.20812;
  unsigned int D.20813;
  struct MonoException * D.20816;
  gboolean D.20817;
  unsigned int ms.56;
  unsigned int D.20821;
  struct MonoInternalThread * cur_thread;
  gboolean ret;

  cur_thread = mono_thread_internal_current ();
  mono_thread_current_check_pending_interrupt ();
  lock_thread (this);
  D.20812 = this->state;
  D.20813 = D.20812 & 8;
  if (D.20813 != 0) goto <D.20814>; else goto <D.20815>;
  <D.20814>:
  unlock_thread (this);
  D.20816 = mono_get_exception_thread_state ("Thread has not been started.");
  mono_raise_exception (D.20816);
  D.20817 = 0;
  return D.20817;
  <D.20815>:
  unlock_thread (this);
  if (ms == -1) goto <D.20818>; else goto <D.20819>;
  <D.20818>:
  ms = -1;
  <D.20819>:
  mono_thread_set_state (cur_thread, 32);
  ms.56 = (unsigned int) ms;
  D.20821 = WaitForSingleObjectEx (thread, ms.56, 1);
  ret = (gboolean) D.20821;
  mono_thread_clr_state (cur_thread, 32);
  if (ret == 0) goto <D.20822>; else goto <D.20823>;
  <D.20822>:
  D.20817 = 1;
  return D.20817;
  <D.20823>:
  D.20817 = 0;
  return D.20817;
}


ves_icall_System_Threading_WaitHandle_WaitAll_internal (struct MonoArray * mono_handles, gint32 ms, gboolean exitContext)
{
  unsigned int D.20825;
  char * D.20826;
  unsigned int D.20827;
  void * * D.20828;
  void * D.20829;
  int D.20832;
  gboolean D.20835;
  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 ();
  numhandles = mono_array_length (mono_handles);
  D.20825 = numhandles * 4;
  handles = monoeg_malloc0 (D.20825);
  i = 0;
  goto <D.18879>;
  <D.18878>:
  D.20826 = mono_array_addr_with_size (mono_handles, 4, i);
  waitHandle = MEM[(struct MonoObject * *)D.20826];
  D.20827 = i * 4;
  D.20828 = handles + D.20827;
  D.20829 = mono_wait_handle_get_handle (waitHandle);
  *D.20828 = D.20829;
  i = i + 1;
  <D.18879>:
  if (i < numhandles) goto <D.18878>; else goto <D.18880>;
  <D.18880>:
  if (ms == -1) goto <D.20830>; else goto <D.20831>;
  <D.20830>:
  ms = -1;
  <D.20831>:
  mono_thread_set_state (thread, 32);
  D.20832 = mono_wait_uninterrupted (thread, 1, numhandles, handles, 1, ms, 1);
  ret = (guint32) D.20832;
  mono_thread_clr_state (thread, 32);
  monoeg_g_free (handles);
  if (ret == 4294967295) goto <D.20833>; else goto <D.20834>;
  <D.20833>:
  D.20835 = 0;
  return D.20835;
  <D.20834>:
  if (ret == 258) goto <D.20836>; else goto <D.20837>;
  <D.20836>:
  D.20835 = 0;
  return D.20835;
  <D.20837>:
  D.20835 = 1;
  return D.20835;
}


mono_wait_uninterrupted (struct MonoInternalThread * thread, gboolean multiple, guint32 numhandles, void * * handles, gboolean waitall, gint32 ms, gboolean alertable)
{
  gint64 iftmp.57;
  unsigned int wait.58;
  unsigned int ms.59;
  void * D.20848;
  long long int D.20854;
  long long int D.20855;
  long long int D.20856;
  gint32 D.20859;
  struct MonoException * exc;
  guint32 ret;
  gint64 start;
  gint32 diff_ms;
  gint32 wait;

  wait = ms;
  if (ms != -1) goto <D.20840>; else goto <D.20841>;
  <D.20840>:
  iftmp.57 = mono_100ns_ticks ();
  goto <D.20842>;
  <D.20841>:
  iftmp.57 = 0;
  <D.20842>:
  start = iftmp.57;
  <D.18866>:
  if (multiple != 0) goto <D.20843>; else goto <D.20844>;
  <D.20843>:
  wait.58 = (unsigned int) wait;
  ret = WaitForMultipleObjectsEx (numhandles, handles, waitall, wait.58, alertable);
  goto <D.20846>;
  <D.20844>:
  ms.59 = (unsigned int) ms;
  D.20848 = *handles;
  ret = WaitForSingleObjectEx (D.20848, ms.59, alertable);
  <D.20846>:
  if (ret != 192) goto <D.18864>; else goto <D.20849>;
  <D.20849>:
  exc = mono_thread_execute_interruption (thread);
  if (exc != 0B) goto <D.20850>; else goto <D.20851>;
  <D.20850>:
  mono_raise_exception (exc);
  <D.20851>:
  if (ms == -1) goto <D.20852>; else goto <D.20853>;
  <D.20852>:
  // predicted unlikely by continue predictor.
  goto <D.18865>;
  <D.20853>:
  D.20854 = mono_100ns_ticks ();
  D.20855 = D.20854 - start;
  D.20856 = D.20855 / 10000;
  diff_ms = (gint32) D.20856;
  if (diff_ms >= ms) goto <D.20857>; else goto <D.20858>;
  <D.20857>:
  ret = 258;
  goto <D.18864>;
  <D.20858>:
  wait = ms - diff_ms;
  <D.18865>:
  goto <D.18866>;
  <D.18864>:
  D.20859 = (gint32) ret;
  return D.20859;
}


ves_icall_System_Threading_WaitHandle_WaitAny_internal (struct MonoArray * mono_handles, gint32 ms, gboolean exitContext)
{
  gint32 D.20863;
  char * D.20864;
  void * D.20865;
  int D.20868;
  unsigned int D.20869;
  unsigned int D.20874;
  unsigned int D.20876;
  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 ();
      numhandles = mono_array_length (mono_handles);
      if (numhandles > 64) goto <D.20861>; else goto <D.20862>;
      <D.20861>:
      D.20863 = -1;
      return D.20863;
      <D.20862>:
      i = 0;
      goto <D.18893>;
      <D.18892>:
      D.20864 = mono_array_addr_with_size (mono_handles, 4, i);
      waitHandle = MEM[(struct MonoObject * *)D.20864];
      D.20865 = mono_wait_handle_get_handle (waitHandle);
      handles[i] = D.20865;
      i = i + 1;
      <D.18893>:
      if (i < numhandles) goto <D.18892>; else goto <D.18894>;
      <D.18894>:
      if (ms == -1) goto <D.20866>; else goto <D.20867>;
      <D.20866>:
      ms = -1;
      <D.20867>:
      mono_thread_set_state (thread, 32);
      D.20868 = mono_wait_uninterrupted (thread, 1, numhandles, &handles, 0, ms, 1);
      ret = (guint32) D.20868;
      mono_thread_clr_state (thread, 32);
      D.20869 = numhandles + 4294967295;
      if (D.20869 >= ret) goto <D.20870>; else goto <D.20871>;
      <D.20870>:
      D.20863 = (gint32) ret;
      return D.20863;
      <D.20871>:
      if (ret > 127) goto <D.20873>; else goto <D.20872>;
      <D.20873>:
      D.20874 = numhandles + 127;
      if (D.20874 >= ret) goto <D.20875>; else goto <D.20872>;
      <D.20875>:
      D.20876 = ret + 4294967168;
      D.20863 = (gint32) D.20876;
      return D.20863;
      <D.20872>:
      D.20863 = (gint32) ret;
      return D.20863;
    }
  finally
    {
      handles = {CLOBBER};
    }
}


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

  thread = mono_thread_internal_current ();
  if (ms == -1) goto <D.20879>; else goto <D.20880>;
  <D.20879>:
  ms = -1;
  <D.20880>:
  mono_thread_current_check_pending_interrupt ();
  mono_thread_set_state (thread, 32);
  D.20881 = mono_wait_uninterrupted (thread, 0, 1, &handle, 0, ms, 1);
  ret = (guint32) D.20881;
  mono_thread_clr_state (thread, 32);
  if (ret == 4294967295) goto <D.20882>; else goto <D.20883>;
  <D.20882>:
  D.20884 = 0;
  return D.20884;
  <D.20883>:
  if (ret == 258) goto <D.20885>; else goto <D.20886>;
  <D.20885>:
  D.20884 = 0;
  return D.20884;
  <D.20886>:
  D.20884 = 1;
  return D.20884;
}


ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal (void * toSignal, void * toWait, gint32 ms, gboolean exitContext)
{
  unsigned int ms.60;
  gboolean D.20891;
  int iftmp.61;
  _Bool D.20895;
  _Bool D.20896;
  _Bool D.20897;
  guint32 ret;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  if (ms == -1) goto <D.20888>; else goto <D.20889>;
  <D.20888>:
  ms = -1;
  <D.20889>:
  mono_thread_current_check_pending_interrupt ();
  mono_thread_set_state (thread, 32);
  ms.60 = (unsigned int) ms;
  ret = SignalObjectAndWait (toSignal, toWait, ms.60, 1);
  mono_thread_clr_state (thread, 32);
  D.20895 = ret != 258;
  D.20896 = ret != 192;
  D.20897 = D.20895 & D.20896;
  if (D.20897 != 0) goto <D.20898>; else goto <D.20893>;
  <D.20898>:
  if (ret != 4294967295) goto <D.20899>; else goto <D.20893>;
  <D.20899>:
  iftmp.61 = 1;
  goto <D.20894>;
  <D.20893>:
  iftmp.61 = 0;
  <D.20894>:
  D.20891 = iftmp.61;
  return D.20891;
}


ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, struct MonoString * name, MonoBoolean * created)
{
  int D.20903;
  mono_unichar2 * D.20905;
  unsigned int D.20906;
  void * D.20909;
  void * mutex;

  *created = 1;
  if (name == 0B) goto <D.20901>; else goto <D.20902>;
  <D.20901>:
  D.20903 = (int) owned;
  mutex = CreateMutex (0B, D.20903, 0B);
  goto <D.20904>;
  <D.20902>:
  D.20905 = mono_string_chars (name);
  D.20903 = (int) owned;
  mutex = CreateMutex (0B, D.20903, D.20905);
  D.20906 = GetLastError ();
  if (D.20906 == 183) goto <D.20907>; else goto <D.20908>;
  <D.20907>:
  *created = 0;
  <D.20908>:
  <D.20904>:
  D.20909 = mutex;
  return D.20909;
}


ves_icall_System_Threading_Mutex_ReleaseMutex_internal (void * handle)
{
  MonoBoolean D.20911;
  int D.20912;

  D.20912 = ReleaseMutex (handle);
  D.20911 = (MonoBoolean) D.20912;
  return D.20911;
}


ves_icall_System_Threading_Mutex_OpenMutex_internal (struct MonoString * name, gint32 rights, gint32 * error)
{
  mono_unichar2 * D.20914;
  unsigned int rights.62;
  unsigned int D.20918;
  int D.20919;
  void * D.20920;
  void * ret;

  *error = 0;
  D.20914 = mono_string_chars (name);
  rights.62 = (unsigned int) rights;
  ret = OpenMutex (rights.62, 0, D.20914);
  if (ret == 0B) goto <D.20916>; else goto <D.20917>;
  <D.20916>:
  D.20918 = GetLastError ();
  D.20919 = (int) D.20918;
  *error = D.20919;
  <D.20917>:
  D.20920 = ret;
  return D.20920;
}


ves_icall_System_Threading_Semaphore_CreateSemaphore_internal (gint32 initialCount, gint32 maximumCount, struct MonoString * name, MonoBoolean * created)
{
  mono_unichar2 * D.20925;
  unsigned int D.20926;
  void * D.20929;
  void * sem;

  *created = 1;
  if (name == 0B) goto <D.20922>; else goto <D.20923>;
  <D.20922>:
  sem = CreateSemaphore (0B, initialCount, maximumCount, 0B);
  goto <D.20924>;
  <D.20923>:
  D.20925 = mono_string_chars (name);
  sem = CreateSemaphore (0B, initialCount, maximumCount, D.20925);
  D.20926 = GetLastError ();
  if (D.20926 == 183) goto <D.20927>; else goto <D.20928>;
  <D.20927>:
  *created = 0;
  <D.20928>:
  <D.20924>:
  D.20929 = sem;
  return D.20929;
}


ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (void * handle, gint32 releaseCount, MonoBoolean * fail)
{
  int D.20931;
  _Bool D.20932;
  unsigned char D.20933;
  gint32 D.20934;
  gint32 prevcount;

  try
    {
      D.20931 = ReleaseSemaphore (handle, releaseCount, &prevcount);
      D.20932 = D.20931 == 0;
      D.20933 = (unsigned char) D.20932;
      *fail = D.20933;
      D.20934 = prevcount;
      return D.20934;
    }
  finally
    {
      prevcount = {CLOBBER};
    }
}


ves_icall_System_Threading_Semaphore_OpenSemaphore_internal (struct MonoString * name, gint32 rights, gint32 * error)
{
  mono_unichar2 * D.20937;
  unsigned int rights.63;
  unsigned int D.20941;
  int D.20942;
  void * D.20943;
  void * ret;

  *error = 0;
  D.20937 = mono_string_chars (name);
  rights.63 = (unsigned int) rights;
  ret = OpenSemaphore (rights.63, 0, D.20937);
  if (ret == 0B) goto <D.20939>; else goto <D.20940>;
  <D.20939>:
  D.20941 = GetLastError ();
  D.20942 = (int) D.20941;
  *error = D.20942;
  <D.20940>:
  D.20943 = ret;
  return D.20943;
}


ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, struct MonoString * name, MonoBoolean * created)
{
  int D.20947;
  int D.20948;
  mono_unichar2 * D.20950;
  unsigned int D.20951;
  void * D.20954;
  void * event;

  *created = 1;
  if (name == 0B) goto <D.20945>; else goto <D.20946>;
  <D.20945>:
  D.20947 = (int) initial;
  D.20948 = (int) manual;
  event = CreateEvent (0B, D.20948, D.20947, 0B);
  goto <D.20949>;
  <D.20946>:
  D.20950 = mono_string_chars (name);
  D.20947 = (int) initial;
  D.20948 = (int) manual;
  event = CreateEvent (0B, D.20948, D.20947, D.20950);
  D.20951 = GetLastError ();
  if (D.20951 == 183) goto <D.20952>; else goto <D.20953>;
  <D.20952>:
  *created = 0;
  <D.20953>:
  <D.20949>:
  D.20954 = event;
  return D.20954;
}


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

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


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

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


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)
{
  mono_unichar2 * D.20960;
  unsigned int rights.64;
  unsigned int D.20964;
  int D.20965;
  void * D.20966;
  void * ret;

  *error = 0;
  D.20960 = mono_string_chars (name);
  rights.64 = (unsigned int) rights;
  ret = OpenEvent (rights.64, 0, D.20960);
  if (ret == 0B) goto <D.20962>; else goto <D.20963>;
  <D.20962>:
  D.20964 = GetLastError ();
  D.20965 = (int) D.20964;
  *error = D.20965;
  <D.20963>:
  D.20966 = ret;
  return D.20966;
}


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

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


ves_icall_System_Threading_Interlocked_Increment_Long (gint64 * location)
{
  unsigned int location.65;
  unsigned int D.20971;
  _Bool D.20972;
  long int D.20973;
  long int D.20974;
  _Bool D.20979;
  long int D.20980;
  long int D.20981;
  long long int D.20984;
  long long int D.20985;
  _Bool D.20988;
  long int D.20989;
  long int D.20990;
  gint64 D.20993;

  location.65 = (unsigned int) location;
  D.20971 = location.65 & 7;
  D.20972 = D.20971 != 0;
  D.20973 = (long int) D.20972;
  D.20974 = __builtin_expect (D.20973, 0);
  if (D.20974 != 0) goto <D.20975>; else goto <D.20976>;
  <D.20975>:
  {
    gint64 ret;

    {
      int ret;

      ret = pthread_mutex_lock (&interlocked_mutex.mutex);
      if (ret != 0) goto <D.20977>; else goto <D.20978>;
      <D.20977>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
      <D.20978>:
      D.20979 = ret != 0;
      D.20980 = (long int) D.20979;
      D.20981 = __builtin_expect (D.20980, 0);
      if (D.20981 != 0) goto <D.20982>; else goto <D.20983>;
      <D.20982>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1764, "ret == 0");
      <D.20983>:
    }
    D.20984 = *location;
    D.20985 = D.20984 + 1;
    *location = D.20985;
    ret = *location;
    {
      int ret;

      ret = pthread_mutex_unlock (&interlocked_mutex.mutex);
      if (ret != 0) goto <D.20986>; else goto <D.20987>;
      <D.20986>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.20987>:
      D.20988 = ret != 0;
      D.20989 = (long int) D.20988;
      D.20990 = __builtin_expect (D.20989, 0);
      if (D.20990 != 0) goto <D.20991>; else goto <D.20992>;
      <D.20991>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1767, "ret == 0");
      <D.20992>:
    }
    D.20993 = ret;
    return D.20993;
  }
  <D.20976>:
  D.20993 = InterlockedIncrement64 (location);
  return D.20993;
}


InterlockedIncrement64 (volatile gint64 * val)
{
  gint64 D.20995;
  long long unsigned int D.20996;

  D.20996 = __sync_add_and_fetch_8 (val, 1);
  D.20995 = (gint64) D.20996;
  return D.20995;
}


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

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


ves_icall_System_Threading_Interlocked_Decrement_Long (gint64 * location)
{
  unsigned int location.66;
  unsigned int D.21001;
  _Bool D.21002;
  long int D.21003;
  long int D.21004;
  _Bool D.21009;
  long int D.21010;
  long int D.21011;
  long long int D.21014;
  long long int D.21015;
  _Bool D.21018;
  long int D.21019;
  long int D.21020;
  gint64 D.21023;

  location.66 = (unsigned int) location;
  D.21001 = location.66 & 7;
  D.21002 = D.21001 != 0;
  D.21003 = (long int) D.21002;
  D.21004 = __builtin_expect (D.21003, 0);
  if (D.21004 != 0) goto <D.21005>; else goto <D.21006>;
  <D.21005>:
  {
    gint64 ret;

    {
      int ret;

      ret = pthread_mutex_lock (&interlocked_mutex.mutex);
      if (ret != 0) goto <D.21007>; else goto <D.21008>;
      <D.21007>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
      <D.21008>:
      D.21009 = ret != 0;
      D.21010 = (long int) D.21009;
      D.21011 = __builtin_expect (D.21010, 0);
      if (D.21011 != 0) goto <D.21012>; else goto <D.21013>;
      <D.21012>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1784, "ret == 0");
      <D.21013>:
    }
    D.21014 = *location;
    D.21015 = D.21014 + -1;
    *location = D.21015;
    ret = *location;
    {
      int ret;

      ret = pthread_mutex_unlock (&interlocked_mutex.mutex);
      if (ret != 0) goto <D.21016>; else goto <D.21017>;
      <D.21016>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.21017>:
      D.21018 = ret != 0;
      D.21019 = (long int) D.21018;
      D.21020 = __builtin_expect (D.21019, 0);
      if (D.21020 != 0) goto <D.21021>; else goto <D.21022>;
      <D.21021>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1787, "ret == 0");
      <D.21022>:
    }
    D.21023 = ret;
    return D.21023;
  }
  <D.21006>:
  D.21023 = InterlockedDecrement64 (location);
  return D.21023;
}


InterlockedDecrement64 (volatile gint64 * val)
{
  gint64 D.21025;
  long long unsigned int D.21026;

  D.21026 = __sync_sub_and_fetch_8 (val, 1);
  D.21025 = (gint64) D.21026;
  return D.21025;
}


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

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


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

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


InterlockedExchangePointer (void * volatile * val, void * new_val)
{
  unsigned int new_val.67;
  unsigned int old_val.68;
  unsigned int D.21034;
  void * D.21035;
  void * D.21036;
  void * old_val;

  <D.18436>:
  old_val = *val;
  new_val.67 = (unsigned int) new_val;
  old_val.68 = (unsigned int) old_val;
  D.21034 = __sync_val_compare_and_swap_4 (val, old_val.68, new_val.67);
  D.21035 = (void *) D.21034;
  if (D.21035 != old_val) goto <D.18436>; else goto <D.18437>;
  <D.18437>:
  D.21036 = old_val;
  return D.21036;
}


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

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


ves_icall_System_Threading_Interlocked_Exchange_Single (gfloat * location, gfloat value)
{
  int D.21040;
  int D.21041;
  gfloat D.21042;
  union IntFloatUnion val;
  union IntFloatUnion ret;

  try
    {
      val.fval = value;
      D.21040 = val.ival;
      D.21041 = InterlockedExchange (location, D.21040);
      ret.ival = D.21041;
      D.21042 = ret.fval;
      return D.21042;
    }
  finally
    {
      val = {CLOBBER};
      ret = {CLOBBER};
    }
}


ves_icall_System_Threading_Interlocked_Exchange_Long (gint64 * location, gint64 value)
{
  unsigned int location.69;
  unsigned int D.21046;
  _Bool D.21047;
  long int D.21048;
  long int D.21049;
  _Bool D.21054;
  long int D.21055;
  long int D.21056;
  _Bool D.21061;
  long int D.21062;
  long int D.21063;
  gint64 D.21066;

  location.69 = (unsigned int) location;
  D.21046 = location.69 & 7;
  D.21047 = D.21046 != 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>:
  {
    gint64 ret;

    {
      int ret;

      ret = pthread_mutex_lock (&interlocked_mutex.mutex);
      if (ret != 0) goto <D.21052>; else goto <D.21053>;
      <D.21052>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
      <D.21053>:
      D.21054 = ret != 0;
      D.21055 = (long int) D.21054;
      D.21056 = __builtin_expect (D.21055, 0);
      if (D.21056 != 0) goto <D.21057>; else goto <D.21058>;
      <D.21057>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1828, "ret == 0");
      <D.21058>:
    }
    ret = *location;
    *location = value;
    {
      int ret;

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


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

  <D.18506>:
  old_val = *val;
  D.21068 = InterlockedCompareExchange64 (val, new_val, old_val);
  if (D.21068 != old_val) goto <D.18506>; else goto <D.18507>;
  <D.18507>:
  D.21069 = old_val;
  return D.21069;
}


InterlockedCompareExchange64 (volatile gint64 * dest, gint64 exch, gint64 comp)
{
  gint64 D.21071;
  long long unsigned int exch.70;
  long long unsigned int comp.71;
  long long unsigned int D.21074;

  exch.70 = (long long unsigned int) exch;
  comp.71 = (long long unsigned int) comp;
  D.21074 = __sync_val_compare_and_swap_8 (dest, comp.71, exch.70);
  D.21071 = (gint64) D.21074;
  return D.21071;
}


ves_icall_System_Threading_Interlocked_Exchange_Double (gdouble * location, gdouble value)
{
  long long int D.21076;
  long long int D.21077;
  gdouble D.21078;
  union LongDoubleUnion val;
  union LongDoubleUnion ret;

  try
    {
      val.fval = value;
      D.21076 = val.ival;
      D.21077 = InterlockedExchange64 (location, D.21076);
      ret.ival = D.21077;
      D.21078 = ret.fval;
      return D.21078;
    }
  finally
    {
      val = {CLOBBER};
      ret = {CLOBBER};
    }
}


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

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


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

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


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

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


ves_icall_System_Threading_Interlocked_CompareExchange_Single (gfloat * location, gfloat value, gfloat comparand)
{
  int D.21087;
  int D.21088;
  int D.21089;
  gfloat D.21090;
  union IntFloatUnion val;
  union IntFloatUnion ret;
  union IntFloatUnion cmp;

  try
    {
      val.fval = value;
      cmp.fval = comparand;
      D.21087 = cmp.ival;
      D.21088 = val.ival;
      D.21089 = InterlockedCompareExchange (location, D.21088, D.21087);
      ret.ival = D.21089;
      D.21090 = ret.fval;
      return D.21090;
    }
  finally
    {
      val = {CLOBBER};
      ret = {CLOBBER};
      cmp = {CLOBBER};
    }
}


ves_icall_System_Threading_Interlocked_CompareExchange_Double (gdouble * location, gdouble value, gdouble comparand)
{
  _Bool D.21095;
  long int D.21096;
  long int D.21097;
  _Bool D.21104;
  long int D.21105;
  long int D.21106;
  gdouble D.21109;
  gdouble old;

  {
    int ret;

    ret = pthread_mutex_lock (&interlocked_mutex.mutex);
    if (ret != 0) goto <D.21093>; else goto <D.21094>;
    <D.21093>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.21094>:
    D.21095 = ret != 0;
    D.21096 = (long int) D.21095;
    D.21097 = __builtin_expect (D.21096, 0);
    if (D.21097 != 0) goto <D.21098>; else goto <D.21099>;
    <D.21098>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1892, "ret == 0");
    <D.21099>:
  }
  old = *location;
  if (old == comparand) goto <D.21100>; else goto <D.21101>;
  <D.21100>:
  *location = value;
  <D.21101>:
  {
    int ret;

    ret = pthread_mutex_unlock (&interlocked_mutex.mutex);
    if (ret != 0) goto <D.21102>; else goto <D.21103>;
    <D.21102>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21103>:
    D.21104 = ret != 0;
    D.21105 = (long int) D.21104;
    D.21106 = __builtin_expect (D.21105, 0);
    if (D.21106 != 0) goto <D.21107>; else goto <D.21108>;
    <D.21107>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1896, "ret == 0");
    <D.21108>:
  }
  D.21109 = old;
  return D.21109;
}


ves_icall_System_Threading_Interlocked_CompareExchange_Long (gint64 * location, gint64 value, gint64 comparand)
{
  unsigned int location.72;
  unsigned int D.21112;
  _Bool D.21113;
  long int D.21114;
  long int D.21115;
  _Bool D.21120;
  long int D.21121;
  long int D.21122;
  _Bool D.21129;
  long int D.21130;
  long int D.21131;
  gint64 D.21134;

  location.72 = (unsigned int) location;
  D.21112 = location.72 & 7;
  D.21113 = D.21112 != 0;
  D.21114 = (long int) D.21113;
  D.21115 = __builtin_expect (D.21114, 0);
  if (D.21115 != 0) goto <D.21116>; else goto <D.21117>;
  <D.21116>:
  {
    gint64 old;

    {
      int ret;

      ret = pthread_mutex_lock (&interlocked_mutex.mutex);
      if (ret != 0) goto <D.21118>; else goto <D.21119>;
      <D.21118>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
      <D.21119>:
      D.21120 = ret != 0;
      D.21121 = (long int) D.21120;
      D.21122 = __builtin_expect (D.21121, 0);
      if (D.21122 != 0) goto <D.21123>; else goto <D.21124>;
      <D.21123>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1908, "ret == 0");
      <D.21124>:
    }
    old = *location;
    if (old == comparand) goto <D.21125>; else goto <D.21126>;
    <D.21125>:
    *location = value;
    <D.21126>:
    {
      int ret;

      ret = pthread_mutex_unlock (&interlocked_mutex.mutex);
      if (ret != 0) goto <D.21127>; else goto <D.21128>;
      <D.21127>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.21128>:
      D.21129 = ret != 0;
      D.21130 = (long int) D.21129;
      D.21131 = __builtin_expect (D.21130, 0);
      if (D.21131 != 0) goto <D.21132>; else goto <D.21133>;
      <D.21132>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1912, "ret == 0");
      <D.21133>:
    }
    D.21134 = old;
    return D.21134;
  }
  <D.21117>:
  D.21134 = InterlockedCompareExchange64 (location, value, comparand);
  return D.21134;
}


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

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


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

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


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

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


InterlockedAdd (volatile gint32 * dest, gint32 add)
{
  gint32 D.21142;
  unsigned int add.73;
  unsigned int D.21144;

  add.73 = (unsigned int) add;
  D.21144 = __sync_add_and_fetch_4 (dest, add.73);
  D.21142 = (gint32) D.21144;
  return D.21142;
}


ves_icall_System_Threading_Interlocked_Add_Long (gint64 * location, gint64 value)
{
  unsigned int location.74;
  unsigned int D.21147;
  _Bool D.21148;
  long int D.21149;
  long int D.21150;
  _Bool D.21155;
  long int D.21156;
  long int D.21157;
  long long int D.21160;
  long long int D.21161;
  _Bool D.21164;
  long int D.21165;
  long int D.21166;
  gint64 D.21169;

  location.74 = (unsigned int) location;
  D.21147 = location.74 & 7;
  D.21148 = D.21147 != 0;
  D.21149 = (long int) D.21148;
  D.21150 = __builtin_expect (D.21149, 0);
  if (D.21150 != 0) goto <D.21151>; else goto <D.21152>;
  <D.21151>:
  {
    gint64 ret;

    {
      int ret;

      ret = pthread_mutex_lock (&interlocked_mutex.mutex);
      if (ret != 0) goto <D.21153>; else goto <D.21154>;
      <D.21153>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
      <D.21154>:
      D.21155 = ret != 0;
      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", 1949, "ret == 0");
      <D.21159>:
    }
    D.21160 = *location;
    D.21161 = D.21160 + value;
    *location = D.21161;
    ret = *location;
    {
      int ret;

      ret = pthread_mutex_unlock (&interlocked_mutex.mutex);
      if (ret != 0) goto <D.21162>; else goto <D.21163>;
      <D.21162>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.21163>:
      D.21164 = ret != 0;
      D.21165 = (long int) D.21164;
      D.21166 = __builtin_expect (D.21165, 0);
      if (D.21166 != 0) goto <D.21167>; else goto <D.21168>;
      <D.21167>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1952, "ret == 0");
      <D.21168>:
    }
    D.21169 = ret;
    return D.21169;
  }
  <D.21152>:
  D.21169 = InterlockedAdd64 (location, value);
  return D.21169;
}


InterlockedAdd64 (volatile gint64 * dest, gint64 add)
{
  gint64 D.21171;
  long long unsigned int add.75;
  long long unsigned int D.21173;

  add.75 = (long long unsigned int) add;
  D.21173 = __sync_add_and_fetch_8 (dest, add.75);
  D.21171 = (gint64) D.21173;
  return D.21171;
}


ves_icall_System_Threading_Interlocked_Read_Long (gint64 * location)
{
  unsigned int location.76;
  unsigned int D.21176;
  _Bool D.21177;
  long int D.21178;
  long int D.21179;
  _Bool D.21184;
  long int D.21185;
  long int D.21186;
  _Bool D.21191;
  long int D.21192;
  long int D.21193;
  gint64 D.21196;

  location.76 = (unsigned int) location;
  D.21176 = location.76 & 7;
  D.21177 = D.21176 != 0;
  D.21178 = (long int) D.21177;
  D.21179 = __builtin_expect (D.21178, 0);
  if (D.21179 != 0) goto <D.21180>; else goto <D.21181>;
  <D.21180>:
  {
    gint64 ret;

    {
      int ret;

      ret = pthread_mutex_lock (&interlocked_mutex.mutex);
      if (ret != 0) goto <D.21182>; else goto <D.21183>;
      <D.21182>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
      <D.21183>:
      D.21184 = ret != 0;
      D.21185 = (long int) D.21184;
      D.21186 = __builtin_expect (D.21185, 0);
      if (D.21186 != 0) goto <D.21187>; else goto <D.21188>;
      <D.21187>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1965, "ret == 0");
      <D.21188>:
    }
    ret = *location;
    {
      int ret;

      ret = pthread_mutex_unlock (&interlocked_mutex.mutex);
      if (ret != 0) goto <D.21189>; else goto <D.21190>;
      <D.21189>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.21190>:
      D.21191 = ret != 0;
      D.21192 = (long int) D.21191;
      D.21193 = __builtin_expect (D.21192, 0);
      if (D.21193 != 0) goto <D.21194>; else goto <D.21195>;
      <D.21194>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1967, "ret == 0");
      <D.21195>:
    }
    D.21196 = ret;
    return D.21196;
  }
  <D.21181>:
  D.21196 = InterlockedRead64 (location);
  return D.21196;
}


InterlockedRead64 (volatile gint64 * src)
{
  gint64 D.21198;
  long long unsigned int D.21199;

  D.21199 = __sync_fetch_and_add_8 (src, 0);
  D.21198 = (gint64) D.21199;
  return D.21198;
}


ves_icall_System_Threading_Thread_MemoryBarrier ()
{
  mono_memory_barrier ();
}


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

  mono_thread_clr_state (this, state);
  D.21201 = state & 4;
  if (D.21201 != 0) goto <D.21202>; else goto <D.21203>;
  <D.21202>:
  background_change_event.77 = background_change_event;
  SetEvent (background_change_event.77);
  <D.21203>:
}


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

  mono_thread_set_state (this, state);
  D.21205 = state & 4;
  if (D.21205 != 0) goto <D.21206>; else goto <D.21207>;
  <D.21206>:
  background_change_event.78 = background_change_event;
  SetEvent (background_change_event.78);
  <D.21207>:
}


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

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


ves_icall_System_Threading_Thread_Interrupt_internal (struct MonoInternalThread * this)
{
  int iftmp.79;
  unsigned int D.21215;
  unsigned int D.21216;
  struct MonoInternalThread * current;
  gboolean throw;

  lock_thread (this);
  current = mono_thread_internal_current ();
  this->thread_interrupt_requested = 1;
  if (current != this) goto <D.21214>; else goto <D.21212>;
  <D.21214>:
  D.21215 = this->state;
  D.21216 = D.21215 & 32;
  if (D.21216 != 0) goto <D.21217>; else goto <D.21212>;
  <D.21217>:
  iftmp.79 = 1;
  goto <D.21213>;
  <D.21212>:
  iftmp.79 = 0;
  <D.21213>:
  throw = iftmp.79;
  unlock_thread (this);
  if (throw != 0) goto <D.21218>; else goto <D.21219>;
  <D.21218>:
  abort_thread_internal (this, 1, 0);
  <D.21219>:
}


abort_thread_internal (struct MonoInternalThread * thread, gboolean can_raise_exception, gboolean install_async_abort)
{
  int D.21220;
  struct MonoInternalThread * D.21223;
  void * D.21228;
  long long unsigned int D.21229;
  long unsigned int D.21230;
  struct MonoRuntimeExceptionHandlingCallbacks * D.21233;
  gboolean (*<T266e>) (struct MonoThreadUnwindState *) D.21234;
  struct MonoThreadUnwindState * D.21235;
  int D.21236;
  unsigned int D.21239;
  gint32 * D.21240;
  int D.21241;
  int iftmp.80;
  struct MonoMethod * D.21248;
  int D.21249;
  int D.21251;
  void * D.21252;
  _Bool D.21253;
  _Bool D.21254;
  _Bool D.21255;
  struct MonoJitInfo * ji;
  struct MonoThreadInfo * info;
  gboolean protected_wrapper;
  gboolean running_managed;

  info = 0B;
  D.21220 = mono_thread_info_new_interrupt_enabled ();
  if (D.21220 == 0) goto <D.21221>; else goto <D.21222>;
  <D.21221>:
  signal_thread_state_change (thread);
  return;
  <D.21222>:
  D.21223 = mono_thread_internal_current ();
  if (D.21223 == thread) goto <D.21224>; else goto <D.21225>;
  <D.21224>:
  {
    struct MonoException * exc;

    exc = mono_thread_request_interruption (can_raise_exception);
    if (exc != 0B) goto <D.21226>; else goto <D.21227>;
    <D.21226>:
    mono_raise_exception (exc);
    <D.21227>:
    D.21228 = thread->handle;
    wapi_interrupt_thread (D.21228);
    return;
  }
  <D.21225>:
  D.21229 = thread->tid;
  D.21230 = (long unsigned int) D.21229;
  info = mono_thread_info_safe_suspend_sync (D.21230, 1);
  if (info == 0B) goto <D.21231>; else goto <D.21232>;
  <D.21231>:
  return;
  <D.21232>:
  D.21233 = mono_get_eh_callbacks ();
  D.21234 = D.21233->mono_install_handler_block_guard;
  D.21235 = &info->suspend_state;
  D.21236 = D.21234 (D.21235);
  if (D.21236 != 0) goto <D.21237>; else goto <D.21238>;
  <D.21237>:
  D.21239 = info->node.key;
  mono_thread_info_resume (D.21239);
  return;
  <D.21238>:
  D.21240 = &thread->interruption_requested;
  D.21241 = InterlockedCompareExchange (D.21240, 1, 0);
  if (D.21241 == 1) goto <D.21242>; else goto <D.21243>;
  <D.21242>:
  D.21239 = info->node.key;
  mono_thread_info_resume (D.21239);
  return;
  <D.21243>:
  InterlockedIncrement (&thread_interruption_requested);
  ji = mono_thread_info_get_last_managed (info);
  if (ji != 0B) goto <D.21247>; else goto <D.21245>;
  <D.21247>:
  D.21248 = mono_jit_info_get_method (ji);
  D.21249 = mono_threads_is_critical_method (D.21248);
  if (D.21249 != 0) goto <D.21250>; else goto <D.21245>;
  <D.21250>:
  iftmp.80 = 1;
  goto <D.21246>;
  <D.21245>:
  iftmp.80 = 0;
  <D.21246>:
  protected_wrapper = iftmp.80;
  D.21251 = info->suspend_state.ctx.eip;
  D.21252 = (void *) D.21251;
  running_managed = mono_jit_info_match (ji, D.21252);
  D.21253 = protected_wrapper == 0;
  D.21254 = running_managed != 0;
  D.21255 = D.21253 & D.21254;
  if (D.21255 != 0) goto <D.21256>; else goto <D.21257>;
  <D.21256>:
  if (install_async_abort != 0) goto <D.21258>; else goto <D.21259>;
  <D.21258>:
  mono_thread_info_setup_async_call (info, self_interrupt_thread, 0B);
  <D.21259>:
  D.21239 = info->node.key;
  mono_thread_info_resume (D.21239);
  goto <D.21260>;
  <D.21257>:
  {
    void * interrupt_handle;

    D.21228 = thread->handle;
    interrupt_handle = wapi_prepare_interrupt_thread (D.21228);
    D.21239 = info->node.key;
    mono_thread_info_resume (D.21239);
    wapi_finish_interrupt_thread (interrupt_handle);
  }
  <D.21260>:
}


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

  info = mono_thread_info_current ();
  D.21262 = mono_thread_internal_current ();
  exc = mono_thread_execute_interruption (D.21262);
  if (exc != 0B) goto <D.21263>; else goto <D.21264>;
  <D.21263>:
  D.21265 = &info->suspend_state.ctx;
  mono_raise_exception_with_context (exc, D.21265);
  <D.21264>:
  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.21266;
  int D.21271;
  void * D.21272;

  D.21266 = mono_thread_internal_current ();
  if (D.21266 == thread) goto <D.21267>; else goto <D.21268>;
  <D.21267>:
  {
    struct MonoException * exc;

    exc = mono_thread_request_interruption (0);
    if (exc != 0B) goto <D.21269>; else goto <D.21270>;
    <D.21269>:
    mono_raise_exception (exc);
    <D.21270>:
  }
  <D.21268>:
  D.21271 = mono_thread_get_abort_signal ();
  mono_thread_kill (thread, D.21271);
  D.21272 = thread->handle;
  wapi_interrupt_thread (D.21272);
}


mono_thread_info_get_last_managed (struct MonoThreadInfo * info)
{
  struct MonoJitInfo * D.21275;
  struct MonoRuntimeExceptionHandlingCallbacks * D.21276;
  void (*<T265e>) (gboolean (*MonoInternalStackWalk) (struct MonoStackFrameInfo *, struct MonoContext *, void *), struct MonoThreadUnwindState *, MonoUnwindOptions, void *) D.21277;
  struct MonoThreadUnwindState * D.21278;
  struct MonoJitInfo * ji;

  try
    {
      ji = 0B;
      if (info == 0B) goto <D.21273>; else goto <D.21274>;
      <D.21273>:
      D.21275 = 0B;
      return D.21275;
      <D.21274>:
      D.21276 = mono_get_eh_callbacks ();
      D.21277 = D.21276->mono_walk_stack_with_state;
      D.21278 = &info->suspend_state;
      D.21277 (last_managed, D.21278, 0, &ji);
      D.21275 = ji;
      return D.21275;
    }
  finally
    {
      ji = {CLOBBER};
    }
}


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

  dest = data;
  D.21281 = frame->ji;
  *dest = D.21281;
  D.21282 = 1;
  return D.21282;
}


mono_threads_is_critical_method (struct MonoMethod * method)
{
  <unnamed-unsigned:5> D.21284;
  int D.21285;
  gboolean D.21286;

  D.21284 = method->wrapper_type;
  D.21285 = (int) D.21284;
  switch (D.21285) <default: <D.21287>, case 4: <D.19159>, case 10: <D.19160>, case 11: <D.19161>>
  <D.19159>:
  <D.19160>:
  <D.19161>:
  D.21286 = 1;
  return D.21286;
  <D.21287>:
  D.21286 = 0;
  return D.21286;
}


mono_jit_info_match (struct MonoJitInfo * ji, void * ip)
{
  gboolean D.21291;
  int iftmp.81;
  void * D.21295;
  int D.21297;
  sizetype D.21298;
  char * D.21299;

  if (ji == 0B) goto <D.21289>; else goto <D.21290>;
  <D.21289>:
  D.21291 = 0;
  return D.21291;
  <D.21290>:
  D.21295 = ji->code_start;
  if (D.21295 <= ip) goto <D.21296>; else goto <D.21293>;
  <D.21296>:
  D.21295 = ji->code_start;
  D.21297 = ji->code_size;
  D.21298 = (sizetype) D.21297;
  D.21299 = D.21295 + D.21298;
  if (D.21299 > ip) goto <D.21300>; else goto <D.21293>;
  <D.21300>:
  iftmp.81 = 1;
  goto <D.21294>;
  <D.21293>:
  iftmp.81 = 0;
  <D.21294>:
  D.21291 = iftmp.81;
  return D.21291;
}


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

  thread = mono_thread_internal_current ();
  throw = 0;
  lock_thread (thread);
  D.21302 = thread->thread_interrupt_requested;
  if (D.21302 != 0) goto <D.21303>; else goto <D.21304>;
  <D.21303>:
  throw = 1;
  thread->thread_interrupt_requested = 0;
  <D.21304>:
  unlock_thread (thread);
  if (throw != 0) goto <D.21305>; else goto <D.21306>;
  <D.21305>:
  D.21307 = mono_get_exception_thread_interrupted ();
  mono_raise_exception (D.21307);
  <D.21306>:
}


mono_thread_get_abort_signal ()
{
  int abort_signum.82;
  int D.21311;
  int D.21312;
  void (*<Te0d>) (int) D.21313;
  void (*<Te50>) (int, struct siginfo_t *, void *) D.21316;
  int D.21319;
  static int abort_signum = -1;
  int i;

  abort_signum.82 = abort_signum;
  if (abort_signum.82 != -1) goto <D.21309>; else goto <D.21310>;
  <D.21309>:
  D.21311 = abort_signum;
  return D.21311;
  <D.21310>:
  D.21312 = __libc_current_sigrtmin ();
  i = D.21312 + 1;
  goto <D.19116>;
  <D.19115>:
  {
    struct sigaction sinfo;

    try
      {
        sigaction (i, 0B, &sinfo);
        D.21313 = sinfo.__sigaction_handler.sa_handler;
        if (D.21313 == 0B) goto <D.21314>; else goto <D.21315>;
        <D.21314>:
        D.21316 = sinfo.__sigaction_handler.sa_sigaction;
        if (D.21316 == 0B) goto <D.21317>; else goto <D.21318>;
        <D.21317>:
        abort_signum = i;
        D.21311 = i;
        return D.21311;
        <D.21318>:
        <D.21315>:
      }
    finally
      {
        sinfo = {CLOBBER};
      }
  }
  i = i + 1;
  <D.19116>:
  D.21319 = __libc_current_sigrtmax ();
  if (D.21319 > i) goto <D.19115>; else goto <D.19117>;
  <D.19117>:
  D.21311 = __libc_current_sigrtmin ();
  return D.21311;
}


ves_icall_System_Threading_Thread_Abort (struct MonoInternalThread * thread, struct MonoObject * state)
{
  unsigned int D.21323;
  unsigned int D.21324;
  unsigned int D.21327;
  unsigned int D.21328;
  unsigned int D.21331;
  unsigned int D.21332;
  int D.21333;
  unsigned int D.21336;
  unsigned int D.21339;
  int D.21340;
  _Bool D.21341;
  long int D.21342;
  long int D.21343;
  int shutting_down.83;

  lock_thread (thread);
  D.21323 = BIT_FIELD_REF <*thread, 32, 224>;
  D.21324 = D.21323 & 145;
  if (D.21324 != 0) goto <D.21325>; else goto <D.21326>;
  <D.21325>:
  unlock_thread (thread);
  return;
  <D.21326>:
  D.21327 = thread->state;
  D.21328 = D.21327 & 8;
  if (D.21328 != 0) goto <D.21329>; else goto <D.21330>;
  <D.21329>:
  D.21327 = thread->state;
  D.21331 = D.21327 | 256;
  thread->state = D.21331;
  unlock_thread (thread);
  return;
  <D.21330>:
  D.21327 = thread->state;
  D.21332 = D.21327 | 128;
  thread->state = D.21332;
  D.21333 = thread->abort_state_handle;
  if (D.21333 != 0) goto <D.21334>; else goto <D.21335>;
  <D.21334>:
  D.21333 = thread->abort_state_handle;
  D.21336 = (unsigned int) D.21333;
  mono_gchandle_free (D.21336);
  <D.21335>:
  if (state != 0B) goto <D.21337>; else goto <D.21338>;
  <D.21337>:
  D.21339 = mono_gchandle_new (state, 0);
  D.21340 = (int) D.21339;
  thread->abort_state_handle = D.21340;
  D.21333 = thread->abort_state_handle;
  D.21341 = D.21333 == 0;
  D.21342 = (long int) D.21341;
  D.21343 = __builtin_expect (D.21342, 0);
  if (D.21343 != 0) goto <D.21344>; else goto <D.21345>;
  <D.21344>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2156, "thread->abort_state_handle");
  <D.21345>:
  goto <D.21346>;
  <D.21338>:
  thread->abort_state_handle = 0;
  <D.21346>:
  thread->abort_exc = 0B;
  unlock_thread (thread);
  shutting_down.83 = shutting_down;
  if (shutting_down.83 == 0) goto <D.21348>; else goto <D.21349>;
  <D.21348>:
  mono_thread_resume (thread);
  <D.21349>:
  abort_thread_internal (thread, 1, 1);
}


mono_thread_resume (struct MonoInternalThread * thread)
{
  unsigned int D.21351;
  unsigned int D.21352;
  unsigned int D.21355;
  gboolean D.21356;
  unsigned int D.21357;
  unsigned int D.21358;

  lock_thread (thread);
  D.21351 = thread->state;
  D.21352 = D.21351 & 2;
  if (D.21352 != 0) goto <D.21353>; else goto <D.21354>;
  <D.21353>:
  D.21351 = thread->state;
  D.21355 = D.21351 & 4294967293;
  thread->state = D.21355;
  unlock_thread (thread);
  D.21356 = 1;
  return D.21356;
  <D.21354>:
  D.21357 = BIT_FIELD_REF <*thread, 32, 224>;
  D.21358 = D.21357 & 344;
  if (D.21358 != 64) goto <D.21359>; else goto <D.21360>;
  <D.21359>:
  unlock_thread (thread);
  D.21356 = 0;
  return D.21356;
  <D.21360>:
  D.21356 = resume_thread_internal (thread);
  return D.21356;
}


resume_thread_internal (struct MonoInternalThread * thread)
{
  int D.21362;
  void * D.21365;
  void * D.21366;
  gboolean D.21369;
  void * D.21370;
  long long unsigned int D.21371;
  long unsigned int D.21372;
  int D.21373;
  unsigned int D.21376;
  unsigned int D.21377;

  D.21362 = mono_thread_info_new_interrupt_enabled ();
  if (D.21362 == 0) goto <D.21363>; else goto <D.21364>;
  <D.21363>:
  D.21365 = CreateEvent (0B, 1, 0, 0B);
  thread->resume_event = D.21365;
  D.21366 = thread->resume_event;
  if (D.21366 == 0B) goto <D.21367>; else goto <D.21368>;
  <D.21367>:
  unlock_thread (thread);
  D.21369 = 0;
  return D.21369;
  <D.21368>:
  D.21370 = thread->suspend_event;
  SetEvent (D.21370);
  unlock_thread (thread);
  D.21366 = thread->resume_event;
  WaitForSingleObject (D.21366, 4294967295);
  D.21366 = thread->resume_event;
  CloseHandle (D.21366);
  thread->resume_event = 0B;
  D.21369 = 1;
  return D.21369;
  <D.21364>:
  unlock_thread (thread);
  D.21371 = thread->tid;
  D.21372 = (long unsigned int) D.21371;
  D.21373 = mono_thread_info_resume (D.21372);
  if (D.21373 == 0) goto <D.21374>; else goto <D.21375>;
  <D.21374>:
  D.21369 = 0;
  return D.21369;
  <D.21375>:
  lock_thread (thread);
  D.21376 = thread->state;
  D.21377 = D.21376 & 4294967231;
  thread->state = D.21377;
  unlock_thread (thread);
  D.21369 = 1;
  return D.21369;
}


ves_icall_System_Threading_Thread_ResetAbort ()
{
  unsigned int D.21379;
  int D.21380;
  unsigned int D.21381;
  struct MonoException * D.21384;
  int D.21385;
  unsigned int D.21388;
  struct MonoInternalThread * thread;
  gboolean was_aborting;

  thread = mono_thread_internal_current ();
  lock_thread (thread);
  D.21379 = thread->state;
  D.21380 = (int) D.21379;
  was_aborting = D.21380 & 128;
  D.21379 = thread->state;
  D.21381 = D.21379 & 4294967167;
  thread->state = D.21381;
  unlock_thread (thread);
  if (was_aborting == 0) goto <D.21382>; else goto <D.21383>;
  <D.21382>:
  {
    const char * msg;

    msg = "Unable to reset abort because no abort was requested";
    D.21384 = mono_get_exception_thread_state (msg);
    mono_raise_exception (D.21384);
  }
  <D.21383>:
  thread->abort_exc = 0B;
  D.21385 = thread->abort_state_handle;
  if (D.21385 != 0) goto <D.21386>; else goto <D.21387>;
  <D.21386>:
  D.21385 = thread->abort_state_handle;
  D.21388 = (unsigned int) D.21385;
  mono_gchandle_free (D.21388);
  thread->abort_state_handle = 0;
  <D.21387>:
}


mono_thread_internal_reset_abort (struct MonoInternalThread * thread)
{
  unsigned int D.21389;
  unsigned int D.21390;
  struct MonoException * D.21391;
  int D.21394;
  unsigned int D.21397;

  lock_thread (thread);
  D.21389 = thread->state;
  D.21390 = D.21389 & 4294967167;
  thread->state = D.21390;
  D.21391 = thread->abort_exc;
  if (D.21391 != 0B) goto <D.21392>; else goto <D.21393>;
  <D.21392>:
  thread->abort_exc = 0B;
  D.21394 = thread->abort_state_handle;
  if (D.21394 != 0) goto <D.21395>; else goto <D.21396>;
  <D.21395>:
  D.21394 = thread->abort_state_handle;
  D.21397 = (unsigned int) D.21394;
  mono_gchandle_free (D.21397);
  thread->abort_state_handle = 0;
  <D.21396>:
  <D.21393>:
  unlock_thread (thread);
}


ves_icall_System_Threading_Thread_GetAbortExceptionState (struct MonoThread * this)
{
  int D.21398;
  struct MonoObject * D.21401;
  unsigned int D.21402;
  _Bool D.21403;
  long int D.21404;
  long int D.21405;
  struct MonoVTable * D.21408;
  struct MonoDomain * D.21409;
  struct MonoObject * exc.84;
  struct MonoObject * * D.21417;
  struct MonoInternalThread * thread;
  struct MonoObject * state;
  struct MonoObject * deserialized;
  struct MonoObject * exc;
  struct MonoDomain * domain;

  try
    {
      thread = this->internal_thread;
      deserialized = 0B;
      D.21398 = thread->abort_state_handle;
      if (D.21398 == 0) goto <D.21399>; else goto <D.21400>;
      <D.21399>:
      D.21401 = 0B;
      return D.21401;
      <D.21400>:
      D.21398 = thread->abort_state_handle;
      D.21402 = (unsigned int) D.21398;
      state = mono_gchandle_get_target (D.21402);
      D.21403 = state == 0B;
      D.21404 = (long int) D.21403;
      D.21405 = __builtin_expect (D.21404, 0);
      if (D.21405 != 0) goto <D.21406>; else goto <D.21407>;
      <D.21406>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2237, "state");
      <D.21407>:
      domain = mono_domain_get ();
      D.21408 = state->vtable;
      D.21409 = D.21408->domain;
      if (D.21409 == domain) goto <D.21410>; else goto <D.21411>;
      <D.21410>:
      D.21401 = state;
      return D.21401;
      <D.21411>:
      deserialized = mono_object_xdomain_representation (state, domain, &exc);
      if (deserialized == 0B) goto <D.21412>; else goto <D.21413>;
      <D.21412>:
      {
        struct MonoException * invalid_op_exc;

        invalid_op_exc = mono_get_exception_invalid_operation ("Thread.ExceptionState cannot access an ExceptionState from a different AppDomain");
        exc.84 = exc;
        if (exc.84 != 0B) goto <D.21415>; else goto <D.21416>;
        <D.21415>:
        exc.84 = exc;
        D.21417 = &invalid_op_exc->inner_ex;
        mono_gc_wbarrier_set_field (invalid_op_exc, D.21417, exc.84);
        <D.21416>:
        mono_raise_exception (invalid_op_exc);
      }
      <D.21413>:
      D.21401 = deserialized;
      return D.21401;
    }
  finally
    {
      exc = {CLOBBER};
    }
}


ves_icall_System_Threading_Thread_Suspend (struct MonoInternalThread * thread)
{
  int D.21420;
  struct MonoException * D.21423;

  D.21420 = mono_thread_suspend (thread);
  if (D.21420 == 0) goto <D.21421>; else goto <D.21422>;
  <D.21421>:
  D.21423 = mono_get_exception_thread_state ("Thread has not been started, or is dead.");
  mono_raise_exception (D.21423);
  <D.21422>:
}


mono_thread_suspend (struct MonoInternalThread * thread)
{
  unsigned int D.21424;
  unsigned int D.21425;
  gboolean D.21428;
  unsigned int D.21429;
  unsigned int D.21432;
  unsigned int D.21433;

  lock_thread (thread);
  D.21424 = BIT_FIELD_REF <*thread, 32, 224>;
  D.21425 = D.21424 & 280;
  if (D.21425 != 0) goto <D.21426>; else goto <D.21427>;
  <D.21426>:
  unlock_thread (thread);
  D.21428 = 0;
  return D.21428;
  <D.21427>:
  D.21424 = BIT_FIELD_REF <*thread, 32, 224>;
  D.21429 = D.21424 & 67;
  if (D.21429 != 0) goto <D.21430>; else goto <D.21431>;
  <D.21430>:
  unlock_thread (thread);
  D.21428 = 1;
  return D.21428;
  <D.21431>:
  D.21432 = thread->state;
  D.21433 = D.21432 | 2;
  thread->state = D.21433;
  unlock_thread (thread);
  suspend_thread_internal (thread, 0);
  D.21428 = 1;
  return D.21428;
}


suspend_thread_internal (struct MonoInternalThread * thread, gboolean interrupt)
{
  int D.21435;
  struct MonoInternalThread * D.21438;
  long long unsigned int D.21442;
  long unsigned int D.21443;
  int iftmp.85;
  struct MonoMethod * D.21450;
  int D.21451;
  int D.21453;
  void * D.21454;
  _Bool D.21455;
  _Bool D.21456;
  _Bool D.21457;
  gint32 * D.21461;
  int D.21462;
  void * D.21467;
  unsigned int D.21468;

  D.21435 = mono_thread_info_new_interrupt_enabled ();
  if (D.21435 == 0) goto <D.21436>; else goto <D.21437>;
  <D.21436>:
  signal_thread_state_change (thread);
  return;
  <D.21437>:
  lock_thread (thread);
  D.21438 = mono_thread_internal_current ();
  if (D.21438 == thread) goto <D.21439>; else goto <D.21440>;
  <D.21439>:
  transition_to_suspended (thread);
  mono_thread_info_self_suspend ();
  goto <D.21441>;
  <D.21440>:
  {
    struct MonoThreadInfo * info;
    struct MonoJitInfo * ji;
    gboolean protected_wrapper;
    gboolean running_managed;

    D.21442 = thread->tid;
    D.21443 = (long unsigned int) D.21442;
    info = mono_thread_info_safe_suspend_sync (D.21443, interrupt);
    if (info == 0B) goto <D.21444>; else goto <D.21445>;
    <D.21444>:
    unlock_thread (thread);
    return;
    <D.21445>:
    ji = mono_thread_info_get_last_managed (info);
    if (ji != 0B) goto <D.21449>; else goto <D.21447>;
    <D.21449>:
    D.21450 = mono_jit_info_get_method (ji);
    D.21451 = mono_threads_is_critical_method (D.21450);
    if (D.21451 != 0) goto <D.21452>; else goto <D.21447>;
    <D.21452>:
    iftmp.85 = 1;
    goto <D.21448>;
    <D.21447>:
    iftmp.85 = 0;
    <D.21448>:
    protected_wrapper = iftmp.85;
    D.21453 = info->suspend_state.ctx.eip;
    D.21454 = (void *) D.21453;
    running_managed = mono_jit_info_match (ji, D.21454);
    D.21455 = running_managed != 0;
    D.21456 = protected_wrapper == 0;
    D.21457 = D.21455 & D.21456;
    if (D.21457 != 0) goto <D.21458>; else goto <D.21459>;
    <D.21458>:
    transition_to_suspended (thread);
    goto <D.21460>;
    <D.21459>:
    {
      void * interrupt_handle;

      D.21461 = &thread->interruption_requested;
      D.21462 = InterlockedCompareExchange (D.21461, 1, 0);
      if (D.21462 == 0) goto <D.21463>; else goto <D.21464>;
      <D.21463>:
      InterlockedIncrement (&thread_interruption_requested);
      <D.21464>:
      if (interrupt != 0) goto <D.21465>; else goto <D.21466>;
      <D.21465>:
      D.21467 = thread->handle;
      interrupt_handle = wapi_prepare_interrupt_thread (D.21467);
      <D.21466>:
      D.21468 = info->node.key;
      mono_thread_info_resume (D.21468);
      if (interrupt != 0) goto <D.21469>; else goto <D.21470>;
      <D.21469>:
      wapi_finish_interrupt_thread (interrupt_handle);
      <D.21470>:
      unlock_thread (thread);
    }
    <D.21460>:
  }
  <D.21441>:
}


ves_icall_System_Threading_Thread_Resume (struct MonoThread * thread)
{
  struct _MonoInternalThread * D.21474;
  int D.21476;
  struct MonoException * D.21477;

  D.21474 = thread->internal_thread;
  if (D.21474 == 0B) goto <D.21472>; else goto <D.21475>;
  <D.21475>:
  D.21474 = thread->internal_thread;
  D.21476 = mono_thread_resume (D.21474);
  if (D.21476 == 0) goto <D.21472>; else goto <D.21473>;
  <D.21472>:
  D.21477 = mono_get_exception_thread_state ("Thread has not been started, or is dead.");
  mono_raise_exception (D.21477);
  <D.21473>:
}


mono_thread_internal_stop (struct MonoInternalThread * thread)
{
  unsigned int D.21478;
  unsigned int D.21479;
  unsigned int D.21482;
  unsigned int D.21483;
  unsigned int D.21484;

  lock_thread (thread);
  D.21478 = BIT_FIELD_REF <*thread, 32, 224>;
  D.21479 = D.21478 & 17;
  if (D.21479 != 0) goto <D.21480>; else goto <D.21481>;
  <D.21480>:
  unlock_thread (thread);
  return;
  <D.21481>:
  mono_thread_resume (thread);
  D.21482 = thread->state;
  D.21483 = D.21482 | 1;
  thread->state = D.21483;
  D.21482 = thread->state;
  D.21484 = D.21482 & 4294967167;
  thread->state = D.21484;
  unlock_thread (thread);
  abort_thread_internal (thread, 1, 1);
}


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

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


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

  {
    gint8 __tmp;

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


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

  {
    gint16 __tmp;

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


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

  {
    gint32 __tmp;

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


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

  {
    gint64 __tmp;

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


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

  {
    volatile void * __tmp;

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


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

  {
    volatile struct MonoObject * __tmp;

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


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

  {
    double __tmp;

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


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

  {
    float __tmp;

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


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

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


InterlockedRead8 (volatile gint8 * src)
{
  gint8 D.21505;
  unsigned char D.21506;

  D.21506 = __sync_fetch_and_add_1 (src, 0);
  D.21505 = (gint8) D.21506;
  return D.21505;
}


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

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


InterlockedRead16 (volatile gint16 * src)
{
  gint16 D.21510;
  short unsigned int D.21511;

  D.21511 = __sync_fetch_and_add_2 (src, 0);
  D.21510 = (gint16) D.21511;
  return D.21510;
}


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

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


InterlockedRead (volatile gint32 * src)
{
  gint32 D.21515;
  unsigned int D.21516;

  D.21516 = __sync_fetch_and_add_4 (src, 0);
  D.21515 = (gint32) D.21516;
  return D.21515;
}


ves_icall_System_Threading_Volatile_Read8 (void * ptr)
{
  unsigned int ptr.86;
  unsigned int D.21519;
  _Bool D.21520;
  long int D.21521;
  long int D.21522;
  _Bool D.21527;
  long int D.21528;
  long int D.21529;
  _Bool D.21534;
  long int D.21535;
  long int D.21536;
  gint64 D.21539;

  ptr.86 = (unsigned int) ptr;
  D.21519 = ptr.86 & 7;
  D.21520 = D.21519 != 0;
  D.21521 = (long int) D.21520;
  D.21522 = __builtin_expect (D.21521, 0);
  if (D.21522 != 0) goto <D.21523>; else goto <D.21524>;
  <D.21523>:
  {
    gint64 val;

    {
      int ret;

      ret = pthread_mutex_lock (&interlocked_mutex.mutex);
      if (ret != 0) goto <D.21525>; else goto <D.21526>;
      <D.21525>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
      <D.21526>:
      D.21527 = ret != 0;
      D.21528 = (long int) D.21527;
      D.21529 = __builtin_expect (D.21528, 0);
      if (D.21529 != 0) goto <D.21530>; else goto <D.21531>;
      <D.21530>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2469, "ret == 0");
      <D.21531>:
    }
    val = MEM[(gint64 *)ptr];
    {
      int ret;

      ret = pthread_mutex_unlock (&interlocked_mutex.mutex);
      if (ret != 0) goto <D.21532>; else goto <D.21533>;
      <D.21532>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.21533>:
      D.21534 = ret != 0;
      D.21535 = (long int) D.21534;
      D.21536 = __builtin_expect (D.21535, 0);
      if (D.21536 != 0) goto <D.21537>; else goto <D.21538>;
      <D.21537>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2471, "ret == 0");
      <D.21538>:
    }
    D.21539 = val;
    return D.21539;
  }
  <D.21524>:
  D.21539 = InterlockedRead64 (ptr);
  return D.21539;
}


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

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


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

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


ves_icall_System_Threading_Volatile_ReadDouble (void * ptr)
{
  unsigned int ptr.87;
  unsigned int D.21546;
  _Bool D.21547;
  long int D.21548;
  long int D.21549;
  _Bool D.21554;
  long int D.21555;
  long int D.21556;
  _Bool D.21561;
  long int D.21562;
  long int D.21563;
  double D.21566;
  long long int D.21567;
  union LongDoubleUnion u;

  try
    {
      ptr.87 = (unsigned int) ptr;
      D.21546 = ptr.87 & 7;
      D.21547 = D.21546 != 0;
      D.21548 = (long int) D.21547;
      D.21549 = __builtin_expect (D.21548, 0);
      if (D.21549 != 0) goto <D.21550>; else goto <D.21551>;
      <D.21550>:
      {
        double val;

        {
          int ret;

          ret = pthread_mutex_lock (&interlocked_mutex.mutex);
          if (ret != 0) goto <D.21552>; else goto <D.21553>;
          <D.21552>:
          monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
          <D.21553>:
          D.21554 = ret != 0;
          D.21555 = (long int) D.21554;
          D.21556 = __builtin_expect (D.21555, 0);
          if (D.21556 != 0) goto <D.21557>; else goto <D.21558>;
          <D.21557>:
          monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2492, "ret == 0");
          <D.21558>:
        }
        val = MEM[(double *)ptr];
        {
          int ret;

          ret = pthread_mutex_unlock (&interlocked_mutex.mutex);
          if (ret != 0) goto <D.21559>; else goto <D.21560>;
          <D.21559>:
          monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
          <D.21560>:
          D.21561 = ret != 0;
          D.21562 = (long int) D.21561;
          D.21563 = __builtin_expect (D.21562, 0);
          if (D.21563 != 0) goto <D.21564>; else goto <D.21565>;
          <D.21564>:
          monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2494, "ret == 0");
          <D.21565>:
        }
        D.21566 = val;
        return D.21566;
      }
      <D.21551>:
      D.21567 = InterlockedRead64 (ptr);
      u.ival = D.21567;
      D.21566 = u.fval;
      return D.21566;
    }
  finally
    {
      u = {CLOBBER};
    }
}


ves_icall_System_Threading_Volatile_ReadFloat (void * ptr)
{
  int D.21570;
  float D.21571;
  union IntFloatUnion u;

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


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

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


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


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


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


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


ves_icall_System_Threading_Thread_VolatileWriteIntPtr (void * ptr, void * value)
{
  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)
{
  MEM[(volatile double *)ptr] = value;
}


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


ves_icall_System_Threading_Volatile_Write1 (void * ptr, gint8 value)
{
  int D.21576;

  D.21576 = (int) value;
  InterlockedWrite8 (ptr, D.21576);
}


InterlockedWrite8 (volatile gint8 * dst, gint8 val)
{
  unsigned char val.88;
  int D.21578;
  unsigned char old_val.89;
  int D.21580;
  unsigned char D.21581;
  signed char D.21582;
  gint8 old_val;

  <D.18456>:
  old_val = *dst;
  val.88 = (unsigned char) val;
  D.21578 = (int) val.88;
  old_val.89 = (unsigned char) old_val;
  D.21580 = (int) old_val.89;
  D.21581 = __sync_val_compare_and_swap_1 (dst, D.21580, D.21578);
  D.21582 = (signed char) D.21581;
  if (D.21582 != old_val) goto <D.18456>; else goto <D.18457>;
  <D.18457>:
}


ves_icall_System_Threading_Volatile_Write2 (void * ptr, gint16 value)
{
  int D.21583;

  D.21583 = (int) value;
  InterlockedWrite16 (ptr, D.21583);
}


InterlockedWrite16 (volatile gint16 * dst, gint16 val)
{
  short unsigned int val.90;
  int D.21585;
  short unsigned int old_val.91;
  int D.21587;
  short unsigned int D.21588;
  short int D.21589;
  gint16 old_val;

  <D.18463>:
  old_val = *dst;
  val.90 = (short unsigned int) val;
  D.21585 = (int) val.90;
  old_val.91 = (short unsigned int) old_val;
  D.21587 = (int) old_val.91;
  D.21588 = __sync_val_compare_and_swap_2 (dst, D.21587, D.21585);
  D.21589 = (short int) D.21588;
  if (D.21589 != old_val) goto <D.18463>; else goto <D.18464>;
  <D.18464>:
}


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


InterlockedWrite (volatile gint32 * dst, gint32 val)
{
  unsigned int val.92;
  unsigned int old_val.93;
  unsigned int D.21592;
  int D.21593;
  gint32 old_val;

  <D.18470>:
  old_val = *dst;
  val.92 = (unsigned int) val;
  old_val.93 = (unsigned int) old_val;
  D.21592 = __sync_val_compare_and_swap_4 (dst, old_val.93, val.92);
  D.21593 = (int) D.21592;
  if (D.21593 != old_val) goto <D.18470>; else goto <D.18471>;
  <D.18471>:
}


ves_icall_System_Threading_Volatile_Write8 (void * ptr, gint64 value)
{
  unsigned int ptr.94;
  unsigned int D.21595;
  _Bool D.21596;
  long int D.21597;
  long int D.21598;
  _Bool D.21603;
  long int D.21604;
  long int D.21605;
  _Bool D.21610;
  long int D.21611;
  long int D.21612;

  ptr.94 = (unsigned int) ptr;
  D.21595 = ptr.94 & 7;
  D.21596 = D.21595 != 0;
  D.21597 = (long int) D.21596;
  D.21598 = __builtin_expect (D.21597, 0);
  if (D.21598 != 0) goto <D.21599>; else goto <D.21600>;
  <D.21599>:
  {
    int ret;

    ret = pthread_mutex_lock (&interlocked_mutex.mutex);
    if (ret != 0) goto <D.21601>; else goto <D.21602>;
    <D.21601>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.21602>:
    D.21603 = ret != 0;
    D.21604 = (long int) D.21603;
    D.21605 = __builtin_expect (D.21604, 0);
    if (D.21605 != 0) goto <D.21606>; else goto <D.21607>;
    <D.21606>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2591, "ret == 0");
    <D.21607>:
  }
  MEM[(gint64 *)ptr] = value;
  {
    int ret;

    ret = pthread_mutex_unlock (&interlocked_mutex.mutex);
    if (ret != 0) goto <D.21608>; else goto <D.21609>;
    <D.21608>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21609>:
    D.21610 = ret != 0;
    D.21611 = (long int) D.21610;
    D.21612 = __builtin_expect (D.21611, 0);
    if (D.21612 != 0) goto <D.21613>; else goto <D.21614>;
    <D.21613>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2593, "ret == 0");
    <D.21614>:
  }
  return;
  <D.21600>:
  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)
{
  unsigned int ptr.95;
  unsigned int D.21617;
  _Bool D.21618;
  long int D.21619;
  long int D.21620;
  _Bool D.21625;
  long int D.21626;
  long int D.21627;
  _Bool D.21632;
  long int D.21633;
  long int D.21634;
  long long int D.21637;
  union LongDoubleUnion u;

  try
    {
      ptr.95 = (unsigned int) ptr;
      D.21617 = ptr.95 & 7;
      D.21618 = D.21617 != 0;
      D.21619 = (long int) D.21618;
      D.21620 = __builtin_expect (D.21619, 0);
      if (D.21620 != 0) goto <D.21621>; else goto <D.21622>;
      <D.21621>:
      {
        int ret;

        ret = pthread_mutex_lock (&interlocked_mutex.mutex);
        if (ret != 0) goto <D.21623>; else goto <D.21624>;
        <D.21623>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.21624>:
        D.21625 = ret != 0;
        D.21626 = (long int) D.21625;
        D.21627 = __builtin_expect (D.21626, 0);
        if (D.21627 != 0) goto <D.21628>; else goto <D.21629>;
        <D.21628>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2614, "ret == 0");
        <D.21629>:
      }
      MEM[(double *)ptr] = value;
      {
        int ret;

        ret = pthread_mutex_unlock (&interlocked_mutex.mutex);
        if (ret != 0) goto <D.21630>; else goto <D.21631>;
        <D.21630>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.21631>:
        D.21632 = ret != 0;
        D.21633 = (long int) D.21632;
        D.21634 = __builtin_expect (D.21633, 0);
        if (D.21634 != 0) goto <D.21635>; else goto <D.21636>;
        <D.21635>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2616, "ret == 0");
        <D.21636>:
      }
      return;
      <D.21622>:
      u.fval = value;
      D.21637 = u.ival;
      InterlockedWrite64 (ptr, D.21637);
    }
  finally
    {
      u = {CLOBBER};
    }
}


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

  try
    {
      u.fval = value;
      D.21641 = u.ival;
      InterlockedWrite (ptr, D.21641);
    }
  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.21642;
  void (*<Tbf>) (void *) destructor.96;
  int D.21644;
  _Bool D.21645;

  destructor.96 = (void (*<Tbf>) (void *)) destructor;
  D.21644 = pthread_key_create (key, destructor.96);
  D.21645 = D.21644 == 0;
  D.21642 = (int) D.21645;
  return D.21642;
}


mono_thread_init (void (*MonoThreadStartCB) (intptr_t, void *, void *) start_cb, void (*MonoThreadAttachCB) (intptr_t, void *) attach_cb)
{
  void * background_change_event.97;
  void * background_change_event.98;
  _Bool D.21649;
  long int D.21650;
  long int D.21651;

  InitializeCriticalSection (&threads_mutex);
  InitializeCriticalSection (&interlocked_mutex);
  InitializeCriticalSection (&contexts_mutex);
  background_change_event.97 = CreateEvent (0B, 1, 0, 0B);
  background_change_event = background_change_event.97;
  background_change_event.98 = background_change_event;
  D.21649 = background_change_event.98 == 0B;
  D.21650 = (long int) D.21649;
  D.21651 = __builtin_expect (D.21650, 0);
  if (D.21651 != 0) goto <D.21652>; else goto <D.21653>;
  <D.21652>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2657, "background_change_event != NULL");
  <D.21653>:
  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.21654;
  unsigned int D.21655;
  unsigned int current_object_key.99;

  D.21654 = mono_environment_exitcode_get ();
  D.21655 = (unsigned int) D.21654;
  _wapi_thread_signal_self (D.21655);
  current_object_key.99 = current_object_key;
  mono_native_tls_free (current_object_key.99);
}


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.21657;

  D.21657 = thread->internal_thread;
  D.21657->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.21660;
  long int D.21661;
  long int D.21662;
  int shutting_down.100;
  _Bool D.21670;
  long int D.21671;
  long int D.21672;
  unsigned int D.21675;
  unsigned int D.21676;
  unsigned int D.21680;
  unsigned int D.21681;
  void * background_change_event.101;
  _Bool D.21685;
  long int D.21686;
  long int D.21687;
  struct MonoInternalThread * current_thread;

  current_thread = mono_thread_internal_current ();
  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.21658>; else goto <D.21659>;
    <D.21658>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.21659>:
    D.21660 = ret != 0;
    D.21661 = (long int) D.21660;
    D.21662 = __builtin_expect (D.21661, 0);
    if (D.21662 != 0) goto <D.21663>; else goto <D.21664>;
    <D.21663>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2934, "ret == 0");
    <D.21664>:
  }
  shutting_down.100 = shutting_down;
  if (shutting_down.100 != 0) goto <D.21666>; else goto <D.21667>;
  <D.21666>:
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.21668>; else goto <D.21669>;
    <D.21668>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21669>:
    D.21670 = ret != 0;
    D.21671 = (long int) D.21670;
    D.21672 = __builtin_expect (D.21671, 0);
    if (D.21672 != 0) goto <D.21673>; else goto <D.21674>;
    <D.21673>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2937, "ret == 0");
    <D.21674>:
  }
  lock_thread (current_thread);
  D.21675 = BIT_FIELD_REF <*current_thread, 32, 224>;
  D.21676 = D.21675 & 131;
  if (D.21676 != 0) goto <D.21677>; else goto <D.21678>;
  <D.21677>:
  unlock_thread (current_thread);
  mono_thread_execute_interruption (current_thread);
  goto <D.21679>;
  <D.21678>:
  D.21680 = current_thread->state;
  D.21681 = D.21680 | 16;
  current_thread->state = D.21681;
  unlock_thread (current_thread);
  <D.21679>:
  mono_domain_unset ();
  ExitThread (0);
  <D.21667>:
  shutting_down = 1;
  background_change_event.101 = background_change_event;
  SetEvent (background_change_event.101);
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.21683>; else goto <D.21684>;
    <D.21683>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21684>:
    D.21685 = ret != 0;
    D.21686 = (long int) D.21685;
    D.21687 = __builtin_expect (D.21686, 0);
    if (D.21687 != 0) goto <D.21688>; else goto <D.21689>;
    <D.21688>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2967, "ret == 0");
    <D.21689>:
  }
}


mono_thread_manage ()
{
  _Bool D.21692;
  long int D.21693;
  long int D.21694;
  struct MonoGHashTable * threads.102;
  _Bool D.21702;
  long int D.21703;
  long int D.21704;
  _Bool D.21709;
  long int D.21710;
  long int D.21711;
  _Bool D.21716;
  long int D.21717;
  long int D.21718;
  int shutting_down.103;
  _Bool D.21726;
  long int D.21727;
  long int D.21728;
  void * background_change_event.104;
  struct MonoInternalThread *[64] * D.21732;
  _Bool D.21735;
  long int D.21736;
  long int D.21737;
  unsigned int D.21740;
  int D.21743;
  struct MonoInternalThread * D.21746;
  struct MonoInternalThread * D.21747;
  _Bool D.21750;
  long int D.21751;
  long int D.21752;
  _Bool D.21757;
  long int D.21758;
  long int D.21759;
  struct wait_data wait_data;
  struct wait_data * wait;

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

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.21690>; else goto <D.21691>;
        <D.21690>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.21691>:
        D.21692 = ret != 0;
        D.21693 = (long int) D.21692;
        D.21694 = __builtin_expect (D.21693, 0);
        if (D.21694 != 0) goto <D.21695>; else goto <D.21696>;
        <D.21695>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2980, "ret == 0");
        <D.21696>:
      }
      threads.102 = threads;
      if (threads.102 == 0B) goto <D.21698>; else goto <D.21699>;
      <D.21698>:
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.21700>; else goto <D.21701>;
        <D.21700>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.21701>:
        D.21702 = ret != 0;
        D.21703 = (long int) D.21702;
        D.21704 = __builtin_expect (D.21703, 0);
        if (D.21704 != 0) goto <D.21705>; else goto <D.21706>;
        <D.21705>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2983, "ret == 0");
        <D.21706>:
      }
      return;
      <D.21699>:
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.21707>; else goto <D.21708>;
        <D.21707>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.21708>:
        D.21709 = ret != 0;
        D.21710 = (long int) D.21709;
        D.21711 = __builtin_expect (D.21710, 0);
        if (D.21711 != 0) goto <D.21712>; else goto <D.21713>;
        <D.21712>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2986, "ret == 0");
        <D.21713>:
      }
      <D.19416>:
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.21714>; else goto <D.21715>;
        <D.21714>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.21715>:
        D.21716 = ret != 0;
        D.21717 = (long int) D.21716;
        D.21718 = __builtin_expect (D.21717, 0);
        if (D.21718 != 0) goto <D.21719>; else goto <D.21720>;
        <D.21719>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2989, "ret == 0");
        <D.21720>:
      }
      shutting_down.103 = shutting_down;
      if (shutting_down.103 != 0) goto <D.21722>; else goto <D.21723>;
      <D.21722>:
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.21724>; else goto <D.21725>;
        <D.21724>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.21725>:
        D.21726 = ret != 0;
        D.21727 = (long int) D.21726;
        D.21728 = __builtin_expect (D.21727, 0);
        if (D.21728 != 0) goto <D.21729>; else goto <D.21730>;
        <D.21729>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2992, "ret == 0");
        <D.21730>:
      }
      goto <D.19414>;
      <D.21723>:
      background_change_event.104 = background_change_event;
      ResetEvent (background_change_event.104);
      wait->num = 0;
      D.21732 = &wait->threads;
      memset (D.21732, 0, 256);
      threads.102 = threads;
      mono_g_hash_table_foreach (threads.102, build_wait_tids, wait);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.21733>; else goto <D.21734>;
        <D.21733>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.21734>:
        D.21735 = ret != 0;
        D.21736 = (long int) D.21735;
        D.21737 = __builtin_expect (D.21736, 0);
        if (D.21737 != 0) goto <D.21738>; else goto <D.21739>;
        <D.21738>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3003, "ret == 0");
        <D.21739>:
      }
      D.21740 = wait->num;
      if (D.21740 != 0) goto <D.21741>; else goto <D.21742>;
      <D.21741>:
      wait_for_tids_or_state_change (wait, 4294967295);
      <D.21742>:
      D.21740 = wait->num;
      if (D.21740 != 0) goto <D.19416>; else goto <D.19414>;
      <D.19414>:
      D.21743 = mono_runtime_try_shutdown ();
      if (D.21743 == 0) goto <D.21744>; else goto <D.21745>;
      <D.21744>:
      D.21746 = mono_thread_internal_current ();
      mono_thread_suspend (D.21746);
      D.21747 = mono_thread_internal_current ();
      mono_thread_execute_interruption (D.21747);
      <D.21745>:
      <D.19419>:
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.21748>; else goto <D.21749>;
        <D.21748>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.21749>:
        D.21750 = ret != 0;
        D.21751 = (long int) D.21750;
        D.21752 = __builtin_expect (D.21751, 0);
        if (D.21752 != 0) goto <D.21753>; else goto <D.21754>;
        <D.21753>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3023, "ret == 0");
        <D.21754>:
      }
      wait->num = 0;
      D.21732 = &wait->threads;
      memset (D.21732, 0, 256);
      threads.102 = threads;
      mono_g_hash_table_foreach_remove (threads.102, remove_and_abort_threads, wait);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.21755>; else goto <D.21756>;
        <D.21755>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.21756>:
        D.21757 = ret != 0;
        D.21758 = (long int) D.21757;
        D.21759 = __builtin_expect (D.21758, 0);
        if (D.21759 != 0) goto <D.21760>; else goto <D.21761>;
        <D.21760>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3030, "ret == 0");
        <D.21761>:
      }
      D.21740 = wait->num;
      if (D.21740 != 0) goto <D.21762>; else goto <D.21763>;
      <D.21762>:
      wait_for_tids (wait, 4294967295);
      <D.21763>:
      D.21740 = wait->num;
      if (D.21740 != 0) goto <D.19419>; else goto <D.19420>;
      <D.19420>:
      sched_yield ();
    }
  finally
    {
      wait_data = {CLOBBER};
    }
}


remove_and_abort_threads (void * key, void * value, void * user)
{
  unsigned int D.21767;
  gboolean D.21770;
  long long unsigned int D.21771;
  long long unsigned int D.21772;
  unsigned int D.21775;
  unsigned int D.21776;
  unsigned int D.21779;
  unsigned int D.21780;
  unsigned int D.21783;
  void * D.21786;
  unsigned int D.21787;
  int iftmp.105;
  int D.21792;
  struct wait_data * wait;
  gsize self;
  struct MonoInternalThread * thread;
  void * handle;

  wait = user;
  self = GetCurrentThreadId ();
  thread = value;
  D.21767 = wait->num;
  if (D.21767 > 63) goto <D.21768>; else goto <D.21769>;
  <D.21768>:
  D.21770 = 0;
  return D.21770;
  <D.21769>:
  D.21771 = thread->tid;
  D.21772 = (long long unsigned int) self;
  if (D.21771 != D.21772) goto <D.21773>; else goto <D.21774>;
  <D.21773>:
  D.21775 = thread->state;
  D.21776 = D.21775 & 4;
  if (D.21776 != 0) goto <D.21777>; else goto <D.21778>;
  <D.21777>:
  D.21779 = thread->flags;
  D.21780 = D.21779 & 1;
  if (D.21780 == 0) goto <D.21781>; else goto <D.21782>;
  <D.21781>:
  D.21771 = thread->tid;
  D.21783 = (unsigned int) D.21771;
  handle = OpenThread (2032639, 1, D.21783);
  if (handle == 0B) goto <D.21784>; else goto <D.21785>;
  <D.21784>:
  D.21770 = 0;
  return D.21770;
  <D.21785>:
  D.21767 = wait->num;
  D.21786 = thread->handle;
  wait->handles[D.21767] = D.21786;
  D.21767 = wait->num;
  wait->threads[D.21767] = thread;
  D.21767 = wait->num;
  D.21787 = D.21767 + 1;
  wait->num = D.21787;
  mono_thread_internal_stop (thread);
  D.21770 = 1;
  return D.21770;
  <D.21782>:
  <D.21778>:
  <D.21774>:
  D.21771 = thread->tid;
  D.21772 = (long long unsigned int) self;
  if (D.21771 != D.21772) goto <D.21791>; else goto <D.21789>;
  <D.21791>:
  D.21792 = mono_gc_is_finalizer_internal_thread (thread);
  if (D.21792 == 0) goto <D.21793>; else goto <D.21789>;
  <D.21793>:
  iftmp.105 = 1;
  goto <D.21790>;
  <D.21789>:
  iftmp.105 = 0;
  <D.21790>:
  D.21770 = iftmp.105;
  return D.21770;
}


build_wait_tids (void * key, void * value, void * user)
{
  unsigned int D.21795;
  unsigned int D.21798;
  unsigned int D.21799;
  int D.21802;
  struct MonoInternalThread * D.21805;
  struct MonoThread * D.21808;
  struct MonoThread * D.21811;
  struct _MonoInternalThread * D.21812;
  unsigned int D.21815;
  unsigned int D.21816;
  long long unsigned int D.21819;
  unsigned int D.21820;
  mono_bool (*<T1c17>) (struct MonoThread *) D.21825;
  struct MonoThread * D.21827;
  int D.21828;
  unsigned int D.21829;
  struct wait_data * wait;

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

    thread = value;
    D.21798 = thread->state;
    D.21799 = D.21798 & 4;
    if (D.21799 != 0) goto <D.21800>; else goto <D.21801>;
    <D.21800>:
    return;
    <D.21801>:
    D.21802 = mono_gc_is_finalizer_internal_thread (thread);
    if (D.21802 != 0) goto <D.21803>; else goto <D.21804>;
    <D.21803>:
    return;
    <D.21804>:
    D.21805 = mono_thread_internal_current ();
    if (D.21805 == thread) goto <D.21806>; else goto <D.21807>;
    <D.21806>:
    return;
    <D.21807>:
    D.21808 = mono_thread_get_main ();
    if (D.21808 != 0B) goto <D.21809>; else goto <D.21810>;
    <D.21809>:
    D.21811 = mono_thread_get_main ();
    D.21812 = D.21811->internal_thread;
    if (D.21812 == thread) goto <D.21813>; else goto <D.21814>;
    <D.21813>:
    return;
    <D.21814>:
    <D.21810>:
    D.21815 = thread->flags;
    D.21816 = D.21815 & 1;
    if (D.21816 != 0) goto <D.21817>; else goto <D.21818>;
    <D.21817>:
    return;
    <D.21818>:
    D.21819 = thread->tid;
    D.21820 = (unsigned int) D.21819;
    handle = OpenThread (2032639, 1, D.21820);
    if (handle == 0B) goto <D.21821>; else goto <D.21822>;
    <D.21821>:
    return;
    <D.21822>:
    D.21825 = thread->manage_callback;
    if (D.21825 == 0B) goto <D.21823>; else goto <D.21826>;
    <D.21826>:
    D.21825 = thread->manage_callback;
    D.21827 = thread->root_domain_thread;
    D.21828 = D.21825 (D.21827);
    if (D.21828 == 1) goto <D.21823>; else goto <D.21824>;
    <D.21823>:
    D.21795 = wait->num;
    wait->handles[D.21795] = handle;
    D.21795 = wait->num;
    wait->threads[D.21795] = thread;
    D.21795 = wait->num;
    D.21829 = D.21795 + 1;
    wait->num = D.21829;
    <D.21824>:
  }
  goto <D.21830>;
  <D.21797>:
  <D.21830>:
}


wait_for_tids_or_state_change (struct wait_data * wait, guint32 timeout)
{
  void * background_change_event.106;
  void *[64] * D.21835;
  void * D.21838;
  unsigned int D.21839;
  struct MonoInternalThread * D.21844;
  long long unsigned int D.21845;
  _Bool D.21848;
  long int D.21849;
  long int D.21850;
  const void * tid.107;
  struct MonoGHashTable * threads.108;
  void * D.21855;
  _Bool D.21860;
  long int D.21861;
  long int D.21862;
  _Bool D.21868;
  long int D.21869;
  long int D.21870;
  guint32 i;
  guint32 ret;
  guint32 count;

  count = wait->num;
  if (count <= 63) goto <D.21832>; else goto <D.21833>;
  <D.21832>:
  background_change_event.106 = background_change_event;
  wait->handles[count] = background_change_event.106;
  count = count + 1;
  <D.21833>:
  D.21835 = &wait->handles;
  ret = WaitForMultipleObjectsEx (count, D.21835, 0, timeout, 1);
  if (ret == 4294967295) goto <D.21836>; else goto <D.21837>;
  <D.21836>:
  return;
  <D.21837>:
  i = 0;
  goto <D.19374>;
  <D.19373>:
  D.21838 = wait->handles[i];
  CloseHandle (D.21838);
  i = i + 1;
  <D.19374>:
  D.21839 = wait->num;
  if (D.21839 > i) goto <D.19373>; else goto <D.19375>;
  <D.19375>:
  if (ret == 258) goto <D.21840>; else goto <D.21841>;
  <D.21840>:
  return;
  <D.21841>:
  D.21839 = wait->num;
  if (D.21839 > ret) goto <D.21842>; else goto <D.21843>;
  <D.21842>:
  {
    gsize tid;

    D.21844 = wait->threads[ret];
    D.21845 = D.21844->tid;
    tid = (gsize) D.21845;
    {
      int ret;

      ret = pthread_mutex_lock (&threads_mutex.mutex);
      if (ret != 0) goto <D.21846>; else goto <D.21847>;
      <D.21846>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
      <D.21847>:
      D.21848 = ret != 0;
      D.21849 = (long int) D.21848;
      D.21850 = __builtin_expect (D.21849, 0);
      if (D.21850 != 0) goto <D.21851>; else goto <D.21852>;
      <D.21851>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2819, "ret == 0");
      <D.21852>:
    }
    tid.107 = (const void *) tid;
    threads.108 = threads;
    D.21855 = mono_g_hash_table_lookup (threads.108, tid.107);
    if (D.21855 != 0B) goto <D.21856>; else goto <D.21857>;
    <D.21856>:
    {
      int ret;

      ret = pthread_mutex_unlock (&threads_mutex.mutex);
      if (ret != 0) goto <D.21858>; else goto <D.21859>;
      <D.21858>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.21859>:
      D.21860 = ret != 0;
      D.21861 = (long int) D.21860;
      D.21862 = __builtin_expect (D.21861, 0);
      if (D.21862 != 0) goto <D.21863>; else goto <D.21864>;
      <D.21863>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2822, "ret == 0");
      <D.21864>:
    }
    D.21844 = wait->threads[ret];
    thread_cleanup (D.21844);
    goto <D.21865>;
    <D.21857>:
    {
      int ret;

      ret = pthread_mutex_unlock (&threads_mutex.mutex);
      if (ret != 0) goto <D.21866>; else goto <D.21867>;
      <D.21866>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.21867>:
      D.21868 = ret != 0;
      D.21869 = (long int) D.21868;
      D.21870 = __builtin_expect (D.21869, 0);
      if (D.21870 != 0) goto <D.21871>; else goto <D.21872>;
      <D.21871>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2826, "ret == 0");
      <D.21872>:
    }
    <D.21865>:
  }
  <D.21843>:
}


memset (void * __dest, int __ch, size_t __len)
{
  int D.21876;
  int D.21881;
  void * D.21883;
  unsigned int D.21884;

  D.21876 = __builtin_constant_p (__len);
  if (D.21876 != 0) goto <D.21877>; else goto <D.21878>;
  <D.21877>:
  if (__len == 0) goto <D.21879>; else goto <D.21880>;
  <D.21879>:
  D.21881 = __builtin_constant_p (__ch);
  if (D.21881 == 0) goto <D.21874>; else goto <D.21882>;
  <D.21882>:
  if (__ch != 0) goto <D.21874>; else goto <D.21875>;
  <D.21874>:
  __warn_memset_zero_len ();
  D.21883 = __dest;
  return D.21883;
  <D.21875>:
  <D.21880>:
  <D.21878>:
  D.21884 = __builtin_object_size (__dest, 0);
  D.21883 = __builtin___memset_chk (__dest, __ch, __len, D.21884);
  return D.21883;
}


wait_for_tids (struct wait_data * wait, guint32 timeout)
{
  void *[64] * D.21886;
  unsigned int D.21887;
  void * D.21890;
  struct MonoInternalThread * D.21893;
  long long unsigned int D.21894;
  _Bool D.21897;
  long int D.21898;
  long int D.21899;
  const void * tid.109;
  struct MonoGHashTable * threads.110;
  void * D.21904;
  _Bool D.21909;
  long int D.21910;
  long int D.21911;
  _Bool D.21917;
  long int D.21918;
  long int D.21919;
  guint32 i;
  guint32 ret;

  D.21886 = &wait->handles;
  D.21887 = wait->num;
  ret = WaitForMultipleObjectsEx (D.21887, D.21886, 1, timeout, 1);
  if (ret == 4294967295) goto <D.21888>; else goto <D.21889>;
  <D.21888>:
  return;
  <D.21889>:
  i = 0;
  goto <D.19357>;
  <D.19356>:
  D.21890 = wait->handles[i];
  CloseHandle (D.21890);
  i = i + 1;
  <D.19357>:
  D.21887 = wait->num;
  if (D.21887 > i) goto <D.19356>; else goto <D.19358>;
  <D.19358>:
  if (ret == 258) goto <D.21891>; else goto <D.21892>;
  <D.21891>:
  return;
  <D.21892>:
  i = 0;
  goto <D.19364>;
  <D.19363>:
  {
    gsize tid;

    D.21893 = wait->threads[i];
    D.21894 = D.21893->tid;
    tid = (gsize) D.21894;
    {
      int ret;

      ret = pthread_mutex_lock (&threads_mutex.mutex);
      if (ret != 0) goto <D.21895>; else goto <D.21896>;
      <D.21895>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
      <D.21896>:
      D.21897 = ret != 0;
      D.21898 = (long int) D.21897;
      D.21899 = __builtin_expect (D.21898, 0);
      if (D.21899 != 0) goto <D.21900>; else goto <D.21901>;
      <D.21900>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2766, "ret == 0");
      <D.21901>:
    }
    tid.109 = (const void *) tid;
    threads.110 = threads;
    D.21904 = mono_g_hash_table_lookup (threads.110, tid.109);
    if (D.21904 != 0B) goto <D.21905>; else goto <D.21906>;
    <D.21905>:
    {
      int ret;

      ret = pthread_mutex_unlock (&threads_mutex.mutex);
      if (ret != 0) goto <D.21907>; else goto <D.21908>;
      <D.21907>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.21908>:
      D.21909 = ret != 0;
      D.21910 = (long int) D.21909;
      D.21911 = __builtin_expect (D.21910, 0);
      if (D.21911 != 0) goto <D.21912>; else goto <D.21913>;
      <D.21912>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2779, "ret == 0");
      <D.21913>:
    }
    D.21893 = wait->threads[i];
    thread_cleanup (D.21893);
    goto <D.21914>;
    <D.21906>:
    {
      int ret;

      ret = pthread_mutex_unlock (&threads_mutex.mutex);
      if (ret != 0) goto <D.21915>; else goto <D.21916>;
      <D.21915>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.21916>:
      D.21917 = ret != 0;
      D.21918 = (long int) D.21917;
      D.21919 = __builtin_expect (D.21918, 0);
      if (D.21919 != 0) goto <D.21920>; else goto <D.21921>;
      <D.21920>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2783, "ret == 0");
      <D.21921>:
    }
    <D.21914>:
  }
  i = i + 1;
  <D.19364>:
  D.21887 = wait->num;
  if (D.21887 > i) goto <D.19363>; else goto <D.19365>;
  <D.19365>:
}


mono_thread_abort_all_other_threads ()
{
  _Bool D.21925;
  long int D.21926;
  long int D.21927;
  void * self.111;
  struct MonoGHashTable * threads.112;
  _Bool D.21934;
  long int D.21935;
  long int D.21936;
  gsize self;

  self = GetCurrentThreadId ();
  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.21923>; else goto <D.21924>;
    <D.21923>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.21924>:
    D.21925 = ret != 0;
    D.21926 = (long int) D.21925;
    D.21927 = __builtin_expect (D.21926, 0);
    if (D.21927 != 0) goto <D.21928>; else goto <D.21929>;
    <D.21928>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3062, "ret == 0");
    <D.21929>:
  }
  self.111 = (void *) self;
  threads.112 = threads;
  mono_g_hash_table_foreach (threads.112, terminate_thread, self.111);
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.21932>; else goto <D.21933>;
    <D.21932>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21933>:
    D.21934 = ret != 0;
    D.21935 = (long int) D.21934;
    D.21936 = __builtin_expect (D.21935, 0);
    if (D.21936 != 0) goto <D.21937>; else goto <D.21938>;
    <D.21937>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3069, "ret == 0");
    <D.21938>:
  }
}


terminate_thread (void * key, void * value, void * user)
{
  long long unsigned int D.21939;
  unsigned int user.113;
  long long unsigned int D.21941;
  struct MonoInternalThread * thread;

  thread = value;
  D.21939 = thread->tid;
  user.113 = (unsigned int) user;
  D.21941 = (long long unsigned int) user.113;
  if (D.21939 != D.21941) goto <D.21942>; else goto <D.21943>;
  <D.21942>:
  <D.21943>:
}


mono_thread_suspend_all_other_threads ()
{
  int shutting_down.114;
  _Bool D.21945;
  long int D.21946;
  long int D.21947;
  struct MonoInternalThread *[64] * D.21950;
  _Bool D.21953;
  long int D.21954;
  long int D.21955;
  struct MonoGHashTable * threads.115;
  _Bool D.21961;
  long int D.21962;
  long int D.21963;
  unsigned int D.21966;
  unsigned int D.21967;
  long long unsigned int D.21970;
  long long unsigned int D.21971;
  int D.21973;
  unsigned int D.21975;
  unsigned int D.21976;
  void * D.21977;
  void * D.21980;
  unsigned int D.21983;
  unsigned int D.21984;
  void * D.21987;
  unsigned int D.21988;
  unsigned int D.21989;
  unsigned int eventidx.116;
  unsigned int D.21993;
  void * * D.21994;
  unsigned int D.21995;
  unsigned int D.21998;
  unsigned int D.21999;
  int D.22000;
  unsigned int i.117;
  int D.22009;
  unsigned int D.22014;
  unsigned int D.22015;
  void * D.22018;
  _Bool D.22023;
  long int D.22024;
  long int D.22025;
  struct MonoGHashTable * threads_starting_up.118;
  unsigned int D.22031;
  _Bool D.22032;
  _Bool D.22036;
  long int D.22037;
  long int D.22038;
  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, 516);
      shutting_down.114 = shutting_down;
      D.21945 = shutting_down.114 == 0;
      D.21946 = (long int) D.21945;
      D.21947 = __builtin_expect (D.21946, 0);
      if (D.21947 != 0) goto <D.21948>; else goto <D.21949>;
      <D.21948>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3128, "shutting_down");
      <D.21949>:
      finished = 0;
      goto <D.19468>;
      <D.19467>:
      wait->num = 0;
      D.21950 = &wait->threads;
      memset (D.21950, 0, 256);
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.21951>; else goto <D.21952>;
        <D.21951>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.21952>:
        D.21953 = ret != 0;
        D.21954 = (long int) D.21953;
        D.21955 = __builtin_expect (D.21954, 0);
        if (D.21955 != 0) goto <D.21956>; else goto <D.21957>;
        <D.21956>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3144, "ret == 0");
        <D.21957>:
      }
      threads.115 = threads;
      mono_g_hash_table_foreach (threads.115, collect_threads_for_suspend, wait);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.21959>; else goto <D.21960>;
        <D.21959>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.21960>:
        D.21961 = ret != 0;
        D.21962 = (long int) D.21961;
        D.21963 = __builtin_expect (D.21962, 0);
        if (D.21963 != 0) goto <D.21964>; else goto <D.21965>;
        <D.21964>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3146, "ret == 0");
        <D.21965>:
      }
      D.21966 = wait->num;
      D.21967 = D.21966 * 4;
      events = monoeg_malloc0 (D.21967);
      eventidx = 0;
      i = 0;
      goto <D.19458>;
      <D.19457>:
      {
        struct MonoInternalThread * thread;
        gboolean signal_suspend;

        thread = wait->threads[i];
        signal_suspend = 0;
        D.21970 = thread->tid;
        D.21971 = (long long unsigned int) self;
        if (D.21970 == D.21971) goto <D.21968>; else goto <D.21972>;
        <D.21972>:
        D.21973 = mono_gc_is_finalizer_internal_thread (thread);
        if (D.21973 != 0) goto <D.21968>; else goto <D.21974>;
        <D.21974>:
        D.21975 = thread->flags;
        D.21976 = D.21975 & 1;
        if (D.21976 != 0) goto <D.21968>; else goto <D.21969>;
        <D.21968>:
        wait->threads[i] = 0B;
        // predicted unlikely by continue predictor.
        goto <D.19456>;
        <D.21969>:
        lock_thread (thread);
        D.21977 = thread->suspended_event;
        if (D.21977 == 0B) goto <D.21978>; else goto <D.21979>;
        <D.21978>:
        D.21980 = CreateEvent (0B, 1, 0, 0B);
        thread->suspended_event = D.21980;
        D.21977 = thread->suspended_event;
        if (D.21977 == 0B) goto <D.21981>; else goto <D.21982>;
        <D.21981>:
        unlock_thread (thread);
        // predicted unlikely by continue predictor.
        goto <D.19456>;
        <D.21982>:
        <D.21979>:
        D.21983 = BIT_FIELD_REF <*thread, 32, 224>;
        D.21984 = D.21983 & 81;
        if (D.21984 != 0) goto <D.21985>; else goto <D.21986>;
        <D.21985>:
        unlock_thread (thread);
        D.21987 = wait->handles[i];
        CloseHandle (D.21987);
        wait->threads[i] = 0B;
        // predicted unlikely by continue predictor.
        goto <D.19456>;
        <D.21986>:
        D.21988 = thread->state;
        D.21989 = D.21988 & 2;
        if (D.21989 == 0) goto <D.21990>; else goto <D.21991>;
        <D.21990>:
        signal_suspend = 1;
        <D.21991>:
        eventidx.116 = eventidx;
        eventidx = eventidx.116 + 1;
        D.21993 = eventidx.116 * 4;
        D.21994 = events + D.21993;
        D.21977 = thread->suspended_event;
        *D.21994 = D.21977;
        D.21988 = thread->state;
        D.21995 = D.21988 & 128;
        if (D.21995 != 0) goto <D.21996>; else goto <D.21997>;
        <D.21996>:
        D.21988 = thread->state;
        D.21998 = D.21988 & 4294967167;
        thread->state = D.21998;
        <D.21997>:
        D.21988 = thread->state;
        D.21999 = D.21988 | 2;
        thread->state = D.21999;
        unlock_thread (thread);
        D.22000 = mono_thread_info_new_interrupt_enabled ();
        if (D.22000 != 0) goto <D.22001>; else goto <D.22002>;
        <D.22001>:
        suspend_thread_internal (thread, 1);
        goto <D.22003>;
        <D.22002>:
        if (signal_suspend != 0) goto <D.22004>; else goto <D.22005>;
        <D.22004>:
        signal_thread_state_change (thread);
        <D.22005>:
        <D.22003>:
      }
      <D.19456>:
      i = i + 1;
      <D.19458>:
      i.117 = (unsigned int) i;
      D.21966 = wait->num;
      if (i.117 < D.21966) goto <D.19457>; else goto <D.19459>;
      <D.19459>:
      if (eventidx != 0) goto <D.22007>; else goto <D.22008>;
      <D.22007>:
      D.22009 = mono_thread_info_new_interrupt_enabled ();
      if (D.22009 == 0) goto <D.22010>; else goto <D.22011>;
      <D.22010>:
      WaitForMultipleObjectsEx (eventidx, events, 1, 100, 0);
      i = 0;
      goto <D.19463>;
      <D.19462>:
      {
        struct MonoInternalThread * thread;

        thread = wait->threads[i];
        if (thread == 0B) goto <D.22012>; else goto <D.22013>;
        <D.22012>:
        // predicted unlikely by continue predictor.
        goto <D.19461>;
        <D.22013>:
        lock_thread (thread);
        D.22014 = thread->state;
        D.22015 = D.22014 & 64;
        if (D.22015 != 0) goto <D.22016>; else goto <D.22017>;
        <D.22016>:
        D.22018 = thread->suspended_event;
        CloseHandle (D.22018);
        thread->suspended_event = 0B;
        <D.22017>:
        unlock_thread (thread);
      }
      <D.19461>:
      i = i + 1;
      <D.19463>:
      i.117 = (unsigned int) i;
      D.21966 = wait->num;
      if (i.117 < D.21966) goto <D.19462>; else goto <D.19464>;
      <D.19464>:
      <D.22011>:
      <D.22008>:
      if (eventidx == 0) goto <D.22019>; else goto <D.22020>;
      <D.22019>:
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22021>; else goto <D.22022>;
        <D.22021>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.22022>:
        D.22023 = ret != 0;
        D.22024 = (long int) D.22023;
        D.22025 = __builtin_expect (D.22024, 0);
        if (D.22025 != 0) goto <D.22026>; else goto <D.22027>;
        <D.22026>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3227, "ret == 0");
        <D.22027>:
      }
      threads_starting_up.118 = threads_starting_up;
      if (threads_starting_up.118 != 0B) goto <D.22029>; else goto <D.22030>;
      <D.22029>:
      threads_starting_up.118 = threads_starting_up;
      D.22031 = mono_g_hash_table_size (threads_starting_up.118);
      D.22032 = D.22031 != 0;
      starting = (gboolean) D.22032;
      goto <D.22033>;
      <D.22030>:
      starting = 0;
      <D.22033>:
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22034>; else goto <D.22035>;
        <D.22034>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.22035>:
        D.22036 = ret != 0;
        D.22037 = (long int) D.22036;
        D.22038 = __builtin_expect (D.22037, 0);
        if (D.22038 != 0) goto <D.22039>; else goto <D.22040>;
        <D.22039>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3232, "ret == 0");
        <D.22040>:
      }
      if (starting != 0) goto <D.22041>; else goto <D.22042>;
      <D.22041>:
      Sleep (100);
      goto <D.22043>;
      <D.22042>:
      finished = 1;
      <D.22043>:
      <D.22020>:
      monoeg_g_free (events);
      <D.19468>:
      if (finished == 0) goto <D.19467>; else goto <D.19469>;
      <D.19469>:
    }
  finally
    {
      wait_data = {CLOBBER};
    }
}


collect_threads_for_suspend (void * key, void * value, void * user_data)
{
  unsigned int D.22044;
  unsigned int D.22045;
  unsigned int D.22048;
  long long unsigned int D.22051;
  unsigned int D.22052;
  unsigned int D.22055;
  struct MonoInternalThread * thread;
  struct wait_data * wait;
  void * handle;

  thread = value;
  wait = user_data;
  D.22044 = BIT_FIELD_REF <*thread, 32, 224>;
  D.22045 = D.22044 & 80;
  if (D.22045 != 0) goto <D.22046>; else goto <D.22047>;
  <D.22046>:
  return;
  <D.22047>:
  D.22048 = wait->num;
  if (D.22048 <= 63) goto <D.22049>; else goto <D.22050>;
  <D.22049>:
  D.22051 = thread->tid;
  D.22052 = (unsigned int) D.22051;
  handle = OpenThread (2032639, 1, D.22052);
  if (handle == 0B) goto <D.22053>; else goto <D.22054>;
  <D.22053>:
  return;
  <D.22054>:
  D.22048 = wait->num;
  wait->handles[D.22048] = handle;
  D.22048 = wait->num;
  wait->threads[D.22048] = thread;
  D.22048 = wait->num;
  D.22055 = D.22048 + 1;
  wait->num = D.22055;
  <D.22050>:
}


mono_threads_perform_thread_dump ()
{
  int thread_dump_requested.119;
  _Bool D.22062;
  long int D.22063;
  long int D.22064;
  struct MonoGHashTable * threads.120;
  _Bool D.22070;
  long int D.22071;
  long int D.22072;

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

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22060>; else goto <D.22061>;
    <D.22060>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.22061>:
    D.22062 = ret != 0;
    D.22063 = (long int) D.22062;
    D.22064 = __builtin_expect (D.22063, 0);
    if (D.22064 != 0) goto <D.22065>; else goto <D.22066>;
    <D.22065>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3357, "ret == 0");
    <D.22066>:
  }
  threads.120 = threads;
  mono_g_hash_table_foreach (threads.120, dump_thread, 0B);
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22068>; else goto <D.22069>;
    <D.22068>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.22069>:
    D.22070 = ret != 0;
    D.22071 = (long int) D.22070;
    D.22072 = __builtin_expect (D.22071, 0);
    if (D.22072 != 0) goto <D.22073>; else goto <D.22074>;
    <D.22073>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3359, "ret == 0");
    <D.22074>:
  }
  thread_dump_requested = 0;
}


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

  thread = value;
  D.22076 = mono_thread_internal_current ();
  if (D.22076 == thread) goto <D.22077>; else goto <D.22078>;
  <D.22077>:
  return;
  <D.22078>:
  D.22079 = thread->tid;
  D.22080 = (long unsigned int) D.22079;
  info = mono_thread_info_safe_suspend_sync (D.22080, 0);
  if (info == 0B) goto <D.22081>; else goto <D.22082>;
  <D.22081>:
  return;
  <D.22082>:
  print_thread_dump (thread, info);
}


print_thread_dump (struct MonoInternalThread * thread, struct MonoThreadInfo * info)
{
  gunichar2 * D.22084;
  unsigned int D.22087;
  long int D.22088;
  struct GError * error.121;
  _Bool D.22090;
  long int D.22091;
  long int D.22092;
  unsigned char D.22096;
  struct MonoRuntimeExceptionHandlingCallbacks * D.22100;
  void (*<T265e>) (gboolean (*MonoInternalStackWalk) (struct MonoStackFrameInfo *, struct MonoContext *, void *), struct MonoThreadUnwindState *, MonoUnwindOptions, void *) D.22101;
  struct MonoThreadUnwindState * D.22102;
  unsigned int D.22103;
  char * D.22104;
  struct _IO_FILE * stdout.122;
  struct GString * text;
  char * name;
  struct GError * error;

  try
    {
      text = monoeg_g_string_new (0B);
      error = 0B;
      D.22084 = thread->name;
      if (D.22084 != 0B) goto <D.22085>; else goto <D.22086>;
      <D.22085>:
      D.22087 = thread->name_len;
      D.22088 = (long int) D.22087;
      D.22084 = thread->name;
      name = monoeg_g_utf16_to_utf8 (D.22084, D.22088, 0B, 0B, &error);
      error.121 = error;
      D.22090 = error.121 != 0B;
      D.22091 = (long int) D.22090;
      D.22092 = __builtin_expect (D.22091, 0);
      if (D.22092 != 0) goto <D.22093>; else goto <D.22094>;
      <D.22093>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3290, "!error");
      <D.22094>:
      monoeg_g_string_append_printf (text, "\n\"%s\"", name);
      monoeg_g_free (name);
      goto <D.22095>;
      <D.22086>:
      D.22096 = thread->threadpool_thread;
      if (D.22096 != 0) goto <D.22097>; else goto <D.22098>;
      <D.22097>:
      monoeg_g_string_append (text, "\n\"<threadpool thread>\"");
      goto <D.22099>;
      <D.22098>:
      monoeg_g_string_append (text, "\n\"<unnamed thread>\"");
      <D.22099>:
      <D.22095>:
      D.22100 = mono_get_eh_callbacks ();
      D.22101 = D.22100->mono_walk_stack_with_state;
      D.22102 = &info->suspend_state;
      D.22101 (print_stack_frame_to_string, D.22102, 0, text);
      D.22103 = info->node.key;
      mono_thread_info_resume (D.22103);
      D.22104 = text->str;
      stdout.122 = stdout;
      fprintf (stdout.122, "%s", D.22104);
      monoeg_g_string_free (text, 1);
      stdout.122 = stdout;
      fflush (stdout.122);
    }
  finally
    {
      error = {CLOBBER};
    }
}


print_stack_frame_to_string (struct MonoStackFrameInfo * frame, struct MonoContext * ctx, void * data)
{
  struct MonoJitInfo * D.22106;
  struct MonoDomain * D.22111;
  int D.22112;
  unsigned int D.22113;
  gboolean D.22115;
  struct GString * p;
  struct MonoMethod * method;

  p = data;
  method = 0B;
  D.22106 = frame->ji;
  if (D.22106 != 0B) goto <D.22107>; else goto <D.22108>;
  <D.22107>:
  D.22106 = frame->ji;
  method = mono_jit_info_get_method (D.22106);
  <D.22108>:
  if (method != 0B) goto <D.22109>; else goto <D.22110>;
  <D.22109>:
  {
    gchar * location;

    D.22111 = frame->domain;
    D.22112 = frame->native_offset;
    D.22113 = (unsigned int) D.22112;
    location = mono_debug_print_stack_frame (method, D.22113, D.22111);
    monoeg_g_string_append_printf (p, "  %s\n", location);
    monoeg_g_free (location);
  }
  goto <D.22114>;
  <D.22110>:
  D.22112 = frame->native_offset;
  monoeg_g_string_append_printf (p, "  at <unknown> <0x%05x>\n", D.22112);
  <D.22114>:
  D.22115 = 0;
  return D.22115;
}


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

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


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

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


mono_threads_request_thread_dump ()
{
  int D.22121;
  _Bool D.22126;
  long int D.22127;
  long int D.22128;
  struct MonoGHashTable * threads.123;
  _Bool D.22134;
  long int D.22135;
  long int D.22136;
  int D.22139;
  struct MonoInternalThread * D.22142;
  unsigned char D.22145;
  void * D.22148;
  unsigned int i.124;
  unsigned int D.22150;
  struct wait_data wait_data;
  struct wait_data * wait;
  int i;

  try
    {
      wait = &wait_data;
      D.22121 = mono_thread_info_new_interrupt_enabled ();
      if (D.22121 != 0) goto <D.22122>; else goto <D.22123>;
      <D.22122>:
      thread_dump_requested = 1;
      mono_gc_finalize_notify ();
      return;
      <D.22123>:
      memset (wait, 0, 516);
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22124>; else goto <D.22125>;
        <D.22124>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.22125>:
        D.22126 = ret != 0;
        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", 3390, "ret == 0");
        <D.22130>:
      }
      threads.123 = threads;
      mono_g_hash_table_foreach (threads.123, collect_threads, wait);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22132>; else goto <D.22133>;
        <D.22132>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.22133>:
        D.22134 = ret != 0;
        D.22135 = (long int) D.22134;
        D.22136 = __builtin_expect (D.22135, 0);
        if (D.22136 != 0) goto <D.22137>; else goto <D.22138>;
        <D.22137>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3392, "ret == 0");
        <D.22138>:
      }
      i = 0;
      goto <D.19516>;
      <D.19515>:
      {
        struct MonoInternalThread * thread;

        thread = wait->threads[i];
        D.22139 = mono_gc_is_finalizer_internal_thread (thread);
        if (D.22139 == 0) goto <D.22140>; else goto <D.22141>;
        <D.22140>:
        D.22142 = mono_thread_internal_current ();
        if (D.22142 != thread) goto <D.22143>; else goto <D.22144>;
        <D.22143>:
        D.22145 = thread->thread_dump_requested;
        if (D.22145 == 0) goto <D.22146>; else goto <D.22147>;
        <D.22146>:
        thread->thread_dump_requested = 1;
        signal_thread_state_change (thread);
        <D.22147>:
        <D.22144>:
        <D.22141>:
        D.22148 = wait->handles[i];
        CloseHandle (D.22148);
      }
      i = i + 1;
      <D.19516>:
      i.124 = (unsigned int) i;
      D.22150 = wait->num;
      if (i.124 < D.22150) goto <D.19515>; else goto <D.19517>;
      <D.19517>:
    }
  finally
    {
      wait_data = {CLOBBER};
    }
}


collect_threads (void * key, void * value, void * user_data)
{
  unsigned int D.22154;
  long long unsigned int D.22157;
  unsigned int D.22158;
  unsigned int D.22161;
  struct MonoInternalThread * thread;
  struct wait_data * wait;
  void * handle;

  thread = value;
  wait = user_data;
  D.22154 = wait->num;
  if (D.22154 <= 63) goto <D.22155>; else goto <D.22156>;
  <D.22155>:
  D.22157 = thread->tid;
  D.22158 = (unsigned int) D.22157;
  handle = OpenThread (2032639, 1, D.22158);
  if (handle == 0B) goto <D.22159>; else goto <D.22160>;
  <D.22159>:
  return;
  <D.22160>:
  D.22154 = wait->num;
  wait->handles[D.22154] = handle;
  D.22154 = wait->num;
  wait->threads[D.22154] = thread;
  D.22154 = wait->num;
  D.22161 = D.22154 + 1;
  wait->num = D.22161;
  <D.22156>:
}


mono_thread_push_appdomain_ref (struct MonoDomain * domain)
{
  volatile int * D.22165;
  int D.22166;
  void * D.22168;
  struct RefStack * D.22171;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  if (thread != 0B) goto <D.22163>; else goto <D.22164>;
  <D.22163>:
  <D.19551>:
  D.22165 = &thread->lock_thread_id;
  D.22166 = InterlockedCompareExchange (D.22165, 1, 0);
  if (D.22166 == 0) goto <D.19550>; else goto <D.22167>;
  <D.22167>:
  goto <D.19551>;
  <D.19550>:
  D.22168 = thread->appdomain_refs;
  if (D.22168 == 0B) goto <D.22169>; else goto <D.22170>;
  <D.22169>:
  D.22171 = ref_stack_new (16);
  thread->appdomain_refs = D.22171;
  <D.22170>:
  D.22168 = thread->appdomain_refs;
  ref_stack_push (D.22168, domain);
  thread->lock_thread_id = 0;
  <D.22164>:
}


ref_stack_new (gint initial_size)
{
  int D.22172;
  unsigned int initial_size.125;
  unsigned int D.22174;
  void * D.22175;
  struct RefStack * D.22176;
  struct RefStack * rs;

  D.22172 = MAX_EXPR <initial_size, 16>;
  initial_size = D.22172 + 1;
  rs = monoeg_malloc0 (12);
  initial_size.125 = (unsigned int) initial_size;
  D.22174 = initial_size.125 * 4;
  D.22175 = monoeg_malloc0 (D.22174);
  rs->refs = D.22175;
  rs->allocated = initial_size;
  D.22176 = rs;
  return D.22176;
}


ref_stack_push (struct RefStack * rs, void * ptr)
{
  _Bool D.22178;
  long int D.22179;
  long int D.22180;
  int D.22183;
  int D.22184;
  unsigned int D.22187;
  unsigned int D.22188;
  unsigned int D.22189;
  void * * D.22190;
  void * D.22191;
  int D.22192;
  unsigned int D.22193;
  void * * D.22194;
  int D.22195;
  int D.22196;
  unsigned int D.22197;
  unsigned int D.22198;
  void * * D.22199;

  D.22178 = rs == 0B;
  D.22179 = (long int) D.22178;
  D.22180 = __builtin_expect (D.22179, 0);
  if (D.22180 != 0) goto <D.22181>; else goto <D.22182>;
  <D.22181>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3443, "rs != NULL");
  <D.22182>:
  D.22183 = rs->bottom;
  D.22184 = rs->allocated;
  if (D.22183 >= D.22184) goto <D.22185>; else goto <D.22186>;
  <D.22185>:
  D.22184 = rs->allocated;
  D.22187 = (unsigned int) D.22184;
  D.22188 = D.22187 * 8;
  D.22189 = D.22188 + 1;
  D.22190 = rs->refs;
  D.22191 = monoeg_realloc (D.22190, D.22189);
  rs->refs = D.22191;
  D.22184 = rs->allocated;
  D.22192 = D.22184 << 1;
  rs->allocated = D.22192;
  D.22190 = rs->refs;
  D.22184 = rs->allocated;
  D.22187 = (unsigned int) D.22184;
  D.22193 = D.22187 * 4;
  D.22194 = D.22190 + D.22193;
  *D.22194 = 0B;
  <D.22186>:
  D.22190 = rs->refs;
  D.22183 = rs->bottom;
  D.22195 = D.22183;
  D.22196 = D.22195 + 1;
  rs->bottom = D.22196;
  D.22197 = (unsigned int) D.22195;
  D.22198 = D.22197 * 4;
  D.22199 = D.22190 + D.22198;
  *D.22199 = ptr;
}


mono_thread_pop_appdomain_ref ()
{
  volatile int * D.22202;
  int D.22203;
  void * D.22205;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  if (thread != 0B) goto <D.22200>; else goto <D.22201>;
  <D.22200>:
  <D.19557>:
  D.22202 = &thread->lock_thread_id;
  D.22203 = InterlockedCompareExchange (D.22202, 1, 0);
  if (D.22203 == 0) goto <D.19556>; else goto <D.22204>;
  <D.22204>:
  goto <D.19557>;
  <D.19556>:
  D.22205 = thread->appdomain_refs;
  ref_stack_pop (D.22205);
  thread->lock_thread_id = 0;
  <D.22201>:
}


ref_stack_pop (struct RefStack * rs)
{
  int D.22209;
  int D.22210;
  void * * D.22211;
  unsigned int D.22212;
  unsigned int D.22213;
  void * * D.22214;

  if (rs == 0B) goto <D.22206>; else goto <D.22208>;
  <D.22208>:
  D.22209 = rs->bottom;
  if (D.22209 == 0) goto <D.22206>; else goto <D.22207>;
  <D.22206>:
  return;
  <D.22207>:
  D.22209 = rs->bottom;
  D.22210 = D.22209 + -1;
  rs->bottom = D.22210;
  D.22211 = rs->refs;
  D.22209 = rs->bottom;
  D.22212 = (unsigned int) D.22209;
  D.22213 = D.22212 * 4;
  D.22214 = D.22211 + D.22213;
  *D.22214 = 0B;
}


mono_thread_internal_has_appdomain_ref (struct MonoInternalThread * thread, struct MonoDomain * domain)
{
  volatile int * D.22216;
  int D.22217;
  void * D.22219;
  gboolean D.22220;
  gboolean res;

  <D.19564>:
  D.22216 = &thread->lock_thread_id;
  D.22217 = InterlockedCompareExchange (D.22216, 1, 0);
  if (D.22217 == 0) goto <D.19563>; else goto <D.22218>;
  <D.22218>:
  goto <D.19564>;
  <D.19563>:
  D.22219 = thread->appdomain_refs;
  res = ref_stack_find (D.22219, domain);
  thread->lock_thread_id = 0;
  D.22220 = res;
  return D.22220;
}


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

  if (rs == 0B) goto <D.22222>; else goto <D.22223>;
  <D.22222>:
  D.22224 = 0;
  return D.22224;
  <D.22223>:
  refs = rs->refs;
  goto <D.19544>;
  <D.19543>:
  D.22225 = *refs;
  if (D.22225 == ptr) goto <D.22226>; else goto <D.22227>;
  <D.22226>:
  D.22224 = 1;
  return D.22224;
  <D.22227>:
  refs = refs + 4;
  <D.19544>:
  if (refs != 0B) goto <D.22228>; else goto <D.19545>;
  <D.22228>:
  D.22225 = *refs;
  if (D.22225 != 0B) goto <D.19543>; else goto <D.19545>;
  <D.19545>:
  D.22224 = 0;
  return D.22224;
}


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

  D.22231 = thread->internal_thread;
  D.22230 = mono_thread_internal_has_appdomain_ref (D.22231, domain);
  return D.22230;
}


mono_threads_abort_appdomain_threads (struct MonoDomain * domain, int timeout)
{
  _Bool D.22235;
  long int D.22236;
  long int D.22237;
  struct MonoGHashTable * threads.126;
  _Bool D.22243;
  long int D.22244;
  long int D.22245;
  unsigned int D.22248;
  struct MonoInternalThread * D.22251;
  unsigned int i.127;
  unsigned int D.22253;
  unsigned int D.22254;
  unsigned int timeout.128;
  unsigned int D.22256;
  _Bool D.22257;
  _Bool D.22258;
  _Bool D.22259;
  gboolean D.22262;
  struct abort_appdomain_data user_data;
  guint32 start_time;
  int orig_timeout;
  int i;

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

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22233>; else goto <D.22234>;
        <D.22233>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.22234>:
        D.22235 = ret != 0;
        D.22236 = (long int) D.22235;
        D.22237 = __builtin_expect (D.22236, 0);
        if (D.22237 != 0) goto <D.22238>; else goto <D.22239>;
        <D.22238>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3580, "ret == 0");
        <D.22239>:
      }
      user_data.domain = domain;
      user_data.wait.num = 0;
      threads.126 = threads;
      mono_g_hash_table_foreach (threads.126, collect_appdomain_thread, &user_data);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22241>; else goto <D.22242>;
        <D.22241>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.22242>:
        D.22243 = ret != 0;
        D.22244 = (long int) D.22243;
        D.22245 = __builtin_expect (D.22244, 0);
        if (D.22245 != 0) goto <D.22246>; else goto <D.22247>;
        <D.22246>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3586, "ret == 0");
        <D.22247>:
      }
      D.22248 = user_data.wait.num;
      if (D.22248 != 0) goto <D.22249>; else goto <D.22250>;
      <D.22249>:
      i = 0;
      goto <D.19593>;
      <D.19592>:
      D.22251 = user_data.wait.threads[i];
      ves_icall_System_Threading_Thread_Abort (D.22251, 0B);
      i = i + 1;
      <D.19593>:
      i.127 = (unsigned int) i;
      D.22248 = user_data.wait.num;
      if (i.127 < D.22248) goto <D.19592>; else goto <D.19594>;
      <D.19594>:
      wait_for_tids (&user_data.wait, 100);
      <D.22250>:
      D.22253 = mono_msec_ticks ();
      D.22254 = D.22253 - start_time;
      timeout.128 = (unsigned int) timeout;
      D.22256 = timeout.128 - D.22254;
      timeout = (int) D.22256;
      start_time = mono_msec_ticks ();
      D.22257 = orig_timeout != -1;
      D.22258 = timeout < 0;
      D.22259 = D.22257 & D.22258;
      if (D.22259 != 0) goto <D.22260>; else goto <D.22261>;
      <D.22260>:
      D.22262 = 0;
      return D.22262;
      <D.22261>:
      D.22248 = user_data.wait.num;
      if (D.22248 != 0) goto <D.19595>; else goto <D.19596>;
      <D.19596>:
      D.22262 = 1;
      return D.22262;
    }
  finally
    {
      user_data = {CLOBBER};
    }
}


collect_appdomain_thread (void * key, void * value, void * user_data)
{
  int D.22265;
  unsigned int D.22268;
  long long unsigned int D.22271;
  unsigned int D.22272;
  unsigned int D.22275;
  struct MonoInternalThread * thread;
  struct abort_appdomain_data * data;
  struct MonoDomain * domain;

  thread = value;
  data = user_data;
  domain = data->domain;
  D.22265 = mono_thread_internal_has_appdomain_ref (thread, domain);
  if (D.22265 != 0) goto <D.22266>; else goto <D.22267>;
  <D.22266>:
  D.22268 = data->wait.num;
  if (D.22268 <= 63) goto <D.22269>; else goto <D.22270>;
  <D.22269>:
  {
    void * handle;

    D.22271 = thread->tid;
    D.22272 = (unsigned int) D.22271;
    handle = OpenThread (2032639, 1, D.22272);
    if (handle == 0B) goto <D.22273>; else goto <D.22274>;
    <D.22273>:
    return;
    <D.22274>:
    D.22268 = data->wait.num;
    data->wait.handles[D.22268] = handle;
    D.22268 = data->wait.num;
    data->wait.threads[D.22268] = thread;
    D.22268 = data->wait.num;
    D.22275 = D.22268 + 1;
    data->wait.num = D.22275;
  }
  goto <D.22276>;
  <D.22270>:
  <D.22276>:
  <D.22267>:
}


mono_threads_clear_cached_culture (struct MonoDomain * domain)
{
  _Bool D.22280;
  long int D.22281;
  long int D.22282;
  struct MonoGHashTable * threads.129;
  _Bool D.22288;
  long int D.22289;
  long int D.22290;

  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22278>; else goto <D.22279>;
    <D.22278>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.22279>:
    D.22280 = ret != 0;
    D.22281 = (long int) D.22280;
    D.22282 = __builtin_expect (D.22281, 0);
    if (D.22282 != 0) goto <D.22283>; else goto <D.22284>;
    <D.22283>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3642, "ret == 0");
    <D.22284>:
  }
  threads.129 = threads;
  mono_g_hash_table_foreach (threads.129, clear_cached_culture, domain);
  {
    int ret;

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


clear_cached_culture (void * key, void * value, void * user_data)
{
  struct MonoArray * D.22293;
  unsigned int i.130;
  char * D.22297;
  struct MonoVTable * D.22300;
  struct MonoDomain * D.22301;
  struct MonoInternalThread * thread;
  struct MonoDomain * domain;
  int i;

  thread = value;
  domain = user_data;
  D.22293 = thread->cached_culture_info;
  if (D.22293 != 0B) goto <D.22294>; else goto <D.22295>;
  <D.22294>:
  i = 0;
  goto <D.19608>;
  <D.19607>:
  {
    struct MonoObject * obj;

    i.130 = (unsigned int) i;
    D.22293 = thread->cached_culture_info;
    D.22297 = mono_array_addr_with_size (D.22293, 4, i.130);
    obj = MEM[(struct MonoObject * *)D.22297];
    if (obj != 0B) goto <D.22298>; else goto <D.22299>;
    <D.22298>:
    D.22300 = obj->vtable;
    D.22301 = D.22300->domain;
    if (D.22301 == domain) goto <D.22302>; else goto <D.22303>;
    <D.22302>:
    {
      struct MonoObject * * __p;

      i.130 = (unsigned int) i;
      D.22293 = thread->cached_culture_info;
      __p = mono_array_addr_with_size (D.22293, 4, i.130);
      *__p = 0B;
    }
    <D.22303>:
    <D.22299>:
  }
  i = i + 1;
  <D.19608>:
  if (i <= 7) goto <D.19607>; else goto <D.19609>;
  <D.19609>:
  <D.22295>:
}


mono_thread_get_undeniable_exception ()
{
  struct MonoException * D.22306;
  int D.22309;
  struct MonoException * D.22312;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  if (thread != 0B) goto <D.22304>; else goto <D.22305>;
  <D.22304>:
  D.22306 = thread->abort_exc;
  if (D.22306 != 0B) goto <D.22307>; else goto <D.22308>;
  <D.22307>:
  D.22309 = is_running_protected_wrapper ();
  if (D.22309 == 0) goto <D.22310>; else goto <D.22311>;
  <D.22310>:
  D.22306 = thread->abort_exc;
  D.22306->trace_ips = 0B;
  D.22306 = thread->abort_exc;
  D.22306->stack_trace = 0B;
  D.22312 = thread->abort_exc;
  return D.22312;
  <D.22311>:
  <D.22308>:
  <D.22305>:
  D.22312 = 0B;
  return D.22312;
}


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

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


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

  if (managed != 0) goto <D.22317>; else goto <D.22318>;
  <D.22317>:
  D.22319 = 1;
  return D.22319;
  <D.22318>:
  D.22320 = mono_threads_is_critical_method (m);
  if (D.22320 != 0) goto <D.22321>; else goto <D.22322>;
  <D.22321>:
  MEM[(gboolean *)data] = 1;
  D.22319 = 1;
  return D.22319;
  <D.22322>:
  D.22319 = 0;
  return D.22319;
}


mono_alloc_special_static_data (guint32 static_type, guint32 size, guint32 align, uintptr_t * bitmap, int numbits)
{
  _Bool D.22328;
  long int D.22329;
  long int D.22330;
  struct MonoGHashTable * threads.131;
  void * offset.132;
  _Bool D.22342;
  long int D.22343;
  long int D.22344;
  _Bool D.22348;
  long int D.22349;
  long int D.22350;
  _Bool D.22355;
  long int D.22356;
  long int D.22357;
  _Bool D.22362;
  long int D.22363;
  long int D.22364;
  uint32_t D.22367;
  guint32 offset;

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

    {
      int ret;

      ret = pthread_mutex_lock (&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_lock 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", 3902, "ret == 0");
      <D.22332>:
    }
    item = search_tls_slot_in_freelist (&thread_static_info, size, align);
    if (item != 0B) goto <D.22333>; else goto <D.22334>;
    <D.22333>:
    offset = item->offset;
    monoeg_g_free (item);
    goto <D.22335>;
    <D.22334>:
    offset = mono_alloc_static_data_slot (&thread_static_info, size, align);
    <D.22335>:
    update_tls_reference_bitmap (offset, bitmap, numbits);
    threads.131 = threads;
    if (threads.131 != 0B) goto <D.22337>; else goto <D.22338>;
    <D.22337>:
    offset.132 = (void *) offset;
    threads.131 = threads;
    mono_g_hash_table_foreach (threads.131, alloc_thread_static_data_helper, offset.132);
    <D.22338>:
    {
      int ret;

      ret = pthread_mutex_unlock (&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_unlock 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", 3915, "ret == 0");
      <D.22346>:
    }
  }
  goto <D.22347>;
  <D.22325>:
  D.22348 = static_type != 2;
  D.22349 = (long int) D.22348;
  D.22350 = __builtin_expect (D.22349, 0);
  if (D.22350 != 0) goto <D.22351>; else goto <D.22352>;
  <D.22351>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3917, "static_type == SPECIAL_STATIC_CONTEXT");
  <D.22352>:
  {
    int ret;

    ret = pthread_mutex_lock (&contexts_mutex.mutex);
    if (ret != 0) goto <D.22353>; else goto <D.22354>;
    <D.22353>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.22354>:
    D.22355 = ret != 0;
    D.22356 = (long int) D.22355;
    D.22357 = __builtin_expect (D.22356, 0);
    if (D.22357 != 0) goto <D.22358>; else goto <D.22359>;
    <D.22358>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3918, "ret == 0");
    <D.22359>:
  }
  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.22360>; else goto <D.22361>;
    <D.22360>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.22361>:
    D.22362 = ret != 0;
    D.22363 = (long int) D.22362;
    D.22364 = __builtin_expect (D.22363, 0);
    if (D.22364 != 0) goto <D.22365>; else goto <D.22366>;
    <D.22365>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3920, "ret == 0");
    <D.22366>:
  }
  offset = offset | 2147483648;
  <D.22347>:
  D.22367 = offset;
  return D.22367;
}


alloc_thread_static_data_helper (void * key, void * value, void * user)
{
  void * * * D.22369;
  struct MonoInternalThread * thread;
  guint32 offset;

  thread = value;
  offset = (guint32) user;
  D.22369 = &thread->static_data;
  mono_alloc_static_data (D.22369, offset, 1);
}


search_tls_slot_in_freelist (struct StaticDataInfo * static_data, guint32 size, guint32 align)
{
  unsigned int D.22370;
  struct MonoThreadDomainTls * D.22375;
  struct MonoThreadDomainTls * D.22377;
  struct MonoThreadDomainTls * prev;
  struct MonoThreadDomainTls * tmp;

  prev = 0B;
  tmp = static_data->freelist;
  goto <D.19695>;
  <D.19694>:
  D.22370 = tmp->size;
  if (D.22370 == size) goto <D.22371>; else goto <D.22372>;
  <D.22371>:
  if (prev != 0B) goto <D.22373>; else goto <D.22374>;
  <D.22373>:
  D.22375 = tmp->next;
  prev->next = D.22375;
  goto <D.22376>;
  <D.22374>:
  D.22375 = tmp->next;
  static_data->freelist = D.22375;
  <D.22376>:
  D.22377 = tmp;
  return D.22377;
  <D.22372>:
  tmp = tmp->next;
  <D.19695>:
  if (tmp != 0B) goto <D.19694>; else goto <D.19696>;
  <D.19696>:
  D.22377 = 0B;
  return D.22377;
}


update_tls_reference_bitmap (guint32 offset, uintptr_t * bitmap, int numbits)
{
  unsigned int D.22379;
  unsigned int D.22380;
  uintptr_t * D.22381;
  int D.22384;
  unsigned int D.22385;
  unsigned int D.22386;
  unsigned int D.22387;
  unsigned int D.22388;
  void * D.22389;
  unsigned int i.133;
  unsigned int D.22391;
  unsigned int D.22392;
  uintptr_t * D.22393;
  unsigned int D.22394;
  int D.22395;
  long int D.22396;
  long unsigned int D.22397;
  long unsigned int D.22398;
  unsigned int i.134;
  unsigned int D.22402;
  unsigned int D.22403;
  unsigned int D.22404;
  uintptr_t * D.22405;
  unsigned int D.22406;
  int D.22407;
  int D.22408;
  long int D.22409;
  long unsigned int D.22410;
  long unsigned int D.22411;
  int i;
  int idx;
  uintptr_t * rb;

  D.22379 = offset >> 24;
  D.22380 = D.22379 + 4294967295;
  idx = (int) D.22380;
  D.22381 = static_reference_bitmaps[idx];
  if (D.22381 == 0B) goto <D.22382>; else goto <D.22383>;
  <D.22382>:
  D.22384 = static_data_size[idx];
  D.22385 = (unsigned int) D.22384;
  D.22386 = D.22385 / 128;
  D.22387 = D.22386 + 1;
  D.22388 = D.22387 * 4;
  D.22389 = monoeg_malloc0 (D.22388);
  static_reference_bitmaps[idx] = D.22389;
  <D.22383>:
  rb = static_reference_bitmaps[idx];
  offset = offset & 16777215;
  offset = offset / 4;
  i = 0;
  goto <D.19706>;
  <D.19705>:
  i.133 = (unsigned int) i;
  D.22391 = i.133 / 4;
  D.22392 = D.22391 * 4;
  D.22393 = bitmap + D.22392;
  D.22394 = *D.22393;
  D.22395 = i & 31;
  D.22396 = 1 << D.22395;
  D.22397 = (long unsigned int) D.22396;
  D.22398 = D.22394 & D.22397;
  if (D.22398 != 0) goto <D.22399>; else goto <D.22400>;
  <D.22399>:
  i.134 = (unsigned int) i;
  D.22402 = offset + i.134;
  D.22403 = D.22402 / 32;
  D.22404 = D.22403 * 4;
  D.22405 = rb + D.22404;
  D.22404 = D.22403 * 4;
  D.22405 = rb + D.22404;
  D.22406 = *D.22405;
  i.134 = (unsigned int) i;
  D.22402 = offset + i.134;
  D.22407 = (int) D.22402;
  D.22408 = D.22407 & 31;
  D.22409 = 1 << D.22408;
  D.22410 = (long unsigned int) D.22409;
  D.22411 = D.22406 | D.22410;
  *D.22405 = D.22411;
  <D.22400>:
  i = i + 1;
  <D.19706>:
  if (i < numbits) goto <D.19705>; else goto <D.19707>;
  <D.19707>:
}


mono_alloc_static_data_slot (struct StaticDataInfo * static_data, guint32 size, guint32 align)
{
  int D.22412;
  int D.22415;
  unsigned int D.22418;
  unsigned int D.22419;
  unsigned int D.22420;
  int D.22421;
  unsigned int D.22422;
  unsigned int D.22423;
  int D.22424;
  unsigned int D.22425;
  int D.22426;
  unsigned int D.22427;
  int D.22430;
  _Bool D.22431;
  long int D.22432;
  long int D.22433;
  _Bool D.22436;
  long int D.22437;
  long int D.22438;
  int D.22441;
  int D.22442;
  int D.22443;
  guint32 D.22444;
  guint32 offset;

  D.22412 = static_data->idx;
  if (D.22412 == 0) goto <D.22413>; else goto <D.22414>;
  <D.22413>:
  D.22415 = static_data->offset;
  if (D.22415 == 0) goto <D.22416>; else goto <D.22417>;
  <D.22416>:
  static_data->offset = 32;
  <D.22417>:
  <D.22414>:
  D.22415 = static_data->offset;
  D.22418 = (unsigned int) D.22415;
  D.22419 = D.22418 + align;
  D.22420 = D.22419 + 4294967295;
  D.22421 = (int) D.22420;
  static_data->offset = D.22421;
  D.22415 = static_data->offset;
  D.22418 = (unsigned int) D.22415;
  D.22422 = -align;
  D.22423 = D.22418 & D.22422;
  D.22424 = (int) D.22423;
  static_data->offset = D.22424;
  D.22415 = static_data->offset;
  D.22418 = (unsigned int) D.22415;
  D.22425 = D.22418 + size;
  D.22412 = static_data->idx;
  D.22426 = static_data_size[D.22412];
  D.22427 = (unsigned int) D.22426;
  if (D.22425 >= D.22427) goto <D.22428>; else goto <D.22429>;
  <D.22428>:
  D.22412 = static_data->idx;
  D.22430 = D.22412 + 1;
  static_data->idx = D.22430;
  D.22412 = static_data->idx;
  D.22426 = static_data_size[D.22412];
  D.22427 = (unsigned int) D.22426;
  D.22431 = D.22427 < size;
  D.22432 = (long int) D.22431;
  D.22433 = __builtin_expect (D.22432, 0);
  if (D.22433 != 0) goto <D.22434>; else goto <D.22435>;
  <D.22434>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3801, "size <= static_data_size [static_data->idx]");
  <D.22435>:
  D.22412 = static_data->idx;
  D.22436 = D.22412 > 7;
  D.22437 = (long int) D.22436;
  D.22438 = __builtin_expect (D.22437, 0);
  if (D.22438 != 0) goto <D.22439>; else goto <D.22440>;
  <D.22439>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3802, "static_data->idx < NUM_STATIC_DATA_IDX");
  <D.22440>:
  static_data->offset = 0;
  <D.22429>:
  D.22415 = static_data->offset;
  D.22412 = static_data->idx;
  D.22430 = D.22412 + 1;
  D.22441 = D.22430 << 24;
  D.22442 = D.22415 | D.22441;
  offset = (guint32) D.22442;
  D.22415 = static_data->offset;
  D.22418 = (unsigned int) D.22415;
  D.22425 = D.22418 + size;
  D.22443 = (int) D.22425;
  static_data->offset = D.22443;
  D.22444 = offset;
  return D.22444;
}


mono_get_special_static_data_for_thread (struct MonoInternalThread * thread, guint32 offset)
{
  unsigned int D.22446;
  unsigned int D.22447;
  void * D.22450;
  void * * D.22453;
  unsigned int idx.135;
  unsigned int D.22456;
  void * * D.22457;
  void * D.22458;
  _Bool D.22461;
  long int D.22462;
  long int D.22463;
  void * * * D.22466;
  _Bool D.22469;
  long int D.22470;
  long int D.22471;
  sizetype D.22474;
  guint32 static_type;
  int idx;

  static_type = offset & 2147483648;
  offset = offset & 2147483647;
  D.22446 = offset >> 24;
  D.22447 = D.22446 + 4294967295;
  idx = (int) D.22447;
  if (static_type == 0) goto <D.22448>; else goto <D.22449>;
  <D.22448>:
  D.22450 = get_thread_static_data (thread, offset);
  return D.22450;
  <D.22449>:
  {
    struct MonoAppContext * context;

    context = mono_context_get ();
    D.22453 = context->static_data;
    if (D.22453 == 0B) goto <D.22451>; else goto <D.22454>;
    <D.22454>:
    D.22453 = context->static_data;
    idx.135 = (unsigned int) idx;
    D.22456 = idx.135 * 4;
    D.22457 = D.22453 + D.22456;
    D.22458 = *D.22457;
    if (D.22458 == 0B) goto <D.22451>; else goto <D.22452>;
    <D.22451>:
    {
      int ret;

      ret = pthread_mutex_lock (&contexts_mutex.mutex);
      if (ret != 0) goto <D.22459>; else goto <D.22460>;
      <D.22459>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
      <D.22460>:
      D.22461 = ret != 0;
      D.22462 = (long int) D.22461;
      D.22463 = __builtin_expect (D.22462, 0);
      if (D.22463 != 0) goto <D.22464>; else goto <D.22465>;
      <D.22464>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3945, "ret == 0");
      <D.22465>:
    }
    D.22466 = &context->static_data;
    mono_alloc_static_data (D.22466, offset, 0);
    {
      int ret;

      ret = pthread_mutex_unlock (&contexts_mutex.mutex);
      if (ret != 0) goto <D.22467>; else goto <D.22468>;
      <D.22467>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.22468>:
      D.22469 = ret != 0;
      D.22470 = (long int) D.22469;
      D.22471 = __builtin_expect (D.22470, 0);
      if (D.22471 != 0) goto <D.22472>; else goto <D.22473>;
      <D.22472>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3947, "ret == 0");
      <D.22473>:
    }
    <D.22452>:
    D.22453 = context->static_data;
    idx.135 = (unsigned int) idx;
    D.22456 = idx.135 * 4;
    D.22457 = D.22453 + D.22456;
    D.22458 = *D.22457;
    D.22474 = offset & 16777215;
    D.22450 = D.22458 + D.22474;
    return D.22450;
  }
}


mono_get_special_static_data (guint32 offset)
{
  void * D.22476;
  struct MonoInternalThread * D.22477;

  D.22477 = mono_thread_internal_current ();
  D.22476 = mono_get_special_static_data_for_thread (D.22477, offset);
  return D.22476;
}


mono_alloc_special_static_data_free (struct GHashTable * special_static_fields)
{
  _Bool D.22481;
  long int D.22482;
  long int D.22483;
  _Bool D.22488;
  long int D.22489;
  long int D.22490;

  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22479>; else goto <D.22480>;
    <D.22479>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.22480>:
    D.22481 = ret != 0;
    D.22482 = (long int) D.22481;
    D.22483 = __builtin_expect (D.22482, 0);
    if (D.22483 != 0) goto <D.22484>; else goto <D.22485>;
    <D.22484>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4020, "ret == 0");
    <D.22485>:
  }
  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.22486>; else goto <D.22487>;
    <D.22486>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.22487>:
    D.22488 = ret != 0;
    D.22489 = (long int) D.22488;
    D.22490 = __builtin_expect (D.22489, 0);
    if (D.22490 != 0) goto <D.22491>; else goto <D.22492>;
    <D.22491>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4022, "ret == 0");
    <D.22492>:
  }
}


do_free_special (void * key, void * value, void * data)
{
  struct MonoType * D.22493;
  int D.22494;
  struct MonoClassField * field;
  guint32 offset;
  gint32 align;
  guint32 size;

  try
    {
      field = key;
      offset = (guint32) value;
      D.22493 = field->type;
      D.22494 = mono_type_size (D.22493, &align);
      size = (guint32) D.22494;
      do_free_special_slot (offset, size);
    }
  finally
    {
      align = {CLOBBER};
    }
}


do_free_special_slot (guint32 offset, guint32 size)
{
  unsigned int D.22497;
  unsigned int D.22498;
  unsigned int D.22499;
  struct MonoGHashTable * threads.136;
  int D.22503;
  struct MonoThreadDomainTls * D.22506;
  guint32 static_type;

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

    try
      {
        item = monoeg_malloc0 (12);
        D.22497 = offset & 2147483647;
        data.offset = D.22497;
        data.size = size;
        D.22498 = data.size;
        D.22499 = data.offset;
        clear_reference_bitmap (D.22499, D.22498);
        threads.136 = threads;
        if (threads.136 != 0B) goto <D.22501>; else goto <D.22502>;
        <D.22501>:
        threads.136 = threads;
        mono_g_hash_table_foreach (threads.136, free_thread_static_data_helper, &data);
        <D.22502>:
        item->offset = offset;
        item->size = size;
        D.22503 = mono_runtime_is_shutting_down ();
        if (D.22503 == 0) goto <D.22504>; else goto <D.22505>;
        <D.22504>:
        D.22506 = thread_static_info.freelist;
        item->next = D.22506;
        thread_static_info.freelist = item;
        goto <D.22507>;
        <D.22505>:
        monoeg_g_free (item);
        <D.22507>:
      }
    finally
      {
        data = {CLOBBER};
      }
  }
  goto <D.22508>;
  <D.22496>:
  <D.22508>:
}


free_thread_static_data_helper (void * key, void * value, void * user)
{
  unsigned int D.22509;
  unsigned int D.22510;
  unsigned int D.22511;
  void * * D.22514;
  unsigned int idx.137;
  unsigned int D.22517;
  void * * D.22518;
  void * D.22519;
  sizetype D.22520;
  unsigned int D.22521;
  struct MonoInternalThread * thread;
  struct TlsOffsetSize * data;
  int idx;
  char * ptr;

  thread = value;
  data = user;
  D.22509 = data->offset;
  D.22510 = D.22509 >> 24;
  D.22511 = D.22510 + 4294967295;
  idx = (int) D.22511;
  D.22514 = thread->static_data;
  if (D.22514 == 0B) goto <D.22512>; else goto <D.22515>;
  <D.22515>:
  D.22514 = thread->static_data;
  idx.137 = (unsigned int) idx;
  D.22517 = idx.137 * 4;
  D.22518 = D.22514 + D.22517;
  D.22519 = *D.22518;
  if (D.22519 == 0B) goto <D.22512>; else goto <D.22513>;
  <D.22512>:
  return;
  <D.22513>:
  D.22514 = thread->static_data;
  idx.137 = (unsigned int) idx;
  D.22517 = idx.137 * 4;
  D.22518 = D.22514 + D.22517;
  D.22519 = *D.22518;
  D.22509 = data->offset;
  D.22520 = D.22509 & 16777215;
  ptr = D.22519 + D.22520;
  D.22521 = data->size;
  mono_gc_bzero_atomic (ptr, D.22521);
}


clear_reference_bitmap (guint32 offset, guint32 size)
{
  unsigned int D.22523;
  unsigned int D.22524;
  unsigned int D.22525;
  unsigned int D.22526;
  uintptr_t * D.22527;
  unsigned int D.22528;
  int offset.138;
  int D.22530;
  long int D.22531;
  long int D.22532;
  long unsigned int D.22533;
  long unsigned int D.22534;
  int idx;
  uintptr_t * rb;

  D.22523 = offset >> 24;
  D.22524 = D.22523 + 4294967295;
  idx = (int) D.22524;
  rb = static_reference_bitmaps[idx];
  offset = offset & 16777215;
  offset = offset / 4;
  size = size / 4;
  size = size + offset;
  goto <D.19715>;
  <D.19714>:
  D.22525 = offset / 32;
  D.22526 = D.22525 * 4;
  D.22527 = rb + D.22526;
  D.22526 = D.22525 * 4;
  D.22527 = rb + D.22526;
  D.22528 = *D.22527;
  offset.138 = (int) offset;
  D.22530 = offset.138 & 31;
  D.22531 = 1 << D.22530;
  D.22532 = ~D.22531;
  D.22533 = (long unsigned int) D.22532;
  D.22534 = D.22528 & D.22533;
  *D.22527 = D.22534;
  offset = offset + 1;
  <D.19715>:
  if (offset < size) goto <D.19714>; else goto <D.19716>;
  <D.19716>:
}


mono_special_static_data_free_slot (guint32 offset, guint32 size)
{
  _Bool D.22537;
  long int D.22538;
  long int D.22539;
  _Bool D.22544;
  long int D.22545;
  long int D.22546;

  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22535>; else goto <D.22536>;
    <D.22535>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.22536>:
    D.22537 = ret != 0;
    D.22538 = (long int) D.22537;
    D.22539 = __builtin_expect (D.22538, 0);
    if (D.22539 != 0) goto <D.22540>; else goto <D.22541>;
    <D.22540>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4028, "ret == 0");
    <D.22541>:
  }
  do_free_special_slot (offset, size);
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22542>; else goto <D.22543>;
    <D.22542>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.22543>:
    D.22544 = ret != 0;
    D.22545 = (long int) D.22544;
    D.22546 = __builtin_expect (D.22545, 0);
    if (D.22546 != 0) goto <D.22547>; else goto <D.22548>;
    <D.22547>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4030, "ret == 0");
    <D.22548>:
  }
}


mono_thread_alloc_tls (struct MonoReflectionType * type)
{
  struct MonoType * D.22549;
  int D.22550;
  int max_set.139;
  int D.22552;
  int align.140;
  unsigned int align.141;
  union mono_mutex_t * D.22557;
  _Bool D.22560;
  long int D.22561;
  long int D.22562;
  struct MonoTlsDataRecord * D.22565;
  _Bool D.22568;
  long int D.22569;
  long int D.22570;
  uint32_t D.22573;
  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.22549 = type->type;
      klass = mono_class_from_mono_type (D.22549);
      bitmap = mono_class_compute_bitmap (klass, &default_bitmap, 128, -2, &max_set, 0);
      D.22549 = type->type;
      D.22550 = mono_type_size (D.22549, &align);
      size = (guint32) D.22550;
      max_set.139 = max_set;
      D.22552 = max_set.139 + 1;
      align.140 = align;
      align.141 = (unsigned int) align.140;
      tls_offset = mono_alloc_special_static_data (1, size, align.141, bitmap, D.22552);
      if (&default_bitmap != bitmap) goto <D.22555>; else goto <D.22556>;
      <D.22555>:
      monoeg_g_free (bitmap);
      <D.22556>:
      tlsrec = monoeg_malloc0 (12);
      tlsrec->tls_offset = tls_offset;
      tlsrec->size = size;
      {
        int ret;

        D.22557 = &domain->lock.mutex;
        ret = pthread_mutex_lock (D.22557);
        if (ret != 0) goto <D.22558>; else goto <D.22559>;
        <D.22558>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.22559>:
        D.22560 = ret != 0;
        D.22561 = (long int) D.22560;
        D.22562 = __builtin_expect (D.22561, 0);
        if (D.22562 != 0) goto <D.22563>; else goto <D.22564>;
        <D.22563>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4060, "ret == 0");
        <D.22564>:
      }
      D.22565 = domain->tlsrec_list;
      tlsrec->next = D.22565;
      domain->tlsrec_list = tlsrec;
      {
        int ret;

        D.22557 = &domain->lock.mutex;
        ret = pthread_mutex_unlock (D.22557);
        if (ret != 0) goto <D.22566>; else goto <D.22567>;
        <D.22566>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.22567>:
        D.22568 = ret != 0;
        D.22569 = (long int) D.22568;
        D.22570 = __builtin_expect (D.22569, 0);
        if (D.22570 != 0) goto <D.22571>; else goto <D.22572>;
        <D.22571>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4063, "ret == 0");
        <D.22572>:
      }
      D.22573 = tls_offset;
      return D.22573;
    }
  finally
    {
      max_set = {CLOBBER};
      default_bitmap = {CLOBBER};
      align = {CLOBBER};
    }
}


mono_thread_destroy_tls (uint32_t tls_offset)
{
  union mono_mutex_t * D.22576;
  _Bool D.22579;
  long int D.22580;
  long int D.22581;
  unsigned int D.22584;
  struct MonoTlsDataRecord * D.22589;
  _Bool D.22593;
  long int D.22594;
  long int D.22595;
  struct MonoTlsDataRecord * prev;
  struct MonoTlsDataRecord * cur;
  guint32 size;
  struct MonoDomain * domain;

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

    D.22576 = &domain->lock.mutex;
    ret = pthread_mutex_lock (D.22576);
    if (ret != 0) goto <D.22577>; else goto <D.22578>;
    <D.22577>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.22578>:
    D.22579 = ret != 0;
    D.22580 = (long int) D.22579;
    D.22581 = __builtin_expect (D.22580, 0);
    if (D.22581 != 0) goto <D.22582>; else goto <D.22583>;
    <D.22582>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4074, "ret == 0");
    <D.22583>:
  }
  cur = domain->tlsrec_list;
  goto <D.19806>;
  <D.19805>:
  D.22584 = cur->tls_offset;
  if (D.22584 == tls_offset) goto <D.22585>; else goto <D.22586>;
  <D.22585>:
  if (prev != 0B) goto <D.22587>; else goto <D.22588>;
  <D.22587>:
  D.22589 = cur->next;
  prev->next = D.22589;
  goto <D.22590>;
  <D.22588>:
  D.22589 = cur->next;
  domain->tlsrec_list = D.22589;
  <D.22590>:
  size = cur->size;
  monoeg_g_free (cur);
  goto <D.19804>;
  <D.22586>:
  prev = cur;
  cur = cur->next;
  <D.19806>:
  if (cur != 0B) goto <D.19805>; else goto <D.19804>;
  <D.19804>:
  {
    int ret;

    D.22576 = &domain->lock.mutex;
    ret = pthread_mutex_unlock (D.22576);
    if (ret != 0) goto <D.22591>; else goto <D.22592>;
    <D.22591>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.22592>:
    D.22593 = ret != 0;
    D.22594 = (long int) D.22593;
    D.22595 = __builtin_expect (D.22594, 0);
    if (D.22595 != 0) goto <D.22596>; else goto <D.22597>;
    <D.22596>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4089, "ret == 0");
    <D.22597>:
  }
  if (size != 0) goto <D.22598>; else goto <D.22599>;
  <D.22598>:
  mono_special_static_data_free_slot (tls_offset, size);
  <D.22599>:
}


mono_thread_destroy_domain_tls (struct MonoDomain * domain)
{
  struct MonoTlsDataRecord * D.22600;
  unsigned int D.22601;

  goto <D.19812>;
  <D.19811>:
  D.22600 = domain->tlsrec_list;
  D.22601 = D.22600->tls_offset;
  mono_thread_destroy_tls (D.22601);
  <D.19812>:
  D.22600 = domain->tlsrec_list;
  if (D.22600 != 0B) goto <D.19811>; else goto <D.19813>;
  <D.19813>:
}


mono_thread_free_local_slot_values (int slot, MonoBoolean thread_local)
{
  struct MonoClassField * local_slots.142;
  struct MonoClass * D.22607;
  struct MonoClassField * local_slots.143;
  union mono_mutex_t * D.22611;
  _Bool D.22614;
  long int D.22615;
  long int D.22616;
  struct GHashTable * D.22619;
  _Bool D.22624;
  long int D.22625;
  long int D.22626;
  unsigned int addr.144;
  unsigned int D.22632;
  unsigned int D.22633;
  unsigned int D.22634;
  unsigned int D.22635;
  int D.22636;
  _Bool D.22639;
  long int D.22640;
  long int D.22641;
  struct MonoGHashTable * threads.145;
  _Bool D.22647;
  long int D.22648;
  long int D.22649;
  struct MonoDomain * domain;
  struct LocalSlotID sid;

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

        addr = 0B;
        local_slots.142 = local_slots;
        if (local_slots.142 == 0B) goto <D.22605>; else goto <D.22606>;
        <D.22605>:
        D.22607 = mono_defaults.thread_class;
        local_slots.143 = mono_class_get_field_from_name (D.22607, "local_slots");
        local_slots = local_slots.143;
        local_slots.142 = local_slots;
        if (local_slots.142 == 0B) goto <D.22609>; else goto <D.22610>;
        <D.22609>:
        monoeg_g_log (0B, 16, "local_slots field not found in Thread class");
        return;
        <D.22610>:
        <D.22606>:
        domain = mono_domain_get ();
        {
          int ret;

          D.22611 = &domain->lock.mutex;
          ret = pthread_mutex_lock (D.22611);
          if (ret != 0) goto <D.22612>; else goto <D.22613>;
          <D.22612>:
          monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
          <D.22613>:
          D.22614 = ret != 0;
          D.22615 = (long int) D.22614;
          D.22616 = __builtin_expect (D.22615, 0);
          if (D.22616 != 0) goto <D.22617>; else goto <D.22618>;
          <D.22617>:
          monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4150, "ret == 0");
          <D.22618>:
        }
        D.22619 = domain->special_static_fields;
        if (D.22619 != 0B) goto <D.22620>; else goto <D.22621>;
        <D.22620>:
        local_slots.142 = local_slots;
        D.22619 = domain->special_static_fields;
        addr = monoeg_g_hash_table_lookup (D.22619, local_slots.142);
        <D.22621>:
        {
          int ret;

          D.22611 = &domain->lock.mutex;
          ret = pthread_mutex_unlock (D.22611);
          if (ret != 0) goto <D.22622>; else goto <D.22623>;
          <D.22622>:
          monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
          <D.22623>:
          D.22624 = ret != 0;
          D.22625 = (long int) D.22624;
          D.22626 = __builtin_expect (D.22625, 0);
          if (D.22626 != 0) goto <D.22627>; else goto <D.22628>;
          <D.22627>:
          monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4153, "ret == 0");
          <D.22628>:
        }
        if (addr == 0B) goto <D.22629>; else goto <D.22630>;
        <D.22629>:
        return;
        <D.22630>:
        addr.144 = (unsigned int) addr;
        sid.offset = addr.144;
        D.22632 = sid.offset;
        D.22633 = D.22632 & 2147483647;
        sid.offset = D.22633;
        D.22632 = sid.offset;
        D.22634 = D.22632 >> 24;
        D.22635 = D.22634 + 4294967295;
        D.22636 = (int) D.22635;
        sid.idx = D.22636;
        {
          int ret;

          ret = pthread_mutex_lock (&threads_mutex.mutex);
          if (ret != 0) goto <D.22637>; else goto <D.22638>;
          <D.22637>:
          monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
          <D.22638>:
          D.22639 = ret != 0;
          D.22640 = (long int) D.22639;
          D.22641 = __builtin_expect (D.22640, 0);
          if (D.22641 != 0) goto <D.22642>; else goto <D.22643>;
          <D.22642>:
          monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4160, "ret == 0");
          <D.22643>:
        }
        threads.145 = threads;
        mono_g_hash_table_foreach (threads.145, clear_local_slot, &sid);
        {
          int ret;

          ret = pthread_mutex_unlock (&threads_mutex.mutex);
          if (ret != 0) goto <D.22645>; else goto <D.22646>;
          <D.22645>:
          monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
          <D.22646>:
          D.22647 = ret != 0;
          D.22648 = (long int) D.22647;
          D.22649 = __builtin_expect (D.22648, 0);
          if (D.22649 != 0) goto <D.22650>; else goto <D.22651>;
          <D.22650>:
          monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4162, "ret == 0");
          <D.22651>:
        }
      }
      goto <D.22652>;
      <D.22603>:
      <D.22652>:
    }
  finally
    {
      sid = {CLOBBER};
    }
}


clear_local_slot (void * key, void * value, void * user_data)
{
  void * * D.22658;
  int D.22660;
  unsigned int D.22661;
  unsigned int D.22662;
  void * * D.22663;
  void * D.22664;
  unsigned int D.22665;
  sizetype D.22666;
  struct MonoArray * * D.22667;
  int D.22671;
  unsigned int D.22672;
  unsigned int D.22673;
  struct LocalSlotID * sid;
  struct MonoInternalThread * thread;
  struct MonoArray * slots_array;

  sid = user_data;
  thread = value;
  D.22658 = thread->static_data;
  if (D.22658 == 0B) goto <D.22656>; else goto <D.22659>;
  <D.22659>:
  D.22658 = thread->static_data;
  D.22660 = sid->idx;
  D.22661 = (unsigned int) D.22660;
  D.22662 = D.22661 * 4;
  D.22663 = D.22658 + D.22662;
  D.22664 = *D.22663;
  if (D.22664 == 0B) goto <D.22656>; else goto <D.22657>;
  <D.22656>:
  return;
  <D.22657>:
  D.22658 = thread->static_data;
  D.22660 = sid->idx;
  D.22661 = (unsigned int) D.22660;
  D.22662 = D.22661 * 4;
  D.22663 = D.22658 + D.22662;
  D.22664 = *D.22663;
  D.22665 = sid->offset;
  D.22666 = D.22665 & 16777215;
  D.22667 = D.22664 + D.22666;
  slots_array = *D.22667;
  if (slots_array == 0B) goto <D.22668>; else goto <D.22670>;
  <D.22670>:
  D.22671 = sid->slot;
  D.22672 = (unsigned int) D.22671;
  D.22673 = mono_array_length (slots_array);
  if (D.22672 >= D.22673) goto <D.22668>; else goto <D.22669>;
  <D.22668>:
  return;
  <D.22669>:
  {
    struct MonoObject * * __p;

    D.22671 = sid->slot;
    D.22672 = (unsigned int) D.22671;
    __p = mono_array_addr_with_size (slots_array, 4, D.22672);
    *__p = 0B;
  }
}


mono_thread_request_interruption (gboolean running_managed)
{
  struct MonoException * D.22677;
  gint32 * D.22678;
  int D.22679;
  int D.22685;
  void (*<T479>) (void) mono_thread_notify_pending_exc_fn.146;
  void * D.22691;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  if (thread == 0B) goto <D.22675>; else goto <D.22676>;
  <D.22675>:
  D.22677 = 0B;
  return D.22677;
  <D.22676>:
  D.22678 = &thread->interruption_requested;
  D.22679 = InterlockedCompareExchange (D.22678, 1, 0);
  if (D.22679 == 1) goto <D.22680>; else goto <D.22681>;
  <D.22680>:
  D.22677 = 0B;
  return D.22677;
  <D.22681>:
  InterlockedIncrement (&thread_interruption_requested);
  if (running_managed == 0) goto <D.22682>; else goto <D.22684>;
  <D.22684>:
  D.22685 = is_running_protected_wrapper ();
  if (D.22685 != 0) goto <D.22682>; else goto <D.22683>;
  <D.22682>:
  mono_thread_notify_pending_exc_fn.146 = mono_thread_notify_pending_exc_fn;
  if (mono_thread_notify_pending_exc_fn.146 != 0B) goto <D.22687>; else goto <D.22688>;
  <D.22687>:
  if (running_managed == 0) goto <D.22689>; else goto <D.22690>;
  <D.22689>:
  mono_thread_notify_pending_exc_fn.146 = mono_thread_notify_pending_exc_fn;
  mono_thread_notify_pending_exc_fn.146 ();
  <D.22690>:
  <D.22688>:
  D.22691 = thread->handle;
  QueueUserAPC (dummy_apc, D.22691, 0B);
  D.22677 = 0B;
  return D.22677;
  <D.22683>:
  D.22677 = mono_thread_execute_interruption (thread);
  return D.22677;
}


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

  D.22693 = 0;
  return D.22693;
}


mono_thread_resume_interruption ()
{
  struct MonoException * D.22697;
  unsigned int D.22698;
  unsigned int D.22699;
  _Bool D.22700;
  gint32 * D.22703;
  int D.22704;
  struct MonoInternalThread * thread;
  gboolean still_aborting;

  thread = mono_thread_internal_current ();
  if (thread == 0B) goto <D.22695>; else goto <D.22696>;
  <D.22695>:
  D.22697 = 0B;
  return D.22697;
  <D.22696>:
  lock_thread (thread);
  D.22698 = thread->state;
  D.22699 = D.22698 & 128;
  D.22700 = D.22699 != 0;
  still_aborting = (gboolean) D.22700;
  unlock_thread (thread);
  if (still_aborting == 0) goto <D.22701>; else goto <D.22702>;
  <D.22701>:
  D.22697 = 0B;
  return D.22697;
  <D.22702>:
  D.22703 = &thread->interruption_requested;
  D.22704 = InterlockedCompareExchange (D.22703, 1, 0);
  if (D.22704 == 1) goto <D.22705>; else goto <D.22706>;
  <D.22705>:
  D.22697 = 0B;
  return D.22697;
  <D.22706>:
  InterlockedIncrement (&thread_interruption_requested);
  wapi_self_interrupt ();
  D.22697 = mono_thread_execute_interruption (thread);
  return D.22697;
}


mono_thread_interruption_requested ()
{
  int thread_interruption_requested.147;
  gboolean D.22713;

  thread_interruption_requested.147 = thread_interruption_requested;
  if (thread_interruption_requested.147 != 0) goto <D.22709>; else goto <D.22710>;
  <D.22709>:
  {
    struct MonoInternalThread * thread;

    thread = mono_thread_internal_current ();
    if (thread != 0B) goto <D.22711>; else goto <D.22712>;
    <D.22711>:
    D.22713 = thread->interruption_requested;
    return D.22713;
    <D.22712>:
  }
  <D.22710>:
  D.22713 = 0;
  return D.22713;
}


mono_thread_interruption_checkpoint ()
{
  mono_thread_interruption_checkpoint_request (0);
}


mono_thread_interruption_checkpoint_request (gboolean bypass_abort_protection)
{
  int D.22719;
  int D.22723;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  if (thread == 0B) goto <D.22715>; else goto <D.22716>;
  <D.22715>:
  return;
  <D.22716>:
  D.22719 = thread->interruption_requested;
  if (D.22719 != 0) goto <D.22720>; else goto <D.22721>;
  <D.22720>:
  if (bypass_abort_protection != 0) goto <D.22717>; else goto <D.22722>;
  <D.22722>:
  D.22723 = is_running_protected_wrapper ();
  if (D.22723 == 0) goto <D.22717>; else goto <D.22718>;
  <D.22717>:
  {
    struct MonoException * exc;

    exc = mono_thread_execute_interruption (thread);
    if (exc != 0B) goto <D.22724>; else goto <D.22725>;
    <D.22724>:
    mono_raise_exception (exc);
    <D.22725>:
  }
  <D.22718>:
  <D.22721>:
}


mono_thread_force_interruption_checkpoint ()
{
  mono_thread_interruption_checkpoint_request (1);
}


mono_thread_get_and_clear_pending_exception ()
{
  struct MonoException * D.22729;
  int D.22730;
  int D.22733;
  struct MonoException * D.22736;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  if (thread == 0B) goto <D.22727>; else goto <D.22728>;
  <D.22727>:
  D.22729 = 0B;
  return D.22729;
  <D.22728>:
  D.22730 = thread->interruption_requested;
  if (D.22730 != 0) goto <D.22731>; else goto <D.22732>;
  <D.22731>:
  D.22733 = is_running_protected_wrapper ();
  if (D.22733 == 0) goto <D.22734>; else goto <D.22735>;
  <D.22734>:
  D.22729 = mono_thread_execute_interruption (thread);
  return D.22729;
  <D.22735>:
  <D.22732>:
  D.22736 = thread->pending_exception;
  if (D.22736 != 0B) goto <D.22737>; else goto <D.22738>;
  <D.22737>:
  {
    struct MonoException * exc;

    exc = thread->pending_exception;
    thread->pending_exception = 0B;
    D.22729 = exc;
    return D.22729;
  }
  <D.22738>:
  D.22729 = 0B;
  return D.22729;
}


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

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


mono_thread_interruption_request_flag ()
{
  gint32 * D.22744;

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


mono_thread_init_apartment_state ()
{

}


mono_thread_cleanup_apartment_state ()
{

}


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

  lock_thread (thread);
  D.22746 = thread->state;
  D.22747 = D.22746 | state;
  thread->state = D.22747;
  unlock_thread (thread);
}


mono_thread_clr_state (struct MonoInternalThread * thread, MonoThreadState state)
{
  unsigned int D.22748;
  unsigned int D.22749;
  unsigned int D.22750;

  lock_thread (thread);
  D.22748 = thread->state;
  D.22749 = ~state;
  D.22750 = D.22748 & D.22749;
  thread->state = D.22750;
  unlock_thread (thread);
}


mono_thread_test_state (struct MonoInternalThread * thread, MonoThreadState test)
{
  unsigned int D.22751;
  unsigned int D.22752;
  gboolean D.22755;
  gboolean ret;

  ret = 0;
  lock_thread (thread);
  D.22751 = thread->state;
  D.22752 = D.22751 & test;
  if (D.22752 != 0) goto <D.22753>; else goto <D.22754>;
  <D.22753>:
  ret = 1;
  <D.22754>:
  unlock_thread (thread);
  D.22755 = ret;
  return D.22755;
}


mono_thread_get_execution_context ()
{
  struct MonoObject * D.22757;
  struct MonoObject * * D.22758;

  D.22758 = get_execution_context_addr ();
  D.22757 = *D.22758;
  return D.22757;
}


get_execution_context_addr ()
{
  struct MonoClass * D.22762;
  _Bool D.22763;
  long int D.22764;
  long int D.22765;
  struct MonoClass * D.22768;
  struct MonoVTable * D.22769;
  _Bool D.22770;
  long int D.22771;
  long int D.22772;
  union mono_mutex_t * D.22775;
  _Bool D.22778;
  long int D.22779;
  long int D.22780;
  struct GHashTable * D.22783;
  void * D.22784;
  _Bool D.22787;
  long int D.22788;
  long int D.22789;
  _Bool D.22792;
  long int D.22793;
  long int D.22794;
  struct MonoObject * * D.22797;
  struct MonoDomain * domain;
  guint32 offset;

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

    D.22762 = mono_defaults.thread_class;
    field = mono_class_get_field_from_name (D.22762, "_ec");
    D.22763 = field == 0B;
    D.22764 = (long int) D.22763;
    D.22765 = __builtin_expect (D.22764, 0);
    if (D.22765 != 0) goto <D.22766>; else goto <D.22767>;
    <D.22766>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4501, "field");
    <D.22767>:
    D.22768 = mono_defaults.appdomain_class;
    D.22769 = mono_class_try_get_vtable (domain, D.22768);
    D.22770 = D.22769 == 0B;
    D.22771 = (long int) D.22770;
    D.22772 = __builtin_expect (D.22771, 0);
    if (D.22772 != 0) goto <D.22773>; else goto <D.22774>;
    <D.22773>:
    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.22774>:
    {
      int ret;

      D.22775 = &domain->lock.mutex;
      ret = pthread_mutex_lock (D.22775);
      if (ret != 0) goto <D.22776>; else goto <D.22777>;
      <D.22776>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
      <D.22777>:
      D.22778 = ret != 0;
      D.22779 = (long int) D.22778;
      D.22780 = __builtin_expect (D.22779, 0);
      if (D.22780 != 0) goto <D.22781>; else goto <D.22782>;
      <D.22781>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4505, "ret == 0");
      <D.22782>:
    }
    D.22783 = domain->special_static_fields;
    D.22784 = monoeg_g_hash_table_lookup (D.22783, field);
    offset = (guint32) D.22784;
    {
      int ret;

      D.22775 = &domain->lock.mutex;
      ret = pthread_mutex_unlock (D.22775);
      if (ret != 0) goto <D.22785>; else goto <D.22786>;
      <D.22785>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.22786>:
      D.22787 = ret != 0;
      D.22788 = (long int) D.22787;
      D.22789 = __builtin_expect (D.22788, 0);
      if (D.22789 != 0) goto <D.22790>; else goto <D.22791>;
      <D.22790>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4507, "ret == 0");
      <D.22791>:
    }
    D.22792 = offset == 0;
    D.22793 = (long int) D.22792;
    D.22794 = __builtin_expect (D.22793, 0);
    if (D.22794 != 0) goto <D.22795>; else goto <D.22796>;
    <D.22795>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4508, "offset");
    <D.22796>:
    domain->execution_context_field_offset = offset;
  }
  <D.22761>:
  D.22797 = mono_get_special_static_data (offset);
  return D.22797;
}


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

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


mono_runtime_set_has_tls_get (gboolean val)
{
  has_tls_get = val;
}


mono_runtime_has_tls_get ()
{
  gboolean D.22800;

  D.22800 = has_tls_get;
  return D.22800;
}


mono_thread_kill (struct MonoInternalThread * thread, int signal)
{
  int D.22802;
  int D.22803;
  long long unsigned int D.22804;
  long unsigned int D.22805;

  D.22803 = mono_thread_get_abort_signal ();
  D.22804 = thread->tid;
  D.22805 = (long unsigned int) D.22804;
  D.22802 = pthread_kill (D.22805, D.22803);
  return D.22802;
}


mono_thread_is_foreign (struct MonoThread * thread)
{
  struct _MonoInternalThread * D.22807;
  mono_bool D.22808;
  int D.22809;
  _Bool D.22810;
  struct MonoThreadInfo * info;

  D.22807 = thread->internal_thread;
  info = D.22807->thread_info;
  D.22809 = info->runtime_thread;
  D.22810 = D.22809 == 0;
  D.22808 = (mono_bool) D.22810;
  return D.22808;
}


