GC_remove_allowed_signals (struct sigset_t * set)
{
  int D.6439;
  int D.6441;
  int D.6443;
  int D.6445;

  D.6439 = sigdelset (set, 2);
  if (D.6439 != 0) goto <D.6437>; else goto <D.6440>;
  <D.6440>:
  D.6441 = sigdelset (set, 3);
  if (D.6441 != 0) goto <D.6437>; else goto <D.6442>;
  <D.6442>:
  D.6443 = sigdelset (set, 6);
  if (D.6443 != 0) goto <D.6437>; else goto <D.6444>;
  <D.6444>:
  D.6445 = sigdelset (set, 15);
  if (D.6445 != 0) goto <D.6437>; else goto <D.6438>;
  <D.6437>:
  GC_abort ("sigdelset() failed");
  <D.6438>:
}


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

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


_GC_suspend_handler (int sig)
{
  long unsigned int D.6449;
  int GC_retry_signals.0;
  void (*<T41b>) (char *, GC_word) GC_current_warn_proc.1;
  long unsigned int D.6456;
  int D.6457;
  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.6447>; else goto <D.6448>;
      <D.6447>:
      GC_abort ("Bad signal in suspend_handler");
      <D.6448>:
      me = GC_lookup_thread (my_thread);
      D.6449 = me->stop_info.last_stop_count;
      if (D.6449 == my_stop_count) goto <D.6450>; else goto <D.6451>;
      <D.6450>:
      GC_retry_signals.0 = GC_retry_signals;
      if (GC_retry_signals.0 == 0) goto <D.6453>; else goto <D.6454>;
      <D.6453>:
      GC_current_warn_proc.1 = GC_current_warn_proc;
      D.6456 = pthread_self ();
      GC_current_warn_proc.1 ("GC Warning: Duplicate suspend signal in thread %lx\n", D.6456);
      <D.6454>:
      return;
      <D.6451>:
      me->stop_info.stack_ptr = &dummy;
      sem_post (&GC_suspend_ack_sem);
      me->stop_info.last_stop_count = my_stop_count;
      <D.6334>:
      me->stop_info.signal = 0;
      sigsuspend (&suspend_handler_mask);
      D.6457 = me->stop_info.signal;
      if (D.6457 != 24) goto <D.6334>; else goto <D.6335>;
      <D.6335>:
      sem_post (&GC_suspend_ack_sem);
    }
  finally
    {
      dummy = {CLOBBER};
    }
}


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

  D.6461 = __errno_location ();
  old_errno = *D.6461;
  _GC_restart_handler (sig);
  D.6461 = __errno_location ();
  *D.6461 = 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.6462>; else goto <D.6463>;
  <D.6462>:
  GC_abort ("Bad signal in suspend_handler");
  <D.6463>:
  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.6467;
  unsigned short D.6468;
  int D.6469;
  int D.6470;
  long unsigned int D.6473;
  int D.6474;
  int D.6478;
  char * D.6484;
  int D.6489;
  sizetype D.6490;
  char * D.6491;
  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.6465>; else goto <D.6466>;
  <D.6465>:
  GC_thr_init ();
  <D.6466>:
  i = 0;
  goto <D.6358>;
  <D.6357>:
  p = GC_threads[i];
  goto <D.6355>;
  <D.6354>:
  D.6467 = p->flags;
  D.6468 = (unsigned short) D.6467;
  D.6469 = (int) D.6468;
  D.6470 = D.6469 & 1;
  if (D.6470 != 0) goto <D.6471>; else goto <D.6472>;
  <D.6471>:
  // predicted unlikely by continue predictor.
  goto <D.6353>;
  <D.6472>:
  D.6473 = p->id;
  D.6474 = pthread_equal (D.6473, me);
  if (D.6474 != 0) goto <D.6475>; else goto <D.6476>;
  <D.6475>:
  lo = GC_approx_sp ();
  found_me = 1;
  goto <D.6477>;
  <D.6476>:
  lo = p->stop_info.stack_ptr;
  <D.6477>:
  D.6467 = p->flags;
  D.6468 = (unsigned short) D.6467;
  D.6469 = (int) D.6468;
  D.6478 = D.6469 & 4;
  if (D.6478 == 0) goto <D.6479>; else goto <D.6480>;
  <D.6479>:
  hi = p->stack_end;
  goto <D.6481>;
  <D.6480>:
  hi = GC_stackbottom;
  <D.6481>:
  if (lo == 0B) goto <D.6482>; else goto <D.6483>;
  <D.6482>:
  GC_abort ("GC_push_all_stacks: sp not set!\n");
  <D.6483>:
  D.6484 = p->altstack;
  if (D.6484 != 0B) goto <D.6485>; else goto <D.6486>;
  <D.6485>:
  D.6484 = p->altstack;
  if (D.6484 <= lo) goto <D.6487>; else goto <D.6488>;
  <D.6487>:
  D.6484 = p->altstack;
  D.6489 = p->altstack_size;
  D.6490 = (sizetype) D.6489;
  D.6491 = D.6484 + D.6490;
  if (D.6491 >= lo) goto <D.6492>; else goto <D.6493>;
  <D.6492>:
  D.6484 = p->altstack;
  D.6489 = p->altstack_size;
  D.6490 = (sizetype) D.6489;
  hi = D.6484 + D.6490;
  <D.6493>:
  <D.6488>:
  <D.6486>:
  GC_push_all_stack (lo, hi);
  <D.6353>:
  p = p->next;
  <D.6355>:
  if (p != 0B) goto <D.6354>; else goto <D.6356>;
  <D.6356>:
  i = i + 1;
  <D.6358>:
  if (i <= 127) goto <D.6357>; else goto <D.6359>;
  <D.6359>:
  if (found_me == 0) goto <D.6494>; else goto <D.6495>;
  <D.6494>:
  GC_in_thread_creation.3 = GC_in_thread_creation;
  if (GC_in_thread_creation.3 == 0) goto <D.6497>; else goto <D.6498>;
  <D.6497>:
  GC_abort ("Collecting from unknown thread.");
  <D.6498>:
  <D.6495>:
}


pthread_equal (pthread_t __thread1, pthread_t __thread2)
{
  int D.6499;
  _Bool D.6500;

  D.6500 = __thread1 == __thread2;
  D.6499 = (int) D.6500;
  return D.6499;
}


GC_suspend_all ()
{
  int GC_stopping_pid.4;
  long unsigned int D.6503;
  short int D.6506;
  unsigned short D.6507;
  int D.6508;
  int D.6509;
  long unsigned int D.6512;
  long unsigned int GC_stop_count.5;
  short int D.6516;
  int D.6519;
  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.6384>;
  <D.6383>:
  p = GC_threads[i];
  goto <D.6381>;
  <D.6380>:
  D.6503 = p->id;
  if (D.6503 != my_thread) goto <D.6504>; else goto <D.6505>;
  <D.6504>:
  D.6506 = p->flags;
  D.6507 = (unsigned short) D.6506;
  D.6508 = (int) D.6507;
  D.6509 = D.6508 & 1;
  if (D.6509 != 0) goto <D.6510>; else goto <D.6511>;
  <D.6510>:
  // predicted unlikely by continue predictor.
  goto <D.6375>;
  <D.6511>:
  D.6512 = p->stop_info.last_stop_count;
  GC_stop_count.5 = GC_stop_count;
  if (D.6512 == GC_stop_count.5) goto <D.6514>; else goto <D.6515>;
  <D.6514>:
  // predicted unlikely by continue predictor.
  goto <D.6375>;
  <D.6515>:
  D.6516 = p->thread_blocked;
  if (D.6516 != 0) goto <D.6517>; else goto <D.6518>;
  <D.6517>:
  // predicted unlikely by continue predictor.
  goto <D.6375>;
  <D.6518>:
  n_live_threads = n_live_threads + 1;
  D.6503 = p->id;
  result = pthread_kill (D.6503, 30);
  switch (result) <default: <D.6379>, case 0: <D.6378>, case 3: <D.6376>>
  <D.6376>:
  n_live_threads = n_live_threads + -1;
  goto <D.6377>;
  <D.6378>:
  goto <D.6377>;
  <D.6379>:
  GC_abort ("pthread_kill failed");
  <D.6377>:
  <D.6505>:
  <D.6375>:
  p = p->next;
  <D.6381>:
  if (p != 0B) goto <D.6380>; else goto <D.6382>;
  <D.6382>:
  i = i + 1;
  <D.6384>:
  if (i <= 127) goto <D.6383>; else goto <D.6385>;
  <D.6385>:
  D.6519 = n_live_threads;
  return D.6519;
}


GC_stop_world ()
{
  void (*<T39e>) (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.6523>; else goto <D.6524>;
  <D.6523>:
  GC_notify_event.6 = GC_notify_event;
  GC_notify_event.6 (6);
  <D.6524>:
  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.6527>; else goto <D.6528>;
  <D.6527>:
  GC_notify_event.6 = GC_notify_event;
  GC_notify_event.6 (7);
  <D.6528>:
}


pthread_stop_world ()
{
  int GC_retry_signals.9;
  int ack_count.10;
  int GC_print_stats.11;
  long int D.6539;
  int D.6540;
  void (*<T41b>) (char *, GC_word) GC_current_warn_proc.12;
  int * D.6544;
  int D.6545;
  long int D.6548;
  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.6530>; else goto <D.6531>;
  <D.6530>:
  {
    long unsigned int wait_usecs;

    wait_usecs = 0;
    <D.6395>:
    {
      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.6393>; else goto <D.6533>;
          <D.6533>:
          if (wait_usecs > 100000) goto <D.6534>; else goto <D.6535>;
          <D.6534>:
          {
            int newly_sent;

            newly_sent = GC_suspend_all ();
            GC_print_stats.11 = GC_print_stats;
            if (GC_print_stats.11 != 0) goto <D.6537>; else goto <D.6538>;
            <D.6537>:
            D.6539 = (long int) newly_sent;
            GC_printf ("Resent %ld signals after timeout\n", D.6539, 0, 0, 0, 0, 0);
            <D.6538>:
            sem_getvalue (&GC_suspend_ack_sem, &ack_count);
            ack_count.10 = ack_count;
            D.6540 = n_live_threads - ack_count.10;
            if (D.6540 > newly_sent) goto <D.6541>; else goto <D.6542>;
            <D.6541>:
            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.6542>:
            wait_usecs = 0;
          }
          <D.6535>:
          usleep (3000);
          wait_usecs = wait_usecs + 3000;
        }
      finally
        {
          ack_count = {CLOBBER};
        }
    }
    goto <D.6395>;
    <D.6393>:
  }
  <D.6531>:
  i = 0;
  goto <D.6400>;
  <D.6399>:
  goto <D.6397>;
  <D.6396>:
  D.6544 = __errno_location ();
  D.6545 = *D.6544;
  if (D.6545 != 4) goto <D.6546>; else goto <D.6547>;
  <D.6546>:
  D.6548 = (long int) code;
  GC_err_printf ("Sem_wait returned %ld\n", D.6548, 0, 0, 0, 0, 0);
  GC_abort ("sem_wait for handler failed");
  <D.6547>:
  <D.6397>:
  code = sem_wait (&GC_suspend_ack_sem);
  if (code != 0) goto <D.6396>; else goto <D.6398>;
  <D.6398>:
  i = i + 1;
  <D.6400>:
  if (i < n_live_threads) goto <D.6399>; else goto <D.6401>;
  <D.6401>:
  GC_stopping_thread = 0;
}


GC_start_world ()
{
  pthread_start_world ();
}


pthread_start_world ()
{
  void (*<T39e>) (GCEventType) GC_notify_event.13;
  long unsigned int D.6554;
  short int D.6557;
  unsigned short D.6558;
  int D.6559;
  int D.6560;
  short int D.6563;
  int * D.6566;
  int D.6567;
  long int D.6570;
  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.6552>; else goto <D.6553>;
  <D.6552>:
  GC_notify_event.13 = GC_notify_event;
  GC_notify_event.13 (8);
  <D.6553>:
  i = 0;
  goto <D.6421>;
  <D.6420>:
  p = GC_threads[i];
  goto <D.6418>;
  <D.6417>:
  D.6554 = p->id;
  if (D.6554 != my_thread) goto <D.6555>; else goto <D.6556>;
  <D.6555>:
  D.6557 = p->flags;
  D.6558 = (unsigned short) D.6557;
  D.6559 = (int) D.6558;
  D.6560 = D.6559 & 1;
  if (D.6560 != 0) goto <D.6561>; else goto <D.6562>;
  <D.6561>:
  // predicted unlikely by continue predictor.
  goto <D.6412>;
  <D.6562>:
  D.6563 = p->thread_blocked;
  if (D.6563 != 0) goto <D.6564>; else goto <D.6565>;
  <D.6564>:
  // predicted unlikely by continue predictor.
  goto <D.6412>;
  <D.6565>:
  n_live_threads = n_live_threads + 1;
  D.6554 = p->id;
  result = pthread_kill (D.6554, 24);
  switch (result) <default: <D.6416>, case 0: <D.6415>, case 3: <D.6413>>
  <D.6413>:
  n_live_threads = n_live_threads + -1;
  goto <D.6414>;
  <D.6415>:
  goto <D.6414>;
  <D.6416>:
  GC_abort ("pthread_kill failed");
  <D.6414>:
  <D.6556>:
  <D.6412>:
  p = p->next;
  <D.6418>:
  if (p != 0B) goto <D.6417>; else goto <D.6419>;
  <D.6419>:
  i = i + 1;
  <D.6421>:
  if (i <= 127) goto <D.6420>; else goto <D.6422>;
  <D.6422>:
  i = 0;
  goto <D.6427>;
  <D.6426>:
  goto <D.6424>;
  <D.6423>:
  D.6566 = __errno_location ();
  D.6567 = *D.6566;
  if (D.6567 != 4) goto <D.6568>; else goto <D.6569>;
  <D.6568>:
  D.6570 = (long int) code;
  GC_err_printf ("Sem_wait returned %ld\n", D.6570, 0, 0, 0, 0, 0);
  GC_abort ("sem_wait for handler failed");
  <D.6569>:
  <D.6424>:
  code = sem_wait (&GC_suspend_ack_sem);
  if (code != 0) goto <D.6423>; else goto <D.6425>;
  <D.6425>:
  i = i + 1;
  <D.6427>:
  if (i < n_live_threads) goto <D.6426>; else goto <D.6428>;
  <D.6428>:
  GC_notify_event.13 = GC_notify_event;
  if (GC_notify_event.13 != 0B) goto <D.6571>; else goto <D.6572>;
  <D.6571>:
  GC_notify_event.13 = GC_notify_event;
  GC_notify_event.13 (9);
  <D.6572>:
}


GC_stop_init ()
{
  pthread_stop_init ();
}


pthread_stop_init ()
{
  int D.6574;
  int D.6577;
  int D.6580;
  int D.6583;
  int D.6586;
  int D.6589;
  char * D.6592;
  char * D.6595;
  int GC_print_stats.14;
  int GC_retry_signals.15;
  struct sigaction act;

  try
    {
      D.6574 = sem_init (&GC_suspend_ack_sem, 0, 0);
      if (D.6574 != 0) goto <D.6575>; else goto <D.6576>;
      <D.6575>:
      GC_abort ("sem_init failed");
      <D.6576>:
      act.sa_flags = 268435456;
      D.6577 = sigfillset (&act.sa_mask);
      if (D.6577 != 0) goto <D.6578>; else goto <D.6579>;
      <D.6578>:
      GC_abort ("sigfillset() failed");
      <D.6579>:
      GC_remove_allowed_signals (&act.sa_mask);
      act.__sigaction_handler.sa_handler = GC_suspend_handler;
      D.6580 = sigaction (30, &act, 0B);
      if (D.6580 != 0) goto <D.6581>; else goto <D.6582>;
      <D.6581>:
      GC_abort ("Cannot set SIG_SUSPEND handler");
      <D.6582>:
      act.__sigaction_handler.sa_handler = GC_restart_handler;
      D.6583 = sigaction (24, &act, 0B);
      if (D.6583 != 0) goto <D.6584>; else goto <D.6585>;
      <D.6584>:
      GC_abort ("Cannot set SIG_THR_RESTART handler");
      <D.6585>:
      D.6586 = sigfillset (&suspend_handler_mask);
      if (D.6586 != 0) goto <D.6587>; else goto <D.6588>;
      <D.6587>:
      GC_abort ("sigfillset() failed");
      <D.6588>:
      GC_remove_allowed_signals (&suspend_handler_mask);
      D.6589 = sigdelset (&suspend_handler_mask, 24);
      if (D.6589 != 0) goto <D.6590>; else goto <D.6591>;
      <D.6590>:
      GC_abort ("sigdelset() failed");
      <D.6591>:
      D.6592 = getenv ("GC_RETRY_SIGNALS");
      if (D.6592 != 0B) goto <D.6593>; else goto <D.6594>;
      <D.6593>:
      GC_retry_signals = 1;
      <D.6594>:
      D.6595 = getenv ("GC_NO_RETRY_SIGNALS");
      if (D.6595 != 0B) goto <D.6596>; else goto <D.6597>;
      <D.6596>:
      GC_retry_signals = 0;
      <D.6597>:
      GC_print_stats.14 = GC_print_stats;
      if (GC_print_stats.14 != 0) goto <D.6599>; else goto <D.6600>;
      <D.6599>:
      GC_retry_signals.15 = GC_retry_signals;
      if (GC_retry_signals.15 != 0) goto <D.6602>; else goto <D.6603>;
      <D.6602>:
      GC_printf ("Will retry suspend signal if necessary.\n", 0, 0, 0, 0, 0, 0);
      <D.6603>:
      <D.6600>:
    }
  finally
    {
      act = {CLOBBER};
    }
}


