GC_remove_allowed_signals (struct sigset_t * set)
{
  int D.8112;
  int D.8114;
  int D.8116;
  int D.8118;

  D.8112 = sigdelset (set, 2);
  if (D.8112 != 0) goto <D.8110>; else goto <D.8113>;
  <D.8113>:
  D.8114 = sigdelset (set, 3);
  if (D.8114 != 0) goto <D.8110>; else goto <D.8115>;
  <D.8115>:
  D.8116 = sigdelset (set, 6);
  if (D.8116 != 0) goto <D.8110>; else goto <D.8117>;
  <D.8117>:
  D.8118 = sigdelset (set, 15);
  if (D.8118 != 0) goto <D.8110>; else goto <D.8111>;
  <D.8110>:
  GC_abort ("sigdelset() failed");
  <D.8111>:
}


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

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


_GC_suspend_handler (int sig)
{
  long unsigned int D.8122;
  int GC_retry_signals.0;
  void (*<Tdd1>) (char *, GC_word) GC_current_warn_proc.1;
  long unsigned int D.8129;
  int D.8130;
  int dummy;
  pthread_t my_thread;
  struct GC_Thread_Rep * me;
  word my_stop_count;

  try
    {
      my_thread = pthread_self ();
      my_stop_count = GC_stop_count;
      if (sig != 30) goto <D.8120>; else goto <D.8121>;
      <D.8120>:
      GC_abort ("Bad signal in suspend_handler");
      <D.8121>:
      me = GC_lookup_thread (my_thread);
      D.8122 = me->stop_info.last_stop_count;
      if (D.8122 == my_stop_count) goto <D.8123>; else goto <D.8124>;
      <D.8123>:
      GC_retry_signals.0 = GC_retry_signals;
      if (GC_retry_signals.0 == 0) goto <D.8126>; else goto <D.8127>;
      <D.8126>:
      GC_current_warn_proc.1 = GC_current_warn_proc;
      D.8129 = pthread_self ();
      GC_current_warn_proc.1 ("GC Warning: Duplicate suspend signal in thread %lx\n", D.8129);
      <D.8127>:
      return;
      <D.8124>:
      me->stop_info.stack_ptr = &dummy;
      sem_post (&GC_suspend_ack_sem);
      me->stop_info.last_stop_count = my_stop_count;
      <D.8005>:
      me->stop_info.signal = 0;
      sigsuspend (&suspend_handler_mask);
      D.8130 = me->stop_info.signal;
      if (D.8130 != 24) goto <D.8005>; else goto <D.8006>;
      <D.8006>:
      sem_post (&GC_suspend_ack_sem);
    }
  finally
    {
      dummy = {CLOBBER};
    }
}


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

  D.8134 = __errno_location ();
  old_errno = *D.8134;
  _GC_restart_handler (sig);
  D.8134 = __errno_location ();
  *D.8134 = 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.8135>; else goto <D.8136>;
  <D.8135>:
  GC_abort ("Bad signal in suspend_handler");
  <D.8136>:
  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.8140;
  unsigned short D.8141;
  int D.8142;
  int D.8143;
  long unsigned int D.8146;
  int D.8147;
  int D.8151;
  char * D.8157;
  int D.8162;
  sizetype D.8163;
  char * D.8164;
  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.8138>; else goto <D.8139>;
  <D.8138>:
  GC_thr_init ();
  <D.8139>:
  i = 0;
  goto <D.8029>;
  <D.8028>:
  p = GC_threads[i];
  goto <D.8026>;
  <D.8025>:
  D.8140 = p->flags;
  D.8141 = (unsigned short) D.8140;
  D.8142 = (int) D.8141;
  D.8143 = D.8142 & 1;
  if (D.8143 != 0) goto <D.8144>; else goto <D.8145>;
  <D.8144>:
  // predicted unlikely by continue predictor.
  goto <D.8024>;
  <D.8145>:
  D.8146 = p->id;
  D.8147 = pthread_equal (D.8146, me);
  if (D.8147 != 0) goto <D.8148>; else goto <D.8149>;
  <D.8148>:
  lo = GC_approx_sp ();
  found_me = 1;
  goto <D.8150>;
  <D.8149>:
  lo = p->stop_info.stack_ptr;
  <D.8150>:
  D.8140 = p->flags;
  D.8141 = (unsigned short) D.8140;
  D.8142 = (int) D.8141;
  D.8151 = D.8142 & 4;
  if (D.8151 == 0) goto <D.8152>; else goto <D.8153>;
  <D.8152>:
  hi = p->stack_end;
  goto <D.8154>;
  <D.8153>:
  hi = GC_stackbottom;
  <D.8154>:
  if (lo == 0B) goto <D.8155>; else goto <D.8156>;
  <D.8155>:
  GC_abort ("GC_push_all_stacks: sp not set!\n");
  <D.8156>:
  D.8157 = p->altstack;
  if (D.8157 != 0B) goto <D.8158>; else goto <D.8159>;
  <D.8158>:
  D.8157 = p->altstack;
  if (D.8157 <= lo) goto <D.8160>; else goto <D.8161>;
  <D.8160>:
  D.8157 = p->altstack;
  D.8162 = p->altstack_size;
  D.8163 = (sizetype) D.8162;
  D.8164 = D.8157 + D.8163;
  if (D.8164 >= lo) goto <D.8165>; else goto <D.8166>;
  <D.8165>:
  D.8157 = p->altstack;
  D.8162 = p->altstack_size;
  D.8163 = (sizetype) D.8162;
  hi = D.8157 + D.8163;
  <D.8166>:
  <D.8161>:
  <D.8159>:
  GC_push_all_stack (lo, hi);
  <D.8024>:
  p = p->next;
  <D.8026>:
  if (p != 0B) goto <D.8025>; else goto <D.8027>;
  <D.8027>:
  i = i + 1;
  <D.8029>:
  if (i <= 127) goto <D.8028>; else goto <D.8030>;
  <D.8030>:
  if (found_me == 0) goto <D.8167>; else goto <D.8168>;
  <D.8167>:
  GC_in_thread_creation.3 = GC_in_thread_creation;
  if (GC_in_thread_creation.3 == 0) goto <D.8170>; else goto <D.8171>;
  <D.8170>:
  GC_abort ("Collecting from unknown thread.");
  <D.8171>:
  <D.8168>:
}


pthread_equal (pthread_t __thread1, pthread_t __thread2)
{
  int D.8172;
  _Bool D.8173;

  D.8173 = __thread1 == __thread2;
  D.8172 = (int) D.8173;
  return D.8172;
}


GC_suspend_all ()
{
  int GC_stopping_pid.4;
  long unsigned int D.8176;
  short int D.8179;
  unsigned short D.8180;
  int D.8181;
  int D.8182;
  long unsigned int D.8185;
  long unsigned int GC_stop_count.5;
  short int D.8189;
  int D.8192;
  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.8055>;
  <D.8054>:
  p = GC_threads[i];
  goto <D.8052>;
  <D.8051>:
  D.8176 = p->id;
  if (D.8176 != my_thread) goto <D.8177>; else goto <D.8178>;
  <D.8177>:
  D.8179 = p->flags;
  D.8180 = (unsigned short) D.8179;
  D.8181 = (int) D.8180;
  D.8182 = D.8181 & 1;
  if (D.8182 != 0) goto <D.8183>; else goto <D.8184>;
  <D.8183>:
  // predicted unlikely by continue predictor.
  goto <D.8046>;
  <D.8184>:
  D.8185 = p->stop_info.last_stop_count;
  GC_stop_count.5 = GC_stop_count;
  if (D.8185 == GC_stop_count.5) goto <D.8187>; else goto <D.8188>;
  <D.8187>:
  // predicted unlikely by continue predictor.
  goto <D.8046>;
  <D.8188>:
  D.8189 = p->thread_blocked;
  if (D.8189 != 0) goto <D.8190>; else goto <D.8191>;
  <D.8190>:
  // predicted unlikely by continue predictor.
  goto <D.8046>;
  <D.8191>:
  n_live_threads = n_live_threads + 1;
  D.8176 = p->id;
  result = pthread_kill (D.8176, 30);
  switch (result) <default: <D.8050>, case 0: <D.8049>, case 3: <D.8047>>
  <D.8047>:
  n_live_threads = n_live_threads + -1;
  goto <D.8048>;
  <D.8049>:
  goto <D.8048>;
  <D.8050>:
  GC_abort ("pthread_kill failed");
  <D.8048>:
  <D.8178>:
  <D.8046>:
  p = p->next;
  <D.8052>:
  if (p != 0B) goto <D.8051>; else goto <D.8053>;
  <D.8053>:
  i = i + 1;
  <D.8055>:
  if (i <= 127) goto <D.8054>; else goto <D.8056>;
  <D.8056>:
  D.8192 = n_live_threads;
  return D.8192;
}


GC_stop_world ()
{
  void (*<Td54>) (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.8196>; else goto <D.8197>;
  <D.8196>:
  GC_notify_event.6 = GC_notify_event;
  GC_notify_event.6 (6);
  <D.8197>:
  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_notify_event.6 = GC_notify_event;
  if (GC_notify_event.6 != 0B) goto <D.8200>; else goto <D.8201>;
  <D.8200>:
  GC_notify_event.6 = GC_notify_event;
  GC_notify_event.6 (7);
  <D.8201>:
}


pthread_stop_world ()
{
  int GC_retry_signals.9;
  int ack_count.10;
  int GC_print_stats.11;
  int D.8212;
  void (*<Tdd1>) (char *, GC_word) GC_current_warn_proc.12;
  int * D.8216;
  int D.8217;
  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.8203>; else goto <D.8204>;
  <D.8203>:
  {
    long unsigned int wait_usecs;

    wait_usecs = 0;
    <D.8066>:
    {
      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.8064>; else goto <D.8206>;
          <D.8206>:
          if (wait_usecs > 100000) goto <D.8207>; else goto <D.8208>;
          <D.8207>:
          {
            int newly_sent;

            newly_sent = GC_suspend_all ();
            GC_print_stats.11 = GC_print_stats;
            if (GC_print_stats.11 != 0) goto <D.8210>; else goto <D.8211>;
            <D.8210>:
            GC_printf ("Resent %ld signals after timeout\n", newly_sent, 0, 0, 0, 0, 0);
            <D.8211>:
            sem_getvalue (&GC_suspend_ack_sem, &ack_count);
            ack_count.10 = ack_count;
            D.8212 = n_live_threads - ack_count.10;
            if (D.8212 > newly_sent) goto <D.8213>; else goto <D.8214>;
            <D.8213>:
            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.8214>:
            wait_usecs = 0;
          }
          <D.8208>:
          usleep (3000);
          wait_usecs = wait_usecs + 3000;
        }
      finally
        {
          ack_count = {CLOBBER};
        }
    }
    goto <D.8066>;
    <D.8064>:
  }
  <D.8204>:
  i = 0;
  goto <D.8071>;
  <D.8070>:
  goto <D.8068>;
  <D.8067>:
  D.8216 = __errno_location ();
  D.8217 = *D.8216;
  if (D.8217 != 4) goto <D.8218>; else goto <D.8219>;
  <D.8218>:
  GC_err_printf ("Sem_wait returned %ld\n", code, 0, 0, 0, 0, 0);
  GC_abort ("sem_wait for handler failed");
  <D.8219>:
  <D.8068>:
  code = sem_wait (&GC_suspend_ack_sem);
  if (code != 0) goto <D.8067>; else goto <D.8069>;
  <D.8069>:
  i = i + 1;
  <D.8071>:
  if (i < n_live_threads) goto <D.8070>; else goto <D.8072>;
  <D.8072>:
  GC_stopping_thread = 0;
}


GC_start_world ()
{
  pthread_start_world ();
}


pthread_start_world ()
{
  void (*<Td54>) (GCEventType) GC_notify_event.13;
  long unsigned int D.8225;
  short int D.8228;
  unsigned short D.8229;
  int D.8230;
  int D.8231;
  short int D.8234;
  int * D.8237;
  int D.8238;
  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.8223>; else goto <D.8224>;
  <D.8223>:
  GC_notify_event.13 = GC_notify_event;
  GC_notify_event.13 (8);
  <D.8224>:
  i = 0;
  goto <D.8092>;
  <D.8091>:
  p = GC_threads[i];
  goto <D.8089>;
  <D.8088>:
  D.8225 = p->id;
  if (D.8225 != my_thread) goto <D.8226>; else goto <D.8227>;
  <D.8226>:
  D.8228 = p->flags;
  D.8229 = (unsigned short) D.8228;
  D.8230 = (int) D.8229;
  D.8231 = D.8230 & 1;
  if (D.8231 != 0) goto <D.8232>; else goto <D.8233>;
  <D.8232>:
  // predicted unlikely by continue predictor.
  goto <D.8083>;
  <D.8233>:
  D.8234 = p->thread_blocked;
  if (D.8234 != 0) goto <D.8235>; else goto <D.8236>;
  <D.8235>:
  // predicted unlikely by continue predictor.
  goto <D.8083>;
  <D.8236>:
  n_live_threads = n_live_threads + 1;
  D.8225 = p->id;
  result = pthread_kill (D.8225, 24);
  switch (result) <default: <D.8087>, case 0: <D.8086>, case 3: <D.8084>>
  <D.8084>:
  n_live_threads = n_live_threads + -1;
  goto <D.8085>;
  <D.8086>:
  goto <D.8085>;
  <D.8087>:
  GC_abort ("pthread_kill failed");
  <D.8085>:
  <D.8227>:
  <D.8083>:
  p = p->next;
  <D.8089>:
  if (p != 0B) goto <D.8088>; else goto <D.8090>;
  <D.8090>:
  i = i + 1;
  <D.8092>:
  if (i <= 127) goto <D.8091>; else goto <D.8093>;
  <D.8093>:
  i = 0;
  goto <D.8098>;
  <D.8097>:
  goto <D.8095>;
  <D.8094>:
  D.8237 = __errno_location ();
  D.8238 = *D.8237;
  if (D.8238 != 4) goto <D.8239>; else goto <D.8240>;
  <D.8239>:
  GC_err_printf ("Sem_wait returned %ld\n", code, 0, 0, 0, 0, 0);
  GC_abort ("sem_wait for handler failed");
  <D.8240>:
  <D.8095>:
  code = sem_wait (&GC_suspend_ack_sem);
  if (code != 0) goto <D.8094>; else goto <D.8096>;
  <D.8096>:
  i = i + 1;
  <D.8098>:
  if (i < n_live_threads) goto <D.8097>; else goto <D.8099>;
  <D.8099>:
  GC_notify_event.13 = GC_notify_event;
  if (GC_notify_event.13 != 0B) goto <D.8241>; else goto <D.8242>;
  <D.8241>:
  GC_notify_event.13 = GC_notify_event;
  GC_notify_event.13 (9);
  <D.8242>:
}


GC_stop_init ()
{
  pthread_stop_init ();
}


pthread_stop_init ()
{
  int D.8244;
  int D.8247;
  int D.8250;
  int D.8253;
  int D.8256;
  int D.8259;
  char * D.8262;
  char * D.8265;
  int GC_print_stats.14;
  int GC_retry_signals.15;
  struct sigaction act;

  try
    {
      D.8244 = sem_init (&GC_suspend_ack_sem, 0, 0);
      if (D.8244 != 0) goto <D.8245>; else goto <D.8246>;
      <D.8245>:
      GC_abort ("sem_init failed");
      <D.8246>:
      act.sa_flags = 268435456;
      D.8247 = sigfillset (&act.sa_mask);
      if (D.8247 != 0) goto <D.8248>; else goto <D.8249>;
      <D.8248>:
      GC_abort ("sigfillset() failed");
      <D.8249>:
      GC_remove_allowed_signals (&act.sa_mask);
      act.__sigaction_handler.sa_handler = GC_suspend_handler;
      D.8250 = sigaction (30, &act, 0B);
      if (D.8250 != 0) goto <D.8251>; else goto <D.8252>;
      <D.8251>:
      GC_abort ("Cannot set SIG_SUSPEND handler");
      <D.8252>:
      act.__sigaction_handler.sa_handler = GC_restart_handler;
      D.8253 = sigaction (24, &act, 0B);
      if (D.8253 != 0) goto <D.8254>; else goto <D.8255>;
      <D.8254>:
      GC_abort ("Cannot set SIG_THR_RESTART handler");
      <D.8255>:
      D.8256 = sigfillset (&suspend_handler_mask);
      if (D.8256 != 0) goto <D.8257>; else goto <D.8258>;
      <D.8257>:
      GC_abort ("sigfillset() failed");
      <D.8258>:
      GC_remove_allowed_signals (&suspend_handler_mask);
      D.8259 = sigdelset (&suspend_handler_mask, 24);
      if (D.8259 != 0) goto <D.8260>; else goto <D.8261>;
      <D.8260>:
      GC_abort ("sigdelset() failed");
      <D.8261>:
      D.8262 = getenv ("GC_RETRY_SIGNALS");
      if (D.8262 != 0B) goto <D.8263>; else goto <D.8264>;
      <D.8263>:
      GC_retry_signals = 1;
      <D.8264>:
      D.8265 = getenv ("GC_NO_RETRY_SIGNALS");
      if (D.8265 != 0B) goto <D.8266>; else goto <D.8267>;
      <D.8266>:
      GC_retry_signals = 0;
      <D.8267>:
      GC_print_stats.14 = GC_print_stats;
      if (GC_print_stats.14 != 0) goto <D.8269>; else goto <D.8270>;
      <D.8269>:
      GC_retry_signals.15 = GC_retry_signals;
      if (GC_retry_signals.15 != 0) goto <D.8272>; else goto <D.8273>;
      <D.8272>:
      GC_printf ("Will retry suspend signal if necessary.\n", 0, 0, 0, 0, 0, 0);
      <D.8273>:
      <D.8270>:
    }
  finally
    {
      act = {CLOBBER};
    }
}


