mono_threads_pthread_create (pthread_t * new_thread, const union pthread_attr_t * attr, void * (*<Tf3c>) (void *) start_routine, void * arg)
{
  int D.12293;
  union MonoSemType * D.12294;
  struct MonoThreadInfoCallbacks * D.12295;
  int (*<T1b8e>) (pthread_t *, const union pthread_attr_t *, void * (*<Tf3c>) (void *), void *) D.12296;
  int D.12299;
  struct ThreadStartInfo * start_info;
  int result;

  start_info = monoeg_malloc0 (28);
  if (start_info == 0B) goto <D.12291>; else goto <D.12292>;
  <D.12291>:
  D.12293 = 12;
  return D.12293;
  <D.12292>:
  D.12294 = &start_info->registered;
  sem_init (D.12294, 0, 0);
  start_info->arg = arg;
  start_info->start_routine = start_routine;
  D.12295 = mono_threads_get_callbacks ();
  D.12296 = D.12295->mono_gc_pthread_create;
  result = D.12296 (new_thread, attr, inner_start_thread, start_info);
  if (result == 0) goto <D.12297>; else goto <D.12298>;
  <D.12297>:
  goto <D.12224>;
  <D.12223>:
  <D.12224>:
  D.12294 = &start_info->registered;
  D.12299 = mono_sem_wait (D.12294, 0);
  if (D.12299 != 0) goto <D.12223>; else goto <D.12225>;
  <D.12225>:
  <D.12298>:
  D.12294 = &start_info->registered;
  sem_destroy (D.12294);
  monoeg_g_free (start_info);
  D.12293 = result;
  return D.12293;
}


inner_start_thread (void * arg)
{
  struct MonoThreadInfo * D.12301;
  union MonoSemType * D.12302;
  _Bool D.12303;
  long int D.12304;
  long int D.12305;
  void * result.0;
  struct MonoDomain * D.12309;
  _Bool D.12310;
  long int D.12311;
  long int D.12312;
  void * D.12315;
  struct ThreadStartInfo * start_info;
  void * t_arg;
  int post_result;
  void * (*<Tf3c>) (void *) start_func;
  void * result;

  try
    {
      start_info = arg;
      t_arg = start_info->arg;
      start_func = start_info->start_routine;
      D.12301 = mono_thread_info_attach (&result);
      D.12301->runtime_thread = 1;
      D.12302 = &start_info->registered;
      post_result = mono_sem_post (D.12302);
      D.12303 = post_result != 0;
      D.12304 = (long int) D.12303;
      D.12305 = __builtin_expect (D.12304, 0);
      if (D.12305 != 0) goto <D.12306>; else goto <D.12307>;
      <D.12306>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads-posix.c", 47, "!post_result");
      <D.12307>:
      result.0 = start_func (t_arg);
      result = result.0;
      D.12309 = mono_domain_get ();
      D.12310 = D.12309 != 0B;
      D.12311 = (long int) D.12310;
      D.12312 = __builtin_expect (D.12311, 0);
      if (D.12312 != 0) goto <D.12313>; else goto <D.12314>;
      <D.12313>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads-posix.c", 50, "!mono_domain_get ()");
      <D.12314>:
      mono_thread_info_dettach ();
      D.12315 = result;
      return D.12315;
    }
  finally
    {
      result = {CLOBBER};
    }
}


mono_threads_init_platform ()
{
  int D.12318;
  int D.12321;

  D.12318 = mono_thread_info_new_interrupt_enabled ();
  if (D.12318 != 0) goto <D.12319>; else goto <D.12320>;
  <D.12319>:
  D.12321 = mono_thread_get_abort_signal ();
  mono_posix_add_signal_handler (D.12321, suspend_signal_handler);
  <D.12320>:
}


suspend_signal_handler (int _dummy, struct siginfo_t * info, void * context)
{
  int D.12322;
  struct MonoThreadInfoRuntimeCallbacks * D.12325;
  gboolean (*<T1b9b>) (struct MonoThreadUnwindState *, void *) D.12326;
  struct MonoThreadUnwindState * D.12327;
  union MonoSemType * D.12328;
  union MonoSemType * D.12331;
  int D.12332;
  void (*<Tbf>) (void *) D.12333;
  struct MonoThreadInfoRuntimeCallbacks * D.12336;
  void (*<T1b95>) (struct MonoContext *, void (*<Tbf>) (void *), void *) D.12337;
  void * D.12338;
  union MonoSemType * D.12339;
  struct MonoThreadInfo * current;
  gboolean ret;

  current = mono_thread_info_current ();
  D.12322 = current->syscall_break_signal;
  if (D.12322 != 0) goto <D.12323>; else goto <D.12324>;
  <D.12323>:
  current->syscall_break_signal = 0;
  return;
  <D.12324>:
  D.12325 = mono_threads_get_runtime_callbacks ();
  D.12326 = D.12325->thread_state_init_from_sigctx;
  D.12327 = &current->suspend_state;
  ret = D.12326 (D.12327, context);
  current->suspend_can_continue = ret;
  D.12328 = &current->begin_suspend_semaphore;
  mono_sem_post (D.12328);
  if (ret == 0) goto <D.12329>; else goto <D.12330>;
  <D.12329>:
  return;
  <D.12330>:
  goto <D.12234>;
  <D.12233>:
  <D.12234>:
  D.12331 = &current->resume_semaphore;
  D.12332 = mono_sem_wait (D.12331, 0);
  if (D.12332 != 0) goto <D.12233>; else goto <D.12235>;
  <D.12235>:
  D.12333 = current->async_target;
  if (D.12333 != 0B) goto <D.12334>; else goto <D.12335>;
  <D.12334>:
  {
    struct MonoContext tmp;

    try
      {
        tmp = current->suspend_state.ctx;
        D.12336 = mono_threads_get_runtime_callbacks ();
        D.12337 = D.12336->setup_async_callback;
        D.12338 = current->user_data;
        D.12333 = current->async_target;
        D.12337 (&tmp, D.12333, D.12338);
        current->user_data = 0B;
        current->async_target = 0B;
        mono_monoctx_to_sigctx (&tmp, context);
      }
    finally
      {
        tmp = {CLOBBER};
      }
  }
  <D.12335>:
  D.12339 = &current->finish_resume_semaphore;
  mono_sem_post (D.12339);
}


mono_posix_add_signal_handler (int signo, void * handler)
{
  void (*<T1a67>) (int, struct siginfo_t *, void *) handler.1;
  _Bool D.12342;
  long int D.12343;
  long int D.12344;
  struct sigaction sa;
  struct sigaction previous_sa;
  int ret;

  try
    {
      handler.1 = (void (*<T1a67>) (int, struct siginfo_t *, void *)) handler;
      sa.__sigaction_handler.sa_sigaction = handler.1;
      sigemptyset (&sa.sa_mask);
      sa.sa_flags = 4;
      ret = sigaction (signo, &sa, &previous_sa);
      D.12342 = ret == -1;
      D.12343 = (long int) D.12342;
      D.12344 = __builtin_expect (D.12343, 0);
      if (D.12344 != 0) goto <D.12345>; else goto <D.12346>;
      <D.12345>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-threads-posix.c", 139, "ret != -1");
      <D.12346>:
    }
  finally
    {
      sa = {CLOBBER};
      previous_sa = {CLOBBER};
    }
}


mono_threads_core_interrupt (struct MonoThreadInfo * info)
{

}


mono_threads_pthread_kill (struct MonoThreadInfo * info, int signum)
{
  int D.12347;
  unsigned int D.12348;

  D.12348 = info->node.key;
  D.12347 = pthread_kill (D.12348, signum);
  return D.12347;
}


mono_threads_core_abort_syscall (struct MonoThreadInfo * info)
{
  int D.12350;

  info->syscall_break_signal = 1;
  D.12350 = mono_thread_get_abort_signal ();
  mono_threads_pthread_kill (info, D.12350);
}


mono_threads_core_needs_abort_syscall ()
{
  gboolean D.12351;

  D.12351 = 1;
  return D.12351;
}


mono_threads_core_suspend (struct MonoThreadInfo * info)
{
  int D.12353;
  union MonoSemType * D.12354;
  int D.12355;
  gboolean D.12356;

  D.12353 = mono_thread_get_abort_signal ();
  mono_threads_pthread_kill (info, D.12353);
  goto <D.12264>;
  <D.12263>:
  <D.12264>:
  D.12354 = &info->begin_suspend_semaphore;
  D.12355 = mono_sem_wait (D.12354, 0);
  if (D.12355 != 0) goto <D.12263>; else goto <D.12265>;
  <D.12265>:
  D.12356 = info->suspend_can_continue;
  return D.12356;
}


mono_threads_core_resume (struct MonoThreadInfo * info)
{
  union MonoSemType * D.12358;
  union MonoSemType * D.12359;
  int D.12360;
  gboolean D.12361;

  D.12358 = &info->resume_semaphore;
  mono_sem_post (D.12358);
  goto <D.12270>;
  <D.12269>:
  <D.12270>:
  D.12359 = &info->finish_resume_semaphore;
  D.12360 = mono_sem_wait (D.12359, 0);
  if (D.12360 != 0) goto <D.12269>; else goto <D.12271>;
  <D.12271>:
  D.12361 = 1;
  return D.12361;
}


mono_threads_platform_register (struct MonoThreadInfo * info)
{
  union MonoSemType * D.12363;

  D.12363 = &info->begin_suspend_semaphore;
  sem_init (D.12363, 0, 0);
}


mono_threads_platform_free (struct MonoThreadInfo * info)
{
  union MonoSemType * D.12364;

  D.12364 = &info->begin_suspend_semaphore;
  sem_destroy (D.12364);
}


mono_native_thread_id_get ()
{
  MonoNativeThreadId D.12365;

  D.12365 = pthread_self ();
  return D.12365;
}


mono_native_thread_id_equals (MonoNativeThreadId id1, MonoNativeThreadId id2)
{
  gboolean D.12367;

  D.12367 = pthread_equal (id1, id2);
  return D.12367;
}


pthread_equal (pthread_t __thread1, pthread_t __thread2)
{
  int D.12369;
  _Bool D.12370;

  D.12370 = __thread1 == __thread2;
  D.12369 = (int) D.12370;
  return D.12369;
}


mono_native_thread_create (MonoNativeThreadId * tid, void * func, void * arg)
{
  gboolean D.12372;
  void * (*<Tf3c>) (void *) func.2;
  int D.12374;
  _Bool D.12375;

  func.2 = (void * (*<Tf3c>) (void *)) func;
  D.12374 = pthread_create (tid, 0B, func.2, arg);
  D.12375 = D.12374 == 0;
  D.12372 = (gboolean) D.12375;
  return D.12372;
}


