GC_remove_allowed_signals (struct sigset_t * set)
{
  int D.6035;
  int D.6037;
  int D.6039;
  int D.6041;

  D.6035 = sigdelset (set, 2);
  if (D.6035 != 0) goto <D.6033>; else goto <D.6036>;
  <D.6036>:
  D.6037 = sigdelset (set, 3);
  if (D.6037 != 0) goto <D.6033>; else goto <D.6038>;
  <D.6038>:
  D.6039 = sigdelset (set, 6);
  if (D.6039 != 0) goto <D.6033>; else goto <D.6040>;
  <D.6040>:
  D.6041 = sigdelset (set, 15);
  if (D.6041 != 0) goto <D.6033>; else goto <D.6034>;
  <D.6033>:
  GC_abort ("sigdelset() failed");
  <D.6034>:
}


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

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


_GC_suspend_handler (int sig)
{
  long unsigned int D.6045;
  int GC_retry_signals.0;
  void (*<T490>) (char *, GC_word) GC_current_warn_proc.1;
  long unsigned int D.6052;
  int D.6053;
  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.6043>; else goto <D.6044>;
      <D.6043>:
      GC_abort ("Bad signal in suspend_handler");
      <D.6044>:
      me = GC_lookup_thread (my_thread);
      D.6045 = me->stop_info.last_stop_count;
      if (D.6045 == my_stop_count) goto <D.6046>; else goto <D.6047>;
      <D.6046>:
      GC_retry_signals.0 = GC_retry_signals;
      if (GC_retry_signals.0 == 0) goto <D.6049>; else goto <D.6050>;
      <D.6049>:
      GC_current_warn_proc.1 = GC_current_warn_proc;
      D.6052 = pthread_self ();
      GC_current_warn_proc.1 ("GC Warning: Duplicate suspend signal in thread %lx\n", D.6052);
      <D.6050>:
      return;
      <D.6047>:
      me->stop_info.stack_ptr = &dummy;
      sem_post (&GC_suspend_ack_sem);
      me->stop_info.last_stop_count = my_stop_count;
      <D.5930>:
      me->stop_info.signal = 0;
      sigsuspend (&suspend_handler_mask);
      D.6053 = me->stop_info.signal;
      if (D.6053 != 24) goto <D.5930>; else goto <D.5931>;
      <D.5931>:
      sem_post (&GC_suspend_ack_sem);
    }
  finally
    {
      dummy = {CLOBBER};
    }
}


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

  D.6057 = __errno_location ();
  old_errno = *D.6057;
  _GC_restart_handler (sig);
  D.6057 = __errno_location ();
  *D.6057 = 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.6058>; else goto <D.6059>;
  <D.6058>:
  GC_abort ("Bad signal in suspend_handler");
  <D.6059>:
  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.6063;
  int D.6064;
  int D.6065;
  long unsigned int D.6068;
  int D.6069;
  int D.6073;
  char * D.6079;
  int D.6084;
  sizetype D.6085;
  char * D.6086;
  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.6061>; else goto <D.6062>;
  <D.6061>:
  GC_thr_init ();
  <D.6062>:
  i = 0;
  goto <D.5954>;
  <D.5953>:
  p = GC_threads[i];
  goto <D.5951>;
  <D.5950>:
  D.6063 = p->flags;
  D.6064 = (int) D.6063;
  D.6065 = D.6064 & 1;
  if (D.6065 != 0) goto <D.6066>; else goto <D.6067>;
  <D.6066>:
  // predicted unlikely by continue predictor.
  goto <D.5949>;
  <D.6067>:
  D.6068 = p->id;
  D.6069 = pthread_equal (D.6068, me);
  if (D.6069 != 0) goto <D.6070>; else goto <D.6071>;
  <D.6070>:
  lo = GC_approx_sp ();
  found_me = 1;
  goto <D.6072>;
  <D.6071>:
  lo = p->stop_info.stack_ptr;
  <D.6072>:
  D.6063 = p->flags;
  D.6064 = (int) D.6063;
  D.6073 = D.6064 & 4;
  if (D.6073 == 0) goto <D.6074>; else goto <D.6075>;
  <D.6074>:
  hi = p->stack_end;
  goto <D.6076>;
  <D.6075>:
  hi = GC_stackbottom;
  <D.6076>:
  if (lo == 0B) goto <D.6077>; else goto <D.6078>;
  <D.6077>:
  GC_abort ("GC_push_all_stacks: sp not set!\n");
  <D.6078>:
  D.6079 = p->altstack;
  if (D.6079 != 0B) goto <D.6080>; else goto <D.6081>;
  <D.6080>:
  D.6079 = p->altstack;
  if (D.6079 <= lo) goto <D.6082>; else goto <D.6083>;
  <D.6082>:
  D.6079 = p->altstack;
  D.6084 = p->altstack_size;
  D.6085 = (sizetype) D.6084;
  D.6086 = D.6079 + D.6085;
  if (D.6086 >= lo) goto <D.6087>; else goto <D.6088>;
  <D.6087>:
  D.6079 = p->altstack;
  D.6084 = p->altstack_size;
  D.6085 = (sizetype) D.6084;
  hi = D.6079 + D.6085;
  <D.6088>:
  <D.6083>:
  <D.6081>:
  GC_push_all_stack (lo, hi);
  <D.5949>:
  p = p->next;
  <D.5951>:
  if (p != 0B) goto <D.5950>; else goto <D.5952>;
  <D.5952>:
  i = i + 1;
  <D.5954>:
  if (i <= 127) goto <D.5953>; else goto <D.5955>;
  <D.5955>:
  if (found_me == 0) goto <D.6089>; else goto <D.6090>;
  <D.6089>:
  GC_in_thread_creation.3 = GC_in_thread_creation;
  if (GC_in_thread_creation.3 == 0) goto <D.6092>; else goto <D.6093>;
  <D.6092>:
  GC_abort ("Collecting from unknown thread.");
  <D.6093>:
  <D.6090>:
}


__attribute__((__gnu_inline__, const, __leaf__, __nothrow__))
pthread_equal (pthread_t __thread1, pthread_t __thread2)
{
  int D.6094;
  _Bool D.6095;

  D.6095 = __thread1 == __thread2;
  D.6094 = (int) D.6095;
  return D.6094;
}


GC_suspend_all ()
{
  int D.6097;
  long unsigned int D.6098;
  short int D.6101;
  int D.6102;
  int D.6103;
  long unsigned int D.6106;
  long unsigned int GC_stop_count.4;
  short int D.6110;
  int D.6113;
  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;
  D.6097 = getpid ();
  GC_stopping_pid = D.6097;
  i = 0;
  goto <D.5980>;
  <D.5979>:
  p = GC_threads[i];
  goto <D.5977>;
  <D.5976>:
  D.6098 = p->id;
  if (D.6098 != my_thread) goto <D.6099>; else goto <D.6100>;
  <D.6099>:
  D.6101 = p->flags;
  D.6102 = (int) D.6101;
  D.6103 = D.6102 & 1;
  if (D.6103 != 0) goto <D.6104>; else goto <D.6105>;
  <D.6104>:
  // predicted unlikely by continue predictor.
  goto <D.5971>;
  <D.6105>:
  D.6106 = p->stop_info.last_stop_count;
  GC_stop_count.4 = GC_stop_count;
  if (D.6106 == GC_stop_count.4) goto <D.6108>; else goto <D.6109>;
  <D.6108>:
  // predicted unlikely by continue predictor.
  goto <D.5971>;
  <D.6109>:
  D.6110 = p->thread_blocked;
  if (D.6110 != 0) goto <D.6111>; else goto <D.6112>;
  <D.6111>:
  // predicted unlikely by continue predictor.
  goto <D.5971>;
  <D.6112>:
  n_live_threads = n_live_threads + 1;
  D.6098 = p->id;
  result = pthread_kill (D.6098, 30);
  switch (result) <default: <D.5975>, case 0: <D.5974>, case 3: <D.5972>>
  <D.5972>:
  n_live_threads = n_live_threads + -1;
  goto <D.5973>;
  <D.5974>:
  goto <D.5973>;
  <D.5975>:
  GC_abort ("pthread_kill failed");
  <D.5973>:
  <D.6100>:
  <D.5971>:
  p = p->next;
  <D.5977>:
  if (p != 0B) goto <D.5976>; else goto <D.5978>;
  <D.5978>:
  i = i + 1;
  <D.5980>:
  if (i <= 127) goto <D.5979>; else goto <D.5981>;
  <D.5981>:
  D.6113 = n_live_threads;
  return D.6113;
}


GC_stop_world ()
{
  void (*<T413>) (GCEventType) GC_notify_event.5;
  long unsigned int GC_stop_count.6;
  long unsigned int D.6120;

  GC_notify_event.5 = GC_notify_event;
  if (GC_notify_event.5 != 0B) goto <D.6117>; else goto <D.6118>;
  <D.6117>:
  GC_notify_event.5 = GC_notify_event;
  GC_notify_event.5 (6);
  <D.6118>:
  GC_acquire_mark_lock ();
  GC_stop_count.6 = GC_stop_count;
  D.6120 = GC_stop_count.6 + 1;
  GC_stop_count = D.6120;
  pthread_stop_world ();
  GC_release_mark_lock ();
  GC_notify_event.5 = GC_notify_event;
  if (GC_notify_event.5 != 0B) goto <D.6121>; else goto <D.6122>;
  <D.6121>:
  GC_notify_event.5 = GC_notify_event;
  GC_notify_event.5 (7);
  <D.6122>:
}


pthread_stop_world ()
{
  int GC_retry_signals.7;
  int ack_count.8;
  int GC_print_stats.9;
  long int D.6133;
  int D.6134;
  void (*<T490>) (char *, GC_word) GC_current_warn_proc.10;
  int * D.6138;
  int D.6139;
  long int D.6142;
  int i;
  int n_live_threads;
  int code;

  n_live_threads = GC_suspend_all ();
  GC_retry_signals.7 = GC_retry_signals;
  if (GC_retry_signals.7 != 0) goto <D.6124>; else goto <D.6125>;
  <D.6124>:
  {
    long unsigned int wait_usecs;

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

      try
        {
          sem_getvalue (&GC_suspend_ack_sem, &ack_count);
          ack_count.8 = ack_count;
          if (ack_count.8 == n_live_threads) goto <D.5989>; else goto <D.6127>;
          <D.6127>:
          if (wait_usecs > 100000) goto <D.6128>; else goto <D.6129>;
          <D.6128>:
          {
            int newly_sent;

            newly_sent = GC_suspend_all ();
            GC_print_stats.9 = GC_print_stats;
            if (GC_print_stats.9 != 0) goto <D.6131>; else goto <D.6132>;
            <D.6131>:
            D.6133 = (long int) newly_sent;
            GC_printf ("Resent %ld signals after timeout\n", D.6133, 0, 0, 0, 0, 0);
            <D.6132>:
            sem_getvalue (&GC_suspend_ack_sem, &ack_count);
            ack_count.8 = ack_count;
            D.6134 = n_live_threads - ack_count.8;
            if (D.6134 > newly_sent) goto <D.6135>; else goto <D.6136>;
            <D.6135>:
            GC_current_warn_proc.10 = GC_current_warn_proc;
            GC_current_warn_proc.10 ("GC Warning: Lost some threads during GC_stop_world?!\n", 0);
            ack_count.8 = ack_count;
            n_live_threads = ack_count.8 + newly_sent;
            <D.6136>:
            wait_usecs = 0;
          }
          <D.6129>:
          usleep (3000);
          wait_usecs = wait_usecs + 3000;
        }
      finally
        {
          ack_count = {CLOBBER};
        }
    }
    goto <D.5991>;
    <D.5989>:
  }
  <D.6125>:
  i = 0;
  goto <D.5996>;
  <D.5995>:
  goto <D.5993>;
  <D.5992>:
  D.6138 = __errno_location ();
  D.6139 = *D.6138;
  if (D.6139 != 4) goto <D.6140>; else goto <D.6141>;
  <D.6140>:
  D.6142 = (long int) code;
  GC_err_printf ("Sem_wait returned %ld\n", D.6142, 0, 0, 0, 0, 0);
  GC_abort ("sem_wait for handler failed");
  <D.6141>:
  <D.5993>:
  code = sem_wait (&GC_suspend_ack_sem);
  if (code != 0) goto <D.5992>; else goto <D.5994>;
  <D.5994>:
  i = i + 1;
  <D.5996>:
  if (i < n_live_threads) goto <D.5995>; else goto <D.5997>;
  <D.5997>:
  GC_stopping_thread = 0;
}


GC_start_world ()
{
  pthread_start_world ();
}


pthread_start_world ()
{
  void (*<T413>) (GCEventType) GC_notify_event.11;
  long unsigned int D.6148;
  short int D.6151;
  int D.6152;
  int D.6153;
  short int D.6156;
  int * D.6159;
  int D.6160;
  long int D.6163;
  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.11 = GC_notify_event;
  if (GC_notify_event.11 != 0B) goto <D.6146>; else goto <D.6147>;
  <D.6146>:
  GC_notify_event.11 = GC_notify_event;
  GC_notify_event.11 (8);
  <D.6147>:
  i = 0;
  goto <D.6017>;
  <D.6016>:
  p = GC_threads[i];
  goto <D.6014>;
  <D.6013>:
  D.6148 = p->id;
  if (D.6148 != my_thread) goto <D.6149>; else goto <D.6150>;
  <D.6149>:
  D.6151 = p->flags;
  D.6152 = (int) D.6151;
  D.6153 = D.6152 & 1;
  if (D.6153 != 0) goto <D.6154>; else goto <D.6155>;
  <D.6154>:
  // predicted unlikely by continue predictor.
  goto <D.6008>;
  <D.6155>:
  D.6156 = p->thread_blocked;
  if (D.6156 != 0) goto <D.6157>; else goto <D.6158>;
  <D.6157>:
  // predicted unlikely by continue predictor.
  goto <D.6008>;
  <D.6158>:
  n_live_threads = n_live_threads + 1;
  D.6148 = p->id;
  result = pthread_kill (D.6148, 24);
  switch (result) <default: <D.6012>, case 0: <D.6011>, case 3: <D.6009>>
  <D.6009>:
  n_live_threads = n_live_threads + -1;
  goto <D.6010>;
  <D.6011>:
  goto <D.6010>;
  <D.6012>:
  GC_abort ("pthread_kill failed");
  <D.6010>:
  <D.6150>:
  <D.6008>:
  p = p->next;
  <D.6014>:
  if (p != 0B) goto <D.6013>; else goto <D.6015>;
  <D.6015>:
  i = i + 1;
  <D.6017>:
  if (i <= 127) goto <D.6016>; else goto <D.6018>;
  <D.6018>:
  i = 0;
  goto <D.6023>;
  <D.6022>:
  goto <D.6020>;
  <D.6019>:
  D.6159 = __errno_location ();
  D.6160 = *D.6159;
  if (D.6160 != 4) goto <D.6161>; else goto <D.6162>;
  <D.6161>:
  D.6163 = (long int) code;
  GC_err_printf ("Sem_wait returned %ld\n", D.6163, 0, 0, 0, 0, 0);
  GC_abort ("sem_wait for handler failed");
  <D.6162>:
  <D.6020>:
  code = sem_wait (&GC_suspend_ack_sem);
  if (code != 0) goto <D.6019>; else goto <D.6021>;
  <D.6021>:
  i = i + 1;
  <D.6023>:
  if (i < n_live_threads) goto <D.6022>; else goto <D.6024>;
  <D.6024>:
  GC_notify_event.11 = GC_notify_event;
  if (GC_notify_event.11 != 0B) goto <D.6164>; else goto <D.6165>;
  <D.6164>:
  GC_notify_event.11 = GC_notify_event;
  GC_notify_event.11 (9);
  <D.6165>:
}


GC_stop_init ()
{
  pthread_stop_init ();
}


pthread_stop_init ()
{
  int D.6167;
  int D.6170;
  int D.6173;
  int D.6176;
  int D.6179;
  int D.6182;
  char * D.6185;
  char * D.6188;
  int GC_print_stats.12;
  int GC_retry_signals.13;
  struct sigaction act;

  try
    {
      D.6167 = sem_init (&GC_suspend_ack_sem, 0, 0);
      if (D.6167 != 0) goto <D.6168>; else goto <D.6169>;
      <D.6168>:
      GC_abort ("sem_init failed");
      <D.6169>:
      act.sa_flags = 268435456;
      D.6170 = sigfillset (&act.sa_mask);
      if (D.6170 != 0) goto <D.6171>; else goto <D.6172>;
      <D.6171>:
      GC_abort ("sigfillset() failed");
      <D.6172>:
      GC_remove_allowed_signals (&act.sa_mask);
      act.__sigaction_handler.sa_handler = GC_suspend_handler;
      D.6173 = sigaction (30, &act, 0B);
      if (D.6173 != 0) goto <D.6174>; else goto <D.6175>;
      <D.6174>:
      GC_abort ("Cannot set SIG_SUSPEND handler");
      <D.6175>:
      act.__sigaction_handler.sa_handler = GC_restart_handler;
      D.6176 = sigaction (24, &act, 0B);
      if (D.6176 != 0) goto <D.6177>; else goto <D.6178>;
      <D.6177>:
      GC_abort ("Cannot set SIG_THR_RESTART handler");
      <D.6178>:
      D.6179 = sigfillset (&suspend_handler_mask);
      if (D.6179 != 0) goto <D.6180>; else goto <D.6181>;
      <D.6180>:
      GC_abort ("sigfillset() failed");
      <D.6181>:
      GC_remove_allowed_signals (&suspend_handler_mask);
      D.6182 = sigdelset (&suspend_handler_mask, 24);
      if (D.6182 != 0) goto <D.6183>; else goto <D.6184>;
      <D.6183>:
      GC_abort ("sigdelset() failed");
      <D.6184>:
      D.6185 = getenv ("GC_RETRY_SIGNALS");
      if (D.6185 != 0B) goto <D.6186>; else goto <D.6187>;
      <D.6186>:
      GC_retry_signals = 1;
      <D.6187>:
      D.6188 = getenv ("GC_NO_RETRY_SIGNALS");
      if (D.6188 != 0B) goto <D.6189>; else goto <D.6190>;
      <D.6189>:
      GC_retry_signals = 0;
      <D.6190>:
      GC_print_stats.12 = GC_print_stats;
      if (GC_print_stats.12 != 0) goto <D.6192>; else goto <D.6193>;
      <D.6192>:
      GC_retry_signals.13 = GC_retry_signals;
      if (GC_retry_signals.13 != 0) goto <D.6195>; else goto <D.6196>;
      <D.6195>:
      GC_printf ("Will retry suspend signal if necessary.\n", 0, 0, 0, 0, 0, 0);
      <D.6196>:
      <D.6193>:
    }
  finally
    {
      act = {CLOBBER};
    }
}


