mono_thread_get_tls_key ()
{
  pthread_key_t D.20314;

  D.20314 = current_object_key;
  return D.20314;
}


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

  {
    guint64 foo;

    __asm__("movq $tls_current_object@TPOFF, %0" : "=r" foo);
    offset = (int) foo;
  }
  D.20316 = offset;
  return D.20316;
}


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


mono_threads_set_default_stacksize (guint32 stacksize)
{
  default_stacksize = stacksize;
}


mono_threads_get_default_stacksize ()
{
  uint32_t D.20321;

  D.20321 = default_stacksize;
  return D.20321;
}


mono_thread_create_internal (struct MonoDomain * domain, void * func, void * arg, gboolean threadpool_thread, gboolean no_detach, guint32 stack_size)
{
  struct _MonoInternalThread * * D.20323;
  guint32 (*<T3208>) (void *) func.1;
  struct MonoInternalThread * D.20327;
  const char * D.20328;
  struct MonoClass * D.20331;
  struct MonoClassField * D.20332;
  unsigned int D.20333;
  unsigned int D.20334;
  long unsigned int D.20335;
  long unsigned int D.20336;
  struct MonoClassField * D.20337;
  int D.20338;
  _Bool D.20339;
  long int D.20340;
  long int D.20341;
  struct MonoThread * thread;
  struct MonoInternalThread * internal;
  struct StartInfo * start_info;
  gboolean res;

  thread = create_thread_object (domain);
  internal = create_internal_thread ();
  D.20323 = &thread->internal_thread;
  mono_gc_wbarrier_set_field (thread, D.20323, internal);
  start_info = monoeg_malloc0 (32);
  func.1 = (guint32 (*<T3208>) (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.20325>; else goto <D.20326>;
  <D.20325>:
  D.20327 = 0B;
  return D.20327;
  <D.20326>:
  D.20328 = mono_check_corlib_version ();
  if (D.20328 == 0B) goto <D.20329>; else goto <D.20330>;
  <D.20329>:
  D.20331 = mono_defaults.internal_thread_class;
  D.20332 = D.20331->fields;
  D.20331 = mono_defaults.internal_thread_class;
  D.20333 = D.20331->field.count;
  D.20334 = D.20333 + 4294967295;
  D.20335 = (long unsigned int) D.20334;
  D.20336 = D.20335 * 32;
  D.20337 = D.20332 + D.20336;
  D.20338 = D.20337->offset;
  D.20339 = D.20338 != 312;
  D.20340 = (long int) D.20339;
  D.20341 = __builtin_expect (D.20340, 0);
  if (D.20341 != 0) goto <D.20342>; else goto <D.20343>;
  <D.20342>:
  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.20343>:
  <D.20330>:
  D.20327 = internal;
  return D.20327;
}


create_thread_object (struct MonoDomain * domain)
{
  struct MonoClass * D.20345;
  struct MonoThread * D.20346;
  struct MonoVTable * vt;

  D.20345 = mono_defaults.thread_class;
  vt = mono_class_vtable (domain, D.20345);
  D.20346 = mono_gc_alloc_mature (vt);
  return D.20346;
}


create_internal_thread ()
{
  struct MonoClass * D.20348;
  struct MonoDomain * D.20349;
  void * D.20350;
  struct CRITICAL_SECTION * D.20351;
  unsigned int D.20352;
  int D.20353;
  int D.20354;
  void * * D.20357;
  struct MonoInternalThread * D.20358;
  struct MonoInternalThread * thread;
  struct MonoVTable * vt;

  D.20348 = mono_defaults.internal_thread_class;
  D.20349 = mono_get_root_domain ();
  vt = mono_class_vtable (D.20349, D.20348);
  thread = mono_gc_alloc_mature (vt);
  D.20350 = monoeg_malloc0 (48);
  thread->synch_cs = D.20350;
  D.20351 = thread->synch_cs;
  InitializeCriticalSection (D.20351);
  thread->apartment_state = 2;
  D.20352 = get_next_managed_thread_id ();
  D.20353 = (int) D.20352;
  thread->managed_id = D.20353;
  D.20354 = mono_gc_is_moving ();
  if (D.20354 != 0) goto <D.20355>; else goto <D.20356>;
  <D.20355>:
  thread->thread_pinning_ref = thread;
  D.20357 = &thread->thread_pinning_ref;
  mono_gc_register_root (D.20357, 8, 0B);
  <D.20356>:
  D.20358 = thread;
  return D.20358;
}


get_next_managed_thread_id ()
{
  guint32 D.20360;
  int D.20361;

  D.20361 = InterlockedIncrement (&managed_thread_id_counter);
  D.20360 = (guint32) D.20361;
  return D.20360;
}


InterlockedIncrement (volatile gint32 * val)
{
  gint32 D.20363;
  unsigned int D.20364;

  D.20364 = __sync_add_and_fetch_4 (val, 1);
  D.20363 = (gint32) D.20364;
  return D.20363;
}


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.20368;
  long int D.20369;
  long int D.20370;
  int shutting_down.2;
  _Bool D.20378;
  long int D.20379;
  long int D.20380;
  gboolean D.20383;
  struct MonoGHashTable * thread_start_args.3;
  int D.20387;
  struct MonoGHashTable * thread_start_args.4;
  void * D.20391;
  struct MonoGHashTable * threads_starting_up.5;
  int D.20395;
  struct MonoGHashTable * threads_starting_up.6;
  _Bool D.20401;
  long int D.20402;
  long int D.20403;
  void * D.20406;
  void * D.20407;
  _Bool D.20412;
  long int D.20413;
  long int D.20414;
  _Bool D.20419;
  long int D.20420;
  long int D.20421;
  unsigned int D.20424;
  guint32 iftmp.7;
  int D.20428;
  _Bool D.20438;
  long int D.20439;
  long int D.20440;
  _Bool D.20445;
  long int D.20446;
  long int D.20447;
  struct MonoException * D.20452;
  unsigned int D.20454;
  long unsigned int tid.8;
  unsigned char D.20456;
  int D.20459;
  void * D.20462;
  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.20366>; else goto <D.20367>;
        <D.20366>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.20367>:
        D.20368 = ret != 0;
        D.20369 = (long int) D.20368;
        D.20370 = __builtin_expect (D.20369, 0);
        if (D.20370 != 0) goto <D.20371>; else goto <D.20372>;
        <D.20371>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 705, "ret == 0");
        <D.20372>:
      }
      shutting_down.2 = shutting_down;
      if (shutting_down.2 != 0) goto <D.20374>; else goto <D.20375>;
      <D.20374>:
      monoeg_g_free (start_info);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.20376>; else goto <D.20377>;
        <D.20376>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.20377>:
        D.20378 = ret != 0;
        D.20379 = (long int) D.20378;
        D.20380 = __builtin_expect (D.20379, 0);
        if (D.20380 != 0) goto <D.20381>; else goto <D.20382>;
        <D.20381>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 708, "ret == 0");
        <D.20382>:
      }
      D.20383 = 0;
      return D.20383;
      <D.20375>:
      thread_start_args.3 = thread_start_args;
      if (thread_start_args.3 == 0B) goto <D.20385>; else goto <D.20386>;
      <D.20385>:
      D.20387 = mono_gc_is_moving ();
      if (D.20387 == 0) goto <D.20388>; else goto <D.20389>;
      <D.20388>:
      mono_gc_register_root (&thread_start_args, 8, 0B);
      <D.20389>:
      thread_start_args.4 = mono_g_hash_table_new (0B, 0B);
      thread_start_args = thread_start_args.4;
      <D.20386>:
      D.20391 = start_info->start_arg;
      thread_start_args.3 = thread_start_args;
      mono_g_hash_table_insert (thread_start_args.3, thread, D.20391);
      threads_starting_up.5 = threads_starting_up;
      if (threads_starting_up.5 == 0B) goto <D.20393>; else goto <D.20394>;
      <D.20393>:
      D.20395 = mono_gc_is_moving ();
      if (D.20395 == 0) goto <D.20396>; else goto <D.20397>;
      <D.20396>:
      mono_gc_register_root (&threads_starting_up, 8, 0B);
      <D.20397>:
      threads_starting_up.6 = mono_g_hash_table_new_type (0B, 0B, 3);
      threads_starting_up = threads_starting_up.6;
      <D.20394>:
      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.20399>; else goto <D.20400>;
        <D.20399>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.20400>:
        D.20401 = ret != 0;
        D.20402 = (long int) D.20401;
        D.20403 = __builtin_expect (D.20402, 0);
        if (D.20403 != 0) goto <D.20404>; else goto <D.20405>;
        <D.20404>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 727, "ret == 0");
        <D.20405>:
      }
      D.20406 = CreateSemaphore (0B, 0, 2147483647, 0B);
      internal->start_notify = D.20406;
      D.20407 = internal->start_notify;
      if (D.20407 == 0B) goto <D.20408>; else goto <D.20409>;
      <D.20408>:
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.20410>; else goto <D.20411>;
        <D.20410>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.20411>:
        D.20412 = ret != 0;
        D.20413 = (long int) D.20412;
        D.20414 = __builtin_expect (D.20413, 0);
        if (D.20414 != 0) goto <D.20415>; else goto <D.20416>;
        <D.20415>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 731, "ret == 0");
        <D.20416>:
      }
      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.20417>; else goto <D.20418>;
        <D.20417>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.20418>:
        D.20419 = ret != 0;
        D.20420 = (long int) D.20419;
        D.20421 = __builtin_expect (D.20420, 0);
        if (D.20421 != 0) goto <D.20422>; else goto <D.20423>;
        <D.20422>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 733, "ret == 0");
        <D.20423>:
      }
      D.20424 = GetLastError ();
      monoeg_g_log (0B, 16, "%s: CreateSemaphore error 0x%x", &__func__, D.20424);
      monoeg_g_free (start_info);
      D.20383 = 0;
      return D.20383;
      <D.20409>:
      if (stack_size == 0) goto <D.20425>; else goto <D.20426>;
      <D.20425>:
      D.20428 = internal->stack_size;
      if (D.20428 != 0) goto <D.20429>; else goto <D.20430>;
      <D.20429>:
      D.20428 = internal->stack_size;
      iftmp.7 = (guint32) D.20428;
      goto <D.20431>;
      <D.20430>:
      iftmp.7 = default_stacksize;
      <D.20431>:
      stack_size = iftmp.7;
      <D.20426>:
      create_flags = 4;
      if (no_detach != 0) goto <D.20432>; else goto <D.20433>;
      <D.20432>:
      create_flags = create_flags | 268435456;
      <D.20433>:
      thread_handle = mono_threads_create_thread (start_wrapper, start_info, stack_size, create_flags, &tid);
      if (thread_handle == 0B) goto <D.20434>; else goto <D.20435>;
      <D.20434>:
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.20436>; else goto <D.20437>;
        <D.20436>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.20437>:
        D.20438 = ret != 0;
        D.20439 = (long int) D.20438;
        D.20440 = __builtin_expect (D.20439, 0);
        if (D.20440 != 0) goto <D.20441>; else goto <D.20442>;
        <D.20441>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 754, "ret == 0");
        <D.20442>:
      }
      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.20443>; else goto <D.20444>;
        <D.20443>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.20444>:
        D.20445 = ret != 0;
        D.20446 = (long int) D.20445;
        D.20447 = __builtin_expect (D.20446, 0);
        if (D.20447 != 0) goto <D.20448>; else goto <D.20449>;
        <D.20448>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 756, "ret == 0");
        <D.20449>:
      }
      monoeg_g_free (start_info);
      if (throw_on_failure != 0) goto <D.20450>; else goto <D.20451>;
      <D.20450>:
      D.20452 = mono_get_exception_execution_engine ("Couldn\'t create thread");
      mono_raise_exception (D.20452);
      goto <D.20453>;
      <D.20451>:
      D.20454 = GetLastError ();
      monoeg_g_log (0B, 16, "%s: CreateThread error 0x%x", &__func__, D.20454);
      <D.20453>:
      D.20383 = 0;
      return D.20383;
      <D.20435>:
      internal->handle = thread_handle;
      tid.8 = tid;
      internal->tid = tid.8;
      D.20456 = (unsigned char) threadpool_thread;
      internal->threadpool_thread = D.20456;
      if (threadpool_thread != 0) goto <D.20457>; else goto <D.20458>;
      <D.20457>:
      mono_thread_set_state (internal, 4);
      <D.20458>:
      D.20459 = handle_store (thread, 0);
      if (D.20459 == 0) goto <D.20460>; else goto <D.20461>;
      <D.20460>:
      D.20383 = 0;
      return D.20383;
      <D.20461>:
      D.20462 = internal->handle;
      ResumeThread (D.20462);
      D.20407 = internal->start_notify;
      if (D.20407 != 0B) goto <D.20463>; else goto <D.20464>;
      <D.20463>:
      D.20407 = internal->start_notify;
      WaitForSingleObjectEx (D.20407, 4294967295, 0);
      D.20407 = internal->start_notify;
      CloseHandle (D.20407);
      internal->start_notify = 0B;
      <D.20464>:
      D.20383 = 1;
      return D.20383;
    }
  finally
    {
      tid = {CLOBBER};
    }
}


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

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


start_wrapper_internal (void * data)
{
  struct MonoThread * D.20469;
  struct MonoVTable * D.20470;
  _Bool D.20471;
  long int D.20472;
  long int D.20473;
  long unsigned int tid.9;
  unsigned int current_object_key.10;
  int D.20478;
  guint32 D.20481;
  long unsigned int tid.11;
  long int tid.12;
  unsigned char D.20484;
  void * D.20487;
  _Bool D.20492;
  long int D.20493;
  long int D.20494;
  struct MonoGHashTable * thread_start_args.13;
  _Bool D.20500;
  long int D.20501;
  long int D.20502;
  struct MonoObject * D.20505;
  _Bool D.20509;
  long int D.20510;
  long int D.20511;
  struct MonoThreadInfo * info;
  struct StartInfo * start_info;
  guint32 (*<T3208>) (void *) start_func;
  void * start_arg;
  gsize tid;
  struct MonoInternalThread * internal;
  struct MonoObject * start_delegate;
  struct MonoDomain * domain;

  try
    {
      start_info = data;
      D.20469 = start_info->obj;
      internal = D.20469->internal_thread;
      start_delegate = start_info->delegate;
      D.20469 = start_info->obj;
      D.20470 = D.20469->obj.vtable;
      domain = D.20470->domain;
      info = mono_thread_info_current ();
      D.20471 = info == 0B;
      D.20472 = (long int) D.20471;
      D.20473 = __builtin_expect (D.20472, 0);
      if (D.20473 != 0) goto <D.20474>; else goto <D.20475>;
      <D.20474>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 570, "info");
      <D.20475>:
      internal->thread_info = info;
      tid.9 = internal->tid;
      tid = tid.9;
      tls_current_object = internal;
      current_object_key.10 = current_object_key;
      mono_native_tls_set_value (current_object_key.10, internal);
      mono_monitor_init_tls ();
      mono_thread_push_appdomain_ref (domain);
      D.20478 = mono_domain_set (domain, 0);
      if (D.20478 == 0) goto <D.20479>; else goto <D.20480>;
      <D.20479>:
      mono_thread_pop_appdomain_ref ();
      D.20481 = 0;
      return D.20481;
      <D.20480>:
      start_func = start_info->func;
      start_arg = start_info->start_arg;
      thread_adjust_static_data (internal);
      D.20469 = start_info->obj;
      init_root_domain_thread (internal, D.20469);
      tid.11 = tid;
      tid.12 = (long int) tid.11;
      mono_thread_new_init (tid.12, &tid, start_func);
      internal->stack_ptr = &tid;
      D.20484 = internal->apartment_state;
      if (D.20484 == 2) goto <D.20485>; else goto <D.20486>;
      <D.20485>:
      internal->apartment_state = 1;
      <D.20486>:
      mono_thread_init_apartment_state ();
      D.20487 = internal->start_notify;
      if (D.20487 != 0B) goto <D.20488>; else goto <D.20489>;
      <D.20488>:
      D.20487 = internal->start_notify;
      ReleaseSemaphore (D.20487, 1, 0B);
      <D.20489>:
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.20490>; else goto <D.20491>;
        <D.20490>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.20491>:
        D.20492 = ret != 0;
        D.20493 = (long int) D.20492;
        D.20494 = __builtin_expect (D.20493, 0);
        if (D.20494 != 0) goto <D.20495>; else goto <D.20496>;
        <D.20495>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 623, "ret == 0");
        <D.20496>:
      }
      D.20469 = start_info->obj;
      thread_start_args.13 = thread_start_args;
      mono_g_hash_table_remove (thread_start_args.13, D.20469);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.20498>; else goto <D.20499>;
        <D.20498>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.20499>:
        D.20500 = ret != 0;
        D.20501 = (long int) D.20500;
        D.20502 = __builtin_expect (D.20501, 0);
        if (D.20502 != 0) goto <D.20503>; else goto <D.20504>;
        <D.20503>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 625, "ret == 0");
        <D.20504>:
      }
      D.20469 = start_info->obj;
      D.20505 = D.20469->ec_to_set;
      mono_thread_set_execution_context (D.20505);
      D.20469 = start_info->obj;
      D.20469->ec_to_set = 0B;
      monoeg_g_free (start_info);
      tid.11 = tid;
      mono_profiler_thread_start (tid.11);
      if (start_func != 0B) goto <D.20506>; else goto <D.20507>;
      <D.20506>:
      start_func (start_arg);
      goto <D.20508>;
      <D.20507>:
      {
        void * args[1];

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


thread_adjust_static_data (struct MonoInternalThread * thread)
{
  _Bool D.20518;
  long int D.20519;
  long int D.20520;
  int D.20525;
  int D.20527;
  int D.20528;
  int D.20529;
  int D.20530;
  void * * * D.20531;
  _Bool D.20534;
  long int D.20535;
  long int D.20536;
  guint32 offset;

  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.20516>; else goto <D.20517>;
    <D.20516>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.20517>:
    D.20518 = ret != 0;
    D.20519 = (long int) D.20518;
    D.20520 = __builtin_expect (D.20519, 0);
    if (D.20520 != 0) goto <D.20521>; else goto <D.20522>;
    <D.20521>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3819, "ret == 0");
    <D.20522>:
  }
  D.20525 = thread_static_info.offset;
  if (D.20525 != 0) goto <D.20523>; else goto <D.20526>;
  <D.20526>:
  D.20527 = thread_static_info.idx;
  if (D.20527 > 0) goto <D.20523>; else goto <D.20524>;
  <D.20523>:
  D.20525 = thread_static_info.offset;
  D.20527 = thread_static_info.idx;
  D.20528 = D.20527 + 1;
  D.20529 = D.20528 << 24;
  D.20530 = D.20525 | D.20529;
  offset = (guint32) D.20530;
  D.20531 = &thread->static_data;
  mono_alloc_static_data (D.20531, offset, 1);
  <D.20524>:
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.20532>; else goto <D.20533>;
    <D.20532>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.20533>:
    D.20534 = ret != 0;
    D.20535 = (long int) D.20534;
    D.20536 = __builtin_expect (D.20535, 0);
    if (D.20536 != 0) goto <D.20537>; else goto <D.20538>;
    <D.20537>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3825, "ret == 0");
    <D.20538>:
  }
}


mono_alloc_static_data (void * * * static_data_ptr, guint32 offset, gboolean threadlocal)
{
  unsigned int D.20539;
  int D.20542;
  void * tls_desc.14;
  void * tls_desc.15;
  void * iftmp.16;
  int D.20553;
  long unsigned int D.20554;
  long unsigned int D.20555;
  long unsigned int D.20556;
  void * * D.20557;
  void * D.20558;
  int D.20563;
  int D.20566;
  long unsigned int D.20567;
  void * D.20568;
  long unsigned int D.20569;
  void * D.20570;
  unsigned int i.17;
  guint idx;
  int i;
  void * * static_data;

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

    D.20542 = mono_gc_user_markers_supported ();
    if (D.20542 != 0) goto <D.20543>; else goto <D.20544>;
    <D.20543>:
    tls_desc.14 = tls_desc;
    if (tls_desc.14 == 0B) goto <D.20546>; else goto <D.20547>;
    <D.20546>:
    tls_desc.15 = mono_gc_make_root_descr_user (mark_tls_slots);
    tls_desc = tls_desc.15;
    <D.20547>:
    <D.20544>:
    if (threadlocal != 0) goto <D.20550>; else goto <D.20551>;
    <D.20550>:
    iftmp.16 = tls_desc;
    goto <D.20552>;
    <D.20551>:
    iftmp.16 = 0B;
    <D.20552>:
    D.20553 = 1024;
    D.20554 = (long unsigned int) D.20553;
    static_data = mono_gc_alloc_fixed (D.20554, iftmp.16);
    *static_data_ptr = static_data;
    *static_data = static_data;
  }
  <D.20541>:
  i = 1;
  goto <D.19990>;
  <D.19989>:
  D.20555 = (long unsigned int) i;
  D.20556 = D.20555 * 8;
  D.20557 = static_data + D.20556;
  D.20558 = *D.20557;
  if (D.20558 != 0B) goto <D.20559>; else goto <D.20560>;
  <D.20559>:
  // predicted unlikely by continue predictor.
  goto <D.19988>;
  <D.20560>:
  D.20563 = mono_gc_user_markers_supported ();
  if (D.20563 != 0) goto <D.20564>; else goto <D.20561>;
  <D.20564>:
  if (threadlocal != 0) goto <D.20565>; else goto <D.20561>;
  <D.20565>:
  D.20555 = (long unsigned int) i;
  D.20556 = D.20555 * 8;
  D.20557 = static_data + D.20556;
  D.20566 = static_data_size[i];
  D.20567 = (long unsigned int) D.20566;
  D.20568 = monoeg_malloc0 (D.20567);
  *D.20557 = D.20568;
  goto <D.20562>;
  <D.20561>:
  D.20555 = (long unsigned int) i;
  D.20556 = D.20555 * 8;
  D.20557 = static_data + D.20556;
  D.20566 = static_data_size[i];
  D.20569 = (long unsigned int) D.20566;
  D.20570 = mono_gc_alloc_fixed (D.20569, 0B);
  *D.20557 = D.20570;
  <D.20562>:
  <D.19988>:
  i = i + 1;
  <D.19990>:
  i.17 = (unsigned int) i;
  if (i.17 <= idx) goto <D.19989>; else goto <D.19991>;
  <D.19991>:
}


mark_tls_slots (void * addr, void (*MonoGCMarkFunc) (void * *) mark_func)
{
  long unsigned int D.20572;
  long unsigned int D.20573;
  void * * D.20574;
  void * D.20575;
  int D.20578;
  long unsigned int D.20579;
  long unsigned int D.20580;
  unsigned int D.20581;
  unsigned int D.20582;
  uintptr_t * D.20583;
  long unsigned int D.20584;
  long unsigned int D.20585;
  uintptr_t * D.20586;
  long unsigned int D.20587;
  void * D.20590;
  int i;
  void * * static_data;

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

    D.20572 = (long unsigned int) i;
    D.20573 = D.20572 * 8;
    D.20574 = static_data + D.20573;
    D.20575 = *D.20574;
    if (D.20575 == 0B) goto <D.20576>; else goto <D.20577>;
    <D.20576>:
    // predicted unlikely by continue predictor.
    goto <D.19967>;
    <D.20577>:
    D.20578 = static_data_size[i];
    D.20579 = (long unsigned int) D.20578;
    D.20580 = D.20579 / 512;
    D.20581 = (unsigned int) D.20580;
    D.20582 = D.20581 + 1;
    numwords = (int) D.20582;
    D.20572 = (long unsigned int) i;
    D.20573 = D.20572 * 8;
    D.20574 = static_data + D.20573;
    ptr = *D.20574;
    j = 0;
    goto <D.19974>;
    <D.19973>:
    {
      uintptr_t bmap;
      void * * p;

      D.20583 = static_reference_bitmaps[i];
      D.20584 = (long unsigned int) j;
      D.20585 = D.20584 * 8;
      D.20586 = D.20583 + D.20585;
      bmap = *D.20586;
      p = ptr;
      goto <D.19971>;
      <D.19970>:
      D.20587 = bmap & 1;
      if (D.20587 != 0) goto <D.20588>; else goto <D.20589>;
      <D.20588>:
      D.20590 = *p;
      if (D.20590 != 0B) goto <D.20591>; else goto <D.20592>;
      <D.20591>:
      mark_func (p);
      <D.20592>:
      <D.20589>:
      p = p + 8;
      bmap = bmap >> 1;
      <D.19971>:
      if (bmap != 0) goto <D.19970>; else goto <D.19972>;
      <D.19972>:
    }
    j = j + 1;
    ptr = ptr + 512;
    <D.19974>:
    if (j < numwords) goto <D.19973>; else goto <D.19975>;
    <D.19975>:
  }
  <D.19967>:
  i = i + 1;
  <D.19977>:
  if (i <= 7) goto <D.19976>; else goto <D.19978>;
  <D.19978>:
}


init_root_domain_thread (struct MonoInternalThread * thread, struct MonoThread * candidate)
{
  struct MonoVTable * D.20596;
  struct MonoDomain * D.20597;
  struct MonoThread * D.20598;
  _Bool D.20599;
  long int D.20600;
  long int D.20601;
  struct MonoThread * * D.20604;
  struct MonoDomain * domain;

  domain = mono_get_root_domain ();
  if (candidate == 0B) goto <D.20593>; else goto <D.20595>;
  <D.20595>:
  D.20596 = candidate->obj.vtable;
  D.20597 = D.20596->domain;
  if (D.20597 != domain) goto <D.20593>; else goto <D.20594>;
  <D.20593>:
  candidate = new_thread_with_internal (domain, thread);
  <D.20594>:
  set_current_thread_for_domain (domain, thread, candidate);
  D.20598 = thread->root_domain_thread;
  D.20599 = D.20598 != 0B;
  D.20600 = (long int) D.20599;
  D.20601 = __builtin_expect (D.20600, 0);
  if (D.20601 != 0) goto <D.20602>; else goto <D.20603>;
  <D.20602>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 542, "!thread->root_domain_thread");
  <D.20603>:
  D.20604 = &thread->root_domain_thread;
  mono_gc_wbarrier_set_field (thread, D.20604, candidate);
}


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

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


set_current_thread_for_domain (struct MonoDomain * domain, struct MonoInternalThread * thread, struct MonoThread * current)
{
  struct MonoVTable * D.20608;
  struct MonoDomain * D.20609;
  _Bool D.20610;
  long int D.20611;
  long int D.20612;
  struct MonoThread * D.20615;
  _Bool D.20616;
  long int D.20617;
  long int D.20618;
  struct MonoThread * * current_thread_ptr;

  current_thread_ptr = get_current_thread_ptr_for_domain (domain, thread);
  D.20608 = current->obj.vtable;
  D.20609 = D.20608->domain;
  D.20610 = D.20609 != domain;
  D.20611 = (long int) D.20610;
  D.20612 = __builtin_expect (D.20611, 0);
  if (D.20612 != 0) goto <D.20613>; else goto <D.20614>;
  <D.20613>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 491, "current->obj.vtable->domain == domain");
  <D.20614>:
  D.20615 = *current_thread_ptr;
  D.20616 = D.20615 != 0B;
  D.20617 = (long int) D.20616;
  D.20618 = __builtin_expect (D.20617, 0);
  if (D.20618 != 0) goto <D.20619>; else goto <D.20620>;
  <D.20619>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 493, "!*current_thread_ptr");
  <D.20620>:
  *current_thread_ptr = current;
}


get_current_thread_ptr_for_domain (struct MonoDomain * domain, struct MonoInternalThread * thread)
{
  struct MonoClassField * current_thread_field.18;
  struct MonoClass * D.20624;
  struct MonoClassField * current_thread_field.19;
  _Bool D.20626;
  long int D.20627;
  long int D.20628;
  union mono_mutex_t * D.20631;
  _Bool D.20634;
  long int D.20635;
  long int D.20636;
  struct GHashTable * D.20639;
  void * D.20640;
  long int D.20641;
  _Bool D.20644;
  long int D.20645;
  long int D.20646;
  _Bool D.20649;
  long int D.20650;
  long int D.20651;
  struct MonoThread * * D.20654;
  static struct MonoClassField * current_thread_field = 0B;
  guint32 offset;

  current_thread_field.18 = current_thread_field;
  if (current_thread_field.18 == 0B) goto <D.20622>; else goto <D.20623>;
  <D.20622>:
  D.20624 = mono_defaults.thread_class;
  current_thread_field.19 = mono_class_get_field_from_name (D.20624, "current_thread");
  current_thread_field = current_thread_field.19;
  current_thread_field.18 = current_thread_field;
  D.20626 = current_thread_field.18 == 0B;
  D.20627 = (long int) D.20626;
  D.20628 = __builtin_expect (D.20627, 0);
  if (D.20628 != 0) goto <D.20629>; else goto <D.20630>;
  <D.20629>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 474, "current_thread_field");
  <D.20630>:
  <D.20623>:
  D.20624 = mono_defaults.thread_class;
  mono_class_vtable (domain, D.20624);
  {
    int ret;

    D.20631 = &domain->lock.mutex;
    ret = pthread_mutex_lock (D.20631);
    if (ret != 0) goto <D.20632>; else goto <D.20633>;
    <D.20632>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.20633>:
    D.20634 = ret != 0;
    D.20635 = (long int) D.20634;
    D.20636 = __builtin_expect (D.20635, 0);
    if (D.20636 != 0) goto <D.20637>; else goto <D.20638>;
    <D.20637>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 478, "ret == 0");
    <D.20638>:
  }
  current_thread_field.18 = current_thread_field;
  D.20639 = domain->special_static_fields;
  D.20640 = monoeg_g_hash_table_lookup (D.20639, current_thread_field.18);
  D.20641 = (long int) D.20640;
  offset = (guint32) D.20641;
  {
    int ret;

    D.20631 = &domain->lock.mutex;
    ret = pthread_mutex_unlock (D.20631);
    if (ret != 0) goto <D.20642>; else goto <D.20643>;
    <D.20642>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.20643>:
    D.20644 = ret != 0;
    D.20645 = (long int) D.20644;
    D.20646 = __builtin_expect (D.20645, 0);
    if (D.20646 != 0) goto <D.20647>; else goto <D.20648>;
    <D.20647>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 480, "ret == 0");
    <D.20648>:
  }
  D.20649 = offset == 0;
  D.20650 = (long int) D.20649;
  D.20651 = __builtin_expect (D.20650, 0);
  if (D.20651 != 0) goto <D.20652>; else goto <D.20653>;
  <D.20652>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 481, "offset");
  <D.20653>:
  D.20654 = get_thread_static_data (thread, offset);
  return D.20654;
}


get_thread_static_data (struct MonoInternalThread * thread, guint32 offset)
{
  signed int offset.20;
  _Bool D.20657;
  long int D.20658;
  long int D.20659;
  unsigned int D.20662;
  unsigned int D.20663;
  void * D.20664;
  void * * D.20665;
  long unsigned int D.20666;
  long unsigned int D.20667;
  void * * D.20668;
  void * D.20669;
  sizetype D.20670;
  sizetype D.20671;
  int idx;

  offset.20 = (signed int) offset;
  D.20657 = offset.20 < 0;
  D.20658 = (long int) D.20657;
  D.20659 = __builtin_expect (D.20658, 0);
  if (D.20659 != 0) goto <D.20660>; else goto <D.20661>;
  <D.20660>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 459, "(offset & 0x80000000) == 0");
  <D.20661>:
  offset = offset & 2147483647;
  D.20662 = offset >> 24;
  D.20663 = D.20662 + 4294967295;
  idx = (int) D.20663;
  D.20665 = thread->static_data;
  D.20666 = (long unsigned int) idx;
  D.20667 = D.20666 * 8;
  D.20668 = D.20665 + D.20667;
  D.20669 = *D.20668;
  D.20670 = (sizetype) offset;
  D.20671 = D.20670 & 16777215;
  D.20664 = D.20669 + D.20671;
  return D.20664;
}


thread_cleanup (struct MonoInternalThread * thread)
{
  _Bool D.20673;
  long int D.20674;
  long int D.20675;
  int D.20678;
  unsigned int D.20681;
  struct MonoArray * D.20682;
  long unsigned int D.20685;
  struct CRITICAL_SECTION * D.20686;
  int shutting_down.21;
  _Bool D.20691;
  long int D.20692;
  long int D.20693;
  unsigned int D.20696;
  unsigned int D.20697;
  unsigned int D.20698;
  gint32 * D.20701;
  int D.20702;
  int D.20705;
  struct MonoInternalThread * D.20708;
  void (*<T21a8>) (struct MonoInternalThread *) mono_thread_cleanup_fn.22;
  long unsigned int D.20714;
  struct MonoInternalThread * D.20715;
  struct MonoInternalThread * D.20718;
  void * * D.20721;
  void * D.20722;
  int D.20725;
  void * * D.20728;

  D.20673 = thread == 0B;
  D.20674 = (long int) D.20673;
  D.20675 = __builtin_expect (D.20674, 0);
  if (D.20675 != 0) goto <D.20676>; else goto <D.20677>;
  <D.20676>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 368, "thread != NULL");
  <D.20677>:
  D.20678 = thread->abort_state_handle;
  if (D.20678 != 0) goto <D.20679>; else goto <D.20680>;
  <D.20679>:
  D.20678 = thread->abort_state_handle;
  D.20681 = (unsigned int) D.20678;
  mono_gchandle_free (D.20681);
  thread->abort_state_handle = 0;
  <D.20680>:
  thread->abort_exc = 0B;
  thread->current_appcontext = 0B;
  D.20682 = thread->cached_culture_info;
  if (D.20682 != 0B) goto <D.20683>; else goto <D.20684>;
  <D.20683>:
  {
    int i;

    i = 0;
    goto <D.18999>;
    <D.18998>:
    {
      struct MonoObject * * __p;

      D.20685 = (long unsigned int) i;
      D.20682 = thread->cached_culture_info;
      __p = mono_array_addr_with_size (D.20682, 8, D.20685);
      *__p = 0B;
    }
    i = i + 1;
    <D.18999>:
    if (i <= 7) goto <D.18998>; else goto <D.19000>;
    <D.19000>:
  }
  <D.20684>:
  D.20686 = thread->synch_cs;
  if (D.20686 != 0B) goto <D.20687>; else goto <D.20688>;
  <D.20687>:
  lock_thread (thread);
  goto <D.20689>;
  <D.20688>:
  shutting_down.21 = shutting_down;
  D.20691 = shutting_down.21 == 0;
  D.20692 = (long int) D.20691;
  D.20693 = __builtin_expect (D.20692, 0);
  if (D.20693 != 0) goto <D.20694>; else goto <D.20695>;
  <D.20694>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 391, "shutting_down");
  <D.20695>:
  <D.20689>:
  D.20696 = thread->state;
  D.20697 = D.20696 | 16;
  thread->state = D.20697;
  D.20696 = thread->state;
  D.20698 = D.20696 & 4294967291;
  thread->state = D.20698;
  D.20686 = thread->synch_cs;
  if (D.20686 != 0B) goto <D.20699>; else goto <D.20700>;
  <D.20699>:
  unlock_thread (thread);
  <D.20700>:
  D.20701 = &thread->interruption_requested;
  D.20702 = InterlockedExchange (D.20701, 0);
  if (D.20702 != 0) goto <D.20703>; else goto <D.20704>;
  <D.20703>:
  InterlockedDecrement (&thread_interruption_requested);
  <D.20704>:
  D.20705 = handle_remove (thread);
  if (D.20705 == 0) goto <D.20706>; else goto <D.20707>;
  <D.20706>:
  D.20708 = mono_thread_internal_current ();
  if (D.20708 == thread) goto <D.20709>; else goto <D.20710>;
  <D.20709>:
  mono_domain_unset ();
  mono_memory_barrier ();
  <D.20710>:
  mono_thread_cleanup_fn.22 = mono_thread_cleanup_fn;
  if (mono_thread_cleanup_fn.22 != 0B) goto <D.20712>; else goto <D.20713>;
  <D.20712>:
  mono_thread_cleanup_fn.22 = mono_thread_cleanup_fn;
  mono_thread_cleanup_fn.22 (thread);
  <D.20713>:
  return;
  <D.20707>:
  mono_release_type_locks (thread);
  D.20714 = thread->tid;
  mono_profiler_thread_end (D.20714);
  D.20715 = mono_thread_internal_current ();
  if (D.20715 == thread) goto <D.20716>; else goto <D.20717>;
  <D.20716>:
  mono_domain_unset ();
  mono_memory_barrier ();
  <D.20717>:
  D.20718 = mono_thread_internal_current ();
  if (D.20718 == thread) goto <D.20719>; else goto <D.20720>;
  <D.20719>:
  mono_thread_pop_appdomain_ref ();
  <D.20720>:
  thread->cached_culture_info = 0B;
  D.20721 = thread->static_data;
  mono_free_static_data (D.20721, 1);
  thread->static_data = 0B;
  D.20722 = thread->appdomain_refs;
  ref_stack_destroy (D.20722);
  thread->appdomain_refs = 0B;
  mono_thread_cleanup_fn.22 = mono_thread_cleanup_fn;
  if (mono_thread_cleanup_fn.22 != 0B) goto <D.20723>; else goto <D.20724>;
  <D.20723>:
  mono_thread_cleanup_fn.22 = mono_thread_cleanup_fn;
  mono_thread_cleanup_fn.22 (thread);
  <D.20724>:
  D.20725 = mono_gc_is_moving ();
  if (D.20725 != 0) goto <D.20726>; else goto <D.20727>;
  <D.20726>:
  D.20728 = &thread->thread_pinning_ref;
  mono_gc_deregister_root (D.20728);
  thread->thread_pinning_ref = 0B;
  <D.20727>:
}


lock_thread (struct MonoInternalThread * thread)
{
  struct CRITICAL_SECTION * D.20730;
  _Bool D.20733;
  long int D.20734;
  long int D.20735;
  union mono_mutex_t * D.20738;
  _Bool D.20741;
  long int D.20742;
  long int D.20743;

  D.20730 = thread->synch_cs;
  if (D.20730 == 0B) goto <D.20731>; else goto <D.20732>;
  <D.20731>:
  ensure_synch_cs_set (thread);
  <D.20732>:
  D.20730 = thread->synch_cs;
  D.20733 = D.20730 == 0B;
  D.20734 = (long int) D.20733;
  D.20735 = __builtin_expect (D.20734, 0);
  if (D.20735 != 0) goto <D.20736>; else goto <D.20737>;
  <D.20736>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 351, "thread->synch_cs");
  <D.20737>:
  {
    int ret;

    D.20730 = thread->synch_cs;
    D.20738 = &D.20730->mutex;
    ret = pthread_mutex_lock (D.20738);
    if (ret != 0) goto <D.20739>; else goto <D.20740>;
    <D.20739>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.20740>:
    D.20741 = ret != 0;
    D.20742 = (long int) D.20741;
    D.20743 = __builtin_expect (D.20742, 0);
    if (D.20743 != 0) goto <D.20744>; else goto <D.20745>;
    <D.20744>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 352, "ret == 0");
    <D.20745>:
  }
}


ensure_synch_cs_set (struct MonoInternalThread * thread)
{
  struct CRITICAL_SECTION * D.20746;
  struct CRITICAL_SECTION * * D.20749;
  void * D.20750;
  struct CRITICAL_SECTION * synch_cs;

  D.20746 = thread->synch_cs;
  if (D.20746 != 0B) goto <D.20747>; else goto <D.20748>;
  <D.20747>:
  return;
  <D.20748>:
  synch_cs = monoeg_malloc0 (48);
  InitializeCriticalSection (synch_cs);
  D.20749 = &thread->synch_cs;
  D.20750 = InterlockedCompareExchangePointer (D.20749, synch_cs, 0B);
  if (D.20750 != 0B) goto <D.20751>; else goto <D.20752>;
  <D.20751>:
  DeleteCriticalSection (synch_cs);
  monoeg_g_free (synch_cs);
  <D.20752>:
}


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

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


unlock_thread (struct MonoInternalThread * thread)
{
  struct CRITICAL_SECTION * D.20759;
  union mono_mutex_t * D.20760;
  _Bool D.20763;
  long int D.20764;
  long int D.20765;

  {
    int ret;

    D.20759 = thread->synch_cs;
    D.20760 = &D.20759->mutex;
    ret = pthread_mutex_unlock (D.20760);
    if (ret != 0) goto <D.20761>; else goto <D.20762>;
    <D.20761>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.20762>:
    D.20763 = ret != 0;
    D.20764 = (long int) D.20763;
    D.20765 = __builtin_expect (D.20764, 0);
    if (D.20765 != 0) goto <D.20766>; else goto <D.20767>;
    <D.20766>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 358, "ret == 0");
    <D.20767>:
  }
}


InterlockedExchange (volatile gint32 * val, gint32 new_val)
{
  unsigned int new_val.25;
  unsigned int old_val.26;
  unsigned int D.20770;
  int D.20771;
  gint32 D.20772;
  gint32 old_val;

  <D.18793>:
  old_val = *val;
  new_val.25 = (unsigned int) new_val;
  old_val.26 = (unsigned int) old_val;
  D.20770 = __sync_val_compare_and_swap_4 (val, old_val.26, new_val.25);
  D.20771 = (int) D.20770;
  if (D.20771 != old_val) goto <D.18793>; else goto <D.18794>;
  <D.18794>:
  D.20772 = old_val;
  return D.20772;
}


InterlockedDecrement (volatile gint32 * val)
{
  gint32 D.20774;
  unsigned int D.20775;

  D.20775 = __sync_sub_and_fetch_4 (val, 1);
  D.20774 = (gint32) D.20775;
  return D.20774;
}


handle_remove (struct MonoInternalThread * thread)
{
  _Bool D.20779;
  long int D.20780;
  long int D.20781;
  struct MonoGHashTable * threads.27;
  const void * tid.28;
  void * D.20788;
  _Bool D.20795;
  long int D.20796;
  long int D.20797;
  gboolean D.20800;
  gboolean ret;
  gsize tid;

  tid = thread->tid;
  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.20777>; else goto <D.20778>;
    <D.20777>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.20778>:
    D.20779 = ret != 0;
    D.20780 = (long int) D.20779;
    D.20781 = __builtin_expect (D.20780, 0);
    if (D.20781 != 0) goto <D.20782>; else goto <D.20783>;
    <D.20782>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 289, "ret == 0");
    <D.20783>:
  }
  threads.27 = threads;
  if (threads.27 != 0B) goto <D.20785>; else goto <D.20786>;
  <D.20785>:
  tid.28 = (const void *) tid;
  threads.27 = threads;
  D.20788 = mono_g_hash_table_lookup (threads.27, tid.28);
  if (D.20788 == thread) goto <D.20789>; else goto <D.20790>;
  <D.20789>:
  tid.28 = (const void *) tid;
  threads.27 = threads;
  mono_g_hash_table_remove (threads.27, tid.28);
  ret = 1;
  goto <D.20791>;
  <D.20790>:
  ret = 0;
  <D.20791>:
  goto <D.20792>;
  <D.20786>:
  ret = 0;
  <D.20792>:
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.20793>; else goto <D.20794>;
    <D.20793>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.20794>:
    D.20795 = ret != 0;
    D.20796 = (long int) D.20795;
    D.20797 = __builtin_expect (D.20796, 0);
    if (D.20797 != 0) goto <D.20798>; else goto <D.20799>;
    <D.20798>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 308, "ret == 0");
    <D.20799>:
  }
  D.20800 = ret;
  return D.20800;
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


mono_free_static_data (void * * static_data, gboolean threadlocal)
{
  long unsigned int D.20802;
  long unsigned int D.20803;
  void * * D.20804;
  int D.20809;
  int i;

  i = 1;
  goto <D.20000>;
  <D.19999>:
  {
    void * p;

    D.20802 = (long unsigned int) i;
    D.20803 = D.20802 * 8;
    D.20804 = static_data + D.20803;
    p = *D.20804;
    if (p == 0B) goto <D.20805>; else goto <D.20806>;
    <D.20805>:
    // predicted unlikely by continue predictor.
    goto <D.19998>;
    <D.20806>:
    D.20802 = (long unsigned int) i;
    D.20803 = D.20802 * 8;
    D.20804 = static_data + D.20803;
    *D.20804 = 0B;
    mono_memory_write_barrier ();
    D.20809 = mono_gc_user_markers_supported ();
    if (D.20809 != 0) goto <D.20810>; else goto <D.20807>;
    <D.20810>:
    if (threadlocal != 0) goto <D.20811>; else goto <D.20807>;
    <D.20811>:
    monoeg_g_free (p);
    goto <D.20808>;
    <D.20807>:
    mono_gc_free_fixed (p);
    <D.20808>:
  }
  <D.19998>:
  i = i + 1;
  <D.20000>:
  if (i <= 7) goto <D.19999>; else goto <D.20001>;
  <D.20001>:
  mono_gc_free_fixed (static_data);
}


mono_memory_write_barrier ()
{
  mono_memory_barrier ();
}


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

  rs = ptr;
  if (rs != 0B) goto <D.20812>; else goto <D.20813>;
  <D.20812>:
  D.20814 = rs->refs;
  monoeg_g_free (D.20814);
  monoeg_g_free (rs);
  <D.20813>:
}


mono_native_tls_set_value (pthread_key_t key, void * value)
{
  int D.20815;
  int D.20816;
  _Bool D.20817;

  D.20816 = pthread_setspecific (key, value);
  D.20817 = D.20816 == 0;
  D.20815 = (int) D.20817;
  return D.20815;
}


handle_store (struct MonoThread * thread, gboolean force_attach)
{
  _Bool D.20821;
  long int D.20822;
  long int D.20823;
  struct MonoGHashTable * threads_starting_up.29;
  int shutting_down.30;
  _Bool D.20836;
  long int D.20837;
  long int D.20838;
  gboolean D.20841;
  struct MonoGHashTable * threads.31;
  int D.20845;
  struct MonoGHashTable * threads.32;
  struct _MonoInternalThread * D.20849;
  _Bool D.20850;
  long int D.20851;
  long int D.20852;
  long unsigned int D.20855;
  void * D.20856;
  _Bool D.20859;
  long int D.20860;
  long int D.20861;

  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.20819>; else goto <D.20820>;
    <D.20819>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.20820>:
    D.20821 = ret != 0;
    D.20822 = (long int) D.20821;
    D.20823 = __builtin_expect (D.20822, 0);
    if (D.20823 != 0) goto <D.20824>; else goto <D.20825>;
    <D.20824>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 253, "ret == 0");
    <D.20825>:
  }
  threads_starting_up.29 = threads_starting_up;
  if (threads_starting_up.29 != 0B) goto <D.20827>; else goto <D.20828>;
  <D.20827>:
  threads_starting_up.29 = threads_starting_up;
  mono_g_hash_table_remove (threads_starting_up.29, thread);
  <D.20828>:
  shutting_down.30 = shutting_down;
  if (shutting_down.30 != 0) goto <D.20830>; else goto <D.20831>;
  <D.20830>:
  if (force_attach == 0) goto <D.20832>; else goto <D.20833>;
  <D.20832>:
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.20834>; else goto <D.20835>;
    <D.20834>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.20835>:
    D.20836 = ret != 0;
    D.20837 = (long int) D.20836;
    D.20838 = __builtin_expect (D.20837, 0);
    if (D.20838 != 0) goto <D.20839>; else goto <D.20840>;
    <D.20839>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 261, "ret == 0");
    <D.20840>:
  }
  D.20841 = 0;
  return D.20841;
  <D.20833>:
  <D.20831>:
  threads.31 = threads;
  if (threads.31 == 0B) goto <D.20843>; else goto <D.20844>;
  <D.20843>:
  D.20845 = mono_gc_is_moving ();
  if (D.20845 == 0) goto <D.20846>; else goto <D.20847>;
  <D.20846>:
  mono_gc_register_root (&threads, 8, 0B);
  <D.20847>:
  threads.32 = mono_g_hash_table_new_type (0B, 0B, 2);
  threads = threads.32;
  <D.20844>:
  D.20849 = thread->internal_thread;
  D.20850 = D.20849 == 0B;
  D.20851 = (long int) D.20850;
  D.20852 = __builtin_expect (D.20851, 0);
  if (D.20852 != 0) goto <D.20853>; else goto <D.20854>;
  <D.20853>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 273, "thread->internal_thread");
  <D.20854>:
  D.20849 = thread->internal_thread;
  D.20849 = thread->internal_thread;
  D.20855 = D.20849->tid;
  D.20856 = (void *) D.20855;
  threads.31 = threads;
  mono_g_hash_table_insert (threads.31, D.20856, D.20849);
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.20857>; else goto <D.20858>;
    <D.20857>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.20858>:
    D.20859 = ret != 0;
    D.20860 = (long int) D.20859;
    D.20861 = __builtin_expect (D.20860, 0);
    if (D.20861 != 0) goto <D.20862>; else goto <D.20863>;
    <D.20862>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 277, "ret == 0");
    <D.20863>:
  }
  D.20841 = 1;
  return D.20841;
}


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.20865;
  guint8 * D.20866;
  int iftmp.33;
  long unsigned int D.20874;
  guint8 * D.20875;
  _Bool D.20876;
  long int D.20877;
  long int D.20878;
  long int D.20881;
  int D.20882;
  int D.20883;
  long int D.20884;
  long int D.20885;
  guint8 * D.20886;
  union pthread_attr_t attr;
  guint8 * current;

  try
    {
      current = &attr;
      *staddr = 0B;
      *stsize = 18446744073709551615;
      pthread_attr_init (&attr);
      D.20865 = pthread_self ();
      pthread_getattr_np (D.20865, &attr);
      pthread_attr_getstack (&attr, staddr, stsize);
      pthread_attr_destroy (&attr);
      D.20866 = *staddr;
      if (D.20866 != 0B) goto <D.20867>; else goto <D.20868>;
      <D.20867>:
      D.20866 = *staddr;
      if (D.20866 >= current) goto <D.20870>; else goto <D.20873>;
      <D.20873>:
      D.20866 = *staddr;
      D.20874 = *stsize;
      D.20875 = D.20866 + D.20874;
      if (D.20875 <= current) goto <D.20870>; else goto <D.20871>;
      <D.20870>:
      iftmp.33 = 1;
      goto <D.20872>;
      <D.20871>:
      iftmp.33 = 0;
      <D.20872>:
      D.20876 = iftmp.33 != 0;
      D.20877 = (long int) D.20876;
      D.20878 = __builtin_expect (D.20877, 0);
      if (D.20878 != 0) goto <D.20879>; else goto <D.20880>;
      <D.20879>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 944, "(current > *staddr) && (current < *staddr + *stsize)");
      <D.20880>:
      <D.20868>:
      D.20866 = *staddr;
      D.20881 = (long int) D.20866;
      D.20882 = mono_pagesize ();
      D.20883 = -D.20882;
      D.20884 = (long int) D.20883;
      D.20885 = D.20881 & D.20884;
      D.20886 = (guint8 *) D.20885;
      *staddr = D.20886;
      return;
    }
  finally
    {
      attr = {CLOBBER};
    }
}


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

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


mono_thread_attach_full (struct MonoDomain * domain, gboolean force_attach)
{
  struct MonoDomain * D.20893;
  struct MonoDomain * domain.34;
  struct MonoThread * D.20897;
  int D.20898;
  long unsigned int D.20901;
  void * thread_handle.35;
  void * thread_handle.36;
  _Bool D.20904;
  long int D.20905;
  long int D.20906;
  long unsigned int tid.37;
  void * D.20910;
  void * D.20911;
  long unsigned int tid.38;
  _Bool D.20913;
  long int D.20914;
  long int D.20915;
  int D.20918;
  unsigned int current_object_key.39;
  struct MonoDomain * D.20922;
  void (*<T13cc>) (intptr_t, void *) mono_thread_attach_cb.40;
  guint8 * staddr.41;
  long int tid.42;
  long unsigned int stsize.43;
  void * D.20934;
  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.20891>; else goto <D.20892>;
      <D.20891>:
      D.20893 = mono_domain_get ();
      domain.34 = domain;
      if (D.20893 != domain.34) goto <D.20895>; else goto <D.20896>;
      <D.20895>:
      domain.34 = domain;
      mono_domain_set (domain.34, 1);
      <D.20896>:
      D.20897 = mono_thread_current ();
      return D.20897;
      <D.20892>:
      D.20898 = mono_gc_register_thread (&domain);
      if (D.20898 == 0) goto <D.20899>; else goto <D.20900>;
      <D.20899>:
      D.20901 = GetCurrentThreadId ();
      monoeg_g_log (0B, 4, "Thread %lu calling into managed code is not registered with the GC. On UNIX, this can be fixed by #include-ing <gc.h> before <pthread.h> in the file containing the thread creation code.", D.20901);
      <D.19124>:
      goto <D.19124>;
      <D.20900>:
      thread = create_internal_thread ();
      thread_handle.35 = GetCurrentThread ();
      thread_handle = thread_handle.35;
      thread_handle.36 = thread_handle;
      D.20904 = thread_handle.36 == 0B;
      D.20905 = (long int) D.20904;
      D.20906 = __builtin_expect (D.20905, 0);
      if (D.20906 != 0) goto <D.20907>; else goto <D.20908>;
      <D.20907>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1028, "thread_handle");
      <D.20908>:
      tid.37 = GetCurrentThreadId ();
      tid = tid.37;
      D.20910 = GetCurrentProcess ();
      thread_handle.36 = thread_handle;
      D.20911 = GetCurrentProcess ();
      DuplicateHandle (D.20911, thread_handle.36, D.20910, &thread_handle, 2032639, 1, 0);
      thread_handle.36 = thread_handle;
      thread->handle = thread_handle.36;
      tid.38 = tid;
      thread->tid = tid.38;
      thread->stack_ptr = &tid;
      info = mono_thread_info_current ();
      D.20913 = info == 0B;
      D.20914 = (long int) D.20913;
      D.20915 = __builtin_expect (D.20914, 0);
      if (D.20915 != 0) goto <D.20916>; else goto <D.20917>;
      <D.20916>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1049, "info");
      <D.20917>:
      thread->thread_info = info;
      domain.34 = domain;
      current_thread = new_thread_with_internal (domain.34, thread);
      D.20918 = handle_store (current_thread, force_attach);
      if (D.20918 == 0) goto <D.20919>; else goto <D.20920>;
      <D.20919>:
      <D.19125>:
      Sleep (10000);
      goto <D.19125>;
      <D.20920>:
      tls_current_object = thread;
      current_object_key.39 = current_object_key;
      mono_native_tls_set_value (current_object_key.39, thread);
      domain.34 = domain;
      mono_domain_set (domain.34, 1);
      mono_monitor_init_tls ();
      thread_adjust_static_data (thread);
      init_root_domain_thread (thread, current_thread);
      D.20922 = mono_get_root_domain ();
      domain.34 = domain;
      if (D.20922 != domain.34) goto <D.20923>; else goto <D.20924>;
      <D.20923>:
      domain.34 = domain;
      set_current_thread_for_domain (domain.34, thread, current_thread);
      <D.20924>:
      mono_thread_attach_cb.40 = mono_thread_attach_cb;
      if (mono_thread_attach_cb.40 != 0B) goto <D.20926>; else goto <D.20927>;
      <D.20926>:
      {
        guint8 * staddr;
        size_t stsize;

        try
          {
            mono_thread_get_stack_bounds (&staddr, &stsize);
            staddr.41 = staddr;
            if (staddr.41 == 0B) goto <D.20929>; else goto <D.20930>;
            <D.20929>:
            mono_thread_attach_cb.40 = mono_thread_attach_cb;
            tid.38 = tid;
            tid.42 = (long int) tid.38;
            mono_thread_attach_cb.40 (tid.42, &tid);
            goto <D.20932>;
            <D.20930>:
            mono_thread_attach_cb.40 = mono_thread_attach_cb;
            staddr.41 = staddr;
            stsize.43 = stsize;
            D.20934 = staddr.41 + stsize.43;
            tid.38 = tid;
            tid.42 = (long int) tid.38;
            mono_thread_attach_cb.40 (tid.42, D.20934);
            <D.20932>:
          }
        finally
          {
            staddr = {CLOBBER};
            stsize = {CLOBBER};
          }
      }
      <D.20927>:
      tid.38 = tid;
      mono_profiler_thread_start (tid.38);
      D.20897 = current_thread;
      return D.20897;
    }
  finally
    {
      thread_handle = {CLOBBER};
      tid = {CLOBBER};
    }
}


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

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


mono_thread_exit ()
{
  unsigned int current_object_key.45;
  struct MonoThread * D.20943;
  struct MonoThread * D.20946;
  struct _MonoInternalThread * D.20947;
  int D.20950;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  thread_cleanup (thread);
  tls_current_object = 0B;
  current_object_key.45 = current_object_key;
  mono_native_tls_set_value (current_object_key.45, 0B);
  mono_domain_unset ();
  D.20943 = mono_thread_get_main ();
  if (D.20943 != 0B) goto <D.20944>; else goto <D.20945>;
  <D.20944>:
  D.20946 = mono_thread_get_main ();
  D.20947 = D.20946->internal_thread;
  if (D.20947 == thread) goto <D.20948>; else goto <D.20949>;
  <D.20948>:
  D.20950 = mono_environment_exitcode_get ();
  exit (D.20950);
  <D.20949>:
  <D.20945>:
  ExitThread (4294967295);
}


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

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


ves_icall_System_Threading_Thread_Thread_internal (struct MonoThread * this, struct MonoObject * start)
{
  struct _MonoInternalThread * D.20952;
  unsigned int D.20955;
  unsigned int D.20956;
  struct MonoException * D.20959;
  void * D.20960;
  unsigned int D.20961;
  struct MonoObject * D.20964;
  struct MonoVTable * D.20965;
  struct MonoDomain * D.20966;
  struct MonoDomain * D.20967;
  _Bool D.20968;
  long int D.20969;
  long int D.20970;
  unsigned int D.20975;
  struct StartInfo * start_info;
  struct MonoInternalThread * internal;
  gboolean res;

  D.20952 = this->internal_thread;
  if (D.20952 == 0B) goto <D.20953>; else goto <D.20954>;
  <D.20953>:
  ves_icall_System_Threading_Thread_ConstructInternalThread (this);
  <D.20954>:
  internal = this->internal_thread;
  lock_thread (internal);
  D.20955 = internal->state;
  D.20956 = D.20955 & 8;
  if (D.20956 == 0) goto <D.20957>; else goto <D.20958>;
  <D.20957>:
  unlock_thread (internal);
  D.20959 = mono_get_exception_thread_state ("Thread has already been started.");
  mono_raise_exception (D.20959);
  D.20960 = 0B;
  return D.20960;
  <D.20958>:
  D.20955 = internal->state;
  D.20961 = D.20955 & 256;
  if (D.20961 != 0) goto <D.20962>; else goto <D.20963>;
  <D.20962>:
  unlock_thread (internal);
  D.20960 = this;
  return D.20960;
  <D.20963>:
  start_info = monoeg_malloc0 (32);
  start_info->func = 0B;
  D.20964 = this->start_obj;
  start_info->start_arg = D.20964;
  start_info->delegate = start;
  start_info->obj = this;
  D.20965 = this->obj.vtable;
  D.20966 = D.20965->domain;
  D.20967 = mono_domain_get ();
  D.20968 = D.20966 != D.20967;
  D.20969 = (long int) D.20968;
  D.20970 = __builtin_expect (D.20969, 0);
  if (D.20970 != 0) goto <D.20971>; else goto <D.20972>;
  <D.20971>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1169, "this->obj.vtable->domain == mono_domain_get ()");
  <D.20972>:
  res = create_thread (this, internal, start_info, 0, 0, 0, 0);
  if (res == 0) goto <D.20973>; else goto <D.20974>;
  <D.20973>:
  unlock_thread (internal);
  D.20960 = 0B;
  return D.20960;
  <D.20974>:
  D.20955 = internal->state;
  D.20975 = D.20955 & 4294967287;
  internal->state = D.20975;
  unlock_thread (internal);
  D.20960 = internal->handle;
  return D.20960;
}


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

  if (thread != 0B) goto <D.20977>; else goto <D.20978>;
  <D.20977>:
  CloseHandle (thread);
  <D.20978>:
  D.20979 = this->synch_cs;
  if (D.20979 != 0B) goto <D.20980>; else goto <D.20981>;
  <D.20980>:
  {
    struct CRITICAL_SECTION * synch_cs;

    synch_cs = this->synch_cs;
    this->synch_cs = 0B;
    DeleteCriticalSection (synch_cs);
    monoeg_g_free (synch_cs);
  }
  <D.20981>:
  D.20982 = this->name;
  if (D.20982 != 0B) goto <D.20983>; else goto <D.20984>;
  <D.20983>:
  {
    void * name;

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


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

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

    exc = mono_thread_execute_interruption (thread);
    if (exc != 0B) goto <D.20987>; else goto <D.20988>;
    <D.20987>:
    mono_raise_exception (exc);
    goto <D.20989>;
    <D.20988>:
    if (ms != -1) goto <D.19157>; else goto <D.20990>;
    <D.20990>:
    <D.20989>:
  }
  goto <D.19158>;
  <D.19157>:
}


mono_thread_execute_interruption (struct MonoInternalThread * thread)
{
  gint32 * D.20991;
  int D.20992;
  void * D.20995;
  unsigned int D.20996;
  unsigned int D.20997;
  struct MonoException * D.21000;
  struct MonoException * D.21003;
  struct MonoException * * D.21004;
  struct MonoException * D.21005;
  unsigned int D.21006;
  unsigned int D.21009;
  struct MonoException * D.21012;
  unsigned char D.21015;

  lock_thread (thread);
  D.20991 = &thread->interruption_requested;
  D.20992 = InterlockedCompareExchange (D.20991, 0, 1);
  if (D.20992 != 0) goto <D.20993>; else goto <D.20994>;
  <D.20993>:
  D.20995 = GetCurrentThread ();
  WaitForSingleObjectEx (D.20995, 0, 1);
  InterlockedDecrement (&thread_interruption_requested);
  wapi_clear_interruption ();
  <D.20994>:
  D.20996 = thread->state;
  D.20997 = D.20996 & 128;
  if (D.20997 != 0) goto <D.20998>; else goto <D.20999>;
  <D.20998>:
  unlock_thread (thread);
  D.21000 = thread->abort_exc;
  if (D.21000 == 0B) goto <D.21001>; else goto <D.21002>;
  <D.21001>:
  D.21003 = mono_get_exception_thread_abort ();
  D.21004 = &thread->abort_exc;
  mono_gc_wbarrier_set_field (thread, D.21004, D.21003);
  <D.21002>:
  D.21005 = thread->abort_exc;
  return D.21005;
  <D.20999>:
  D.20996 = thread->state;
  D.21006 = D.20996 & 2;
  if (D.21006 != 0) goto <D.21007>; else goto <D.21008>;
  <D.21007>:
  self_suspend_internal (thread);
  D.21005 = 0B;
  return D.21005;
  <D.21008>:
  D.20996 = thread->state;
  D.21009 = D.20996 & 1;
  if (D.21009 != 0) goto <D.21010>; else goto <D.21011>;
  <D.21010>:
  unlock_thread (thread);
  mono_thread_exit ();
  D.21005 = 0B;
  return D.21005;
  <D.21011>:
  D.21012 = thread->pending_exception;
  if (D.21012 != 0B) goto <D.21013>; else goto <D.21014>;
  <D.21013>:
  {
    struct MonoException * exc;

    exc = thread->pending_exception;
    thread->pending_exception = 0B;
    unlock_thread (thread);
    D.21005 = exc;
    return D.21005;
  }
  <D.21014>:
  D.21015 = thread->thread_interrupt_requested;
  if (D.21015 != 0) goto <D.21016>; else goto <D.21017>;
  <D.21016>:
  thread->thread_interrupt_requested = 0;
  unlock_thread (thread);
  D.21005 = mono_get_exception_thread_interrupted ();
  return D.21005;
  <D.21017>:
  unlock_thread (thread);
  D.21005 = 0B;
  return D.21005;
}


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

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


self_suspend_internal (struct MonoInternalThread * thread)
{
  int D.21024;
  unsigned int D.21027;
  unsigned int D.21028;
  unsigned int D.21029;
  void * D.21030;
  void * D.21031;
  void * D.21034;
  int shutting_down.49;
  unsigned int D.21040;
  void * D.21041;

  D.21024 = mono_thread_info_new_interrupt_enabled ();
  if (D.21024 == 0) goto <D.21025>; else goto <D.21026>;
  <D.21025>:
  D.21027 = thread->state;
  D.21028 = D.21027 & 4294967293;
  thread->state = D.21028;
  D.21027 = thread->state;
  D.21029 = D.21027 | 64;
  thread->state = D.21029;
  D.21030 = CreateEvent (0B, 1, 0, 0B);
  thread->suspend_event = D.21030;
  D.21031 = thread->suspend_event;
  if (D.21031 == 0B) goto <D.21032>; else goto <D.21033>;
  <D.21032>:
  unlock_thread (thread);
  return;
  <D.21033>:
  D.21034 = thread->suspended_event;
  if (D.21034 != 0B) goto <D.21035>; else goto <D.21036>;
  <D.21035>:
  D.21034 = thread->suspended_event;
  SetEvent (D.21034);
  <D.21036>:
  unlock_thread (thread);
  shutting_down.49 = shutting_down;
  if (shutting_down.49 != 0) goto <D.21038>; else goto <D.21039>;
  <D.21038>:
  <D.20305>:
  Sleep (1000);
  goto <D.20305>;
  <D.21039>:
  D.21031 = thread->suspend_event;
  WaitForSingleObject (D.21031, 4294967295);
  lock_thread (thread);
  D.21031 = thread->suspend_event;
  CloseHandle (D.21031);
  thread->suspend_event = 0B;
  D.21027 = thread->state;
  D.21040 = D.21027 & 4294967231;
  thread->state = D.21040;
  D.21041 = thread->resume_event;
  SetEvent (D.21041);
  unlock_thread (thread);
  return;
  <D.21026>:
  transition_to_suspended (thread);
  mono_thread_info_self_suspend ();
}


transition_to_suspended (struct MonoInternalThread * thread)
{
  unsigned int D.21043;
  unsigned int D.21044;
  long unsigned int D.21049;
  unsigned int D.21051;
  unsigned int D.21052;

  D.21043 = thread->state;
  D.21044 = D.21043 & 2;
  if (D.21044 == 0) goto <D.21045>; else goto <D.21046>;
  <D.21045>:
  if (1 != 0) goto <D.21047>; else goto <D.21048>;
  <D.21047>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4693, "0");
  <D.21048>:
  D.21049 = thread->tid;
  mono_thread_info_resume (D.21049);
  goto <D.21050>;
  <D.21046>:
  D.21043 = thread->state;
  D.21051 = D.21043 & 4294967293;
  thread->state = D.21051;
  D.21043 = thread->state;
  D.21052 = D.21043 | 64;
  thread->state = D.21052;
  mono_thread_info_finish_suspend ();
  <D.21050>:
  unlock_thread (thread);
}


ves_icall_System_Threading_Thread_SpinWait_nop ()
{

}


ves_icall_System_Threading_Thread_GetDomainID ()
{
  gint32 D.21053;
  struct MonoDomain * D.21054;

  D.21054 = mono_domain_get ();
  D.21053 = D.21054->domain_id;
  return D.21053;
}


ves_icall_System_Threading_Thread_Yield ()
{
  gboolean D.21056;
  int D.21057;
  _Bool D.21058;

  D.21057 = sched_yield ();
  D.21058 = D.21057 == 0;
  D.21056 = (gboolean) D.21058;
  return D.21056;
}


mono_thread_get_name (struct MonoInternalThread * this_obj, guint32 * name_len)
{
  gunichar2 * D.21060;
  unsigned int D.21064;
  long unsigned int D.21065;
  long unsigned int D.21066;
  gunichar2 * D.21067;
  gunichar2 * res;

  lock_thread (this_obj);
  D.21060 = this_obj->name;
  if (D.21060 == 0B) goto <D.21061>; else goto <D.21062>;
  <D.21061>:
  *name_len = 0;
  res = 0B;
  goto <D.21063>;
  <D.21062>:
  D.21064 = this_obj->name_len;
  *name_len = D.21064;
  D.21064 = this_obj->name_len;
  D.21065 = (long unsigned int) D.21064;
  D.21066 = D.21065 * 2;
  res = monoeg_malloc (D.21066);
  D.21064 = this_obj->name_len;
  D.21065 = (long unsigned int) D.21064;
  D.21066 = D.21065 * 2;
  D.21060 = this_obj->name;
  memcpy (res, D.21060, D.21066);
  <D.21063>:
  unlock_thread (this_obj);
  D.21067 = res;
  return D.21067;
}


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

  D.21070 = __builtin_object_size (__dest, 0);
  D.21069 = __builtin___memcpy_chk (__dest, __src, __len, D.21070);
  return D.21069;
}


ves_icall_System_Threading_Thread_GetName_internal (struct MonoInternalThread * this_obj)
{
  gunichar2 * D.21072;
  unsigned int D.21076;
  int D.21077;
  struct MonoDomain * D.21078;
  struct MonoString * D.21079;
  struct MonoString * str;

  lock_thread (this_obj);
  D.21072 = this_obj->name;
  if (D.21072 == 0B) goto <D.21073>; else goto <D.21074>;
  <D.21073>:
  str = 0B;
  goto <D.21075>;
  <D.21074>:
  D.21076 = this_obj->name_len;
  D.21077 = (int) D.21076;
  D.21072 = this_obj->name;
  D.21078 = mono_domain_get ();
  str = mono_string_new_utf16 (D.21078, D.21072, D.21077);
  <D.21075>:
  unlock_thread (this_obj);
  D.21079 = str;
  return D.21079;
}


mono_thread_set_name_internal (struct MonoInternalThread * this_obj, struct MonoString * name, gboolean managed)
{
  long unsigned int D.21081;
  long unsigned int D.21082;
  struct MonoException * D.21085;
  int D.21088;
  long unsigned int D.21089;
  long unsigned int D.21090;
  void * D.21091;
  int D.21092;
  int D.21093;
  long unsigned int D.21094;
  mono_unichar2 * D.21095;
  gunichar2 * D.21096;
  int D.21097;
  unsigned int D.21098;
  long unsigned int D.21102;
  long unsigned int D.21105;

  lock_thread (this_obj);
  D.21081 = this_obj->flags;
  D.21082 = D.21081 & 2;
  if (D.21082 != 0) goto <D.21083>; else goto <D.21084>;
  <D.21083>:
  unlock_thread (this_obj);
  D.21085 = mono_get_exception_invalid_operation ("Thread.Name can only be set once.");
  mono_raise_exception (D.21085);
  return;
  <D.21084>:
  if (name != 0B) goto <D.21086>; else goto <D.21087>;
  <D.21086>:
  D.21088 = mono_string_length (name);
  D.21089 = (long unsigned int) D.21088;
  D.21090 = D.21089 * 2;
  D.21091 = monoeg_malloc (D.21090);
  this_obj->name = D.21091;
  D.21092 = mono_string_length (name);
  D.21093 = D.21092 * 2;
  D.21094 = (long unsigned int) D.21093;
  D.21095 = mono_string_chars (name);
  D.21096 = this_obj->name;
  memcpy (D.21096, D.21095, D.21094);
  D.21097 = mono_string_length (name);
  D.21098 = (unsigned int) D.21097;
  this_obj->name_len = D.21098;
  goto <D.21099>;
  <D.21087>:
  this_obj->name = 0B;
  <D.21099>:
  if (managed != 0) goto <D.21100>; else goto <D.21101>;
  <D.21100>:
  D.21081 = this_obj->flags;
  D.21102 = D.21081 | 2;
  this_obj->flags = D.21102;
  <D.21101>:
  unlock_thread (this_obj);
  D.21096 = this_obj->name;
  if (D.21096 != 0B) goto <D.21103>; else goto <D.21104>;
  <D.21103>:
  {
    char * tname;

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


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.21107;
  struct MonoDomain * D.21108;

  D.21108 = mono_get_root_domain ();
  D.21107 = byte_array_to_domain (arr, D.21108);
  return D.21107;
}


byte_array_to_domain (struct MonoArray * arr, struct MonoDomain * domain)
{
  struct MonoArray * D.21112;
  struct MonoVTable * D.21113;
  struct MonoDomain * D.21114;
  unsigned int D.21117;
  long unsigned int D.21118;
  struct MonoClass * D.21119;
  long unsigned int D.21120;
  char * D.21121;
  char * D.21122;
  struct MonoArray * copy;

  if (arr == 0B) goto <D.21110>; else goto <D.21111>;
  <D.21110>:
  D.21112 = 0B;
  return D.21112;
  <D.21111>:
  D.21113 = MEM[(struct MonoObject *)arr].vtable;
  D.21114 = D.21113->domain;
  if (D.21114 == domain) goto <D.21115>; else goto <D.21116>;
  <D.21115>:
  D.21112 = arr;
  return D.21112;
  <D.21116>:
  D.21117 = arr->max_length;
  D.21118 = (long unsigned int) D.21117;
  D.21119 = mono_defaults.byte_class;
  copy = mono_array_new (domain, D.21119, D.21118);
  D.21117 = arr->max_length;
  D.21120 = (long unsigned int) D.21117;
  D.21121 = mono_array_addr_with_size (arr, 1, 0);
  D.21122 = mono_array_addr_with_size (copy, 1, 0);
  memmove (D.21122, D.21121, D.21120);
  D.21112 = copy;
  return D.21112;
}


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

  D.21125 = __builtin_object_size (__dest, 0);
  D.21124 = __builtin___memmove_chk (__dest, __src, __len, D.21125);
  return D.21124;
}


ves_icall_System_Threading_Thread_ByteArrayToCurrentDomain (struct MonoArray * arr)
{
  struct MonoArray * D.21127;
  struct MonoDomain * D.21128;

  D.21128 = mono_domain_get ();
  D.21127 = byte_array_to_domain (arr, D.21128);
  return D.21127;
}


mono_thread_current ()
{
  _Bool D.21130;
  long int D.21131;
  long int D.21132;
  struct MonoThread * D.21135;
  struct MonoDomain * D.21138;
  _Bool D.21139;
  long int D.21140;
  long int D.21141;
  struct MonoThread * D.21144;
  struct MonoThread * D.21145;
  struct MonoDomain * domain;
  struct MonoInternalThread * internal;
  struct MonoThread * * current_thread_ptr;

  domain = mono_domain_get ();
  internal = mono_thread_internal_current ();
  D.21130 = internal == 0B;
  D.21131 = (long int) D.21130;
  D.21132 = __builtin_expect (D.21131, 0);
  if (D.21132 != 0) goto <D.21133>; else goto <D.21134>;
  <D.21133>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1382, "internal");
  <D.21134>:
  current_thread_ptr = get_current_thread_ptr_for_domain (domain, internal);
  D.21135 = *current_thread_ptr;
  if (D.21135 == 0B) goto <D.21136>; else goto <D.21137>;
  <D.21136>:
  D.21138 = mono_get_root_domain ();
  D.21139 = D.21138 == domain;
  D.21140 = (long int) D.21139;
  D.21141 = __builtin_expect (D.21140, 0);
  if (D.21141 != 0) goto <D.21142>; else goto <D.21143>;
  <D.21142>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 1386, "domain != mono_get_root_domain ()");
  <D.21143>:
  D.21144 = new_thread_with_internal (domain, internal);
  *current_thread_ptr = D.21144;
  <D.21137>:
  D.21145 = *current_thread_ptr;
  return D.21145;
}


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

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


ves_icall_System_Threading_Thread_Join_internal (struct MonoInternalThread * this, int ms, void * thread)
{
  unsigned int D.21149;
  unsigned int D.21150;
  struct MonoException * D.21153;
  gboolean D.21154;
  unsigned int ms.50;
  unsigned int D.21158;
  struct MonoInternalThread * cur_thread;
  gboolean ret;

  cur_thread = mono_thread_internal_current ();
  mono_thread_current_check_pending_interrupt ();
  lock_thread (this);
  D.21149 = this->state;
  D.21150 = D.21149 & 8;
  if (D.21150 != 0) goto <D.21151>; else goto <D.21152>;
  <D.21151>:
  unlock_thread (this);
  D.21153 = mono_get_exception_thread_state ("Thread has not been started.");
  mono_raise_exception (D.21153);
  D.21154 = 0;
  return D.21154;
  <D.21152>:
  unlock_thread (this);
  if (ms == -1) goto <D.21155>; else goto <D.21156>;
  <D.21155>:
  ms = -1;
  <D.21156>:
  mono_thread_set_state (cur_thread, 32);
  ms.50 = (unsigned int) ms;
  D.21158 = WaitForSingleObjectEx (thread, ms.50, 1);
  ret = (gboolean) D.21158;
  mono_thread_clr_state (cur_thread, 32);
  if (ret == 0) goto <D.21159>; else goto <D.21160>;
  <D.21159>:
  D.21154 = 1;
  return D.21154;
  <D.21160>:
  D.21154 = 0;
  return D.21154;
}


ves_icall_System_Threading_WaitHandle_WaitAll_internal (struct MonoArray * mono_handles, gint32 ms, gboolean exitContext)
{
  long unsigned int D.21162;
  long unsigned int D.21163;
  long unsigned int D.21164;
  long unsigned int D.21165;
  char * D.21166;
  long unsigned int D.21167;
  long unsigned int D.21168;
  void * * D.21169;
  void * D.21170;
  int D.21173;
  gboolean D.21176;
  void * * handles;
  guint32 numhandles;
  guint32 ret;
  guint32 i;
  struct MonoObject * waitHandle;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  mono_thread_current_check_pending_interrupt ();
  D.21162 = mono_array_length (mono_handles);
  numhandles = (guint32) D.21162;
  D.21163 = (long unsigned int) numhandles;
  D.21164 = D.21163 * 8;
  handles = monoeg_malloc0 (D.21164);
  i = 0;
  goto <D.19244>;
  <D.19243>:
  D.21165 = (long unsigned int) i;
  D.21166 = mono_array_addr_with_size (mono_handles, 8, D.21165);
  waitHandle = MEM[(struct MonoObject * *)D.21166];
  D.21167 = (long unsigned int) i;
  D.21168 = D.21167 * 8;
  D.21169 = handles + D.21168;
  D.21170 = mono_wait_handle_get_handle (waitHandle);
  *D.21169 = D.21170;
  i = i + 1;
  <D.19244>:
  if (i < numhandles) goto <D.19243>; else goto <D.19245>;
  <D.19245>:
  if (ms == -1) goto <D.21171>; else goto <D.21172>;
  <D.21171>:
  ms = -1;
  <D.21172>:
  mono_thread_set_state (thread, 32);
  D.21173 = mono_wait_uninterrupted (thread, 1, numhandles, handles, 1, ms, 1);
  ret = (guint32) D.21173;
  mono_thread_clr_state (thread, 32);
  monoeg_g_free (handles);
  if (ret == 4294967295) goto <D.21174>; else goto <D.21175>;
  <D.21174>:
  D.21176 = 0;
  return D.21176;
  <D.21175>:
  if (ret == 258) goto <D.21177>; else goto <D.21178>;
  <D.21177>:
  D.21176 = 0;
  return D.21176;
  <D.21178>:
  D.21176 = 1;
  return D.21176;
}


mono_wait_uninterrupted (struct MonoInternalThread * thread, gboolean multiple, guint32 numhandles, void * * handles, gboolean waitall, gint32 ms, gboolean alertable)
{
  gint64 iftmp.51;
  unsigned int wait.52;
  unsigned int ms.53;
  void * D.21189;
  long int D.21195;
  long int D.21196;
  long int D.21197;
  gint32 D.21200;
  struct MonoException * exc;
  guint32 ret;
  gint64 start;
  gint32 diff_ms;
  gint32 wait;

  wait = ms;
  if (ms != -1) goto <D.21181>; else goto <D.21182>;
  <D.21181>:
  iftmp.51 = mono_100ns_ticks ();
  goto <D.21183>;
  <D.21182>:
  iftmp.51 = 0;
  <D.21183>:
  start = iftmp.51;
  <D.19231>:
  if (multiple != 0) goto <D.21184>; else goto <D.21185>;
  <D.21184>:
  wait.52 = (unsigned int) wait;
  ret = WaitForMultipleObjectsEx (numhandles, handles, waitall, wait.52, alertable);
  goto <D.21187>;
  <D.21185>:
  ms.53 = (unsigned int) ms;
  D.21189 = *handles;
  ret = WaitForSingleObjectEx (D.21189, ms.53, alertable);
  <D.21187>:
  if (ret != 192) goto <D.19229>; else goto <D.21190>;
  <D.21190>:
  exc = mono_thread_execute_interruption (thread);
  if (exc != 0B) goto <D.21191>; else goto <D.21192>;
  <D.21191>:
  mono_raise_exception (exc);
  <D.21192>:
  if (ms == -1) goto <D.21193>; else goto <D.21194>;
  <D.21193>:
  // predicted unlikely by continue predictor.
  goto <D.19230>;
  <D.21194>:
  D.21195 = mono_100ns_ticks ();
  D.21196 = D.21195 - start;
  D.21197 = D.21196 / 10000;
  diff_ms = (gint32) D.21197;
  if (diff_ms >= ms) goto <D.21198>; else goto <D.21199>;
  <D.21198>:
  ret = 258;
  goto <D.19229>;
  <D.21199>:
  wait = ms - diff_ms;
  <D.19230>:
  goto <D.19231>;
  <D.19229>:
  D.21200 = (gint32) ret;
  return D.21200;
}


ves_icall_System_Threading_WaitHandle_WaitAny_internal (struct MonoArray * mono_handles, gint32 ms, gboolean exitContext)
{
  long unsigned int D.21202;
  gint32 D.21205;
  long unsigned int D.21206;
  char * D.21207;
  void * D.21208;
  int D.21211;
  unsigned int D.21212;
  unsigned int D.21217;
  unsigned int D.21219;
  void * handles[64];
  guint32 numhandles;
  guint32 ret;
  guint32 i;
  struct MonoObject * waitHandle;
  struct MonoInternalThread * thread;

  try
    {
      thread = mono_thread_internal_current ();
      mono_thread_current_check_pending_interrupt ();
      D.21202 = mono_array_length (mono_handles);
      numhandles = (guint32) D.21202;
      if (numhandles > 64) goto <D.21203>; else goto <D.21204>;
      <D.21203>:
      D.21205 = -1;
      return D.21205;
      <D.21204>:
      i = 0;
      goto <D.19258>;
      <D.19257>:
      D.21206 = (long unsigned int) i;
      D.21207 = mono_array_addr_with_size (mono_handles, 8, D.21206);
      waitHandle = MEM[(struct MonoObject * *)D.21207];
      D.21208 = mono_wait_handle_get_handle (waitHandle);
      handles[i] = D.21208;
      i = i + 1;
      <D.19258>:
      if (i < numhandles) goto <D.19257>; else goto <D.19259>;
      <D.19259>:
      if (ms == -1) goto <D.21209>; else goto <D.21210>;
      <D.21209>:
      ms = -1;
      <D.21210>:
      mono_thread_set_state (thread, 32);
      D.21211 = mono_wait_uninterrupted (thread, 1, numhandles, &handles, 0, ms, 1);
      ret = (guint32) D.21211;
      mono_thread_clr_state (thread, 32);
      D.21212 = numhandles + 4294967295;
      if (D.21212 >= ret) goto <D.21213>; else goto <D.21214>;
      <D.21213>:
      D.21205 = (gint32) ret;
      return D.21205;
      <D.21214>:
      if (ret > 127) goto <D.21216>; else goto <D.21215>;
      <D.21216>:
      D.21217 = numhandles + 127;
      if (D.21217 >= ret) goto <D.21218>; else goto <D.21215>;
      <D.21218>:
      D.21219 = ret + 4294967168;
      D.21205 = (gint32) D.21219;
      return D.21205;
      <D.21215>:
      D.21205 = (gint32) ret;
      return D.21205;
    }
  finally
    {
      handles = {CLOBBER};
    }
}


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

  thread = mono_thread_internal_current ();
  if (ms == -1) goto <D.21222>; else goto <D.21223>;
  <D.21222>:
  ms = -1;
  <D.21223>:
  mono_thread_current_check_pending_interrupt ();
  mono_thread_set_state (thread, 32);
  D.21224 = mono_wait_uninterrupted (thread, 0, 1, &handle, 0, ms, 1);
  ret = (guint32) D.21224;
  mono_thread_clr_state (thread, 32);
  if (ret == 4294967295) goto <D.21225>; else goto <D.21226>;
  <D.21225>:
  D.21227 = 0;
  return D.21227;
  <D.21226>:
  if (ret == 258) goto <D.21228>; else goto <D.21229>;
  <D.21228>:
  D.21227 = 0;
  return D.21227;
  <D.21229>:
  D.21227 = 1;
  return D.21227;
}


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

  thread = mono_thread_internal_current ();
  if (ms == -1) goto <D.21231>; else goto <D.21232>;
  <D.21231>:
  ms = -1;
  <D.21232>:
  mono_thread_current_check_pending_interrupt ();
  mono_thread_set_state (thread, 32);
  ms.54 = (unsigned int) ms;
  ret = SignalObjectAndWait (toSignal, toWait, ms.54, 1);
  mono_thread_clr_state (thread, 32);
  D.21238 = ret != 258;
  D.21239 = ret != 192;
  D.21240 = D.21238 & D.21239;
  if (D.21240 != 0) goto <D.21241>; else goto <D.21236>;
  <D.21241>:
  if (ret != 4294967295) goto <D.21242>; else goto <D.21236>;
  <D.21242>:
  iftmp.55 = 1;
  goto <D.21237>;
  <D.21236>:
  iftmp.55 = 0;
  <D.21237>:
  D.21234 = iftmp.55;
  return D.21234;
}


ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, struct MonoString * name, MonoBoolean * created)
{
  int D.21246;
  mono_unichar2 * D.21248;
  unsigned int D.21249;
  void * D.21252;
  void * mutex;

  *created = 1;
  if (name == 0B) goto <D.21244>; else goto <D.21245>;
  <D.21244>:
  D.21246 = (int) owned;
  mutex = CreateMutex (0B, D.21246, 0B);
  goto <D.21247>;
  <D.21245>:
  D.21248 = mono_string_chars (name);
  D.21246 = (int) owned;
  mutex = CreateMutex (0B, D.21246, D.21248);
  D.21249 = GetLastError ();
  if (D.21249 == 183) goto <D.21250>; else goto <D.21251>;
  <D.21250>:
  *created = 0;
  <D.21251>:
  <D.21247>:
  D.21252 = mutex;
  return D.21252;
}


ves_icall_System_Threading_Mutex_ReleaseMutex_internal (void * handle)
{
  MonoBoolean D.21254;
  int D.21255;

  D.21255 = ReleaseMutex (handle);
  D.21254 = (MonoBoolean) D.21255;
  return D.21254;
}


ves_icall_System_Threading_Mutex_OpenMutex_internal (struct MonoString * name, gint32 rights, gint32 * error)
{
  mono_unichar2 * D.21257;
  unsigned int rights.56;
  unsigned int D.21261;
  int D.21262;
  void * D.21263;
  void * ret;

  *error = 0;
  D.21257 = mono_string_chars (name);
  rights.56 = (unsigned int) rights;
  ret = OpenMutex (rights.56, 0, D.21257);
  if (ret == 0B) goto <D.21259>; else goto <D.21260>;
  <D.21259>:
  D.21261 = GetLastError ();
  D.21262 = (int) D.21261;
  *error = D.21262;
  <D.21260>:
  D.21263 = ret;
  return D.21263;
}


ves_icall_System_Threading_Semaphore_CreateSemaphore_internal (gint32 initialCount, gint32 maximumCount, struct MonoString * name, MonoBoolean * created)
{
  mono_unichar2 * D.21268;
  unsigned int D.21269;
  void * D.21272;
  void * sem;

  *created = 1;
  if (name == 0B) goto <D.21265>; else goto <D.21266>;
  <D.21265>:
  sem = CreateSemaphore (0B, initialCount, maximumCount, 0B);
  goto <D.21267>;
  <D.21266>:
  D.21268 = mono_string_chars (name);
  sem = CreateSemaphore (0B, initialCount, maximumCount, D.21268);
  D.21269 = GetLastError ();
  if (D.21269 == 183) goto <D.21270>; else goto <D.21271>;
  <D.21270>:
  *created = 0;
  <D.21271>:
  <D.21267>:
  D.21272 = sem;
  return D.21272;
}


ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (void * handle, gint32 releaseCount, MonoBoolean * fail)
{
  int D.21274;
  _Bool D.21275;
  unsigned char D.21276;
  gint32 D.21277;
  gint32 prevcount;

  try
    {
      D.21274 = ReleaseSemaphore (handle, releaseCount, &prevcount);
      D.21275 = D.21274 == 0;
      D.21276 = (unsigned char) D.21275;
      *fail = D.21276;
      D.21277 = prevcount;
      return D.21277;
    }
  finally
    {
      prevcount = {CLOBBER};
    }
}


ves_icall_System_Threading_Semaphore_OpenSemaphore_internal (struct MonoString * name, gint32 rights, gint32 * error)
{
  mono_unichar2 * D.21280;
  unsigned int rights.57;
  unsigned int D.21284;
  int D.21285;
  void * D.21286;
  void * ret;

  *error = 0;
  D.21280 = mono_string_chars (name);
  rights.57 = (unsigned int) rights;
  ret = OpenSemaphore (rights.57, 0, D.21280);
  if (ret == 0B) goto <D.21282>; else goto <D.21283>;
  <D.21282>:
  D.21284 = GetLastError ();
  D.21285 = (int) D.21284;
  *error = D.21285;
  <D.21283>:
  D.21286 = ret;
  return D.21286;
}


ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, struct MonoString * name, MonoBoolean * created)
{
  int D.21290;
  int D.21291;
  mono_unichar2 * D.21293;
  unsigned int D.21294;
  void * D.21297;
  void * event;

  *created = 1;
  if (name == 0B) goto <D.21288>; else goto <D.21289>;
  <D.21288>:
  D.21290 = (int) initial;
  D.21291 = (int) manual;
  event = CreateEvent (0B, D.21291, D.21290, 0B);
  goto <D.21292>;
  <D.21289>:
  D.21293 = mono_string_chars (name);
  D.21290 = (int) initial;
  D.21291 = (int) manual;
  event = CreateEvent (0B, D.21291, D.21290, D.21293);
  D.21294 = GetLastError ();
  if (D.21294 == 183) goto <D.21295>; else goto <D.21296>;
  <D.21295>:
  *created = 0;
  <D.21296>:
  <D.21292>:
  D.21297 = event;
  return D.21297;
}


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

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


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

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


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.21303;
  unsigned int rights.58;
  unsigned int D.21307;
  int D.21308;
  void * D.21309;
  void * ret;

  *error = 0;
  D.21303 = mono_string_chars (name);
  rights.58 = (unsigned int) rights;
  ret = OpenEvent (rights.58, 0, D.21303);
  if (ret == 0B) goto <D.21305>; else goto <D.21306>;
  <D.21305>:
  D.21307 = GetLastError ();
  D.21308 = (int) D.21307;
  *error = D.21308;
  <D.21306>:
  D.21309 = ret;
  return D.21309;
}


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

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


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

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


InterlockedIncrement64 (volatile gint64 * val)
{
  gint64 D.21315;
  long unsigned int D.21316;

  D.21316 = __sync_add_and_fetch_8 (val, 1);
  D.21315 = (gint64) D.21316;
  return D.21315;
}


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

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


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

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


InterlockedDecrement64 (volatile gint64 * val)
{
  gint64 D.21322;
  long unsigned int D.21323;

  D.21323 = __sync_sub_and_fetch_8 (val, 1);
  D.21322 = (gint64) D.21323;
  return D.21322;
}


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

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


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

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


InterlockedExchangePointer (void * volatile * val, void * new_val)
{
  long unsigned int new_val.59;
  long unsigned int old_val.60;
  long unsigned int D.21331;
  void * D.21332;
  void * D.21333;
  void * old_val;

  <D.18800>:
  old_val = *val;
  new_val.59 = (long unsigned int) new_val;
  old_val.60 = (long unsigned int) old_val;
  D.21331 = __sync_val_compare_and_swap_8 (val, old_val.60, new_val.59);
  D.21332 = (void *) D.21331;
  if (D.21332 != old_val) goto <D.18800>; else goto <D.18801>;
  <D.18801>:
  D.21333 = old_val;
  return D.21333;
}


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

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


ves_icall_System_Threading_Interlocked_Exchange_Single (gfloat * location, gfloat value)
{
  int D.21337;
  int D.21338;
  gfloat D.21339;
  union IntFloatUnion val;
  union IntFloatUnion ret;

  try
    {
      val.fval = value;
      D.21337 = val.ival;
      D.21338 = InterlockedExchange (location, D.21337);
      ret.ival = D.21338;
      D.21339 = ret.fval;
      return D.21339;
    }
  finally
    {
      val = {CLOBBER};
      ret = {CLOBBER};
    }
}


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

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


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

  <D.18870>:
  old_val = *val;
  D.21344 = InterlockedCompareExchange64 (val, new_val, old_val);
  if (D.21344 != old_val) goto <D.18870>; else goto <D.18871>;
  <D.18871>:
  D.21345 = old_val;
  return D.21345;
}


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

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


ves_icall_System_Threading_Interlocked_Exchange_Double (gdouble * location, gdouble value)
{
  long int D.21352;
  long int D.21353;
  gdouble D.21354;
  union LongDoubleUnion val;
  union LongDoubleUnion ret;

  try
    {
      val.fval = value;
      D.21352 = val.ival;
      D.21353 = InterlockedExchange64 (location, D.21352);
      ret.ival = D.21353;
      D.21354 = ret.fval;
      return D.21354;
    }
  finally
    {
      val = {CLOBBER};
      ret = {CLOBBER};
    }
}


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

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


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

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


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

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


ves_icall_System_Threading_Interlocked_CompareExchange_Single (gfloat * location, gfloat value, gfloat comparand)
{
  int D.21363;
  int D.21364;
  int D.21365;
  gfloat D.21366;
  union IntFloatUnion val;
  union IntFloatUnion ret;
  union IntFloatUnion cmp;

  try
    {
      val.fval = value;
      cmp.fval = comparand;
      D.21363 = cmp.ival;
      D.21364 = val.ival;
      D.21365 = InterlockedCompareExchange (location, D.21364, D.21363);
      ret.ival = D.21365;
      D.21366 = ret.fval;
      return D.21366;
    }
  finally
    {
      val = {CLOBBER};
      ret = {CLOBBER};
      cmp = {CLOBBER};
    }
}


ves_icall_System_Threading_Interlocked_CompareExchange_Double (gdouble * location, gdouble value, gdouble comparand)
{
  long int D.21369;
  void * D.21370;
  long int D.21371;
  void * D.21372;
  void * D.21373;
  long int D.21374;
  gdouble D.21375;
  union LongDoubleUnion val;
  union LongDoubleUnion comp;
  union LongDoubleUnion ret;

  try
    {
      val.fval = value;
      comp.fval = comparand;
      D.21369 = comp.ival;
      D.21370 = (void *) D.21369;
      D.21371 = val.ival;
      D.21372 = (void *) D.21371;
      D.21373 = InterlockedCompareExchangePointer (location, D.21372, D.21370);
      D.21374 = (long int) D.21373;
      ret.ival = D.21374;
      D.21375 = ret.fval;
      return D.21375;
    }
  finally
    {
      val = {CLOBBER};
      comp = {CLOBBER};
      ret = {CLOBBER};
    }
}


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

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


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

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


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

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


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

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


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

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


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

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


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

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


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

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


InterlockedRead64 (volatile gint64 * src)
{
  gint64 D.21398;
  long unsigned int D.21399;

  D.21399 = __sync_fetch_and_add_8 (src, 0);
  D.21398 = (gint64) D.21399;
  return D.21398;
}


ves_icall_System_Threading_Thread_MemoryBarrier ()
{
  mono_memory_barrier ();
}


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

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


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

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


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

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


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

  lock_thread (this);
  current = mono_thread_internal_current ();
  this->thread_interrupt_requested = 1;
  if (current != this) goto <D.21414>; else goto <D.21412>;
  <D.21414>:
  D.21415 = this->state;
  D.21416 = D.21415 & 32;
  if (D.21416 != 0) goto <D.21417>; else goto <D.21412>;
  <D.21417>:
  iftmp.67 = 1;
  goto <D.21413>;
  <D.21412>:
  iftmp.67 = 0;
  <D.21413>:
  throw = iftmp.67;
  unlock_thread (this);
  if (throw != 0) goto <D.21418>; else goto <D.21419>;
  <D.21418>:
  abort_thread_internal (this, 1, 0);
  <D.21419>:
}


abort_thread_internal (struct MonoInternalThread * thread, gboolean can_raise_exception, gboolean install_async_abort)
{
  int D.21420;
  struct MonoInternalThread * D.21423;
  void * D.21428;
  long unsigned int D.21429;
  struct MonoRuntimeExceptionHandlingCallbacks * D.21432;
  gboolean (*<T271a>) (struct MonoThreadUnwindState *) D.21433;
  struct MonoThreadUnwindState * D.21434;
  int D.21435;
  long unsigned int D.21438;
  gint32 * D.21439;
  int D.21440;
  int iftmp.68;
  struct MonoMethod * D.21447;
  int D.21448;
  long int D.21450;
  void * D.21451;
  _Bool D.21452;
  _Bool D.21453;
  _Bool D.21454;
  struct MonoJitInfo * ji;
  struct MonoThreadInfo * info;
  gboolean protected_wrapper;
  gboolean running_managed;

  info = 0B;
  D.21420 = mono_thread_info_new_interrupt_enabled ();
  if (D.21420 == 0) goto <D.21421>; else goto <D.21422>;
  <D.21421>:
  signal_thread_state_change (thread);
  return;
  <D.21422>:
  D.21423 = mono_thread_internal_current ();
  if (D.21423 == thread) goto <D.21424>; else goto <D.21425>;
  <D.21424>:
  {
    struct MonoException * exc;

    exc = mono_thread_request_interruption (can_raise_exception);
    if (exc != 0B) goto <D.21426>; else goto <D.21427>;
    <D.21426>:
    mono_raise_exception (exc);
    <D.21427>:
    D.21428 = thread->handle;
    wapi_interrupt_thread (D.21428);
    return;
  }
  <D.21425>:
  D.21429 = thread->tid;
  info = mono_thread_info_safe_suspend_sync (D.21429, 1);
  if (info == 0B) goto <D.21430>; else goto <D.21431>;
  <D.21430>:
  return;
  <D.21431>:
  D.21432 = mono_get_eh_callbacks ();
  D.21433 = D.21432->mono_install_handler_block_guard;
  D.21434 = &info->suspend_state;
  D.21435 = D.21433 (D.21434);
  if (D.21435 != 0) goto <D.21436>; else goto <D.21437>;
  <D.21436>:
  D.21438 = info->node.key;
  mono_thread_info_resume (D.21438);
  return;
  <D.21437>:
  D.21439 = &thread->interruption_requested;
  D.21440 = InterlockedCompareExchange (D.21439, 1, 0);
  if (D.21440 == 1) goto <D.21441>; else goto <D.21442>;
  <D.21441>:
  D.21438 = info->node.key;
  mono_thread_info_resume (D.21438);
  return;
  <D.21442>:
  InterlockedIncrement (&thread_interruption_requested);
  ji = mono_thread_info_get_last_managed (info);
  if (ji != 0B) goto <D.21446>; else goto <D.21444>;
  <D.21446>:
  D.21447 = mono_jit_info_get_method (ji);
  D.21448 = mono_threads_is_critical_method (D.21447);
  if (D.21448 != 0) goto <D.21449>; else goto <D.21444>;
  <D.21449>:
  iftmp.68 = 1;
  goto <D.21445>;
  <D.21444>:
  iftmp.68 = 0;
  <D.21445>:
  protected_wrapper = iftmp.68;
  D.21450 = info->suspend_state.ctx.rip;
  D.21451 = (void *) D.21450;
  running_managed = mono_jit_info_match (ji, D.21451);
  D.21452 = protected_wrapper == 0;
  D.21453 = running_managed != 0;
  D.21454 = D.21452 & D.21453;
  if (D.21454 != 0) goto <D.21455>; else goto <D.21456>;
  <D.21455>:
  if (install_async_abort != 0) goto <D.21457>; else goto <D.21458>;
  <D.21457>:
  mono_thread_info_setup_async_call (info, self_interrupt_thread, 0B);
  <D.21458>:
  D.21438 = info->node.key;
  mono_thread_info_resume (D.21438);
  goto <D.21459>;
  <D.21456>:
  {
    void * interrupt_handle;

    D.21428 = thread->handle;
    interrupt_handle = wapi_prepare_interrupt_thread (D.21428);
    D.21438 = info->node.key;
    mono_thread_info_resume (D.21438);
    wapi_finish_interrupt_thread (interrupt_handle);
  }
  <D.21459>:
}


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

  info = mono_thread_info_current ();
  D.21461 = mono_thread_internal_current ();
  exc = mono_thread_execute_interruption (D.21461);
  if (exc != 0B) goto <D.21462>; else goto <D.21463>;
  <D.21462>:
  D.21464 = &info->suspend_state.ctx;
  mono_raise_exception_with_context (exc, D.21464);
  <D.21463>:
  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.21465;
  int D.21470;
  void * D.21471;

  D.21465 = mono_thread_internal_current ();
  if (D.21465 == thread) goto <D.21466>; else goto <D.21467>;
  <D.21466>:
  {
    struct MonoException * exc;

    exc = mono_thread_request_interruption (0);
    if (exc != 0B) goto <D.21468>; else goto <D.21469>;
    <D.21468>:
    mono_raise_exception (exc);
    <D.21469>:
  }
  <D.21467>:
  D.21470 = mono_thread_get_abort_signal ();
  mono_thread_kill (thread, D.21470);
  D.21471 = thread->handle;
  wapi_interrupt_thread (D.21471);
}


mono_thread_info_get_last_managed (struct MonoThreadInfo * info)
{
  struct MonoJitInfo * D.21474;
  struct MonoRuntimeExceptionHandlingCallbacks * D.21475;
  void (*<T270a>) (gboolean (*MonoInternalStackWalk) (struct MonoStackFrameInfo *, struct MonoContext *, void *), struct MonoThreadUnwindState *, MonoUnwindOptions, void *) D.21476;
  struct MonoThreadUnwindState * D.21477;
  struct MonoJitInfo * ji;

  try
    {
      ji = 0B;
      if (info == 0B) goto <D.21472>; else goto <D.21473>;
      <D.21472>:
      D.21474 = 0B;
      return D.21474;
      <D.21473>:
      D.21475 = mono_get_eh_callbacks ();
      D.21476 = D.21475->mono_walk_stack_with_state;
      D.21477 = &info->suspend_state;
      D.21476 (last_managed, D.21477, 0, &ji);
      D.21474 = ji;
      return D.21474;
    }
  finally
    {
      ji = {CLOBBER};
    }
}


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

  dest = data;
  D.21480 = frame->ji;
  *dest = D.21480;
  D.21481 = 1;
  return D.21481;
}


mono_threads_is_critical_method (struct MonoMethod * method)
{
  <unnamed-unsigned:5> D.21483;
  int D.21484;
  gboolean D.21485;

  D.21483 = method->wrapper_type;
  D.21484 = (int) D.21483;
  switch (D.21484) <default: <D.21486>, case 4: <D.19506>, case 10: <D.19507>, case 11: <D.19508>>
  <D.19506>:
  <D.19507>:
  <D.19508>:
  D.21485 = 1;
  return D.21485;
  <D.21486>:
  D.21485 = 0;
  return D.21485;
}


mono_jit_info_match (struct MonoJitInfo * ji, void * ip)
{
  gboolean D.21490;
  int iftmp.69;
  void * D.21494;
  int D.21496;
  sizetype D.21497;
  char * D.21498;

  if (ji == 0B) goto <D.21488>; else goto <D.21489>;
  <D.21488>:
  D.21490 = 0;
  return D.21490;
  <D.21489>:
  D.21494 = ji->code_start;
  if (D.21494 <= ip) goto <D.21495>; else goto <D.21492>;
  <D.21495>:
  D.21494 = ji->code_start;
  D.21496 = ji->code_size;
  D.21497 = (sizetype) D.21496;
  D.21498 = D.21494 + D.21497;
  if (D.21498 > ip) goto <D.21499>; else goto <D.21492>;
  <D.21499>:
  iftmp.69 = 1;
  goto <D.21493>;
  <D.21492>:
  iftmp.69 = 0;
  <D.21493>:
  D.21490 = iftmp.69;
  return D.21490;
}


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

  thread = mono_thread_internal_current ();
  throw = 0;
  lock_thread (thread);
  D.21501 = thread->thread_interrupt_requested;
  if (D.21501 != 0) goto <D.21502>; else goto <D.21503>;
  <D.21502>:
  throw = 1;
  thread->thread_interrupt_requested = 0;
  <D.21503>:
  unlock_thread (thread);
  if (throw != 0) goto <D.21504>; else goto <D.21505>;
  <D.21504>:
  D.21506 = mono_get_exception_thread_interrupted ();
  mono_raise_exception (D.21506);
  <D.21505>:
}


mono_thread_get_abort_signal ()
{
  int abort_signum.70;
  int D.21510;
  int D.21511;
  void (*<Teba>) (int) D.21512;
  void (*<Tefd>) (int, struct siginfo_t *, void *) D.21515;
  int D.21518;
  static int abort_signum = -1;
  int i;

  abort_signum.70 = abort_signum;
  if (abort_signum.70 != -1) goto <D.21508>; else goto <D.21509>;
  <D.21508>:
  D.21510 = abort_signum;
  return D.21510;
  <D.21509>:
  D.21511 = __libc_current_sigrtmin ();
  i = D.21511 + 1;
  goto <D.19463>;
  <D.19462>:
  {
    struct sigaction sinfo;

    try
      {
        sigaction (i, 0B, &sinfo);
        D.21512 = sinfo.__sigaction_handler.sa_handler;
        if (D.21512 == 0B) goto <D.21513>; else goto <D.21514>;
        <D.21513>:
        D.21515 = sinfo.__sigaction_handler.sa_sigaction;
        if (D.21515 == 0B) goto <D.21516>; else goto <D.21517>;
        <D.21516>:
        abort_signum = i;
        D.21510 = i;
        return D.21510;
        <D.21517>:
        <D.21514>:
      }
    finally
      {
        sinfo = {CLOBBER};
      }
  }
  i = i + 1;
  <D.19463>:
  D.21518 = __libc_current_sigrtmax ();
  if (D.21518 > i) goto <D.19462>; else goto <D.19464>;
  <D.19464>:
  D.21510 = __libc_current_sigrtmin ();
  return D.21510;
}


ves_icall_System_Threading_Thread_Abort (struct MonoInternalThread * thread, struct MonoObject * state)
{
  unsigned int D.21522;
  unsigned int D.21523;
  unsigned int D.21526;
  unsigned int D.21527;
  unsigned int D.21530;
  unsigned int D.21531;
  int D.21532;
  unsigned int D.21535;
  unsigned int D.21538;
  int D.21539;
  _Bool D.21540;
  long int D.21541;
  long int D.21542;
  int shutting_down.71;

  lock_thread (thread);
  D.21522 = BIT_FIELD_REF <*thread, 32, 416>;
  D.21523 = D.21522 & 145;
  if (D.21523 != 0) goto <D.21524>; else goto <D.21525>;
  <D.21524>:
  unlock_thread (thread);
  return;
  <D.21525>:
  D.21526 = thread->state;
  D.21527 = D.21526 & 8;
  if (D.21527 != 0) goto <D.21528>; else goto <D.21529>;
  <D.21528>:
  D.21526 = thread->state;
  D.21530 = D.21526 | 256;
  thread->state = D.21530;
  unlock_thread (thread);
  return;
  <D.21529>:
  D.21526 = thread->state;
  D.21531 = D.21526 | 128;
  thread->state = D.21531;
  D.21532 = thread->abort_state_handle;
  if (D.21532 != 0) goto <D.21533>; else goto <D.21534>;
  <D.21533>:
  D.21532 = thread->abort_state_handle;
  D.21535 = (unsigned int) D.21532;
  mono_gchandle_free (D.21535);
  <D.21534>:
  if (state != 0B) goto <D.21536>; else goto <D.21537>;
  <D.21536>:
  D.21538 = mono_gchandle_new (state, 0);
  D.21539 = (int) D.21538;
  thread->abort_state_handle = D.21539;
  D.21532 = thread->abort_state_handle;
  D.21540 = D.21532 == 0;
  D.21541 = (long int) D.21540;
  D.21542 = __builtin_expect (D.21541, 0);
  if (D.21542 != 0) goto <D.21543>; else goto <D.21544>;
  <D.21543>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2156, "thread->abort_state_handle");
  <D.21544>:
  goto <D.21545>;
  <D.21537>:
  thread->abort_state_handle = 0;
  <D.21545>:
  thread->abort_exc = 0B;
  unlock_thread (thread);
  shutting_down.71 = shutting_down;
  if (shutting_down.71 == 0) goto <D.21547>; else goto <D.21548>;
  <D.21547>:
  mono_thread_resume (thread);
  <D.21548>:
  abort_thread_internal (thread, 1, 1);
}


mono_thread_resume (struct MonoInternalThread * thread)
{
  unsigned int D.21550;
  unsigned int D.21551;
  unsigned int D.21554;
  gboolean D.21555;
  unsigned int D.21556;
  unsigned int D.21557;

  lock_thread (thread);
  D.21550 = thread->state;
  D.21551 = D.21550 & 2;
  if (D.21551 != 0) goto <D.21552>; else goto <D.21553>;
  <D.21552>:
  D.21550 = thread->state;
  D.21554 = D.21550 & 4294967293;
  thread->state = D.21554;
  unlock_thread (thread);
  D.21555 = 1;
  return D.21555;
  <D.21553>:
  D.21556 = BIT_FIELD_REF <*thread, 32, 416>;
  D.21557 = D.21556 & 344;
  if (D.21557 != 64) goto <D.21558>; else goto <D.21559>;
  <D.21558>:
  unlock_thread (thread);
  D.21555 = 0;
  return D.21555;
  <D.21559>:
  D.21555 = resume_thread_internal (thread);
  return D.21555;
}


resume_thread_internal (struct MonoInternalThread * thread)
{
  int D.21561;
  void * D.21564;
  void * D.21565;
  gboolean D.21568;
  void * D.21569;
  long unsigned int D.21570;
  int D.21571;
  unsigned int D.21574;
  unsigned int D.21575;

  D.21561 = mono_thread_info_new_interrupt_enabled ();
  if (D.21561 == 0) goto <D.21562>; else goto <D.21563>;
  <D.21562>:
  D.21564 = CreateEvent (0B, 1, 0, 0B);
  thread->resume_event = D.21564;
  D.21565 = thread->resume_event;
  if (D.21565 == 0B) goto <D.21566>; else goto <D.21567>;
  <D.21566>:
  unlock_thread (thread);
  D.21568 = 0;
  return D.21568;
  <D.21567>:
  D.21569 = thread->suspend_event;
  SetEvent (D.21569);
  unlock_thread (thread);
  D.21565 = thread->resume_event;
  WaitForSingleObject (D.21565, 4294967295);
  D.21565 = thread->resume_event;
  CloseHandle (D.21565);
  thread->resume_event = 0B;
  D.21568 = 1;
  return D.21568;
  <D.21563>:
  unlock_thread (thread);
  D.21570 = thread->tid;
  D.21571 = mono_thread_info_resume (D.21570);
  if (D.21571 == 0) goto <D.21572>; else goto <D.21573>;
  <D.21572>:
  D.21568 = 0;
  return D.21568;
  <D.21573>:
  lock_thread (thread);
  D.21574 = thread->state;
  D.21575 = D.21574 & 4294967231;
  thread->state = D.21575;
  unlock_thread (thread);
  D.21568 = 1;
  return D.21568;
}


ves_icall_System_Threading_Thread_ResetAbort ()
{
  unsigned int D.21577;
  int D.21578;
  unsigned int D.21579;
  struct MonoException * D.21582;
  int D.21583;
  unsigned int D.21586;
  struct MonoInternalThread * thread;
  gboolean was_aborting;

  thread = mono_thread_internal_current ();
  lock_thread (thread);
  D.21577 = thread->state;
  D.21578 = (int) D.21577;
  was_aborting = D.21578 & 128;
  D.21577 = thread->state;
  D.21579 = D.21577 & 4294967167;
  thread->state = D.21579;
  unlock_thread (thread);
  if (was_aborting == 0) goto <D.21580>; else goto <D.21581>;
  <D.21580>:
  {
    const char * msg;

    msg = "Unable to reset abort because no abort was requested";
    D.21582 = mono_get_exception_thread_state (msg);
    mono_raise_exception (D.21582);
  }
  <D.21581>:
  thread->abort_exc = 0B;
  D.21583 = thread->abort_state_handle;
  if (D.21583 != 0) goto <D.21584>; else goto <D.21585>;
  <D.21584>:
  D.21583 = thread->abort_state_handle;
  D.21586 = (unsigned int) D.21583;
  mono_gchandle_free (D.21586);
  thread->abort_state_handle = 0;
  <D.21585>:
}


mono_thread_internal_reset_abort (struct MonoInternalThread * thread)
{
  unsigned int D.21587;
  unsigned int D.21588;
  struct MonoException * D.21589;
  int D.21592;
  unsigned int D.21595;

  lock_thread (thread);
  D.21587 = thread->state;
  D.21588 = D.21587 & 4294967167;
  thread->state = D.21588;
  D.21589 = thread->abort_exc;
  if (D.21589 != 0B) goto <D.21590>; else goto <D.21591>;
  <D.21590>:
  thread->abort_exc = 0B;
  D.21592 = thread->abort_state_handle;
  if (D.21592 != 0) goto <D.21593>; else goto <D.21594>;
  <D.21593>:
  D.21592 = thread->abort_state_handle;
  D.21595 = (unsigned int) D.21592;
  mono_gchandle_free (D.21595);
  thread->abort_state_handle = 0;
  <D.21594>:
  <D.21591>:
  unlock_thread (thread);
}


ves_icall_System_Threading_Thread_GetAbortExceptionState (struct MonoThread * this)
{
  int D.21596;
  struct MonoObject * D.21599;
  unsigned int D.21600;
  _Bool D.21601;
  long int D.21602;
  long int D.21603;
  struct MonoVTable * D.21606;
  struct MonoDomain * D.21607;
  struct MonoObject * exc.72;
  struct MonoObject * * D.21615;
  struct MonoInternalThread * thread;
  struct MonoObject * state;
  struct MonoObject * deserialized;
  struct MonoObject * exc;
  struct MonoDomain * domain;

  try
    {
      thread = this->internal_thread;
      deserialized = 0B;
      D.21596 = thread->abort_state_handle;
      if (D.21596 == 0) goto <D.21597>; else goto <D.21598>;
      <D.21597>:
      D.21599 = 0B;
      return D.21599;
      <D.21598>:
      D.21596 = thread->abort_state_handle;
      D.21600 = (unsigned int) D.21596;
      state = mono_gchandle_get_target (D.21600);
      D.21601 = state == 0B;
      D.21602 = (long int) D.21601;
      D.21603 = __builtin_expect (D.21602, 0);
      if (D.21603 != 0) goto <D.21604>; else goto <D.21605>;
      <D.21604>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2237, "state");
      <D.21605>:
      domain = mono_domain_get ();
      D.21606 = state->vtable;
      D.21607 = D.21606->domain;
      if (D.21607 == domain) goto <D.21608>; else goto <D.21609>;
      <D.21608>:
      D.21599 = state;
      return D.21599;
      <D.21609>:
      deserialized = mono_object_xdomain_representation (state, domain, &exc);
      if (deserialized == 0B) goto <D.21610>; else goto <D.21611>;
      <D.21610>:
      {
        struct MonoException * invalid_op_exc;

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


ves_icall_System_Threading_Thread_Suspend (struct MonoInternalThread * thread)
{
  int D.21618;
  struct MonoException * D.21621;

  D.21618 = mono_thread_suspend (thread);
  if (D.21618 == 0) goto <D.21619>; else goto <D.21620>;
  <D.21619>:
  D.21621 = mono_get_exception_thread_state ("Thread has not been started, or is dead.");
  mono_raise_exception (D.21621);
  <D.21620>:
}


mono_thread_suspend (struct MonoInternalThread * thread)
{
  unsigned int D.21622;
  unsigned int D.21623;
  gboolean D.21626;
  unsigned int D.21627;
  unsigned int D.21630;
  unsigned int D.21631;

  lock_thread (thread);
  D.21622 = BIT_FIELD_REF <*thread, 32, 416>;
  D.21623 = D.21622 & 280;
  if (D.21623 != 0) goto <D.21624>; else goto <D.21625>;
  <D.21624>:
  unlock_thread (thread);
  D.21626 = 0;
  return D.21626;
  <D.21625>:
  D.21622 = BIT_FIELD_REF <*thread, 32, 416>;
  D.21627 = D.21622 & 67;
  if (D.21627 != 0) goto <D.21628>; else goto <D.21629>;
  <D.21628>:
  unlock_thread (thread);
  D.21626 = 1;
  return D.21626;
  <D.21629>:
  D.21630 = thread->state;
  D.21631 = D.21630 | 2;
  thread->state = D.21631;
  unlock_thread (thread);
  suspend_thread_internal (thread, 0);
  D.21626 = 1;
  return D.21626;
}


suspend_thread_internal (struct MonoInternalThread * thread, gboolean interrupt)
{
  int D.21633;
  struct MonoInternalThread * D.21636;
  long unsigned int D.21640;
  int iftmp.73;
  struct MonoMethod * D.21647;
  int D.21648;
  long int D.21650;
  void * D.21651;
  _Bool D.21652;
  _Bool D.21653;
  _Bool D.21654;
  gint32 * D.21658;
  int D.21659;
  void * D.21664;
  long unsigned int D.21665;

  D.21633 = mono_thread_info_new_interrupt_enabled ();
  if (D.21633 == 0) goto <D.21634>; else goto <D.21635>;
  <D.21634>:
  signal_thread_state_change (thread);
  return;
  <D.21635>:
  lock_thread (thread);
  D.21636 = mono_thread_internal_current ();
  if (D.21636 == thread) goto <D.21637>; else goto <D.21638>;
  <D.21637>:
  transition_to_suspended (thread);
  mono_thread_info_self_suspend ();
  goto <D.21639>;
  <D.21638>:
  {
    struct MonoThreadInfo * info;
    struct MonoJitInfo * ji;
    gboolean protected_wrapper;
    gboolean running_managed;

    D.21640 = thread->tid;
    info = mono_thread_info_safe_suspend_sync (D.21640, interrupt);
    if (info == 0B) goto <D.21641>; else goto <D.21642>;
    <D.21641>:
    unlock_thread (thread);
    return;
    <D.21642>:
    ji = mono_thread_info_get_last_managed (info);
    if (ji != 0B) goto <D.21646>; else goto <D.21644>;
    <D.21646>:
    D.21647 = mono_jit_info_get_method (ji);
    D.21648 = mono_threads_is_critical_method (D.21647);
    if (D.21648 != 0) goto <D.21649>; else goto <D.21644>;
    <D.21649>:
    iftmp.73 = 1;
    goto <D.21645>;
    <D.21644>:
    iftmp.73 = 0;
    <D.21645>:
    protected_wrapper = iftmp.73;
    D.21650 = info->suspend_state.ctx.rip;
    D.21651 = (void *) D.21650;
    running_managed = mono_jit_info_match (ji, D.21651);
    D.21652 = running_managed != 0;
    D.21653 = protected_wrapper == 0;
    D.21654 = D.21652 & D.21653;
    if (D.21654 != 0) goto <D.21655>; else goto <D.21656>;
    <D.21655>:
    transition_to_suspended (thread);
    goto <D.21657>;
    <D.21656>:
    {
      void * interrupt_handle;

      D.21658 = &thread->interruption_requested;
      D.21659 = InterlockedCompareExchange (D.21658, 1, 0);
      if (D.21659 == 0) goto <D.21660>; else goto <D.21661>;
      <D.21660>:
      InterlockedIncrement (&thread_interruption_requested);
      <D.21661>:
      if (interrupt != 0) goto <D.21662>; else goto <D.21663>;
      <D.21662>:
      D.21664 = thread->handle;
      interrupt_handle = wapi_prepare_interrupt_thread (D.21664);
      <D.21663>:
      D.21665 = info->node.key;
      mono_thread_info_resume (D.21665);
      if (interrupt != 0) goto <D.21666>; else goto <D.21667>;
      <D.21666>:
      wapi_finish_interrupt_thread (interrupt_handle);
      <D.21667>:
      unlock_thread (thread);
    }
    <D.21657>:
  }
  <D.21639>:
}


ves_icall_System_Threading_Thread_Resume (struct MonoThread * thread)
{
  struct _MonoInternalThread * D.21671;
  int D.21673;
  struct MonoException * D.21674;

  D.21671 = thread->internal_thread;
  if (D.21671 == 0B) goto <D.21669>; else goto <D.21672>;
  <D.21672>:
  D.21671 = thread->internal_thread;
  D.21673 = mono_thread_resume (D.21671);
  if (D.21673 == 0) goto <D.21669>; else goto <D.21670>;
  <D.21669>:
  D.21674 = mono_get_exception_thread_state ("Thread has not been started, or is dead.");
  mono_raise_exception (D.21674);
  <D.21670>:
}


mono_thread_internal_stop (struct MonoInternalThread * thread)
{
  unsigned int D.21675;
  unsigned int D.21676;
  unsigned int D.21679;
  unsigned int D.21680;
  unsigned int D.21681;

  lock_thread (thread);
  D.21675 = BIT_FIELD_REF <*thread, 32, 416>;
  D.21676 = D.21675 & 17;
  if (D.21676 != 0) goto <D.21677>; else goto <D.21678>;
  <D.21677>:
  unlock_thread (thread);
  return;
  <D.21678>:
  mono_thread_resume (thread);
  D.21679 = thread->state;
  D.21680 = D.21679 | 1;
  thread->state = D.21680;
  D.21679 = thread->state;
  D.21681 = D.21679 & 4294967167;
  thread->state = D.21681;
  unlock_thread (thread);
  abort_thread_internal (thread, 1, 1);
}


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

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


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

  {
    gint8 __tmp;

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


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

  {
    gint16 __tmp;

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


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

  {
    gint32 __tmp;

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


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

  {
    gint64 __tmp;

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


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

  {
    volatile void * __tmp;

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


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

  {
    volatile struct MonoObject * __tmp;

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


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

  {
    double __tmp;

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


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

  {
    float __tmp;

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


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

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


InterlockedRead8 (volatile gint8 * src)
{
  gint8 D.21702;
  unsigned char D.21703;

  D.21703 = __sync_fetch_and_add_1 (src, 0);
  D.21702 = (gint8) D.21703;
  return D.21702;
}


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

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


InterlockedRead16 (volatile gint16 * src)
{
  gint16 D.21707;
  short unsigned int D.21708;

  D.21708 = __sync_fetch_and_add_2 (src, 0);
  D.21707 = (gint16) D.21708;
  return D.21707;
}


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

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


InterlockedRead (volatile gint32 * src)
{
  gint32 D.21712;
  unsigned int D.21713;

  D.21713 = __sync_fetch_and_add_4 (src, 0);
  D.21712 = (gint32) D.21713;
  return D.21712;
}


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

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


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

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


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

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


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

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


ves_icall_System_Threading_Volatile_ReadFloat (void * ptr)
{
  int D.21725;
  float D.21726;
  union IntFloatUnion u;

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


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

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


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

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


InterlockedWrite8 (volatile gint8 * dst, gint8 val)
{
  unsigned char val.74;
  int D.21733;
  unsigned char old_val.75;
  int D.21735;
  unsigned char D.21736;
  signed char D.21737;
  gint8 old_val;

  <D.18820>:
  old_val = *dst;
  val.74 = (unsigned char) val;
  D.21733 = (int) val.74;
  old_val.75 = (unsigned char) old_val;
  D.21735 = (int) old_val.75;
  D.21736 = __sync_val_compare_and_swap_1 (dst, D.21735, D.21733);
  D.21737 = (signed char) D.21736;
  if (D.21737 != old_val) goto <D.18820>; else goto <D.18821>;
  <D.18821>:
}


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

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


InterlockedWrite16 (volatile gint16 * dst, gint16 val)
{
  short unsigned int val.76;
  int D.21740;
  short unsigned int old_val.77;
  int D.21742;
  short unsigned int D.21743;
  short int D.21744;
  gint16 old_val;

  <D.18827>:
  old_val = *dst;
  val.76 = (short unsigned int) val;
  D.21740 = (int) val.76;
  old_val.77 = (short unsigned int) old_val;
  D.21742 = (int) old_val.77;
  D.21743 = __sync_val_compare_and_swap_2 (dst, D.21742, D.21740);
  D.21744 = (short int) D.21743;
  if (D.21744 != old_val) goto <D.18827>; else goto <D.18828>;
  <D.18828>:
}


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


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

  <D.18834>:
  old_val = *dst;
  val.78 = (unsigned int) val;
  old_val.79 = (unsigned int) old_val;
  D.21747 = __sync_val_compare_and_swap_4 (dst, old_val.79, val.78);
  D.21748 = (int) D.21747;
  if (D.21748 != old_val) goto <D.18834>; else goto <D.18835>;
  <D.18835>:
}


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


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


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


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


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

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


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

  try
    {
      u.fval = value;
      D.21750 = u.ival;
      InterlockedWrite (ptr, D.21750);
    }
  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.21751;
  void (*<Tc2>) (void *) destructor.80;
  int D.21753;
  _Bool D.21754;

  destructor.80 = (void (*<Tc2>) (void *)) destructor;
  D.21753 = pthread_key_create (key, destructor.80);
  D.21754 = D.21753 == 0;
  D.21751 = (int) D.21754;
  return D.21751;
}


mono_thread_init (void (*MonoThreadStartCB) (intptr_t, void *, void *) start_cb, void (*MonoThreadAttachCB) (intptr_t, void *) attach_cb)
{
  void * background_change_event.81;
  void * background_change_event.82;
  _Bool D.21758;
  long int D.21759;
  long int D.21760;

  InitializeCriticalSection (&threads_mutex);
  InitializeCriticalSection (&interlocked_mutex);
  InitializeCriticalSection (&contexts_mutex);
  background_change_event.81 = CreateEvent (0B, 1, 0, 0B);
  background_change_event = background_change_event.81;
  background_change_event.82 = background_change_event;
  D.21758 = background_change_event.82 == 0B;
  D.21759 = (long int) D.21758;
  D.21760 = __builtin_expect (D.21759, 0);
  if (D.21760 != 0) goto <D.21761>; else goto <D.21762>;
  <D.21761>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2657, "background_change_event != NULL");
  <D.21762>:
  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.21763;
  unsigned int D.21764;
  unsigned int current_object_key.83;

  D.21763 = mono_environment_exitcode_get ();
  D.21764 = (unsigned int) D.21763;
  _wapi_thread_signal_self (D.21764);
  current_object_key.83 = current_object_key;
  mono_native_tls_free (current_object_key.83);
}


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


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


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

  D.21766 = thread->internal_thread;
  D.21766->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.21769;
  long int D.21770;
  long int D.21771;
  int shutting_down.84;
  _Bool D.21779;
  long int D.21780;
  long int D.21781;
  unsigned int D.21784;
  unsigned int D.21785;
  unsigned int D.21789;
  unsigned int D.21790;
  void * background_change_event.85;
  _Bool D.21794;
  long int D.21795;
  long int D.21796;
  struct MonoInternalThread * current_thread;

  current_thread = mono_thread_internal_current ();
  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.21767>; else goto <D.21768>;
    <D.21767>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.21768>:
    D.21769 = ret != 0;
    D.21770 = (long int) D.21769;
    D.21771 = __builtin_expect (D.21770, 0);
    if (D.21771 != 0) goto <D.21772>; else goto <D.21773>;
    <D.21772>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2934, "ret == 0");
    <D.21773>:
  }
  shutting_down.84 = shutting_down;
  if (shutting_down.84 != 0) goto <D.21775>; else goto <D.21776>;
  <D.21775>:
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.21777>; else goto <D.21778>;
    <D.21777>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21778>:
    D.21779 = ret != 0;
    D.21780 = (long int) D.21779;
    D.21781 = __builtin_expect (D.21780, 0);
    if (D.21781 != 0) goto <D.21782>; else goto <D.21783>;
    <D.21782>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2937, "ret == 0");
    <D.21783>:
  }
  lock_thread (current_thread);
  D.21784 = BIT_FIELD_REF <*current_thread, 32, 416>;
  D.21785 = D.21784 & 131;
  if (D.21785 != 0) goto <D.21786>; else goto <D.21787>;
  <D.21786>:
  unlock_thread (current_thread);
  mono_thread_execute_interruption (current_thread);
  goto <D.21788>;
  <D.21787>:
  D.21789 = current_thread->state;
  D.21790 = D.21789 | 16;
  current_thread->state = D.21790;
  unlock_thread (current_thread);
  <D.21788>:
  mono_domain_unset ();
  ExitThread (0);
  <D.21776>:
  shutting_down = 1;
  background_change_event.85 = background_change_event;
  SetEvent (background_change_event.85);
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.21792>; else goto <D.21793>;
    <D.21792>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21793>:
    D.21794 = ret != 0;
    D.21795 = (long int) D.21794;
    D.21796 = __builtin_expect (D.21795, 0);
    if (D.21796 != 0) goto <D.21797>; else goto <D.21798>;
    <D.21797>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2967, "ret == 0");
    <D.21798>:
  }
}


mono_thread_manage ()
{
  _Bool D.21801;
  long int D.21802;
  long int D.21803;
  struct MonoGHashTable * threads.86;
  _Bool D.21811;
  long int D.21812;
  long int D.21813;
  _Bool D.21818;
  long int D.21819;
  long int D.21820;
  _Bool D.21825;
  long int D.21826;
  long int D.21827;
  int shutting_down.87;
  _Bool D.21835;
  long int D.21836;
  long int D.21837;
  void * background_change_event.88;
  struct MonoInternalThread *[64] * D.21841;
  _Bool D.21844;
  long int D.21845;
  long int D.21846;
  unsigned int D.21849;
  int D.21852;
  struct MonoInternalThread * D.21855;
  struct MonoInternalThread * D.21856;
  _Bool D.21859;
  long int D.21860;
  long int D.21861;
  _Bool D.21866;
  long int D.21867;
  long int D.21868;
  struct wait_data wait_data;
  struct wait_data * wait;

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

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.21799>; else goto <D.21800>;
        <D.21799>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.21800>:
        D.21801 = ret != 0;
        D.21802 = (long int) D.21801;
        D.21803 = __builtin_expect (D.21802, 0);
        if (D.21803 != 0) goto <D.21804>; else goto <D.21805>;
        <D.21804>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2980, "ret == 0");
        <D.21805>:
      }
      threads.86 = threads;
      if (threads.86 == 0B) goto <D.21807>; else goto <D.21808>;
      <D.21807>:
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.21809>; else goto <D.21810>;
        <D.21809>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.21810>:
        D.21811 = ret != 0;
        D.21812 = (long int) D.21811;
        D.21813 = __builtin_expect (D.21812, 0);
        if (D.21813 != 0) goto <D.21814>; else goto <D.21815>;
        <D.21814>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2983, "ret == 0");
        <D.21815>:
      }
      return;
      <D.21808>:
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.21816>; else goto <D.21817>;
        <D.21816>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.21817>:
        D.21818 = ret != 0;
        D.21819 = (long int) D.21818;
        D.21820 = __builtin_expect (D.21819, 0);
        if (D.21820 != 0) goto <D.21821>; else goto <D.21822>;
        <D.21821>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2986, "ret == 0");
        <D.21822>:
      }
      <D.19753>:
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.21823>; else goto <D.21824>;
        <D.21823>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.21824>:
        D.21825 = ret != 0;
        D.21826 = (long int) D.21825;
        D.21827 = __builtin_expect (D.21826, 0);
        if (D.21827 != 0) goto <D.21828>; else goto <D.21829>;
        <D.21828>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2989, "ret == 0");
        <D.21829>:
      }
      shutting_down.87 = shutting_down;
      if (shutting_down.87 != 0) goto <D.21831>; else goto <D.21832>;
      <D.21831>:
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.21833>; else goto <D.21834>;
        <D.21833>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.21834>:
        D.21835 = ret != 0;
        D.21836 = (long int) D.21835;
        D.21837 = __builtin_expect (D.21836, 0);
        if (D.21837 != 0) goto <D.21838>; else goto <D.21839>;
        <D.21838>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2992, "ret == 0");
        <D.21839>:
      }
      goto <D.19751>;
      <D.21832>:
      background_change_event.88 = background_change_event;
      ResetEvent (background_change_event.88);
      wait->num = 0;
      D.21841 = &wait->threads;
      memset (D.21841, 0, 512);
      threads.86 = threads;
      mono_g_hash_table_foreach (threads.86, build_wait_tids, wait);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.21842>; else goto <D.21843>;
        <D.21842>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.21843>:
        D.21844 = ret != 0;
        D.21845 = (long int) D.21844;
        D.21846 = __builtin_expect (D.21845, 0);
        if (D.21846 != 0) goto <D.21847>; else goto <D.21848>;
        <D.21847>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3003, "ret == 0");
        <D.21848>:
      }
      D.21849 = wait->num;
      if (D.21849 != 0) goto <D.21850>; else goto <D.21851>;
      <D.21850>:
      wait_for_tids_or_state_change (wait, 4294967295);
      <D.21851>:
      D.21849 = wait->num;
      if (D.21849 != 0) goto <D.19753>; else goto <D.19751>;
      <D.19751>:
      D.21852 = mono_runtime_try_shutdown ();
      if (D.21852 == 0) goto <D.21853>; else goto <D.21854>;
      <D.21853>:
      D.21855 = mono_thread_internal_current ();
      mono_thread_suspend (D.21855);
      D.21856 = mono_thread_internal_current ();
      mono_thread_execute_interruption (D.21856);
      <D.21854>:
      <D.19756>:
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.21857>; else goto <D.21858>;
        <D.21857>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.21858>:
        D.21859 = ret != 0;
        D.21860 = (long int) D.21859;
        D.21861 = __builtin_expect (D.21860, 0);
        if (D.21861 != 0) goto <D.21862>; else goto <D.21863>;
        <D.21862>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3023, "ret == 0");
        <D.21863>:
      }
      wait->num = 0;
      D.21841 = &wait->threads;
      memset (D.21841, 0, 512);
      threads.86 = threads;
      mono_g_hash_table_foreach_remove (threads.86, remove_and_abort_threads, wait);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.21864>; else goto <D.21865>;
        <D.21864>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.21865>:
        D.21866 = ret != 0;
        D.21867 = (long int) D.21866;
        D.21868 = __builtin_expect (D.21867, 0);
        if (D.21868 != 0) goto <D.21869>; else goto <D.21870>;
        <D.21869>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3030, "ret == 0");
        <D.21870>:
      }
      D.21849 = wait->num;
      if (D.21849 != 0) goto <D.21871>; else goto <D.21872>;
      <D.21871>:
      wait_for_tids (wait, 4294967295);
      <D.21872>:
      D.21849 = wait->num;
      if (D.21849 != 0) goto <D.19756>; else goto <D.19757>;
      <D.19757>:
      sched_yield ();
    }
  finally
    {
      wait_data = {CLOBBER};
    }
}


remove_and_abort_threads (void * key, void * value, void * user)
{
  unsigned int D.21876;
  gboolean D.21879;
  long unsigned int D.21880;
  unsigned int D.21883;
  unsigned int D.21884;
  long unsigned int D.21887;
  long unsigned int D.21888;
  void * D.21893;
  unsigned int D.21894;
  int iftmp.89;
  int D.21899;
  struct wait_data * wait;
  gsize self;
  struct MonoInternalThread * thread;
  void * handle;

  wait = user;
  self = GetCurrentThreadId ();
  thread = value;
  D.21876 = wait->num;
  if (D.21876 > 63) goto <D.21877>; else goto <D.21878>;
  <D.21877>:
  D.21879 = 0;
  return D.21879;
  <D.21878>:
  D.21880 = thread->tid;
  if (D.21880 != self) goto <D.21881>; else goto <D.21882>;
  <D.21881>:
  D.21883 = thread->state;
  D.21884 = D.21883 & 4;
  if (D.21884 != 0) goto <D.21885>; else goto <D.21886>;
  <D.21885>:
  D.21887 = thread->flags;
  D.21888 = D.21887 & 1;
  if (D.21888 == 0) goto <D.21889>; else goto <D.21890>;
  <D.21889>:
  D.21880 = thread->tid;
  handle = OpenThread (2032639, 1, D.21880);
  if (handle == 0B) goto <D.21891>; else goto <D.21892>;
  <D.21891>:
  D.21879 = 0;
  return D.21879;
  <D.21892>:
  D.21876 = wait->num;
  D.21893 = thread->handle;
  wait->handles[D.21876] = D.21893;
  D.21876 = wait->num;
  wait->threads[D.21876] = thread;
  D.21876 = wait->num;
  D.21894 = D.21876 + 1;
  wait->num = D.21894;
  mono_thread_internal_stop (thread);
  D.21879 = 1;
  return D.21879;
  <D.21890>:
  <D.21886>:
  <D.21882>:
  D.21880 = thread->tid;
  if (D.21880 != self) goto <D.21898>; else goto <D.21896>;
  <D.21898>:
  D.21899 = mono_gc_is_finalizer_internal_thread (thread);
  if (D.21899 == 0) goto <D.21900>; else goto <D.21896>;
  <D.21900>:
  iftmp.89 = 1;
  goto <D.21897>;
  <D.21896>:
  iftmp.89 = 0;
  <D.21897>:
  D.21879 = iftmp.89;
  return D.21879;
}


build_wait_tids (void * key, void * value, void * user)
{
  unsigned int D.21902;
  unsigned int D.21905;
  unsigned int D.21906;
  int D.21909;
  struct MonoInternalThread * D.21912;
  struct MonoThread * D.21915;
  struct MonoThread * D.21918;
  struct _MonoInternalThread * D.21919;
  long unsigned int D.21922;
  long unsigned int D.21923;
  long unsigned int D.21926;
  mono_bool (*<T1ccc>) (struct MonoThread *) D.21931;
  struct MonoThread * D.21933;
  int D.21934;
  unsigned int D.21935;
  struct wait_data * wait;

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

    thread = value;
    D.21905 = thread->state;
    D.21906 = D.21905 & 4;
    if (D.21906 != 0) goto <D.21907>; else goto <D.21908>;
    <D.21907>:
    return;
    <D.21908>:
    D.21909 = mono_gc_is_finalizer_internal_thread (thread);
    if (D.21909 != 0) goto <D.21910>; else goto <D.21911>;
    <D.21910>:
    return;
    <D.21911>:
    D.21912 = mono_thread_internal_current ();
    if (D.21912 == thread) goto <D.21913>; else goto <D.21914>;
    <D.21913>:
    return;
    <D.21914>:
    D.21915 = mono_thread_get_main ();
    if (D.21915 != 0B) goto <D.21916>; else goto <D.21917>;
    <D.21916>:
    D.21918 = mono_thread_get_main ();
    D.21919 = D.21918->internal_thread;
    if (D.21919 == thread) goto <D.21920>; else goto <D.21921>;
    <D.21920>:
    return;
    <D.21921>:
    <D.21917>:
    D.21922 = thread->flags;
    D.21923 = D.21922 & 1;
    if (D.21923 != 0) goto <D.21924>; else goto <D.21925>;
    <D.21924>:
    return;
    <D.21925>:
    D.21926 = thread->tid;
    handle = OpenThread (2032639, 1, D.21926);
    if (handle == 0B) goto <D.21927>; else goto <D.21928>;
    <D.21927>:
    return;
    <D.21928>:
    D.21931 = thread->manage_callback;
    if (D.21931 == 0B) goto <D.21929>; else goto <D.21932>;
    <D.21932>:
    D.21931 = thread->manage_callback;
    D.21933 = thread->root_domain_thread;
    D.21934 = D.21931 (D.21933);
    if (D.21934 == 1) goto <D.21929>; else goto <D.21930>;
    <D.21929>:
    D.21902 = wait->num;
    wait->handles[D.21902] = handle;
    D.21902 = wait->num;
    wait->threads[D.21902] = thread;
    D.21902 = wait->num;
    D.21935 = D.21902 + 1;
    wait->num = D.21935;
    <D.21930>:
  }
  goto <D.21936>;
  <D.21904>:
  <D.21936>:
}


wait_for_tids_or_state_change (struct wait_data * wait, guint32 timeout)
{
  void * background_change_event.90;
  void *[64] * D.21941;
  void * D.21944;
  unsigned int D.21945;
  struct MonoInternalThread * D.21950;
  _Bool D.21953;
  long int D.21954;
  long int D.21955;
  const void * tid.91;
  struct MonoGHashTable * threads.92;
  void * D.21960;
  _Bool D.21965;
  long int D.21966;
  long int D.21967;
  _Bool D.21973;
  long int D.21974;
  long int D.21975;
  guint32 i;
  guint32 ret;
  guint32 count;

  count = wait->num;
  if (count <= 63) goto <D.21938>; else goto <D.21939>;
  <D.21938>:
  background_change_event.90 = background_change_event;
  wait->handles[count] = background_change_event.90;
  count = count + 1;
  <D.21939>:
  D.21941 = &wait->handles;
  ret = WaitForMultipleObjectsEx (count, D.21941, 0, timeout, 1);
  if (ret == 4294967295) goto <D.21942>; else goto <D.21943>;
  <D.21942>:
  return;
  <D.21943>:
  i = 0;
  goto <D.19711>;
  <D.19710>:
  D.21944 = wait->handles[i];
  CloseHandle (D.21944);
  i = i + 1;
  <D.19711>:
  D.21945 = wait->num;
  if (D.21945 > i) goto <D.19710>; else goto <D.19712>;
  <D.19712>:
  if (ret == 258) goto <D.21946>; else goto <D.21947>;
  <D.21946>:
  return;
  <D.21947>:
  D.21945 = wait->num;
  if (D.21945 > ret) goto <D.21948>; else goto <D.21949>;
  <D.21948>:
  {
    gsize tid;

    D.21950 = wait->threads[ret];
    tid = D.21950->tid;
    {
      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", 2819, "ret == 0");
      <D.21957>:
    }
    tid.91 = (const void *) tid;
    threads.92 = threads;
    D.21960 = mono_g_hash_table_lookup (threads.92, tid.91);
    if (D.21960 != 0B) goto <D.21961>; else goto <D.21962>;
    <D.21961>:
    {
      int ret;

      ret = pthread_mutex_unlock (&threads_mutex.mutex);
      if (ret != 0) goto <D.21963>; else goto <D.21964>;
      <D.21963>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.21964>:
      D.21965 = ret != 0;
      D.21966 = (long int) D.21965;
      D.21967 = __builtin_expect (D.21966, 0);
      if (D.21967 != 0) goto <D.21968>; else goto <D.21969>;
      <D.21968>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2822, "ret == 0");
      <D.21969>:
    }
    D.21950 = wait->threads[ret];
    thread_cleanup (D.21950);
    goto <D.21970>;
    <D.21962>:
    {
      int ret;

      ret = pthread_mutex_unlock (&threads_mutex.mutex);
      if (ret != 0) goto <D.21971>; else goto <D.21972>;
      <D.21971>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.21972>:
      D.21973 = ret != 0;
      D.21974 = (long int) D.21973;
      D.21975 = __builtin_expect (D.21974, 0);
      if (D.21975 != 0) goto <D.21976>; else goto <D.21977>;
      <D.21976>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2826, "ret == 0");
      <D.21977>:
    }
    <D.21970>:
  }
  <D.21949>:
}


memset (void * __dest, int __ch, size_t __len)
{
  int D.21981;
  int D.21986;
  void * D.21988;
  long unsigned int D.21989;

  D.21981 = __builtin_constant_p (__len);
  if (D.21981 != 0) goto <D.21982>; else goto <D.21983>;
  <D.21982>:
  if (__len == 0) goto <D.21984>; else goto <D.21985>;
  <D.21984>:
  D.21986 = __builtin_constant_p (__ch);
  if (D.21986 == 0) goto <D.21979>; else goto <D.21987>;
  <D.21987>:
  if (__ch != 0) goto <D.21979>; else goto <D.21980>;
  <D.21979>:
  __warn_memset_zero_len ();
  D.21988 = __dest;
  return D.21988;
  <D.21980>:
  <D.21985>:
  <D.21983>:
  D.21989 = __builtin_object_size (__dest, 0);
  D.21988 = __builtin___memset_chk (__dest, __ch, __len, D.21989);
  return D.21988;
}


wait_for_tids (struct wait_data * wait, guint32 timeout)
{
  void *[64] * D.21991;
  unsigned int D.21992;
  void * D.21995;
  struct MonoInternalThread * D.21998;
  _Bool D.22001;
  long int D.22002;
  long int D.22003;
  const void * tid.93;
  struct MonoGHashTable * threads.94;
  void * D.22008;
  _Bool D.22013;
  long int D.22014;
  long int D.22015;
  _Bool D.22021;
  long int D.22022;
  long int D.22023;
  guint32 i;
  guint32 ret;

  D.21991 = &wait->handles;
  D.21992 = wait->num;
  ret = WaitForMultipleObjectsEx (D.21992, D.21991, 1, timeout, 1);
  if (ret == 4294967295) goto <D.21993>; else goto <D.21994>;
  <D.21993>:
  return;
  <D.21994>:
  i = 0;
  goto <D.19694>;
  <D.19693>:
  D.21995 = wait->handles[i];
  CloseHandle (D.21995);
  i = i + 1;
  <D.19694>:
  D.21992 = wait->num;
  if (D.21992 > i) goto <D.19693>; else goto <D.19695>;
  <D.19695>:
  if (ret == 258) goto <D.21996>; else goto <D.21997>;
  <D.21996>:
  return;
  <D.21997>:
  i = 0;
  goto <D.19701>;
  <D.19700>:
  {
    gsize tid;

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

      ret = pthread_mutex_lock (&threads_mutex.mutex);
      if (ret != 0) goto <D.21999>; else goto <D.22000>;
      <D.21999>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
      <D.22000>:
      D.22001 = ret != 0;
      D.22002 = (long int) D.22001;
      D.22003 = __builtin_expect (D.22002, 0);
      if (D.22003 != 0) goto <D.22004>; else goto <D.22005>;
      <D.22004>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2766, "ret == 0");
      <D.22005>:
    }
    tid.93 = (const void *) tid;
    threads.94 = threads;
    D.22008 = mono_g_hash_table_lookup (threads.94, tid.93);
    if (D.22008 != 0B) goto <D.22009>; else goto <D.22010>;
    <D.22009>:
    {
      int ret;

      ret = pthread_mutex_unlock (&threads_mutex.mutex);
      if (ret != 0) goto <D.22011>; else goto <D.22012>;
      <D.22011>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.22012>:
      D.22013 = ret != 0;
      D.22014 = (long int) D.22013;
      D.22015 = __builtin_expect (D.22014, 0);
      if (D.22015 != 0) goto <D.22016>; else goto <D.22017>;
      <D.22016>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2779, "ret == 0");
      <D.22017>:
    }
    D.21998 = wait->threads[i];
    thread_cleanup (D.21998);
    goto <D.22018>;
    <D.22010>:
    {
      int ret;

      ret = pthread_mutex_unlock (&threads_mutex.mutex);
      if (ret != 0) goto <D.22019>; else goto <D.22020>;
      <D.22019>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.22020>:
      D.22021 = ret != 0;
      D.22022 = (long int) D.22021;
      D.22023 = __builtin_expect (D.22022, 0);
      if (D.22023 != 0) goto <D.22024>; else goto <D.22025>;
      <D.22024>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 2783, "ret == 0");
      <D.22025>:
    }
    <D.22018>:
  }
  i = i + 1;
  <D.19701>:
  D.21992 = wait->num;
  if (D.21992 > i) goto <D.19700>; else goto <D.19702>;
  <D.19702>:
}


mono_thread_abort_all_other_threads ()
{
  _Bool D.22029;
  long int D.22030;
  long int D.22031;
  void * self.95;
  struct MonoGHashTable * threads.96;
  _Bool D.22038;
  long int D.22039;
  long int D.22040;
  gsize self;

  self = GetCurrentThreadId ();
  {
    int ret;

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

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22036>; else goto <D.22037>;
    <D.22036>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.22037>:
    D.22038 = ret != 0;
    D.22039 = (long int) D.22038;
    D.22040 = __builtin_expect (D.22039, 0);
    if (D.22040 != 0) goto <D.22041>; else goto <D.22042>;
    <D.22041>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3069, "ret == 0");
    <D.22042>:
  }
}


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

  thread = value;
  D.22043 = thread->tid;
  user.97 = (long unsigned int) user;
  if (D.22043 != user.97) goto <D.22045>; else goto <D.22046>;
  <D.22045>:
  <D.22046>:
}


mono_thread_suspend_all_other_threads ()
{
  int shutting_down.98;
  _Bool D.22048;
  long int D.22049;
  long int D.22050;
  struct MonoInternalThread *[64] * D.22053;
  _Bool D.22056;
  long int D.22057;
  long int D.22058;
  struct MonoGHashTable * threads.99;
  _Bool D.22064;
  long int D.22065;
  long int D.22066;
  unsigned int D.22069;
  long unsigned int D.22070;
  long unsigned int D.22071;
  long unsigned int D.22074;
  int D.22076;
  long unsigned int D.22078;
  long unsigned int D.22079;
  void * D.22080;
  void * D.22083;
  unsigned int D.22086;
  unsigned int D.22087;
  void * D.22090;
  unsigned int D.22091;
  unsigned int D.22092;
  unsigned int eventidx.100;
  long unsigned int D.22096;
  long unsigned int D.22097;
  void * * D.22098;
  unsigned int D.22099;
  unsigned int D.22102;
  unsigned int D.22103;
  int D.22104;
  unsigned int i.101;
  int D.22113;
  unsigned int D.22118;
  unsigned int D.22119;
  void * D.22122;
  _Bool D.22127;
  long int D.22128;
  long int D.22129;
  struct MonoGHashTable * threads_starting_up.102;
  unsigned int D.22135;
  _Bool D.22136;
  _Bool D.22140;
  long int D.22141;
  long int D.22142;
  struct wait_data wait_data;
  struct wait_data * wait;
  int i;
  gsize self;
  void * * events;
  guint32 eventidx;
  gboolean starting;
  gboolean finished;

  try
    {
      wait = &wait_data;
      self = GetCurrentThreadId ();
      eventidx = 0;
      memset (wait, 0, 1032);
      shutting_down.98 = shutting_down;
      D.22048 = shutting_down.98 == 0;
      D.22049 = (long int) D.22048;
      D.22050 = __builtin_expect (D.22049, 0);
      if (D.22050 != 0) goto <D.22051>; else goto <D.22052>;
      <D.22051>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3128, "shutting_down");
      <D.22052>:
      finished = 0;
      goto <D.19805>;
      <D.19804>:
      wait->num = 0;
      D.22053 = &wait->threads;
      memset (D.22053, 0, 512);
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22054>; else goto <D.22055>;
        <D.22054>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.22055>:
        D.22056 = ret != 0;
        D.22057 = (long int) D.22056;
        D.22058 = __builtin_expect (D.22057, 0);
        if (D.22058 != 0) goto <D.22059>; else goto <D.22060>;
        <D.22059>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3144, "ret == 0");
        <D.22060>:
      }
      threads.99 = threads;
      mono_g_hash_table_foreach (threads.99, collect_threads_for_suspend, wait);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22062>; else goto <D.22063>;
        <D.22062>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.22063>:
        D.22064 = ret != 0;
        D.22065 = (long int) D.22064;
        D.22066 = __builtin_expect (D.22065, 0);
        if (D.22066 != 0) goto <D.22067>; else goto <D.22068>;
        <D.22067>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3146, "ret == 0");
        <D.22068>:
      }
      D.22069 = wait->num;
      D.22070 = (long unsigned int) D.22069;
      D.22071 = D.22070 * 8;
      events = monoeg_malloc0 (D.22071);
      eventidx = 0;
      i = 0;
      goto <D.19795>;
      <D.19794>:
      {
        struct MonoInternalThread * thread;
        gboolean signal_suspend;

        thread = wait->threads[i];
        signal_suspend = 0;
        D.22074 = thread->tid;
        if (D.22074 == self) goto <D.22072>; else goto <D.22075>;
        <D.22075>:
        D.22076 = mono_gc_is_finalizer_internal_thread (thread);
        if (D.22076 != 0) goto <D.22072>; else goto <D.22077>;
        <D.22077>:
        D.22078 = thread->flags;
        D.22079 = D.22078 & 1;
        if (D.22079 != 0) goto <D.22072>; else goto <D.22073>;
        <D.22072>:
        wait->threads[i] = 0B;
        // predicted unlikely by continue predictor.
        goto <D.19793>;
        <D.22073>:
        lock_thread (thread);
        D.22080 = thread->suspended_event;
        if (D.22080 == 0B) goto <D.22081>; else goto <D.22082>;
        <D.22081>:
        D.22083 = CreateEvent (0B, 1, 0, 0B);
        thread->suspended_event = D.22083;
        D.22080 = thread->suspended_event;
        if (D.22080 == 0B) goto <D.22084>; else goto <D.22085>;
        <D.22084>:
        unlock_thread (thread);
        // predicted unlikely by continue predictor.
        goto <D.19793>;
        <D.22085>:
        <D.22082>:
        D.22086 = BIT_FIELD_REF <*thread, 32, 416>;
        D.22087 = D.22086 & 81;
        if (D.22087 != 0) goto <D.22088>; else goto <D.22089>;
        <D.22088>:
        unlock_thread (thread);
        D.22090 = wait->handles[i];
        CloseHandle (D.22090);
        wait->threads[i] = 0B;
        // predicted unlikely by continue predictor.
        goto <D.19793>;
        <D.22089>:
        D.22091 = thread->state;
        D.22092 = D.22091 & 2;
        if (D.22092 == 0) goto <D.22093>; else goto <D.22094>;
        <D.22093>:
        signal_suspend = 1;
        <D.22094>:
        eventidx.100 = eventidx;
        eventidx = eventidx.100 + 1;
        D.22096 = (long unsigned int) eventidx.100;
        D.22097 = D.22096 * 8;
        D.22098 = events + D.22097;
        D.22080 = thread->suspended_event;
        *D.22098 = D.22080;
        D.22091 = thread->state;
        D.22099 = D.22091 & 128;
        if (D.22099 != 0) goto <D.22100>; else goto <D.22101>;
        <D.22100>:
        D.22091 = thread->state;
        D.22102 = D.22091 & 4294967167;
        thread->state = D.22102;
        <D.22101>:
        D.22091 = thread->state;
        D.22103 = D.22091 | 2;
        thread->state = D.22103;
        unlock_thread (thread);
        D.22104 = mono_thread_info_new_interrupt_enabled ();
        if (D.22104 != 0) goto <D.22105>; else goto <D.22106>;
        <D.22105>:
        suspend_thread_internal (thread, 1);
        goto <D.22107>;
        <D.22106>:
        if (signal_suspend != 0) goto <D.22108>; else goto <D.22109>;
        <D.22108>:
        signal_thread_state_change (thread);
        <D.22109>:
        <D.22107>:
      }
      <D.19793>:
      i = i + 1;
      <D.19795>:
      i.101 = (unsigned int) i;
      D.22069 = wait->num;
      if (i.101 < D.22069) goto <D.19794>; else goto <D.19796>;
      <D.19796>:
      if (eventidx != 0) goto <D.22111>; else goto <D.22112>;
      <D.22111>:
      D.22113 = mono_thread_info_new_interrupt_enabled ();
      if (D.22113 == 0) goto <D.22114>; else goto <D.22115>;
      <D.22114>:
      WaitForMultipleObjectsEx (eventidx, events, 1, 100, 0);
      i = 0;
      goto <D.19800>;
      <D.19799>:
      {
        struct MonoInternalThread * thread;

        thread = wait->threads[i];
        if (thread == 0B) goto <D.22116>; else goto <D.22117>;
        <D.22116>:
        // predicted unlikely by continue predictor.
        goto <D.19798>;
        <D.22117>:
        lock_thread (thread);
        D.22118 = thread->state;
        D.22119 = D.22118 & 64;
        if (D.22119 != 0) goto <D.22120>; else goto <D.22121>;
        <D.22120>:
        D.22122 = thread->suspended_event;
        CloseHandle (D.22122);
        thread->suspended_event = 0B;
        <D.22121>:
        unlock_thread (thread);
      }
      <D.19798>:
      i = i + 1;
      <D.19800>:
      i.101 = (unsigned int) i;
      D.22069 = wait->num;
      if (i.101 < D.22069) goto <D.19799>; else goto <D.19801>;
      <D.19801>:
      <D.22115>:
      <D.22112>:
      if (eventidx == 0) goto <D.22123>; else goto <D.22124>;
      <D.22123>:
      {
        int ret;

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22125>; else goto <D.22126>;
        <D.22125>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.22126>:
        D.22127 = ret != 0;
        D.22128 = (long int) D.22127;
        D.22129 = __builtin_expect (D.22128, 0);
        if (D.22129 != 0) goto <D.22130>; else goto <D.22131>;
        <D.22130>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3227, "ret == 0");
        <D.22131>:
      }
      threads_starting_up.102 = threads_starting_up;
      if (threads_starting_up.102 != 0B) goto <D.22133>; else goto <D.22134>;
      <D.22133>:
      threads_starting_up.102 = threads_starting_up;
      D.22135 = mono_g_hash_table_size (threads_starting_up.102);
      D.22136 = D.22135 != 0;
      starting = (gboolean) D.22136;
      goto <D.22137>;
      <D.22134>:
      starting = 0;
      <D.22137>:
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22138>; else goto <D.22139>;
        <D.22138>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.22139>:
        D.22140 = ret != 0;
        D.22141 = (long int) D.22140;
        D.22142 = __builtin_expect (D.22141, 0);
        if (D.22142 != 0) goto <D.22143>; else goto <D.22144>;
        <D.22143>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3232, "ret == 0");
        <D.22144>:
      }
      if (starting != 0) goto <D.22145>; else goto <D.22146>;
      <D.22145>:
      Sleep (100);
      goto <D.22147>;
      <D.22146>:
      finished = 1;
      <D.22147>:
      <D.22124>:
      monoeg_g_free (events);
      <D.19805>:
      if (finished == 0) goto <D.19804>; else goto <D.19806>;
      <D.19806>:
    }
  finally
    {
      wait_data = {CLOBBER};
    }
}


collect_threads_for_suspend (void * key, void * value, void * user_data)
{
  unsigned int D.22148;
  unsigned int D.22149;
  unsigned int D.22152;
  long unsigned int D.22155;
  unsigned int D.22158;
  struct MonoInternalThread * thread;
  struct wait_data * wait;
  void * handle;

  thread = value;
  wait = user_data;
  D.22148 = BIT_FIELD_REF <*thread, 32, 416>;
  D.22149 = D.22148 & 80;
  if (D.22149 != 0) goto <D.22150>; else goto <D.22151>;
  <D.22150>:
  return;
  <D.22151>:
  D.22152 = wait->num;
  if (D.22152 <= 63) goto <D.22153>; else goto <D.22154>;
  <D.22153>:
  D.22155 = thread->tid;
  handle = OpenThread (2032639, 1, D.22155);
  if (handle == 0B) goto <D.22156>; else goto <D.22157>;
  <D.22156>:
  return;
  <D.22157>:
  D.22152 = wait->num;
  wait->handles[D.22152] = handle;
  D.22152 = wait->num;
  wait->threads[D.22152] = thread;
  D.22152 = wait->num;
  D.22158 = D.22152 + 1;
  wait->num = D.22158;
  <D.22154>:
}


mono_threads_perform_thread_dump ()
{
  int thread_dump_requested.103;
  _Bool D.22165;
  long int D.22166;
  long int D.22167;
  struct MonoGHashTable * threads.104;
  _Bool D.22173;
  long int D.22174;
  long int D.22175;

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

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22163>; else goto <D.22164>;
    <D.22163>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.22164>:
    D.22165 = ret != 0;
    D.22166 = (long int) D.22165;
    D.22167 = __builtin_expect (D.22166, 0);
    if (D.22167 != 0) goto <D.22168>; else goto <D.22169>;
    <D.22168>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3357, "ret == 0");
    <D.22169>:
  }
  threads.104 = threads;
  mono_g_hash_table_foreach (threads.104, dump_thread, 0B);
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22171>; else goto <D.22172>;
    <D.22171>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.22172>:
    D.22173 = ret != 0;
    D.22174 = (long int) D.22173;
    D.22175 = __builtin_expect (D.22174, 0);
    if (D.22175 != 0) goto <D.22176>; else goto <D.22177>;
    <D.22176>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3359, "ret == 0");
    <D.22177>:
  }
  thread_dump_requested = 0;
}


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

  thread = value;
  D.22179 = mono_thread_internal_current ();
  if (D.22179 == thread) goto <D.22180>; else goto <D.22181>;
  <D.22180>:
  return;
  <D.22181>:
  D.22182 = thread->tid;
  info = mono_thread_info_safe_suspend_sync (D.22182, 0);
  if (info == 0B) goto <D.22183>; else goto <D.22184>;
  <D.22183>:
  return;
  <D.22184>:
  print_thread_dump (thread, info);
}


print_thread_dump (struct MonoInternalThread * thread, struct MonoThreadInfo * info)
{
  gunichar2 * D.22186;
  unsigned int D.22189;
  long int D.22190;
  struct GError * error.105;
  _Bool D.22192;
  long int D.22193;
  long int D.22194;
  unsigned char D.22198;
  struct MonoRuntimeExceptionHandlingCallbacks * D.22202;
  void (*<T270a>) (gboolean (*MonoInternalStackWalk) (struct MonoStackFrameInfo *, struct MonoContext *, void *), struct MonoThreadUnwindState *, MonoUnwindOptions, void *) D.22203;
  struct MonoThreadUnwindState * D.22204;
  long unsigned int D.22205;
  char * D.22206;
  struct _IO_FILE * stdout.106;
  struct GString * text;
  char * name;
  struct GError * error;

  try
    {
      text = monoeg_g_string_new (0B);
      error = 0B;
      D.22186 = thread->name;
      if (D.22186 != 0B) goto <D.22187>; else goto <D.22188>;
      <D.22187>:
      D.22189 = thread->name_len;
      D.22190 = (long int) D.22189;
      D.22186 = thread->name;
      name = monoeg_g_utf16_to_utf8 (D.22186, D.22190, 0B, 0B, &error);
      error.105 = error;
      D.22192 = error.105 != 0B;
      D.22193 = (long int) D.22192;
      D.22194 = __builtin_expect (D.22193, 0);
      if (D.22194 != 0) goto <D.22195>; else goto <D.22196>;
      <D.22195>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3290, "!error");
      <D.22196>:
      monoeg_g_string_append_printf (text, "\n\"%s\"", name);
      monoeg_g_free (name);
      goto <D.22197>;
      <D.22188>:
      D.22198 = thread->threadpool_thread;
      if (D.22198 != 0) goto <D.22199>; else goto <D.22200>;
      <D.22199>:
      monoeg_g_string_append (text, "\n\"<threadpool thread>\"");
      goto <D.22201>;
      <D.22200>:
      monoeg_g_string_append (text, "\n\"<unnamed thread>\"");
      <D.22201>:
      <D.22197>:
      D.22202 = mono_get_eh_callbacks ();
      D.22203 = D.22202->mono_walk_stack_with_state;
      D.22204 = &info->suspend_state;
      D.22203 (print_stack_frame_to_string, D.22204, 0, text);
      D.22205 = info->node.key;
      mono_thread_info_resume (D.22205);
      D.22206 = text->str;
      stdout.106 = stdout;
      fprintf (stdout.106, "%s", D.22206);
      monoeg_g_string_free (text, 1);
      stdout.106 = stdout;
      fflush (stdout.106);
    }
  finally
    {
      error = {CLOBBER};
    }
}


print_stack_frame_to_string (struct MonoStackFrameInfo * frame, struct MonoContext * ctx, void * data)
{
  struct MonoJitInfo * D.22208;
  struct MonoDomain * D.22213;
  int D.22214;
  unsigned int D.22215;
  gboolean D.22217;
  struct GString * p;
  struct MonoMethod * method;

  p = data;
  method = 0B;
  D.22208 = frame->ji;
  if (D.22208 != 0B) goto <D.22209>; else goto <D.22210>;
  <D.22209>:
  D.22208 = frame->ji;
  method = mono_jit_info_get_method (D.22208);
  <D.22210>:
  if (method != 0B) goto <D.22211>; else goto <D.22212>;
  <D.22211>:
  {
    gchar * location;

    D.22213 = frame->domain;
    D.22214 = frame->native_offset;
    D.22215 = (unsigned int) D.22214;
    location = mono_debug_print_stack_frame (method, D.22215, D.22213);
    monoeg_g_string_append_printf (p, "  %s\n", location);
    monoeg_g_free (location);
  }
  goto <D.22216>;
  <D.22212>:
  D.22214 = frame->native_offset;
  monoeg_g_string_append_printf (p, "  at <unknown> <0x%05x>\n", D.22214);
  <D.22216>:
  D.22217 = 0;
  return D.22217;
}


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

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


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

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


mono_threads_request_thread_dump ()
{
  int D.22223;
  _Bool D.22228;
  long int D.22229;
  long int D.22230;
  struct MonoGHashTable * threads.107;
  _Bool D.22236;
  long int D.22237;
  long int D.22238;
  int D.22241;
  struct MonoInternalThread * D.22244;
  unsigned char D.22247;
  void * D.22250;
  unsigned int i.108;
  unsigned int D.22252;
  struct wait_data wait_data;
  struct wait_data * wait;
  int i;

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

        ret = pthread_mutex_lock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22226>; else goto <D.22227>;
        <D.22226>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.22227>:
        D.22228 = ret != 0;
        D.22229 = (long int) D.22228;
        D.22230 = __builtin_expect (D.22229, 0);
        if (D.22230 != 0) goto <D.22231>; else goto <D.22232>;
        <D.22231>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3390, "ret == 0");
        <D.22232>:
      }
      threads.107 = threads;
      mono_g_hash_table_foreach (threads.107, collect_threads, wait);
      {
        int ret;

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22234>; else goto <D.22235>;
        <D.22234>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.22235>:
        D.22236 = ret != 0;
        D.22237 = (long int) D.22236;
        D.22238 = __builtin_expect (D.22237, 0);
        if (D.22238 != 0) goto <D.22239>; else goto <D.22240>;
        <D.22239>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3392, "ret == 0");
        <D.22240>:
      }
      i = 0;
      goto <D.19853>;
      <D.19852>:
      {
        struct MonoInternalThread * thread;

        thread = wait->threads[i];
        D.22241 = mono_gc_is_finalizer_internal_thread (thread);
        if (D.22241 == 0) goto <D.22242>; else goto <D.22243>;
        <D.22242>:
        D.22244 = mono_thread_internal_current ();
        if (D.22244 != thread) goto <D.22245>; else goto <D.22246>;
        <D.22245>:
        D.22247 = thread->thread_dump_requested;
        if (D.22247 == 0) goto <D.22248>; else goto <D.22249>;
        <D.22248>:
        thread->thread_dump_requested = 1;
        signal_thread_state_change (thread);
        <D.22249>:
        <D.22246>:
        <D.22243>:
        D.22250 = wait->handles[i];
        CloseHandle (D.22250);
      }
      i = i + 1;
      <D.19853>:
      i.108 = (unsigned int) i;
      D.22252 = wait->num;
      if (i.108 < D.22252) goto <D.19852>; else goto <D.19854>;
      <D.19854>:
    }
  finally
    {
      wait_data = {CLOBBER};
    }
}


collect_threads (void * key, void * value, void * user_data)
{
  unsigned int D.22256;
  long unsigned int D.22259;
  unsigned int D.22262;
  struct MonoInternalThread * thread;
  struct wait_data * wait;
  void * handle;

  thread = value;
  wait = user_data;
  D.22256 = wait->num;
  if (D.22256 <= 63) goto <D.22257>; else goto <D.22258>;
  <D.22257>:
  D.22259 = thread->tid;
  handle = OpenThread (2032639, 1, D.22259);
  if (handle == 0B) goto <D.22260>; else goto <D.22261>;
  <D.22260>:
  return;
  <D.22261>:
  D.22256 = wait->num;
  wait->handles[D.22256] = handle;
  D.22256 = wait->num;
  wait->threads[D.22256] = thread;
  D.22256 = wait->num;
  D.22262 = D.22256 + 1;
  wait->num = D.22262;
  <D.22258>:
}


mono_thread_push_appdomain_ref (struct MonoDomain * domain)
{
  volatile int * D.22266;
  int D.22267;
  void * D.22269;
  struct RefStack * D.22272;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  if (thread != 0B) goto <D.22264>; else goto <D.22265>;
  <D.22264>:
  <D.19888>:
  D.22266 = &thread->lock_thread_id;
  D.22267 = InterlockedCompareExchange (D.22266, 1, 0);
  if (D.22267 == 0) goto <D.19887>; else goto <D.22268>;
  <D.22268>:
  goto <D.19888>;
  <D.19887>:
  D.22269 = thread->appdomain_refs;
  if (D.22269 == 0B) goto <D.22270>; else goto <D.22271>;
  <D.22270>:
  D.22272 = ref_stack_new (16);
  thread->appdomain_refs = D.22272;
  <D.22271>:
  D.22269 = thread->appdomain_refs;
  ref_stack_push (D.22269, domain);
  thread->lock_thread_id = 0;
  <D.22265>:
}


ref_stack_new (gint initial_size)
{
  int D.22273;
  long unsigned int D.22274;
  long unsigned int D.22275;
  void * D.22276;
  struct RefStack * D.22277;
  struct RefStack * rs;

  D.22273 = MAX_EXPR <initial_size, 16>;
  initial_size = D.22273 + 1;
  rs = monoeg_malloc0 (16);
  D.22274 = (long unsigned int) initial_size;
  D.22275 = D.22274 * 8;
  D.22276 = monoeg_malloc0 (D.22275);
  rs->refs = D.22276;
  rs->allocated = initial_size;
  D.22277 = rs;
  return D.22277;
}


ref_stack_push (struct RefStack * rs, void * ptr)
{
  _Bool D.22279;
  long int D.22280;
  long int D.22281;
  int D.22284;
  int D.22285;
  int D.22288;
  long unsigned int D.22289;
  long unsigned int D.22290;
  long unsigned int D.22291;
  void * * D.22292;
  void * D.22293;
  int D.22294;
  long unsigned int D.22295;
  long unsigned int D.22296;
  void * * D.22297;
  int D.22298;
  int D.22299;
  long unsigned int D.22300;
  long unsigned int D.22301;
  void * * D.22302;

  D.22279 = rs == 0B;
  D.22280 = (long int) D.22279;
  D.22281 = __builtin_expect (D.22280, 0);
  if (D.22281 != 0) goto <D.22282>; else goto <D.22283>;
  <D.22282>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3443, "rs != NULL");
  <D.22283>:
  D.22284 = rs->bottom;
  D.22285 = rs->allocated;
  if (D.22284 >= D.22285) goto <D.22286>; else goto <D.22287>;
  <D.22286>:
  D.22285 = rs->allocated;
  D.22288 = D.22285 * 2;
  D.22289 = (long unsigned int) D.22288;
  D.22290 = D.22289 * 8;
  D.22291 = D.22290 + 1;
  D.22292 = rs->refs;
  D.22293 = monoeg_realloc (D.22292, D.22291);
  rs->refs = D.22293;
  D.22285 = rs->allocated;
  D.22294 = D.22285 << 1;
  rs->allocated = D.22294;
  D.22292 = rs->refs;
  D.22285 = rs->allocated;
  D.22295 = (long unsigned int) D.22285;
  D.22296 = D.22295 * 8;
  D.22297 = D.22292 + D.22296;
  *D.22297 = 0B;
  <D.22287>:
  D.22292 = rs->refs;
  D.22284 = rs->bottom;
  D.22298 = D.22284;
  D.22299 = D.22298 + 1;
  rs->bottom = D.22299;
  D.22300 = (long unsigned int) D.22298;
  D.22301 = D.22300 * 8;
  D.22302 = D.22292 + D.22301;
  *D.22302 = ptr;
}


mono_thread_pop_appdomain_ref ()
{
  volatile int * D.22305;
  int D.22306;
  void * D.22308;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  if (thread != 0B) goto <D.22303>; else goto <D.22304>;
  <D.22303>:
  <D.19894>:
  D.22305 = &thread->lock_thread_id;
  D.22306 = InterlockedCompareExchange (D.22305, 1, 0);
  if (D.22306 == 0) goto <D.19893>; else goto <D.22307>;
  <D.22307>:
  goto <D.19894>;
  <D.19893>:
  D.22308 = thread->appdomain_refs;
  ref_stack_pop (D.22308);
  thread->lock_thread_id = 0;
  <D.22304>:
}


ref_stack_pop (struct RefStack * rs)
{
  int D.22312;
  int D.22313;
  void * * D.22314;
  long unsigned int D.22315;
  long unsigned int D.22316;
  void * * D.22317;

  if (rs == 0B) goto <D.22309>; else goto <D.22311>;
  <D.22311>:
  D.22312 = rs->bottom;
  if (D.22312 == 0) goto <D.22309>; else goto <D.22310>;
  <D.22309>:
  return;
  <D.22310>:
  D.22312 = rs->bottom;
  D.22313 = D.22312 + -1;
  rs->bottom = D.22313;
  D.22314 = rs->refs;
  D.22312 = rs->bottom;
  D.22315 = (long unsigned int) D.22312;
  D.22316 = D.22315 * 8;
  D.22317 = D.22314 + D.22316;
  *D.22317 = 0B;
}


mono_thread_internal_has_appdomain_ref (struct MonoInternalThread * thread, struct MonoDomain * domain)
{
  volatile int * D.22319;
  int D.22320;
  void * D.22322;
  gboolean D.22323;
  gboolean res;

  <D.19901>:
  D.22319 = &thread->lock_thread_id;
  D.22320 = InterlockedCompareExchange (D.22319, 1, 0);
  if (D.22320 == 0) goto <D.19900>; else goto <D.22321>;
  <D.22321>:
  goto <D.19901>;
  <D.19900>:
  D.22322 = thread->appdomain_refs;
  res = ref_stack_find (D.22322, domain);
  thread->lock_thread_id = 0;
  D.22323 = res;
  return D.22323;
}


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

  if (rs == 0B) goto <D.22325>; else goto <D.22326>;
  <D.22325>:
  D.22327 = 0;
  return D.22327;
  <D.22326>:
  refs = rs->refs;
  goto <D.19881>;
  <D.19880>:
  D.22328 = *refs;
  if (D.22328 == ptr) goto <D.22329>; else goto <D.22330>;
  <D.22329>:
  D.22327 = 1;
  return D.22327;
  <D.22330>:
  refs = refs + 8;
  <D.19881>:
  if (refs != 0B) goto <D.22331>; else goto <D.19882>;
  <D.22331>:
  D.22328 = *refs;
  if (D.22328 != 0B) goto <D.19880>; else goto <D.19882>;
  <D.19882>:
  D.22327 = 0;
  return D.22327;
}


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

  D.22334 = thread->internal_thread;
  D.22333 = mono_thread_internal_has_appdomain_ref (D.22334, domain);
  return D.22333;
}


mono_threads_abort_appdomain_threads (struct MonoDomain * domain, int timeout)
{
  _Bool D.22338;
  long int D.22339;
  long int D.22340;
  struct MonoGHashTable * threads.109;
  _Bool D.22346;
  long int D.22347;
  long int D.22348;
  unsigned int D.22351;
  struct MonoInternalThread * D.22354;
  unsigned int i.110;
  unsigned int D.22356;
  unsigned int D.22357;
  unsigned int timeout.111;
  unsigned int D.22359;
  _Bool D.22360;
  _Bool D.22361;
  _Bool D.22362;
  gboolean D.22365;
  struct abort_appdomain_data user_data;
  guint32 start_time;
  int orig_timeout;
  int i;

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

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

        ret = pthread_mutex_unlock (&threads_mutex.mutex);
        if (ret != 0) goto <D.22344>; else goto <D.22345>;
        <D.22344>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.22345>:
        D.22346 = ret != 0;
        D.22347 = (long int) D.22346;
        D.22348 = __builtin_expect (D.22347, 0);
        if (D.22348 != 0) goto <D.22349>; else goto <D.22350>;
        <D.22349>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3586, "ret == 0");
        <D.22350>:
      }
      D.22351 = user_data.wait.num;
      if (D.22351 != 0) goto <D.22352>; else goto <D.22353>;
      <D.22352>:
      i = 0;
      goto <D.19930>;
      <D.19929>:
      D.22354 = user_data.wait.threads[i];
      ves_icall_System_Threading_Thread_Abort (D.22354, 0B);
      i = i + 1;
      <D.19930>:
      i.110 = (unsigned int) i;
      D.22351 = user_data.wait.num;
      if (i.110 < D.22351) goto <D.19929>; else goto <D.19931>;
      <D.19931>:
      wait_for_tids (&user_data.wait, 100);
      <D.22353>:
      D.22356 = mono_msec_ticks ();
      D.22357 = D.22356 - start_time;
      timeout.111 = (unsigned int) timeout;
      D.22359 = timeout.111 - D.22357;
      timeout = (int) D.22359;
      start_time = mono_msec_ticks ();
      D.22360 = orig_timeout != -1;
      D.22361 = timeout < 0;
      D.22362 = D.22360 & D.22361;
      if (D.22362 != 0) goto <D.22363>; else goto <D.22364>;
      <D.22363>:
      D.22365 = 0;
      return D.22365;
      <D.22364>:
      D.22351 = user_data.wait.num;
      if (D.22351 != 0) goto <D.19932>; else goto <D.19933>;
      <D.19933>:
      D.22365 = 1;
      return D.22365;
    }
  finally
    {
      user_data = {CLOBBER};
    }
}


collect_appdomain_thread (void * key, void * value, void * user_data)
{
  int D.22368;
  unsigned int D.22371;
  long unsigned int D.22374;
  unsigned int D.22377;
  struct MonoInternalThread * thread;
  struct abort_appdomain_data * data;
  struct MonoDomain * domain;

  thread = value;
  data = user_data;
  domain = data->domain;
  D.22368 = mono_thread_internal_has_appdomain_ref (thread, domain);
  if (D.22368 != 0) goto <D.22369>; else goto <D.22370>;
  <D.22369>:
  D.22371 = data->wait.num;
  if (D.22371 <= 63) goto <D.22372>; else goto <D.22373>;
  <D.22372>:
  {
    void * handle;

    D.22374 = thread->tid;
    handle = OpenThread (2032639, 1, D.22374);
    if (handle == 0B) goto <D.22375>; else goto <D.22376>;
    <D.22375>:
    return;
    <D.22376>:
    D.22371 = data->wait.num;
    data->wait.handles[D.22371] = handle;
    D.22371 = data->wait.num;
    data->wait.threads[D.22371] = thread;
    D.22371 = data->wait.num;
    D.22377 = D.22371 + 1;
    data->wait.num = D.22377;
  }
  goto <D.22378>;
  <D.22373>:
  <D.22378>:
  <D.22370>:
}


mono_threads_clear_cached_culture (struct MonoDomain * domain)
{
  _Bool D.22382;
  long int D.22383;
  long int D.22384;
  struct MonoGHashTable * threads.112;
  _Bool D.22390;
  long int D.22391;
  long int D.22392;

  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22380>; else goto <D.22381>;
    <D.22380>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.22381>:
    D.22382 = ret != 0;
    D.22383 = (long int) D.22382;
    D.22384 = __builtin_expect (D.22383, 0);
    if (D.22384 != 0) goto <D.22385>; else goto <D.22386>;
    <D.22385>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3642, "ret == 0");
    <D.22386>:
  }
  threads.112 = threads;
  mono_g_hash_table_foreach (threads.112, clear_cached_culture, domain);
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22388>; else goto <D.22389>;
    <D.22388>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.22389>:
    D.22390 = ret != 0;
    D.22391 = (long int) D.22390;
    D.22392 = __builtin_expect (D.22391, 0);
    if (D.22392 != 0) goto <D.22393>; else goto <D.22394>;
    <D.22393>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3644, "ret == 0");
    <D.22394>:
  }
}


clear_cached_culture (void * key, void * value, void * user_data)
{
  struct MonoArray * D.22395;
  long unsigned int D.22398;
  char * D.22399;
  struct MonoVTable * D.22402;
  struct MonoDomain * D.22403;
  struct MonoInternalThread * thread;
  struct MonoDomain * domain;
  int i;

  thread = value;
  domain = user_data;
  D.22395 = thread->cached_culture_info;
  if (D.22395 != 0B) goto <D.22396>; else goto <D.22397>;
  <D.22396>:
  i = 0;
  goto <D.19945>;
  <D.19944>:
  {
    struct MonoObject * obj;

    D.22398 = (long unsigned int) i;
    D.22395 = thread->cached_culture_info;
    D.22399 = mono_array_addr_with_size (D.22395, 8, D.22398);
    obj = MEM[(struct MonoObject * *)D.22399];
    if (obj != 0B) goto <D.22400>; else goto <D.22401>;
    <D.22400>:
    D.22402 = obj->vtable;
    D.22403 = D.22402->domain;
    if (D.22403 == domain) goto <D.22404>; else goto <D.22405>;
    <D.22404>:
    {
      struct MonoObject * * __p;

      D.22398 = (long unsigned int) i;
      D.22395 = thread->cached_culture_info;
      __p = mono_array_addr_with_size (D.22395, 8, D.22398);
      *__p = 0B;
    }
    <D.22405>:
    <D.22401>:
  }
  i = i + 1;
  <D.19945>:
  if (i <= 7) goto <D.19944>; else goto <D.19946>;
  <D.19946>:
  <D.22397>:
}


mono_thread_get_undeniable_exception ()
{
  struct MonoException * D.22408;
  int D.22411;
  struct MonoException * D.22414;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  if (thread != 0B) goto <D.22406>; else goto <D.22407>;
  <D.22406>:
  D.22408 = thread->abort_exc;
  if (D.22408 != 0B) goto <D.22409>; else goto <D.22410>;
  <D.22409>:
  D.22411 = is_running_protected_wrapper ();
  if (D.22411 == 0) goto <D.22412>; else goto <D.22413>;
  <D.22412>:
  D.22408 = thread->abort_exc;
  D.22408->trace_ips = 0B;
  D.22408 = thread->abort_exc;
  D.22408->stack_trace = 0B;
  D.22414 = thread->abort_exc;
  return D.22414;
  <D.22413>:
  <D.22410>:
  <D.22407>:
  D.22414 = 0B;
  return D.22414;
}


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

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


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

  if (managed != 0) goto <D.22419>; else goto <D.22420>;
  <D.22419>:
  D.22421 = 1;
  return D.22421;
  <D.22420>:
  D.22422 = mono_threads_is_critical_method (m);
  if (D.22422 != 0) goto <D.22423>; else goto <D.22424>;
  <D.22423>:
  MEM[(gboolean *)data] = 1;
  D.22421 = 1;
  return D.22421;
  <D.22424>:
  D.22421 = 0;
  return D.22421;
}


mono_alloc_special_static_data (guint32 static_type, guint32 size, guint32 align, uintptr_t * bitmap, int numbits)
{
  _Bool D.22430;
  long int D.22431;
  long int D.22432;
  struct MonoGHashTable * threads.113;
  long unsigned int D.22441;
  void * D.22442;
  _Bool D.22445;
  long int D.22446;
  long int D.22447;
  _Bool D.22451;
  long int D.22452;
  long int D.22453;
  _Bool D.22458;
  long int D.22459;
  long int D.22460;
  _Bool D.22465;
  long int D.22466;
  long int D.22467;
  uint32_t D.22470;
  guint32 offset;

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

    {
      int ret;

      ret = pthread_mutex_lock (&threads_mutex.mutex);
      if (ret != 0) goto <D.22428>; else goto <D.22429>;
      <D.22428>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
      <D.22429>:
      D.22430 = ret != 0;
      D.22431 = (long int) D.22430;
      D.22432 = __builtin_expect (D.22431, 0);
      if (D.22432 != 0) goto <D.22433>; else goto <D.22434>;
      <D.22433>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3902, "ret == 0");
      <D.22434>:
    }
    item = search_tls_slot_in_freelist (&thread_static_info, size, align);
    if (item != 0B) goto <D.22435>; else goto <D.22436>;
    <D.22435>:
    offset = item->offset;
    monoeg_g_free (item);
    goto <D.22437>;
    <D.22436>:
    offset = mono_alloc_static_data_slot (&thread_static_info, size, align);
    <D.22437>:
    update_tls_reference_bitmap (offset, bitmap, numbits);
    threads.113 = threads;
    if (threads.113 != 0B) goto <D.22439>; else goto <D.22440>;
    <D.22439>:
    D.22441 = (long unsigned int) offset;
    D.22442 = (void *) D.22441;
    threads.113 = threads;
    mono_g_hash_table_foreach (threads.113, alloc_thread_static_data_helper, D.22442);
    <D.22440>:
    {
      int ret;

      ret = pthread_mutex_unlock (&threads_mutex.mutex);
      if (ret != 0) goto <D.22443>; else goto <D.22444>;
      <D.22443>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.22444>:
      D.22445 = ret != 0;
      D.22446 = (long int) D.22445;
      D.22447 = __builtin_expect (D.22446, 0);
      if (D.22447 != 0) goto <D.22448>; else goto <D.22449>;
      <D.22448>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3915, "ret == 0");
      <D.22449>:
    }
  }
  goto <D.22450>;
  <D.22427>:
  D.22451 = static_type != 2;
  D.22452 = (long int) D.22451;
  D.22453 = __builtin_expect (D.22452, 0);
  if (D.22453 != 0) goto <D.22454>; else goto <D.22455>;
  <D.22454>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3917, "static_type == SPECIAL_STATIC_CONTEXT");
  <D.22455>:
  {
    int ret;

    ret = pthread_mutex_lock (&contexts_mutex.mutex);
    if (ret != 0) goto <D.22456>; else goto <D.22457>;
    <D.22456>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.22457>:
    D.22458 = ret != 0;
    D.22459 = (long int) D.22458;
    D.22460 = __builtin_expect (D.22459, 0);
    if (D.22460 != 0) goto <D.22461>; else goto <D.22462>;
    <D.22461>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3918, "ret == 0");
    <D.22462>:
  }
  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.22463>; else goto <D.22464>;
    <D.22463>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.22464>:
    D.22465 = ret != 0;
    D.22466 = (long int) D.22465;
    D.22467 = __builtin_expect (D.22466, 0);
    if (D.22467 != 0) goto <D.22468>; else goto <D.22469>;
    <D.22468>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3920, "ret == 0");
    <D.22469>:
  }
  offset = offset | 2147483648;
  <D.22450>:
  D.22470 = offset;
  return D.22470;
}


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

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


search_tls_slot_in_freelist (struct StaticDataInfo * static_data, guint32 size, guint32 align)
{
  unsigned int D.22474;
  struct MonoThreadDomainTls * D.22479;
  struct MonoThreadDomainTls * D.22481;
  struct MonoThreadDomainTls * prev;
  struct MonoThreadDomainTls * tmp;

  prev = 0B;
  tmp = static_data->freelist;
  goto <D.20032>;
  <D.20031>:
  D.22474 = tmp->size;
  if (D.22474 == size) goto <D.22475>; else goto <D.22476>;
  <D.22475>:
  if (prev != 0B) goto <D.22477>; else goto <D.22478>;
  <D.22477>:
  D.22479 = tmp->next;
  prev->next = D.22479;
  goto <D.22480>;
  <D.22478>:
  D.22479 = tmp->next;
  static_data->freelist = D.22479;
  <D.22480>:
  D.22481 = tmp;
  return D.22481;
  <D.22476>:
  tmp = tmp->next;
  <D.20032>:
  if (tmp != 0B) goto <D.20031>; else goto <D.20033>;
  <D.20033>:
  D.22481 = 0B;
  return D.22481;
}


update_tls_reference_bitmap (guint32 offset, uintptr_t * bitmap, int numbits)
{
  unsigned int D.22483;
  unsigned int D.22484;
  uintptr_t * D.22485;
  int D.22488;
  long unsigned int D.22489;
  long unsigned int D.22490;
  long unsigned int D.22491;
  long unsigned int D.22492;
  void * D.22493;
  long unsigned int D.22494;
  long unsigned int D.22495;
  long unsigned int D.22496;
  uintptr_t * D.22497;
  long unsigned int D.22498;
  int D.22499;
  long int D.22500;
  long unsigned int D.22501;
  long unsigned int D.22502;
  unsigned int i.115;
  unsigned int D.22506;
  unsigned int D.22507;
  long unsigned int D.22508;
  long unsigned int D.22509;
  uintptr_t * D.22510;
  long unsigned int D.22511;
  int D.22512;
  int D.22513;
  long int D.22514;
  long unsigned int D.22515;
  long unsigned int D.22516;
  int i;
  int idx;
  uintptr_t * rb;

  D.22483 = offset >> 24;
  D.22484 = D.22483 + 4294967295;
  idx = (int) D.22484;
  D.22485 = static_reference_bitmaps[idx];
  if (D.22485 == 0B) goto <D.22486>; else goto <D.22487>;
  <D.22486>:
  D.22488 = static_data_size[idx];
  D.22489 = (long unsigned int) D.22488;
  D.22490 = D.22489 / 512;
  D.22491 = D.22490 + 1;
  D.22492 = D.22491 * 8;
  D.22493 = monoeg_malloc0 (D.22492);
  static_reference_bitmaps[idx] = D.22493;
  <D.22487>:
  rb = static_reference_bitmaps[idx];
  offset = offset & 16777215;
  offset = offset / 8;
  i = 0;
  goto <D.20043>;
  <D.20042>:
  D.22494 = (long unsigned int) i;
  D.22495 = D.22494 / 8;
  D.22496 = D.22495 * 8;
  D.22497 = bitmap + D.22496;
  D.22498 = *D.22497;
  D.22499 = i & 63;
  D.22500 = 1 << D.22499;
  D.22501 = (long unsigned int) D.22500;
  D.22502 = D.22498 & D.22501;
  if (D.22502 != 0) goto <D.22503>; else goto <D.22504>;
  <D.22503>:
  i.115 = (unsigned int) i;
  D.22506 = offset + i.115;
  D.22507 = D.22506 / 64;
  D.22508 = (long unsigned int) D.22507;
  D.22509 = D.22508 * 8;
  D.22510 = rb + D.22509;
  D.22508 = (long unsigned int) D.22507;
  D.22509 = D.22508 * 8;
  D.22510 = rb + D.22509;
  D.22511 = *D.22510;
  i.115 = (unsigned int) i;
  D.22506 = offset + i.115;
  D.22512 = (int) D.22506;
  D.22513 = D.22512 & 63;
  D.22514 = 1 << D.22513;
  D.22515 = (long unsigned int) D.22514;
  D.22516 = D.22511 | D.22515;
  *D.22510 = D.22516;
  <D.22504>:
  i = i + 1;
  <D.20043>:
  if (i < numbits) goto <D.20042>; else goto <D.20044>;
  <D.20044>:
}


mono_alloc_static_data_slot (struct StaticDataInfo * static_data, guint32 size, guint32 align)
{
  signed long D.22517;
  long unsigned int D.22518;
  long unsigned int D.22519;
  int D.22522;
  unsigned int D.22523;
  unsigned int D.22524;
  unsigned int D.22525;
  int D.22526;
  unsigned int D.22527;
  unsigned int D.22528;
  int D.22529;
  unsigned int D.22530;
  int D.22531;
  int D.22532;
  unsigned int D.22533;
  int D.22536;
  _Bool D.22537;
  long int D.22538;
  long int D.22539;
  _Bool D.22542;
  long int D.22543;
  long int D.22544;
  int D.22547;
  int D.22548;
  int D.22549;
  guint32 D.22550;
  guint32 offset;

  D.22517 = BIT_FIELD_REF <*static_data, 64, 0>;
  D.22518 = (long unsigned int) D.22517;
  D.22519 = D.22518;
  if (D.22519 == 0) goto <D.22520>; else goto <D.22521>;
  <D.22520>:
  static_data->offset = 64;
  <D.22521>:
  D.22522 = static_data->offset;
  D.22523 = (unsigned int) D.22522;
  D.22524 = D.22523 + align;
  D.22525 = D.22524 + 4294967295;
  D.22526 = (int) D.22525;
  static_data->offset = D.22526;
  D.22522 = static_data->offset;
  D.22523 = (unsigned int) D.22522;
  D.22527 = -align;
  D.22528 = D.22523 & D.22527;
  D.22529 = (int) D.22528;
  static_data->offset = D.22529;
  D.22522 = static_data->offset;
  D.22523 = (unsigned int) D.22522;
  D.22530 = D.22523 + size;
  D.22531 = static_data->idx;
  D.22532 = static_data_size[D.22531];
  D.22533 = (unsigned int) D.22532;
  if (D.22530 >= D.22533) goto <D.22534>; else goto <D.22535>;
  <D.22534>:
  D.22531 = static_data->idx;
  D.22536 = D.22531 + 1;
  static_data->idx = D.22536;
  D.22531 = static_data->idx;
  D.22532 = static_data_size[D.22531];
  D.22533 = (unsigned int) D.22532;
  D.22537 = D.22533 < size;
  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", 3801, "size <= static_data_size [static_data->idx]");
  <D.22541>:
  D.22531 = static_data->idx;
  D.22542 = D.22531 > 7;
  D.22543 = (long int) D.22542;
  D.22544 = __builtin_expect (D.22543, 0);
  if (D.22544 != 0) goto <D.22545>; else goto <D.22546>;
  <D.22545>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3802, "static_data->idx < NUM_STATIC_DATA_IDX");
  <D.22546>:
  static_data->offset = 0;
  <D.22535>:
  D.22522 = static_data->offset;
  D.22531 = static_data->idx;
  D.22536 = D.22531 + 1;
  D.22547 = D.22536 << 24;
  D.22548 = D.22522 | D.22547;
  offset = (guint32) D.22548;
  D.22522 = static_data->offset;
  D.22523 = (unsigned int) D.22522;
  D.22530 = D.22523 + size;
  D.22549 = (int) D.22530;
  static_data->offset = D.22549;
  D.22550 = offset;
  return D.22550;
}


mono_get_special_static_data_for_thread (struct MonoInternalThread * thread, guint32 offset)
{
  unsigned int D.22552;
  unsigned int D.22553;
  void * D.22556;
  void * * D.22559;
  long unsigned int D.22561;
  long unsigned int D.22562;
  void * * D.22563;
  void * D.22564;
  _Bool D.22567;
  long int D.22568;
  long int D.22569;
  void * * * D.22572;
  _Bool D.22575;
  long int D.22576;
  long int D.22577;
  sizetype D.22580;
  sizetype D.22581;
  guint32 static_type;
  int idx;

  static_type = offset & 2147483648;
  offset = offset & 2147483647;
  D.22552 = offset >> 24;
  D.22553 = D.22552 + 4294967295;
  idx = (int) D.22553;
  if (static_type == 0) goto <D.22554>; else goto <D.22555>;
  <D.22554>:
  D.22556 = get_thread_static_data (thread, offset);
  return D.22556;
  <D.22555>:
  {
    struct MonoAppContext * context;

    context = mono_context_get ();
    D.22559 = context->static_data;
    if (D.22559 == 0B) goto <D.22557>; else goto <D.22560>;
    <D.22560>:
    D.22559 = context->static_data;
    D.22561 = (long unsigned int) idx;
    D.22562 = D.22561 * 8;
    D.22563 = D.22559 + D.22562;
    D.22564 = *D.22563;
    if (D.22564 == 0B) goto <D.22557>; else goto <D.22558>;
    <D.22557>:
    {
      int ret;

      ret = pthread_mutex_lock (&contexts_mutex.mutex);
      if (ret != 0) goto <D.22565>; else goto <D.22566>;
      <D.22565>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
      <D.22566>:
      D.22567 = ret != 0;
      D.22568 = (long int) D.22567;
      D.22569 = __builtin_expect (D.22568, 0);
      if (D.22569 != 0) goto <D.22570>; else goto <D.22571>;
      <D.22570>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3945, "ret == 0");
      <D.22571>:
    }
    D.22572 = &context->static_data;
    mono_alloc_static_data (D.22572, offset, 0);
    {
      int ret;

      ret = pthread_mutex_unlock (&contexts_mutex.mutex);
      if (ret != 0) goto <D.22573>; else goto <D.22574>;
      <D.22573>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.22574>:
      D.22575 = ret != 0;
      D.22576 = (long int) D.22575;
      D.22577 = __builtin_expect (D.22576, 0);
      if (D.22577 != 0) goto <D.22578>; else goto <D.22579>;
      <D.22578>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 3947, "ret == 0");
      <D.22579>:
    }
    <D.22558>:
    D.22559 = context->static_data;
    D.22561 = (long unsigned int) idx;
    D.22562 = D.22561 * 8;
    D.22563 = D.22559 + D.22562;
    D.22564 = *D.22563;
    D.22580 = (sizetype) offset;
    D.22581 = D.22580 & 16777215;
    D.22556 = D.22564 + D.22581;
    return D.22556;
  }
}


mono_get_special_static_data (guint32 offset)
{
  void * D.22583;
  struct MonoInternalThread * D.22584;

  D.22584 = mono_thread_internal_current ();
  D.22583 = mono_get_special_static_data_for_thread (D.22584, offset);
  return D.22583;
}


mono_alloc_special_static_data_free (struct GHashTable * special_static_fields)
{
  _Bool D.22588;
  long int D.22589;
  long int D.22590;
  _Bool D.22595;
  long int D.22596;
  long int D.22597;

  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22586>; else goto <D.22587>;
    <D.22586>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.22587>:
    D.22588 = ret != 0;
    D.22589 = (long int) D.22588;
    D.22590 = __builtin_expect (D.22589, 0);
    if (D.22590 != 0) goto <D.22591>; else goto <D.22592>;
    <D.22591>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4020, "ret == 0");
    <D.22592>:
  }
  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.22593>; else goto <D.22594>;
    <D.22593>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.22594>:
    D.22595 = ret != 0;
    D.22596 = (long int) D.22595;
    D.22597 = __builtin_expect (D.22596, 0);
    if (D.22597 != 0) goto <D.22598>; else goto <D.22599>;
    <D.22598>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4022, "ret == 0");
    <D.22599>:
  }
}


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

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


do_free_special_slot (guint32 offset, guint32 size)
{
  unsigned int D.22605;
  unsigned int D.22606;
  unsigned int D.22607;
  struct MonoGHashTable * threads.117;
  int D.22611;
  struct MonoThreadDomainTls * D.22614;
  guint32 static_type;

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

    try
      {
        item = monoeg_malloc0 (16);
        D.22605 = offset & 2147483647;
        data.offset = D.22605;
        data.size = size;
        D.22606 = data.size;
        D.22607 = data.offset;
        clear_reference_bitmap (D.22607, D.22606);
        threads.117 = threads;
        if (threads.117 != 0B) goto <D.22609>; else goto <D.22610>;
        <D.22609>:
        threads.117 = threads;
        mono_g_hash_table_foreach (threads.117, free_thread_static_data_helper, &data);
        <D.22610>:
        item->offset = offset;
        item->size = size;
        D.22611 = mono_runtime_is_shutting_down ();
        if (D.22611 == 0) goto <D.22612>; else goto <D.22613>;
        <D.22612>:
        D.22614 = thread_static_info.freelist;
        item->next = D.22614;
        thread_static_info.freelist = item;
        goto <D.22615>;
        <D.22613>:
        monoeg_g_free (item);
        <D.22615>:
      }
    finally
      {
        data = {CLOBBER};
      }
  }
  goto <D.22616>;
  <D.22604>:
  <D.22616>:
}


free_thread_static_data_helper (void * key, void * value, void * user)
{
  unsigned int D.22617;
  unsigned int D.22618;
  unsigned int D.22619;
  void * * D.22622;
  long unsigned int D.22624;
  long unsigned int D.22625;
  void * * D.22626;
  void * D.22627;
  sizetype D.22628;
  sizetype D.22629;
  unsigned int D.22630;
  long unsigned int D.22631;
  struct MonoInternalThread * thread;
  struct TlsOffsetSize * data;
  int idx;
  char * ptr;

  thread = value;
  data = user;
  D.22617 = data->offset;
  D.22618 = D.22617 >> 24;
  D.22619 = D.22618 + 4294967295;
  idx = (int) D.22619;
  D.22622 = thread->static_data;
  if (D.22622 == 0B) goto <D.22620>; else goto <D.22623>;
  <D.22623>:
  D.22622 = thread->static_data;
  D.22624 = (long unsigned int) idx;
  D.22625 = D.22624 * 8;
  D.22626 = D.22622 + D.22625;
  D.22627 = *D.22626;
  if (D.22627 == 0B) goto <D.22620>; else goto <D.22621>;
  <D.22620>:
  return;
  <D.22621>:
  D.22622 = thread->static_data;
  D.22624 = (long unsigned int) idx;
  D.22625 = D.22624 * 8;
  D.22626 = D.22622 + D.22625;
  D.22627 = *D.22626;
  D.22617 = data->offset;
  D.22628 = (sizetype) D.22617;
  D.22629 = D.22628 & 16777215;
  ptr = D.22627 + D.22629;
  D.22630 = data->size;
  D.22631 = (long unsigned int) D.22630;
  mono_gc_bzero_atomic (ptr, D.22631);
}


clear_reference_bitmap (guint32 offset, guint32 size)
{
  unsigned int D.22633;
  unsigned int D.22634;
  unsigned int D.22635;
  long unsigned int D.22636;
  long unsigned int D.22637;
  uintptr_t * D.22638;
  long unsigned int D.22639;
  int offset.118;
  int D.22641;
  long int D.22642;
  long int D.22643;
  long unsigned int D.22644;
  long unsigned int D.22645;
  int idx;
  uintptr_t * rb;

  D.22633 = offset >> 24;
  D.22634 = D.22633 + 4294967295;
  idx = (int) D.22634;
  rb = static_reference_bitmaps[idx];
  offset = offset & 16777215;
  offset = offset / 8;
  size = size / 8;
  size = size + offset;
  goto <D.20052>;
  <D.20051>:
  D.22635 = offset / 64;
  D.22636 = (long unsigned int) D.22635;
  D.22637 = D.22636 * 8;
  D.22638 = rb + D.22637;
  D.22636 = (long unsigned int) D.22635;
  D.22637 = D.22636 * 8;
  D.22638 = rb + D.22637;
  D.22639 = *D.22638;
  offset.118 = (int) offset;
  D.22641 = offset.118 & 63;
  D.22642 = 1 << D.22641;
  D.22643 = ~D.22642;
  D.22644 = (long unsigned int) D.22643;
  D.22645 = D.22639 & D.22644;
  *D.22638 = D.22645;
  offset = offset + 1;
  <D.20052>:
  if (offset < size) goto <D.20051>; else goto <D.20053>;
  <D.20053>:
}


mono_special_static_data_free_slot (guint32 offset, guint32 size)
{
  _Bool D.22648;
  long int D.22649;
  long int D.22650;
  _Bool D.22655;
  long int D.22656;
  long int D.22657;

  {
    int ret;

    ret = pthread_mutex_lock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22646>; else goto <D.22647>;
    <D.22646>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.22647>:
    D.22648 = ret != 0;
    D.22649 = (long int) D.22648;
    D.22650 = __builtin_expect (D.22649, 0);
    if (D.22650 != 0) goto <D.22651>; else goto <D.22652>;
    <D.22651>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4028, "ret == 0");
    <D.22652>:
  }
  do_free_special_slot (offset, size);
  {
    int ret;

    ret = pthread_mutex_unlock (&threads_mutex.mutex);
    if (ret != 0) goto <D.22653>; else goto <D.22654>;
    <D.22653>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.22654>:
    D.22655 = ret != 0;
    D.22656 = (long int) D.22655;
    D.22657 = __builtin_expect (D.22656, 0);
    if (D.22657 != 0) goto <D.22658>; else goto <D.22659>;
    <D.22658>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4030, "ret == 0");
    <D.22659>:
  }
}


mono_thread_alloc_tls (struct MonoReflectionType * type)
{
  struct MonoType * D.22660;
  int D.22661;
  int max_set.119;
  int D.22663;
  int align.120;
  unsigned int align.121;
  union mono_mutex_t * D.22668;
  _Bool D.22671;
  long int D.22672;
  long int D.22673;
  struct MonoTlsDataRecord * D.22676;
  _Bool D.22679;
  long int D.22680;
  long int D.22681;
  uint32_t D.22684;
  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.22660 = type->type;
      klass = mono_class_from_mono_type (D.22660);
      bitmap = mono_class_compute_bitmap (klass, &default_bitmap, 256, -2, &max_set, 0);
      D.22660 = type->type;
      D.22661 = mono_type_size (D.22660, &align);
      size = (guint32) D.22661;
      max_set.119 = max_set;
      D.22663 = max_set.119 + 1;
      align.120 = align;
      align.121 = (unsigned int) align.120;
      tls_offset = mono_alloc_special_static_data (1, size, align.121, bitmap, D.22663);
      if (&default_bitmap != bitmap) goto <D.22666>; else goto <D.22667>;
      <D.22666>:
      monoeg_g_free (bitmap);
      <D.22667>:
      tlsrec = monoeg_malloc0 (16);
      tlsrec->tls_offset = tls_offset;
      tlsrec->size = size;
      {
        int ret;

        D.22668 = &domain->lock.mutex;
        ret = pthread_mutex_lock (D.22668);
        if (ret != 0) goto <D.22669>; else goto <D.22670>;
        <D.22669>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.22670>:
        D.22671 = ret != 0;
        D.22672 = (long int) D.22671;
        D.22673 = __builtin_expect (D.22672, 0);
        if (D.22673 != 0) goto <D.22674>; else goto <D.22675>;
        <D.22674>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4060, "ret == 0");
        <D.22675>:
      }
      D.22676 = domain->tlsrec_list;
      tlsrec->next = D.22676;
      domain->tlsrec_list = tlsrec;
      {
        int ret;

        D.22668 = &domain->lock.mutex;
        ret = pthread_mutex_unlock (D.22668);
        if (ret != 0) goto <D.22677>; else goto <D.22678>;
        <D.22677>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.22678>:
        D.22679 = ret != 0;
        D.22680 = (long int) D.22679;
        D.22681 = __builtin_expect (D.22680, 0);
        if (D.22681 != 0) goto <D.22682>; else goto <D.22683>;
        <D.22682>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4063, "ret == 0");
        <D.22683>:
      }
      D.22684 = tls_offset;
      return D.22684;
    }
  finally
    {
      max_set = {CLOBBER};
      default_bitmap = {CLOBBER};
      align = {CLOBBER};
    }
}


mono_thread_destroy_tls (uint32_t tls_offset)
{
  union mono_mutex_t * D.22687;
  _Bool D.22690;
  long int D.22691;
  long int D.22692;
  unsigned int D.22695;
  struct MonoTlsDataRecord * D.22700;
  _Bool D.22704;
  long int D.22705;
  long int D.22706;
  struct MonoTlsDataRecord * prev;
  struct MonoTlsDataRecord * cur;
  guint32 size;
  struct MonoDomain * domain;

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

    D.22687 = &domain->lock.mutex;
    ret = pthread_mutex_lock (D.22687);
    if (ret != 0) goto <D.22688>; else goto <D.22689>;
    <D.22688>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.22689>:
    D.22690 = ret != 0;
    D.22691 = (long int) D.22690;
    D.22692 = __builtin_expect (D.22691, 0);
    if (D.22692 != 0) goto <D.22693>; else goto <D.22694>;
    <D.22693>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4074, "ret == 0");
    <D.22694>:
  }
  cur = domain->tlsrec_list;
  goto <D.20143>;
  <D.20142>:
  D.22695 = cur->tls_offset;
  if (D.22695 == tls_offset) goto <D.22696>; else goto <D.22697>;
  <D.22696>:
  if (prev != 0B) goto <D.22698>; else goto <D.22699>;
  <D.22698>:
  D.22700 = cur->next;
  prev->next = D.22700;
  goto <D.22701>;
  <D.22699>:
  D.22700 = cur->next;
  domain->tlsrec_list = D.22700;
  <D.22701>:
  size = cur->size;
  monoeg_g_free (cur);
  goto <D.20141>;
  <D.22697>:
  prev = cur;
  cur = cur->next;
  <D.20143>:
  if (cur != 0B) goto <D.20142>; else goto <D.20141>;
  <D.20141>:
  {
    int ret;

    D.22687 = &domain->lock.mutex;
    ret = pthread_mutex_unlock (D.22687);
    if (ret != 0) goto <D.22702>; else goto <D.22703>;
    <D.22702>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.22703>:
    D.22704 = ret != 0;
    D.22705 = (long int) D.22704;
    D.22706 = __builtin_expect (D.22705, 0);
    if (D.22706 != 0) goto <D.22707>; else goto <D.22708>;
    <D.22707>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4089, "ret == 0");
    <D.22708>:
  }
  if (size != 0) goto <D.22709>; else goto <D.22710>;
  <D.22709>:
  mono_special_static_data_free_slot (tls_offset, size);
  <D.22710>:
}


mono_thread_destroy_domain_tls (struct MonoDomain * domain)
{
  struct MonoTlsDataRecord * D.22711;
  unsigned int D.22712;

  goto <D.20149>;
  <D.20148>:
  D.22711 = domain->tlsrec_list;
  D.22712 = D.22711->tls_offset;
  mono_thread_destroy_tls (D.22712);
  <D.20149>:
  D.22711 = domain->tlsrec_list;
  if (D.22711 != 0B) goto <D.20148>; else goto <D.20150>;
  <D.20150>:
}


mono_thread_free_local_slot_values (int slot, MonoBoolean thread_local)
{
  struct MonoClassField * local_slots.122;
  struct MonoClass * D.22718;
  struct MonoClassField * local_slots.123;
  union mono_mutex_t * D.22722;
  _Bool D.22725;
  long int D.22726;
  long int D.22727;
  struct GHashTable * D.22730;
  _Bool D.22735;
  long int D.22736;
  long int D.22737;
  long int addr.124;
  unsigned int D.22743;
  unsigned int D.22744;
  unsigned int D.22745;
  unsigned int D.22746;
  unsigned int D.22747;
  int D.22748;
  _Bool D.22751;
  long int D.22752;
  long int D.22753;
  struct MonoGHashTable * threads.125;
  _Bool D.22759;
  long int D.22760;
  long int D.22761;
  struct MonoDomain * domain;
  struct LocalSlotID sid;

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

        addr = 0B;
        local_slots.122 = local_slots;
        if (local_slots.122 == 0B) goto <D.22716>; else goto <D.22717>;
        <D.22716>:
        D.22718 = mono_defaults.thread_class;
        local_slots.123 = mono_class_get_field_from_name (D.22718, "local_slots");
        local_slots = local_slots.123;
        local_slots.122 = local_slots;
        if (local_slots.122 == 0B) goto <D.22720>; else goto <D.22721>;
        <D.22720>:
        monoeg_g_log (0B, 16, "local_slots field not found in Thread class");
        return;
        <D.22721>:
        <D.22717>:
        domain = mono_domain_get ();
        {
          int ret;

          D.22722 = &domain->lock.mutex;
          ret = pthread_mutex_lock (D.22722);
          if (ret != 0) goto <D.22723>; else goto <D.22724>;
          <D.22723>:
          monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
          <D.22724>:
          D.22725 = ret != 0;
          D.22726 = (long int) D.22725;
          D.22727 = __builtin_expect (D.22726, 0);
          if (D.22727 != 0) goto <D.22728>; else goto <D.22729>;
          <D.22728>:
          monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4150, "ret == 0");
          <D.22729>:
        }
        D.22730 = domain->special_static_fields;
        if (D.22730 != 0B) goto <D.22731>; else goto <D.22732>;
        <D.22731>:
        local_slots.122 = local_slots;
        D.22730 = domain->special_static_fields;
        addr = monoeg_g_hash_table_lookup (D.22730, local_slots.122);
        <D.22732>:
        {
          int ret;

          D.22722 = &domain->lock.mutex;
          ret = pthread_mutex_unlock (D.22722);
          if (ret != 0) goto <D.22733>; else goto <D.22734>;
          <D.22733>:
          monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
          <D.22734>:
          D.22735 = ret != 0;
          D.22736 = (long int) D.22735;
          D.22737 = __builtin_expect (D.22736, 0);
          if (D.22737 != 0) goto <D.22738>; else goto <D.22739>;
          <D.22738>:
          monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4153, "ret == 0");
          <D.22739>:
        }
        if (addr == 0B) goto <D.22740>; else goto <D.22741>;
        <D.22740>:
        return;
        <D.22741>:
        addr.124 = (long int) addr;
        D.22743 = (unsigned int) addr.124;
        sid.offset = D.22743;
        D.22744 = sid.offset;
        D.22745 = D.22744 & 2147483647;
        sid.offset = D.22745;
        D.22744 = sid.offset;
        D.22746 = D.22744 >> 24;
        D.22747 = D.22746 + 4294967295;
        D.22748 = (int) D.22747;
        sid.idx = D.22748;
        {
          int ret;

          ret = pthread_mutex_lock (&threads_mutex.mutex);
          if (ret != 0) goto <D.22749>; else goto <D.22750>;
          <D.22749>:
          monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
          <D.22750>:
          D.22751 = ret != 0;
          D.22752 = (long int) D.22751;
          D.22753 = __builtin_expect (D.22752, 0);
          if (D.22753 != 0) goto <D.22754>; else goto <D.22755>;
          <D.22754>:
          monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4160, "ret == 0");
          <D.22755>:
        }
        threads.125 = threads;
        mono_g_hash_table_foreach (threads.125, clear_local_slot, &sid);
        {
          int ret;

          ret = pthread_mutex_unlock (&threads_mutex.mutex);
          if (ret != 0) goto <D.22757>; else goto <D.22758>;
          <D.22757>:
          monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
          <D.22758>:
          D.22759 = ret != 0;
          D.22760 = (long int) D.22759;
          D.22761 = __builtin_expect (D.22760, 0);
          if (D.22761 != 0) goto <D.22762>; else goto <D.22763>;
          <D.22762>:
          monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4162, "ret == 0");
          <D.22763>:
        }
      }
      goto <D.22764>;
      <D.22714>:
      <D.22764>:
    }
  finally
    {
      sid = {CLOBBER};
    }
}


clear_local_slot (void * key, void * value, void * user_data)
{
  void * * D.22770;
  int D.22772;
  long unsigned int D.22773;
  long unsigned int D.22774;
  void * * D.22775;
  void * D.22776;
  unsigned int D.22777;
  sizetype D.22778;
  sizetype D.22779;
  struct MonoArray * * D.22780;
  int D.22784;
  long unsigned int D.22785;
  long unsigned int D.22786;
  struct LocalSlotID * sid;
  struct MonoInternalThread * thread;
  struct MonoArray * slots_array;

  sid = user_data;
  thread = value;
  D.22770 = thread->static_data;
  if (D.22770 == 0B) goto <D.22768>; else goto <D.22771>;
  <D.22771>:
  D.22770 = thread->static_data;
  D.22772 = sid->idx;
  D.22773 = (long unsigned int) D.22772;
  D.22774 = D.22773 * 8;
  D.22775 = D.22770 + D.22774;
  D.22776 = *D.22775;
  if (D.22776 == 0B) goto <D.22768>; else goto <D.22769>;
  <D.22768>:
  return;
  <D.22769>:
  D.22770 = thread->static_data;
  D.22772 = sid->idx;
  D.22773 = (long unsigned int) D.22772;
  D.22774 = D.22773 * 8;
  D.22775 = D.22770 + D.22774;
  D.22776 = *D.22775;
  D.22777 = sid->offset;
  D.22778 = (sizetype) D.22777;
  D.22779 = D.22778 & 16777215;
  D.22780 = D.22776 + D.22779;
  slots_array = *D.22780;
  if (slots_array == 0B) goto <D.22781>; else goto <D.22783>;
  <D.22783>:
  D.22784 = sid->slot;
  D.22785 = (long unsigned int) D.22784;
  D.22786 = mono_array_length (slots_array);
  if (D.22785 >= D.22786) goto <D.22781>; else goto <D.22782>;
  <D.22781>:
  return;
  <D.22782>:
  {
    struct MonoObject * * __p;

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


mono_thread_request_interruption (gboolean running_managed)
{
  struct MonoException * D.22790;
  gint32 * D.22791;
  int D.22792;
  int D.22798;
  void (*<T552>) (void) mono_thread_notify_pending_exc_fn.126;
  void * D.22804;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  if (thread == 0B) goto <D.22788>; else goto <D.22789>;
  <D.22788>:
  D.22790 = 0B;
  return D.22790;
  <D.22789>:
  D.22791 = &thread->interruption_requested;
  D.22792 = InterlockedCompareExchange (D.22791, 1, 0);
  if (D.22792 == 1) goto <D.22793>; else goto <D.22794>;
  <D.22793>:
  D.22790 = 0B;
  return D.22790;
  <D.22794>:
  InterlockedIncrement (&thread_interruption_requested);
  if (running_managed == 0) goto <D.22795>; else goto <D.22797>;
  <D.22797>:
  D.22798 = is_running_protected_wrapper ();
  if (D.22798 != 0) goto <D.22795>; else goto <D.22796>;
  <D.22795>:
  mono_thread_notify_pending_exc_fn.126 = mono_thread_notify_pending_exc_fn;
  if (mono_thread_notify_pending_exc_fn.126 != 0B) goto <D.22800>; else goto <D.22801>;
  <D.22800>:
  if (running_managed == 0) goto <D.22802>; else goto <D.22803>;
  <D.22802>:
  mono_thread_notify_pending_exc_fn.126 = mono_thread_notify_pending_exc_fn;
  mono_thread_notify_pending_exc_fn.126 ();
  <D.22803>:
  <D.22801>:
  D.22804 = thread->handle;
  QueueUserAPC (dummy_apc, D.22804, 0B);
  D.22790 = 0B;
  return D.22790;
  <D.22796>:
  D.22790 = mono_thread_execute_interruption (thread);
  return D.22790;
}


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

  D.22806 = 0;
  return D.22806;
}


mono_thread_resume_interruption ()
{
  struct MonoException * D.22810;
  unsigned int D.22811;
  unsigned int D.22812;
  _Bool D.22813;
  gint32 * D.22816;
  int D.22817;
  struct MonoInternalThread * thread;
  gboolean still_aborting;

  thread = mono_thread_internal_current ();
  if (thread == 0B) goto <D.22808>; else goto <D.22809>;
  <D.22808>:
  D.22810 = 0B;
  return D.22810;
  <D.22809>:
  lock_thread (thread);
  D.22811 = thread->state;
  D.22812 = D.22811 & 128;
  D.22813 = D.22812 != 0;
  still_aborting = (gboolean) D.22813;
  unlock_thread (thread);
  if (still_aborting == 0) goto <D.22814>; else goto <D.22815>;
  <D.22814>:
  D.22810 = 0B;
  return D.22810;
  <D.22815>:
  D.22816 = &thread->interruption_requested;
  D.22817 = InterlockedCompareExchange (D.22816, 1, 0);
  if (D.22817 == 1) goto <D.22818>; else goto <D.22819>;
  <D.22818>:
  D.22810 = 0B;
  return D.22810;
  <D.22819>:
  InterlockedIncrement (&thread_interruption_requested);
  wapi_self_interrupt ();
  D.22810 = mono_thread_execute_interruption (thread);
  return D.22810;
}


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

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

    thread = mono_thread_internal_current ();
    if (thread != 0B) goto <D.22824>; else goto <D.22825>;
    <D.22824>:
    D.22826 = thread->interruption_requested;
    return D.22826;
    <D.22825>:
  }
  <D.22823>:
  D.22826 = 0;
  return D.22826;
}


mono_thread_interruption_checkpoint ()
{
  mono_thread_interruption_checkpoint_request (0);
}


mono_thread_interruption_checkpoint_request (gboolean bypass_abort_protection)
{
  int D.22832;
  int D.22836;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  if (thread == 0B) goto <D.22828>; else goto <D.22829>;
  <D.22828>:
  return;
  <D.22829>:
  D.22832 = thread->interruption_requested;
  if (D.22832 != 0) goto <D.22833>; else goto <D.22834>;
  <D.22833>:
  if (bypass_abort_protection != 0) goto <D.22830>; else goto <D.22835>;
  <D.22835>:
  D.22836 = is_running_protected_wrapper ();
  if (D.22836 == 0) goto <D.22830>; else goto <D.22831>;
  <D.22830>:
  {
    struct MonoException * exc;

    exc = mono_thread_execute_interruption (thread);
    if (exc != 0B) goto <D.22837>; else goto <D.22838>;
    <D.22837>:
    mono_raise_exception (exc);
    <D.22838>:
  }
  <D.22831>:
  <D.22834>:
}


mono_thread_force_interruption_checkpoint ()
{
  mono_thread_interruption_checkpoint_request (1);
}


mono_thread_get_and_clear_pending_exception ()
{
  struct MonoException * D.22842;
  int D.22843;
  int D.22846;
  struct MonoException * D.22849;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  if (thread == 0B) goto <D.22840>; else goto <D.22841>;
  <D.22840>:
  D.22842 = 0B;
  return D.22842;
  <D.22841>:
  D.22843 = thread->interruption_requested;
  if (D.22843 != 0) goto <D.22844>; else goto <D.22845>;
  <D.22844>:
  D.22846 = is_running_protected_wrapper ();
  if (D.22846 == 0) goto <D.22847>; else goto <D.22848>;
  <D.22847>:
  D.22842 = mono_thread_execute_interruption (thread);
  return D.22842;
  <D.22848>:
  <D.22845>:
  D.22849 = thread->pending_exception;
  if (D.22849 != 0B) goto <D.22850>; else goto <D.22851>;
  <D.22850>:
  {
    struct MonoException * exc;

    exc = thread->pending_exception;
    thread->pending_exception = 0B;
    D.22842 = exc;
    return D.22842;
  }
  <D.22851>:
  D.22842 = 0B;
  return D.22842;
}


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

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


mono_thread_interruption_request_flag ()
{
  gint32 * D.22857;

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


mono_thread_init_apartment_state ()
{

}


mono_thread_cleanup_apartment_state ()
{

}


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

  lock_thread (thread);
  D.22859 = thread->state;
  D.22860 = D.22859 | state;
  thread->state = D.22860;
  unlock_thread (thread);
}


mono_thread_clr_state (struct MonoInternalThread * thread, MonoThreadState state)
{
  unsigned int D.22861;
  unsigned int D.22862;
  unsigned int D.22863;

  lock_thread (thread);
  D.22861 = thread->state;
  D.22862 = ~state;
  D.22863 = D.22861 & D.22862;
  thread->state = D.22863;
  unlock_thread (thread);
}


mono_thread_test_state (struct MonoInternalThread * thread, MonoThreadState test)
{
  unsigned int D.22864;
  unsigned int D.22865;
  gboolean D.22868;
  gboolean ret;

  ret = 0;
  lock_thread (thread);
  D.22864 = thread->state;
  D.22865 = D.22864 & test;
  if (D.22865 != 0) goto <D.22866>; else goto <D.22867>;
  <D.22866>:
  ret = 1;
  <D.22867>:
  unlock_thread (thread);
  D.22868 = ret;
  return D.22868;
}


mono_thread_get_execution_context ()
{
  struct MonoObject * D.22870;
  struct MonoObject * * D.22871;

  D.22871 = get_execution_context_addr ();
  D.22870 = *D.22871;
  return D.22870;
}


get_execution_context_addr ()
{
  struct MonoClass * D.22875;
  _Bool D.22876;
  long int D.22877;
  long int D.22878;
  struct MonoClass * D.22881;
  struct MonoVTable * D.22882;
  _Bool D.22883;
  long int D.22884;
  long int D.22885;
  union mono_mutex_t * D.22888;
  _Bool D.22891;
  long int D.22892;
  long int D.22893;
  struct GHashTable * D.22896;
  void * D.22897;
  long int D.22898;
  _Bool D.22901;
  long int D.22902;
  long int D.22903;
  _Bool D.22906;
  long int D.22907;
  long int D.22908;
  struct MonoObject * * D.22911;
  struct MonoDomain * domain;
  guint32 offset;

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

    D.22875 = mono_defaults.thread_class;
    field = mono_class_get_field_from_name (D.22875, "_ec");
    D.22876 = field == 0B;
    D.22877 = (long int) D.22876;
    D.22878 = __builtin_expect (D.22877, 0);
    if (D.22878 != 0) goto <D.22879>; else goto <D.22880>;
    <D.22879>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4501, "field");
    <D.22880>:
    D.22881 = mono_defaults.appdomain_class;
    D.22882 = mono_class_try_get_vtable (domain, D.22881);
    D.22883 = D.22882 == 0B;
    D.22884 = (long int) D.22883;
    D.22885 = __builtin_expect (D.22884, 0);
    if (D.22885 != 0) goto <D.22886>; else goto <D.22887>;
    <D.22886>:
    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.22887>:
    {
      int ret;

      D.22888 = &domain->lock.mutex;
      ret = pthread_mutex_lock (D.22888);
      if (ret != 0) goto <D.22889>; else goto <D.22890>;
      <D.22889>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
      <D.22890>:
      D.22891 = ret != 0;
      D.22892 = (long int) D.22891;
      D.22893 = __builtin_expect (D.22892, 0);
      if (D.22893 != 0) goto <D.22894>; else goto <D.22895>;
      <D.22894>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4505, "ret == 0");
      <D.22895>:
    }
    D.22896 = domain->special_static_fields;
    D.22897 = monoeg_g_hash_table_lookup (D.22896, field);
    D.22898 = (long int) D.22897;
    offset = (guint32) D.22898;
    {
      int ret;

      D.22888 = &domain->lock.mutex;
      ret = pthread_mutex_unlock (D.22888);
      if (ret != 0) goto <D.22899>; else goto <D.22900>;
      <D.22899>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.22900>:
      D.22901 = ret != 0;
      D.22902 = (long int) D.22901;
      D.22903 = __builtin_expect (D.22902, 0);
      if (D.22903 != 0) goto <D.22904>; else goto <D.22905>;
      <D.22904>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4507, "ret == 0");
      <D.22905>:
    }
    D.22906 = offset == 0;
    D.22907 = (long int) D.22906;
    D.22908 = __builtin_expect (D.22907, 0);
    if (D.22908 != 0) goto <D.22909>; else goto <D.22910>;
    <D.22909>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threads.c", 4508, "offset");
    <D.22910>:
    domain->execution_context_field_offset = offset;
  }
  <D.22874>:
  D.22911 = mono_get_special_static_data (offset);
  return D.22911;
}


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

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


mono_runtime_set_has_tls_get (gboolean val)
{
  has_tls_get = val;
}


mono_runtime_has_tls_get ()
{
  gboolean D.22914;

  D.22914 = has_tls_get;
  return D.22914;
}


mono_thread_kill (struct MonoInternalThread * thread, int signal)
{
  int D.22916;
  int D.22917;
  long unsigned int D.22918;

  D.22917 = mono_thread_get_abort_signal ();
  D.22918 = thread->tid;
  D.22916 = pthread_kill (D.22918, D.22917);
  return D.22916;
}


mono_thread_is_foreign (struct MonoThread * thread)
{
  struct _MonoInternalThread * D.22920;
  mono_bool D.22921;
  int D.22922;
  _Bool D.22923;
  struct MonoThreadInfo * info;

  D.22920 = thread->internal_thread;
  info = D.22920->thread_info;
  D.22922 = info->runtime_thread;
  D.22923 = D.22922 == 0;
  D.22921 = (mono_bool) D.22923;
  return D.22921;
}


