GC_remove_allowed_signals (struct sigset_t * set)
{
  int D.5950;
  int D.5952;
  int D.5954;
  int D.5956;

  D.5950 = sigdelset (set, 2);
  if (D.5950 != 0) goto <D.5948>; else goto <D.5951>;
  <D.5951>:
  D.5952 = sigdelset (set, 3);
  if (D.5952 != 0) goto <D.5948>; else goto <D.5953>;
  <D.5953>:
  D.5954 = sigdelset (set, 6);
  if (D.5954 != 0) goto <D.5948>; else goto <D.5955>;
  <D.5955>:
  D.5956 = sigdelset (set, 15);
  if (D.5956 != 0) goto <D.5948>; else goto <D.5949>;
  <D.5948>:
  GC_abort ("sigdelset() failed");
  <D.5949>:
}


GC_suspend_handler (int sig)
{
  int * D.5957;
  int old_errno;

  D.5957 = __errno_location ();
  old_errno = *D.5957;
  _GC_suspend_handler (sig);
  D.5957 = __errno_location ();
  *D.5957 = old_errno;
}


_GC_suspend_handler (int sig)
{
  long unsigned int D.5960;
  int GC_retry_signals.0;
  void (*<T41a>) (char *, GC_word) GC_current_warn_proc.1;
  long unsigned int D.5967;
  int D.5968;
  int dummy;
  pthread_t my_thread;
  struct GC_Thread_Rep * me;
  word my_mark_no;
  word my_stop_count;

  try
    {
      my_thread = pthread_self ();
      my_mark_no = GC_mark_no;
      my_stop_count = GC_stop_count;
      if (sig != 30) goto <D.5958>; else goto <D.5959>;
      <D.5958>:
      GC_abort ("Bad signal in suspend_handler");
      <D.5959>:
      me = GC_lookup_thread (my_thread);
      D.5960 = me->stop_info.last_stop_count;
      if (D.5960 == my_stop_count) goto <D.5961>; else goto <D.5962>;
      <D.5961>:
      GC_retry_signals.0 = GC_retry_signals;
      if (GC_retry_signals.0 == 0) goto <D.5964>; else goto <D.5965>;
      <D.5964>:
      GC_current_warn_proc.1 = GC_current_warn_proc;
      D.5967 = pthread_self ();
      GC_current_warn_proc.1 ("GC Warning: Duplicate suspend signal in thread %lx\n", D.5967);
      <D.5965>:
      return;
      <D.5962>:
      me->stop_info.stack_ptr = &dummy;
      sem_post (&GC_suspend_ack_sem);
      me->stop_info.last_stop_count = my_stop_count;
      <D.5845>:
      me->stop_info.signal = 0;
      sigsuspend (&suspend_handler_mask);
      D.5968 = me->stop_info.signal;
      if (D.5968 != 24) goto <D.5845>; else goto <D.5846>;
      <D.5846>:
      sem_post (&GC_suspend_ack_sem);
    }
  finally
    {
      dummy = {CLOBBER};
    }
}


GC_restart_handler (int sig)
{
  int * D.5972;
  int old_errno;

  D.5972 = __errno_location ();
  old_errno = *D.5972;
  _GC_restart_handler (sig);
  D.5972 = __errno_location ();
  *D.5972 = old_errno;
}


_GC_restart_handler (int sig)
{
  pthread_t my_thread;
  struct GC_Thread_Rep * me;

  my_thread = pthread_self ();
  if (sig != 24) goto <D.5973>; else goto <D.5974>;
  <D.5973>:
  GC_abort ("Bad signal in suspend_handler");
  <D.5974>:
  me = GC_lookup_thread (my_thread);
  me->stop_info.signal = 24;
}


GC_push_all_stacks ()
{
  pthread_push_all_stacks ();
}


pthread_push_all_stacks ()
{
  int GC_thr_initialized.2;
  short int D.5978;
  int D.5979;
  int D.5980;
  long unsigned int D.5983;
  int D.5984;
  int D.5988;
  char * D.5994;
  int D.5999;
  sizetype D.6000;
  char * D.6001;
  int GC_in_thread_creation.3;
  GC_bool found_me;
  int i;
  struct GC_Thread_Rep * p;
  char * lo;
  char * hi;
  pthread_t me;

  found_me = 0;
  me = pthread_self ();
  GC_thr_initialized.2 = GC_thr_initialized;
  if (GC_thr_initialized.2 == 0) goto <D.5976>; else goto <D.5977>;
  <D.5976>:
  GC_thr_init ();
  <D.5977>:
  i = 0;
  goto <D.5869>;
  <D.5868>:
  p = GC_threads[i];
  goto <D.5866>;
  <D.5865>:
  D.5978 = p->flags;
  D.5979 = (int) D.5978;
  D.5980 = D.5979 & 1;
  if (D.5980 != 0) goto <D.5981>; else goto <D.5982>;
  <D.5981>:
  // predicted unlikely by continue predictor.
  goto <D.5864>;
  <D.5982>:
  D.5983 = p->id;
  D.5984 = pthread_equal (D.5983, me);
  if (D.5984 != 0) goto <D.5985>; else goto <D.5986>;
  <D.5985>:
  lo = GC_approx_sp ();
  found_me = 1;
  goto <D.5987>;
  <D.5986>:
  lo = p->stop_info.stack_ptr;
  <D.5987>:
  D.5978 = p->flags;
  D.5979 = (int) D.5978;
  D.5988 = D.5979 & 4;
  if (D.5988 == 0) goto <D.5989>; else goto <D.5990>;
  <D.5989>:
  hi = p->stack_end;
  goto <D.5991>;
  <D.5990>:
  hi = GC_stackbottom;
  <D.5991>:
  if (lo == 0B) goto <D.5992>; else goto <D.5993>;
  <D.5992>:
  GC_abort ("GC_push_all_stacks: sp not set!\n");
  <D.5993>:
  D.5994 = p->altstack;
  if (D.5994 != 0B) goto <D.5995>; else goto <D.5996>;
  <D.5995>:
  D.5994 = p->altstack;
  if (D.5994 <= lo) goto <D.5997>; else goto <D.5998>;
  <D.5997>:
  D.5994 = p->altstack;
  D.5999 = p->altstack_size;
  D.6000 = (sizetype) D.5999;
  D.6001 = D.5994 + D.6000;
  if (D.6001 >= lo) goto <D.6002>; else goto <D.6003>;
  <D.6002>:
  D.5994 = p->altstack;
  D.5999 = p->altstack_size;
  D.6000 = (sizetype) D.5999;
  hi = D.5994 + D.6000;
  <D.6003>:
  <D.5998>:
  <D.5996>:
  GC_push_all_stack (lo, hi);
  <D.5864>:
  p = p->next;
  <D.5866>:
  if (p != 0B) goto <D.5865>; else goto <D.5867>;
  <D.5867>:
  i = i + 1;
  <D.5869>:
  if (i <= 127) goto <D.5868>; else goto <D.5870>;
  <D.5870>:
  if (found_me == 0) goto <D.6004>; else goto <D.6005>;
  <D.6004>:
  GC_in_thread_creation.3 = GC_in_thread_creation;
  if (GC_in_thread_creation.3 == 0) goto <D.6007>; else goto <D.6008>;
  <D.6007>:
  GC_abort ("Collecting from unknown thread.");
  <D.6008>:
  <D.6005>:
}


pthread_equal (pthread_t __thread1, pthread_t __thread2)
{
  int D.6009;
  _Bool D.6010;

  D.6010 = __thread1 == __thread2;
  D.6009 = (int) D.6010;
  return D.6009;
}


GC_suspend_all ()
{
  int GC_stopping_pid.4;
  long unsigned int D.6013;
  short int D.6016;
  int D.6017;
  int D.6018;
  long unsigned int D.6021;
  long unsigned int GC_stop_count.5;
  short int D.6025;
  int D.6028;
  int n_live_threads;
  int i;
  struct GC_Thread_Rep * p;
  int result;
  pthread_t my_thread;

  n_live_threads = 0;
  my_thread = pthread_self ();
  GC_stopping_thread = my_thread;
  GC_stopping_pid.4 = getpid ();
  GC_stopping_pid = GC_stopping_pid.4;
  i = 0;
  goto <D.5895>;
  <D.5894>:
  p = GC_threads[i];
  goto <D.5892>;
  <D.5891>:
  D.6013 = p->id;
  if (D.6013 != my_thread) goto <D.6014>; else goto <D.6015>;
  <D.6014>:
  D.6016 = p->flags;
  D.6017 = (int) D.6016;
  D.6018 = D.6017 & 1;
  if (D.6018 != 0) goto <D.6019>; else goto <D.6020>;
  <D.6019>:
  // predicted unlikely by continue predictor.
  goto <D.5886>;
  <D.6020>:
  D.6021 = p->stop_info.last_stop_count;
  GC_stop_count.5 = GC_stop_count;
  if (D.6021 == GC_stop_count.5) goto <D.6023>; else goto <D.6024>;
  <D.6023>:
  // predicted unlikely by continue predictor.
  goto <D.5886>;
  <D.6024>:
  D.6025 = p->thread_blocked;
  if (D.6025 != 0) goto <D.6026>; else goto <D.6027>;
  <D.6026>:
  // predicted unlikely by continue predictor.
  goto <D.5886>;
  <D.6027>:
  n_live_threads = n_live_threads + 1;
  D.6013 = p->id;
  result = pthread_kill (D.6013, 30);
  switch (result) <default: <D.5890>, case 0: <D.5889>, case 3: <D.5887>>
  <D.5887>:
  n_live_threads = n_live_threads + -1;
  goto <D.5888>;
  <D.5889>:
  goto <D.5888>;
  <D.5890>:
  GC_abort ("pthread_kill failed");
  <D.5888>:
  <D.6015>:
  <D.5886>:
  p = p->next;
  <D.5892>:
  if (p != 0B) goto <D.5891>; else goto <D.5893>;
  <D.5893>:
  i = i + 1;
  <D.5895>:
  if (i <= 127) goto <D.5894>; else goto <D.5896>;
  <D.5896>:
  D.6028 = n_live_threads;
  return D.6028;
}


GC_stop_world ()
{
  void (*<T39d>) (GCEventType) GC_notify_event.6;
  long unsigned int GC_stop_count.7;
  long unsigned int GC_stop_count.8;

  GC_notify_event.6 = GC_notify_event;
  if (GC_notify_event.6 != 0B) goto <D.6032>; else goto <D.6033>;
  <D.6032>:
  GC_notify_event.6 = GC_notify_event;
  GC_notify_event.6 (6);
  <D.6033>:
  GC_acquire_mark_lock ();
  GC_stop_count.7 = GC_stop_count;
  GC_stop_count.8 = GC_stop_count.7 + 1;
  GC_stop_count = GC_stop_count.8;
  pthread_stop_world ();
  GC_release_mark_lock ();
  GC_notify_event.6 = GC_notify_event;
  if (GC_notify_event.6 != 0B) goto <D.6036>; else goto <D.6037>;
  <D.6036>:
  GC_notify_event.6 = GC_notify_event;
  GC_notify_event.6 (7);
  <D.6037>:
}


pthread_stop_world ()
{
  int GC_retry_signals.9;
  int ack_count.10;
  int GC_print_stats.11;
  long int D.6048;
  int D.6049;
  void (*<T41a>) (char *, GC_word) GC_current_warn_proc.12;
  int * D.6053;
  int D.6054;
  long int D.6057;
  int i;
  int n_live_threads;
  int code;

  n_live_threads = GC_suspend_all ();
  GC_retry_signals.9 = GC_retry_signals;
  if (GC_retry_signals.9 != 0) goto <D.6039>; else goto <D.6040>;
  <D.6039>:
  {
    long unsigned int wait_usecs;

    wait_usecs = 0;
    <D.5906>:
    {
      int ack_count;

      try
        {
          sem_getvalue (&GC_suspend_ack_sem, &ack_count);
          ack_count.10 = ack_count;
          if (ack_count.10 == n_live_threads) goto <D.5904>; else goto <D.6042>;
          <D.6042>:
          if (wait_usecs > 100000) goto <D.6043>; else goto <D.6044>;
          <D.6043>:
          {
            int newly_sent;

            newly_sent = GC_suspend_all ();
            GC_print_stats.11 = GC_print_stats;
            if (GC_print_stats.11 != 0) goto <D.6046>; else goto <D.6047>;
            <D.6046>:
            D.6048 = (long int) newly_sent;
            GC_printf ("Resent %ld signals after timeout\n", D.6048, 0, 0, 0, 0, 0);
            <D.6047>:
            sem_getvalue (&GC_suspend_ack_sem, &ack_count);
            ack_count.10 = ack_count;
            D.6049 = n_live_threads - ack_count.10;
            if (D.6049 > newly_sent) goto <D.6050>; else goto <D.6051>;
            <D.6050>:
            GC_current_warn_proc.12 = GC_current_warn_proc;
            GC_current_warn_proc.12 ("GC Warning: Lost some threads during GC_stop_world?!\n", 0);
            ack_count.10 = ack_count;
            n_live_threads = ack_count.10 + newly_sent;
            <D.6051>:
            wait_usecs = 0;
          }
          <D.6044>:
          usleep (3000);
          wait_usecs = wait_usecs + 3000;
        }
      finally
        {
          ack_count = {CLOBBER};
        }
    }
    goto <D.5906>;
    <D.5904>:
  }
  <D.6040>:
  i = 0;
  goto <D.5911>;
  <D.5910>:
  goto <D.5908>;
  <D.5907>:
  D.6053 = __errno_location ();
  D.6054 = *D.6053;
  if (D.6054 != 4) goto <D.6055>; else goto <D.6056>;
  <D.6055>:
  D.6057 = (long int) code;
  GC_err_printf ("Sem_wait returned %ld\n", D.6057, 0, 0, 0, 0, 0);
  GC_abort ("sem_wait for handler failed");
  <D.6056>:
  <D.5908>:
  code = sem_wait (&GC_suspend_ack_sem);
  if (code != 0) goto <D.5907>; else goto <D.5909>;
  <D.5909>:
  i = i + 1;
  <D.5911>:
  if (i < n_live_threads) goto <D.5910>; else goto <D.5912>;
  <D.5912>:
  GC_stopping_thread = 0;
}


GC_start_world ()
{
  pthread_start_world ();
}


pthread_start_world ()
{
  void (*<T39d>) (GCEventType) GC_notify_event.13;
  long unsigned int D.6063;
  short int D.6066;
  int D.6067;
  int D.6068;
  short int D.6071;
  int * D.6074;
  int D.6075;
  long int D.6078;
  pthread_t my_thread;
  register int i;
  register struct GC_Thread_Rep * p;
  register int n_live_threads;
  register int result;
  int code;

  my_thread = pthread_self ();
  n_live_threads = 0;
  GC_notify_event.13 = GC_notify_event;
  if (GC_notify_event.13 != 0B) goto <D.6061>; else goto <D.6062>;
  <D.6061>:
  GC_notify_event.13 = GC_notify_event;
  GC_notify_event.13 (8);
  <D.6062>:
  i = 0;
  goto <D.5932>;
  <D.5931>:
  p = GC_threads[i];
  goto <D.5929>;
  <D.5928>:
  D.6063 = p->id;
  if (D.6063 != my_thread) goto <D.6064>; else goto <D.6065>;
  <D.6064>:
  D.6066 = p->flags;
  D.6067 = (int) D.6066;
  D.6068 = D.6067 & 1;
  if (D.6068 != 0) goto <D.6069>; else goto <D.6070>;
  <D.6069>:
  // predicted unlikely by continue predictor.
  goto <D.5923>;
  <D.6070>:
  D.6071 = p->thread_blocked;
  if (D.6071 != 0) goto <D.6072>; else goto <D.6073>;
  <D.6072>:
  // predicted unlikely by continue predictor.
  goto <D.5923>;
  <D.6073>:
  n_live_threads = n_live_threads + 1;
  D.6063 = p->id;
  result = pthread_kill (D.6063, 24);
  switch (result) <default: <D.5927>, case 0: <D.5926>, case 3: <D.5924>>
  <D.5924>:
  n_live_threads = n_live_threads + -1;
  goto <D.5925>;
  <D.5926>:
  goto <D.5925>;
  <D.5927>:
  GC_abort ("pthread_kill failed");
  <D.5925>:
  <D.6065>:
  <D.5923>:
  p = p->next;
  <D.5929>:
  if (p != 0B) goto <D.5928>; else goto <D.5930>;
  <D.5930>:
  i = i + 1;
  <D.5932>:
  if (i <= 127) goto <D.5931>; else goto <D.5933>;
  <D.5933>:
  i = 0;
  goto <D.5938>;
  <D.5937>:
  goto <D.5935>;
  <D.5934>:
  D.6074 = __errno_location ();
  D.6075 = *D.6074;
  if (D.6075 != 4) goto <D.6076>; else goto <D.6077>;
  <D.6076>:
  D.6078 = (long int) code;
  GC_err_printf ("Sem_wait returned %ld\n", D.6078, 0, 0, 0, 0, 0);
  GC_abort ("sem_wait for handler failed");
  <D.6077>:
  <D.5935>:
  code = sem_wait (&GC_suspend_ack_sem);
  if (code != 0) goto <D.5934>; else goto <D.5936>;
  <D.5936>:
  i = i + 1;
  <D.5938>:
  if (i < n_live_threads) goto <D.5937>; else goto <D.5939>;
  <D.5939>:
  GC_notify_event.13 = GC_notify_event;
  if (GC_notify_event.13 != 0B) goto <D.6079>; else goto <D.6080>;
  <D.6079>:
  GC_notify_event.13 = GC_notify_event;
  GC_notify_event.13 (9);
  <D.6080>:
}


GC_stop_init ()
{
  pthread_stop_init ();
}


pthread_stop_init ()
{
  int D.6082;
  int D.6085;
  int D.6088;
  int D.6091;
  int D.6094;
  int D.6097;
  char * D.6100;
  char * D.6103;
  int GC_print_stats.14;
  int GC_retry_signals.15;
  struct sigaction act;

  try
    {
      D.6082 = sem_init (&GC_suspend_ack_sem, 0, 0);
      if (D.6082 != 0) goto <D.6083>; else goto <D.6084>;
      <D.6083>:
      GC_abort ("sem_init failed");
      <D.6084>:
      act.sa_flags = 268435456;
      D.6085 = sigfillset (&act.sa_mask);
      if (D.6085 != 0) goto <D.6086>; else goto <D.6087>;
      <D.6086>:
      GC_abort ("sigfillset() failed");
      <D.6087>:
      GC_remove_allowed_signals (&act.sa_mask);
      act.__sigaction_handler.sa_handler = GC_suspend_handler;
      D.6088 = sigaction (30, &act, 0B);
      if (D.6088 != 0) goto <D.6089>; else goto <D.6090>;
      <D.6089>:
      GC_abort ("Cannot set SIG_SUSPEND handler");
      <D.6090>:
      act.__sigaction_handler.sa_handler = GC_restart_handler;
      D.6091 = sigaction (24, &act, 0B);
      if (D.6091 != 0) goto <D.6092>; else goto <D.6093>;
      <D.6092>:
      GC_abort ("Cannot set SIG_THR_RESTART handler");
      <D.6093>:
      D.6094 = sigfillset (&suspend_handler_mask);
      if (D.6094 != 0) goto <D.6095>; else goto <D.6096>;
      <D.6095>:
      GC_abort ("sigfillset() failed");
      <D.6096>:
      GC_remove_allowed_signals (&suspend_handler_mask);
      D.6097 = sigdelset (&suspend_handler_mask, 24);
      if (D.6097 != 0) goto <D.6098>; else goto <D.6099>;
      <D.6098>:
      GC_abort ("sigdelset() failed");
      <D.6099>:
      D.6100 = getenv ("GC_RETRY_SIGNALS");
      if (D.6100 != 0B) goto <D.6101>; else goto <D.6102>;
      <D.6101>:
      GC_retry_signals = 1;
      <D.6102>:
      D.6103 = getenv ("GC_NO_RETRY_SIGNALS");
      if (D.6103 != 0B) goto <D.6104>; else goto <D.6105>;
      <D.6104>:
      GC_retry_signals = 0;
      <D.6105>:
      GC_print_stats.14 = GC_print_stats;
      if (GC_print_stats.14 != 0) goto <D.6107>; else goto <D.6108>;
      <D.6107>:
      GC_retry_signals.15 = GC_retry_signals;
      if (GC_retry_signals.15 != 0) goto <D.6110>; else goto <D.6111>;
      <D.6110>:
      GC_printf ("Will retry suspend signal if necessary.\n", 0, 0, 0, 0, 0, 0);
      <D.6111>:
      <D.6108>:
    }
  finally
    {
      act = {CLOBBER};
    }
}


