GC_remove_allowed_signals (struct sigset_t * set)
{
  int D.5600;
  int D.5602;
  int D.5604;
  int D.5606;

  D.5600 = sigdelset (set, 2);
  if (D.5600 != 0) goto <D.5598>; else goto <D.5601>;
  <D.5601>:
  D.5602 = sigdelset (set, 3);
  if (D.5602 != 0) goto <D.5598>; else goto <D.5603>;
  <D.5603>:
  D.5604 = sigdelset (set, 6);
  if (D.5604 != 0) goto <D.5598>; else goto <D.5605>;
  <D.5605>:
  D.5606 = sigdelset (set, 15);
  if (D.5606 != 0) goto <D.5598>; else goto <D.5599>;
  <D.5598>:
  GC_abort ("sigdelset() failed");
  <D.5599>:
}


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

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


_GC_suspend_handler (int sig)
{
  long unsigned int D.5610;
  int GC_retry_signals.0;
  void (*<T33e>) (char *, GC_word) GC_current_warn_proc.1;
  long unsigned int D.5617;
  int D.5618;
  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.5608>; else goto <D.5609>;
      <D.5608>:
      GC_abort ("Bad signal in suspend_handler");
      <D.5609>:
      me = GC_lookup_thread (my_thread);
      D.5610 = me->stop_info.last_stop_count;
      if (D.5610 == my_stop_count) goto <D.5611>; else goto <D.5612>;
      <D.5611>:
      GC_retry_signals.0 = GC_retry_signals;
      if (GC_retry_signals.0 == 0) goto <D.5614>; else goto <D.5615>;
      <D.5614>:
      GC_current_warn_proc.1 = GC_current_warn_proc;
      D.5617 = pthread_self ();
      GC_current_warn_proc.1 ("GC Warning: Duplicate suspend signal in thread %lx\n", D.5617);
      <D.5615>:
      return;
      <D.5612>:
      me->stop_info.stack_ptr = &dummy;
      sem_post (&GC_suspend_ack_sem);
      me->stop_info.last_stop_count = my_stop_count;
      <D.5495>:
      me->stop_info.signal = 0;
      sigsuspend (&suspend_handler_mask);
      D.5618 = me->stop_info.signal;
      if (D.5618 != 24) goto <D.5495>; else goto <D.5496>;
      <D.5496>:
      sem_post (&GC_suspend_ack_sem);
    }
  finally
    {
      dummy = {CLOBBER};
    }
}


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

  D.5622 = __errno_location ();
  old_errno = *D.5622;
  _GC_restart_handler (sig);
  D.5622 = __errno_location ();
  *D.5622 = 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.5623>; else goto <D.5624>;
  <D.5623>:
  GC_abort ("Bad signal in suspend_handler");
  <D.5624>:
  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.5628;
  int D.5629;
  int D.5630;
  long unsigned int D.5633;
  int D.5634;
  int D.5638;
  char * D.5644;
  int D.5649;
  sizetype D.5650;
  char * D.5651;
  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.5626>; else goto <D.5627>;
  <D.5626>:
  GC_thr_init ();
  <D.5627>:
  i = 0;
  goto <D.5519>;
  <D.5518>:
  p = GC_threads[i];
  goto <D.5516>;
  <D.5515>:
  D.5628 = p->flags;
  D.5629 = (int) D.5628;
  D.5630 = D.5629 & 1;
  if (D.5630 != 0) goto <D.5631>; else goto <D.5632>;
  <D.5631>:
  // predicted unlikely by continue predictor.
  goto <D.5514>;
  <D.5632>:
  D.5633 = p->id;
  D.5634 = pthread_equal (D.5633, me);
  if (D.5634 != 0) goto <D.5635>; else goto <D.5636>;
  <D.5635>:
  lo = GC_approx_sp ();
  found_me = 1;
  goto <D.5637>;
  <D.5636>:
  lo = p->stop_info.stack_ptr;
  <D.5637>:
  D.5628 = p->flags;
  D.5629 = (int) D.5628;
  D.5638 = D.5629 & 4;
  if (D.5638 == 0) goto <D.5639>; else goto <D.5640>;
  <D.5639>:
  hi = p->stack_end;
  goto <D.5641>;
  <D.5640>:
  hi = GC_stackbottom;
  <D.5641>:
  if (lo == 0B) goto <D.5642>; else goto <D.5643>;
  <D.5642>:
  GC_abort ("GC_push_all_stacks: sp not set!\n");
  <D.5643>:
  D.5644 = p->altstack;
  if (D.5644 != 0B) goto <D.5645>; else goto <D.5646>;
  <D.5645>:
  D.5644 = p->altstack;
  if (D.5644 <= lo) goto <D.5647>; else goto <D.5648>;
  <D.5647>:
  D.5644 = p->altstack;
  D.5649 = p->altstack_size;
  D.5650 = (sizetype) D.5649;
  D.5651 = D.5644 + D.5650;
  if (D.5651 >= lo) goto <D.5652>; else goto <D.5653>;
  <D.5652>:
  D.5644 = p->altstack;
  D.5649 = p->altstack_size;
  D.5650 = (sizetype) D.5649;
  hi = D.5644 + D.5650;
  <D.5653>:
  <D.5648>:
  <D.5646>:
  GC_push_all_stack (lo, hi);
  <D.5514>:
  p = p->next;
  <D.5516>:
  if (p != 0B) goto <D.5515>; else goto <D.5517>;
  <D.5517>:
  i = i + 1;
  <D.5519>:
  if (i <= 127) goto <D.5518>; else goto <D.5520>;
  <D.5520>:
  if (found_me == 0) goto <D.5654>; else goto <D.5655>;
  <D.5654>:
  GC_in_thread_creation.3 = GC_in_thread_creation;
  if (GC_in_thread_creation.3 == 0) goto <D.5657>; else goto <D.5658>;
  <D.5657>:
  GC_abort ("Collecting from unknown thread.");
  <D.5658>:
  <D.5655>:
}


pthread_equal (pthread_t __thread1, pthread_t __thread2)
{
  int D.5659;
  _Bool D.5660;

  D.5660 = __thread1 == __thread2;
  D.5659 = (int) D.5660;
  return D.5659;
}


GC_suspend_all ()
{
  int GC_stopping_pid.4;
  long unsigned int D.5663;
  short int D.5666;
  int D.5667;
  int D.5668;
  long unsigned int D.5671;
  long unsigned int GC_stop_count.5;
  short int D.5675;
  int D.5678;
  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.5545>;
  <D.5544>:
  p = GC_threads[i];
  goto <D.5542>;
  <D.5541>:
  D.5663 = p->id;
  if (D.5663 != my_thread) goto <D.5664>; else goto <D.5665>;
  <D.5664>:
  D.5666 = p->flags;
  D.5667 = (int) D.5666;
  D.5668 = D.5667 & 1;
  if (D.5668 != 0) goto <D.5669>; else goto <D.5670>;
  <D.5669>:
  // predicted unlikely by continue predictor.
  goto <D.5536>;
  <D.5670>:
  D.5671 = p->stop_info.last_stop_count;
  GC_stop_count.5 = GC_stop_count;
  if (D.5671 == GC_stop_count.5) goto <D.5673>; else goto <D.5674>;
  <D.5673>:
  // predicted unlikely by continue predictor.
  goto <D.5536>;
  <D.5674>:
  D.5675 = p->thread_blocked;
  if (D.5675 != 0) goto <D.5676>; else goto <D.5677>;
  <D.5676>:
  // predicted unlikely by continue predictor.
  goto <D.5536>;
  <D.5677>:
  n_live_threads = n_live_threads + 1;
  D.5663 = p->id;
  result = pthread_kill (D.5663, 30);
  switch (result) <default: <D.5540>, case 0: <D.5539>, case 3: <D.5537>>
  <D.5537>:
  n_live_threads = n_live_threads + -1;
  goto <D.5538>;
  <D.5539>:
  goto <D.5538>;
  <D.5540>:
  GC_abort ("pthread_kill failed");
  <D.5538>:
  <D.5665>:
  <D.5536>:
  p = p->next;
  <D.5542>:
  if (p != 0B) goto <D.5541>; else goto <D.5543>;
  <D.5543>:
  i = i + 1;
  <D.5545>:
  if (i <= 127) goto <D.5544>; else goto <D.5546>;
  <D.5546>:
  D.5678 = n_live_threads;
  return D.5678;
}


GC_stop_world ()
{
  void (*<T2c1>) (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.5682>; else goto <D.5683>;
  <D.5682>:
  GC_notify_event.6 = GC_notify_event;
  GC_notify_event.6 (6);
  <D.5683>:
  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.5686>; else goto <D.5687>;
  <D.5686>:
  GC_notify_event.6 = GC_notify_event;
  GC_notify_event.6 (7);
  <D.5687>:
}


pthread_stop_world ()
{
  int GC_retry_signals.9;
  int ack_count.10;
  int GC_print_stats.11;
  int D.5698;
  void (*<T33e>) (char *, GC_word) GC_current_warn_proc.12;
  int * D.5702;
  int D.5703;
  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.5689>; else goto <D.5690>;
  <D.5689>:
  {
    long unsigned int wait_usecs;

    wait_usecs = 0;
    <D.5556>:
    {
      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.5554>; else goto <D.5692>;
          <D.5692>:
          if (wait_usecs > 100000) goto <D.5693>; else goto <D.5694>;
          <D.5693>:
          {
            int newly_sent;

            newly_sent = GC_suspend_all ();
            GC_print_stats.11 = GC_print_stats;
            if (GC_print_stats.11 != 0) goto <D.5696>; else goto <D.5697>;
            <D.5696>:
            GC_printf ("Resent %ld signals after timeout\n", newly_sent, 0, 0, 0, 0, 0);
            <D.5697>:
            sem_getvalue (&GC_suspend_ack_sem, &ack_count);
            ack_count.10 = ack_count;
            D.5698 = n_live_threads - ack_count.10;
            if (D.5698 > newly_sent) goto <D.5699>; else goto <D.5700>;
            <D.5699>:
            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.5700>:
            wait_usecs = 0;
          }
          <D.5694>:
          usleep (3000);
          wait_usecs = wait_usecs + 3000;
        }
      finally
        {
          ack_count = {CLOBBER};
        }
    }
    goto <D.5556>;
    <D.5554>:
  }
  <D.5690>:
  i = 0;
  goto <D.5561>;
  <D.5560>:
  goto <D.5558>;
  <D.5557>:
  D.5702 = __errno_location ();
  D.5703 = *D.5702;
  if (D.5703 != 4) goto <D.5704>; else goto <D.5705>;
  <D.5704>:
  GC_err_printf ("Sem_wait returned %ld\n", code, 0, 0, 0, 0, 0);
  GC_abort ("sem_wait for handler failed");
  <D.5705>:
  <D.5558>:
  code = sem_wait (&GC_suspend_ack_sem);
  if (code != 0) goto <D.5557>; else goto <D.5559>;
  <D.5559>:
  i = i + 1;
  <D.5561>:
  if (i < n_live_threads) goto <D.5560>; else goto <D.5562>;
  <D.5562>:
  GC_stopping_thread = 0;
}


GC_start_world ()
{
  pthread_start_world ();
}


pthread_start_world ()
{
  void (*<T2c1>) (GCEventType) GC_notify_event.13;
  long unsigned int D.5711;
  short int D.5714;
  int D.5715;
  int D.5716;
  short int D.5719;
  int * D.5722;
  int D.5723;
  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.5709>; else goto <D.5710>;
  <D.5709>:
  GC_notify_event.13 = GC_notify_event;
  GC_notify_event.13 (8);
  <D.5710>:
  i = 0;
  goto <D.5582>;
  <D.5581>:
  p = GC_threads[i];
  goto <D.5579>;
  <D.5578>:
  D.5711 = p->id;
  if (D.5711 != my_thread) goto <D.5712>; else goto <D.5713>;
  <D.5712>:
  D.5714 = p->flags;
  D.5715 = (int) D.5714;
  D.5716 = D.5715 & 1;
  if (D.5716 != 0) goto <D.5717>; else goto <D.5718>;
  <D.5717>:
  // predicted unlikely by continue predictor.
  goto <D.5573>;
  <D.5718>:
  D.5719 = p->thread_blocked;
  if (D.5719 != 0) goto <D.5720>; else goto <D.5721>;
  <D.5720>:
  // predicted unlikely by continue predictor.
  goto <D.5573>;
  <D.5721>:
  n_live_threads = n_live_threads + 1;
  D.5711 = p->id;
  result = pthread_kill (D.5711, 24);
  switch (result) <default: <D.5577>, case 0: <D.5576>, case 3: <D.5574>>
  <D.5574>:
  n_live_threads = n_live_threads + -1;
  goto <D.5575>;
  <D.5576>:
  goto <D.5575>;
  <D.5577>:
  GC_abort ("pthread_kill failed");
  <D.5575>:
  <D.5713>:
  <D.5573>:
  p = p->next;
  <D.5579>:
  if (p != 0B) goto <D.5578>; else goto <D.5580>;
  <D.5580>:
  i = i + 1;
  <D.5582>:
  if (i <= 127) goto <D.5581>; else goto <D.5583>;
  <D.5583>:
  i = 0;
  goto <D.5588>;
  <D.5587>:
  goto <D.5585>;
  <D.5584>:
  D.5722 = __errno_location ();
  D.5723 = *D.5722;
  if (D.5723 != 4) goto <D.5724>; else goto <D.5725>;
  <D.5724>:
  GC_err_printf ("Sem_wait returned %ld\n", code, 0, 0, 0, 0, 0);
  GC_abort ("sem_wait for handler failed");
  <D.5725>:
  <D.5585>:
  code = sem_wait (&GC_suspend_ack_sem);
  if (code != 0) goto <D.5584>; else goto <D.5586>;
  <D.5586>:
  i = i + 1;
  <D.5588>:
  if (i < n_live_threads) goto <D.5587>; else goto <D.5589>;
  <D.5589>:
  GC_notify_event.13 = GC_notify_event;
  if (GC_notify_event.13 != 0B) goto <D.5726>; else goto <D.5727>;
  <D.5726>:
  GC_notify_event.13 = GC_notify_event;
  GC_notify_event.13 (9);
  <D.5727>:
}


GC_stop_init ()
{
  pthread_stop_init ();
}


pthread_stop_init ()
{
  int D.5729;
  int D.5732;
  int D.5735;
  int D.5738;
  int D.5741;
  int D.5744;
  char * D.5747;
  char * D.5750;
  int GC_print_stats.14;
  int GC_retry_signals.15;
  struct sigaction act;

  try
    {
      D.5729 = sem_init (&GC_suspend_ack_sem, 0, 0);
      if (D.5729 != 0) goto <D.5730>; else goto <D.5731>;
      <D.5730>:
      GC_abort ("sem_init failed");
      <D.5731>:
      act.sa_flags = 268435456;
      D.5732 = sigfillset (&act.sa_mask);
      if (D.5732 != 0) goto <D.5733>; else goto <D.5734>;
      <D.5733>:
      GC_abort ("sigfillset() failed");
      <D.5734>:
      GC_remove_allowed_signals (&act.sa_mask);
      act.__sigaction_handler.sa_handler = GC_suspend_handler;
      D.5735 = sigaction (30, &act, 0B);
      if (D.5735 != 0) goto <D.5736>; else goto <D.5737>;
      <D.5736>:
      GC_abort ("Cannot set SIG_SUSPEND handler");
      <D.5737>:
      act.__sigaction_handler.sa_handler = GC_restart_handler;
      D.5738 = sigaction (24, &act, 0B);
      if (D.5738 != 0) goto <D.5739>; else goto <D.5740>;
      <D.5739>:
      GC_abort ("Cannot set SIG_THR_RESTART handler");
      <D.5740>:
      D.5741 = sigfillset (&suspend_handler_mask);
      if (D.5741 != 0) goto <D.5742>; else goto <D.5743>;
      <D.5742>:
      GC_abort ("sigfillset() failed");
      <D.5743>:
      GC_remove_allowed_signals (&suspend_handler_mask);
      D.5744 = sigdelset (&suspend_handler_mask, 24);
      if (D.5744 != 0) goto <D.5745>; else goto <D.5746>;
      <D.5745>:
      GC_abort ("sigdelset() failed");
      <D.5746>:
      D.5747 = getenv ("GC_RETRY_SIGNALS");
      if (D.5747 != 0B) goto <D.5748>; else goto <D.5749>;
      <D.5748>:
      GC_retry_signals = 1;
      <D.5749>:
      D.5750 = getenv ("GC_NO_RETRY_SIGNALS");
      if (D.5750 != 0B) goto <D.5751>; else goto <D.5752>;
      <D.5751>:
      GC_retry_signals = 0;
      <D.5752>:
      GC_print_stats.14 = GC_print_stats;
      if (GC_print_stats.14 != 0) goto <D.5754>; else goto <D.5755>;
      <D.5754>:
      GC_retry_signals.15 = GC_retry_signals;
      if (GC_retry_signals.15 != 0) goto <D.5757>; else goto <D.5758>;
      <D.5757>:
      GC_printf ("Will retry suspend signal if necessary.\n", 0, 0, 0, 0, 0, 0);
      <D.5758>:
      <D.5755>:
    }
  finally
    {
      act = {CLOBBER};
    }
}


