GC_remove_allowed_signals (struct sigset_t * set)
{
  int D.5532;
  int D.5534;
  int D.5536;
  int D.5538;

  D.5532 = sigdelset (set, 2);
  if (D.5532 != 0) goto <D.5530>; else goto <D.5533>;
  <D.5533>:
  D.5534 = sigdelset (set, 3);
  if (D.5534 != 0) goto <D.5530>; else goto <D.5535>;
  <D.5535>:
  D.5536 = sigdelset (set, 6);
  if (D.5536 != 0) goto <D.5530>; else goto <D.5537>;
  <D.5537>:
  D.5538 = sigdelset (set, 15);
  if (D.5538 != 0) goto <D.5530>; else goto <D.5531>;
  <D.5530>:
  GC_abort ("sigdelset() failed");
  <D.5531>:
}


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

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


_GC_suspend_handler (int sig)
{
  long unsigned int D.5542;
  int GC_retry_signals.0;
  void (*<T32e>) (char *, GC_word) GC_current_warn_proc.1;
  long unsigned int D.5549;
  int D.5550;
  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 != 19) goto <D.5540>; else goto <D.5541>;
      <D.5540>:
      GC_abort ("Bad signal in suspend_handler");
      <D.5541>:
      me = GC_lookup_thread (my_thread);
      D.5542 = me->stop_info.last_stop_count;
      if (D.5542 == my_stop_count) goto <D.5543>; else goto <D.5544>;
      <D.5543>:
      GC_retry_signals.0 = GC_retry_signals;
      if (GC_retry_signals.0 == 0) goto <D.5546>; else goto <D.5547>;
      <D.5546>:
      GC_current_warn_proc.1 = GC_current_warn_proc;
      D.5549 = pthread_self ();
      GC_current_warn_proc.1 ("GC Warning: Duplicate suspend signal in thread %lx\n", D.5549);
      <D.5547>:
      return;
      <D.5544>:
      me->stop_info.stack_ptr = &dummy;
      sem_post (&GC_suspend_ack_sem);
      me->stop_info.last_stop_count = my_stop_count;
      <D.5427>:
      me->stop_info.signal = 0;
      sigsuspend (&suspend_handler_mask);
      D.5550 = me->stop_info.signal;
      if (D.5550 != 30) goto <D.5427>; else goto <D.5428>;
      <D.5428>:
      sem_post (&GC_suspend_ack_sem);
    }
  finally
    {
      dummy = {CLOBBER};
    }
}


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

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


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

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


GC_push_all_stacks ()
{
  pthread_push_all_stacks ();
}


pthread_push_all_stacks ()
{
  int GC_thr_initialized.2;
  short int D.5560;
  unsigned short D.5561;
  int D.5562;
  int D.5563;
  long unsigned int D.5566;
  int D.5567;
  int D.5571;
  char * D.5577;
  int D.5582;
  sizetype D.5583;
  char * D.5584;
  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.5558>; else goto <D.5559>;
  <D.5558>:
  GC_thr_init ();
  <D.5559>:
  i = 0;
  goto <D.5451>;
  <D.5450>:
  p = GC_threads[i];
  goto <D.5448>;
  <D.5447>:
  D.5560 = p->flags;
  D.5561 = (unsigned short) D.5560;
  D.5562 = (int) D.5561;
  D.5563 = D.5562 & 1;
  if (D.5563 != 0) goto <D.5564>; else goto <D.5565>;
  <D.5564>:
  // predicted unlikely by continue predictor.
  goto <D.5446>;
  <D.5565>:
  D.5566 = p->id;
  D.5567 = pthread_equal (D.5566, me);
  if (D.5567 != 0) goto <D.5568>; else goto <D.5569>;
  <D.5568>:
  lo = GC_approx_sp ();
  found_me = 1;
  goto <D.5570>;
  <D.5569>:
  lo = p->stop_info.stack_ptr;
  <D.5570>:
  D.5560 = p->flags;
  D.5561 = (unsigned short) D.5560;
  D.5562 = (int) D.5561;
  D.5571 = D.5562 & 4;
  if (D.5571 == 0) goto <D.5572>; else goto <D.5573>;
  <D.5572>:
  hi = p->stack_end;
  goto <D.5574>;
  <D.5573>:
  hi = GC_stackbottom;
  <D.5574>:
  if (lo == 0B) goto <D.5575>; else goto <D.5576>;
  <D.5575>:
  GC_abort ("GC_push_all_stacks: sp not set!\n");
  <D.5576>:
  D.5577 = p->altstack;
  if (D.5577 != 0B) goto <D.5578>; else goto <D.5579>;
  <D.5578>:
  D.5577 = p->altstack;
  if (D.5577 <= lo) goto <D.5580>; else goto <D.5581>;
  <D.5580>:
  D.5577 = p->altstack;
  D.5582 = p->altstack_size;
  D.5583 = (sizetype) D.5582;
  D.5584 = D.5577 + D.5583;
  if (D.5584 >= lo) goto <D.5585>; else goto <D.5586>;
  <D.5585>:
  D.5577 = p->altstack;
  D.5582 = p->altstack_size;
  D.5583 = (sizetype) D.5582;
  hi = D.5577 + D.5583;
  <D.5586>:
  <D.5581>:
  <D.5579>:
  GC_push_all_stack (lo, hi);
  <D.5446>:
  p = p->next;
  <D.5448>:
  if (p != 0B) goto <D.5447>; else goto <D.5449>;
  <D.5449>:
  i = i + 1;
  <D.5451>:
  if (i <= 127) goto <D.5450>; else goto <D.5452>;
  <D.5452>:
  if (found_me == 0) goto <D.5587>; else goto <D.5588>;
  <D.5587>:
  GC_in_thread_creation.3 = GC_in_thread_creation;
  if (GC_in_thread_creation.3 == 0) goto <D.5590>; else goto <D.5591>;
  <D.5590>:
  GC_abort ("Collecting from unknown thread.");
  <D.5591>:
  <D.5588>:
}


pthread_equal (pthread_t __thread1, pthread_t __thread2)
{
  int D.5592;
  _Bool D.5593;

  D.5593 = __thread1 == __thread2;
  D.5592 = (int) D.5593;
  return D.5592;
}


GC_suspend_all ()
{
  int GC_stopping_pid.4;
  long unsigned int D.5596;
  short int D.5599;
  unsigned short D.5600;
  int D.5601;
  int D.5602;
  long unsigned int D.5605;
  long unsigned int GC_stop_count.5;
  short int D.5609;
  int D.5612;
  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.5477>;
  <D.5476>:
  p = GC_threads[i];
  goto <D.5474>;
  <D.5473>:
  D.5596 = p->id;
  if (D.5596 != my_thread) goto <D.5597>; else goto <D.5598>;
  <D.5597>:
  D.5599 = p->flags;
  D.5600 = (unsigned short) D.5599;
  D.5601 = (int) D.5600;
  D.5602 = D.5601 & 1;
  if (D.5602 != 0) goto <D.5603>; else goto <D.5604>;
  <D.5603>:
  // predicted unlikely by continue predictor.
  goto <D.5468>;
  <D.5604>:
  D.5605 = p->stop_info.last_stop_count;
  GC_stop_count.5 = GC_stop_count;
  if (D.5605 == GC_stop_count.5) goto <D.5607>; else goto <D.5608>;
  <D.5607>:
  // predicted unlikely by continue predictor.
  goto <D.5468>;
  <D.5608>:
  D.5609 = p->thread_blocked;
  if (D.5609 != 0) goto <D.5610>; else goto <D.5611>;
  <D.5610>:
  // predicted unlikely by continue predictor.
  goto <D.5468>;
  <D.5611>:
  n_live_threads = n_live_threads + 1;
  D.5596 = p->id;
  result = pthread_kill (D.5596, 19);
  switch (result) <default: <D.5472>, case 0: <D.5471>, case 3: <D.5469>>
  <D.5469>:
  n_live_threads = n_live_threads + -1;
  goto <D.5470>;
  <D.5471>:
  goto <D.5470>;
  <D.5472>:
  GC_abort ("pthread_kill failed");
  <D.5470>:
  <D.5598>:
  <D.5468>:
  p = p->next;
  <D.5474>:
  if (p != 0B) goto <D.5473>; else goto <D.5475>;
  <D.5475>:
  i = i + 1;
  <D.5477>:
  if (i <= 127) goto <D.5476>; else goto <D.5478>;
  <D.5478>:
  D.5612 = n_live_threads;
  return D.5612;
}


GC_stop_world ()
{
  void (*<T2b1>) (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.5616>; else goto <D.5617>;
  <D.5616>:
  GC_notify_event.6 = GC_notify_event;
  GC_notify_event.6 (6);
  <D.5617>:
  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.5620>; else goto <D.5621>;
  <D.5620>:
  GC_notify_event.6 = GC_notify_event;
  GC_notify_event.6 (7);
  <D.5621>:
}


pthread_stop_world ()
{
  int GC_retry_signals.9;
  int ack_count.10;
  int GC_print_stats.11;
  int D.5632;
  void (*<T32e>) (char *, GC_word) GC_current_warn_proc.12;
  int * D.5636;
  int D.5637;
  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.5623>; else goto <D.5624>;
  <D.5623>:
  {
    long unsigned int wait_usecs;

    wait_usecs = 0;
    <D.5488>:
    {
      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.5486>; else goto <D.5626>;
          <D.5626>:
          if (wait_usecs > 100000) goto <D.5627>; else goto <D.5628>;
          <D.5627>:
          {
            int newly_sent;

            newly_sent = GC_suspend_all ();
            GC_print_stats.11 = GC_print_stats;
            if (GC_print_stats.11 != 0) goto <D.5630>; else goto <D.5631>;
            <D.5630>:
            GC_printf ("Resent %ld signals after timeout\n", newly_sent, 0, 0, 0, 0, 0);
            <D.5631>:
            sem_getvalue (&GC_suspend_ack_sem, &ack_count);
            ack_count.10 = ack_count;
            D.5632 = n_live_threads - ack_count.10;
            if (D.5632 > newly_sent) goto <D.5633>; else goto <D.5634>;
            <D.5633>:
            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.5634>:
            wait_usecs = 0;
          }
          <D.5628>:
          usleep (3000);
          wait_usecs = wait_usecs + 3000;
        }
      finally
        {
          ack_count = {CLOBBER};
        }
    }
    goto <D.5488>;
    <D.5486>:
  }
  <D.5624>:
  i = 0;
  goto <D.5493>;
  <D.5492>:
  goto <D.5490>;
  <D.5489>:
  D.5636 = __errno_location ();
  D.5637 = *D.5636;
  if (D.5637 != 4) goto <D.5638>; else goto <D.5639>;
  <D.5638>:
  GC_err_printf ("Sem_wait returned %ld\n", code, 0, 0, 0, 0, 0);
  GC_abort ("sem_wait for handler failed");
  <D.5639>:
  <D.5490>:
  code = sem_wait (&GC_suspend_ack_sem);
  if (code != 0) goto <D.5489>; else goto <D.5491>;
  <D.5491>:
  i = i + 1;
  <D.5493>:
  if (i < n_live_threads) goto <D.5492>; else goto <D.5494>;
  <D.5494>:
  GC_stopping_thread = 0;
}


GC_start_world ()
{
  pthread_start_world ();
}


pthread_start_world ()
{
  void (*<T2b1>) (GCEventType) GC_notify_event.13;
  long unsigned int D.5645;
  short int D.5648;
  unsigned short D.5649;
  int D.5650;
  int D.5651;
  short int D.5654;
  int * D.5657;
  int D.5658;
  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.5643>; else goto <D.5644>;
  <D.5643>:
  GC_notify_event.13 = GC_notify_event;
  GC_notify_event.13 (8);
  <D.5644>:
  i = 0;
  goto <D.5514>;
  <D.5513>:
  p = GC_threads[i];
  goto <D.5511>;
  <D.5510>:
  D.5645 = p->id;
  if (D.5645 != my_thread) goto <D.5646>; else goto <D.5647>;
  <D.5646>:
  D.5648 = p->flags;
  D.5649 = (unsigned short) D.5648;
  D.5650 = (int) D.5649;
  D.5651 = D.5650 & 1;
  if (D.5651 != 0) goto <D.5652>; else goto <D.5653>;
  <D.5652>:
  // predicted unlikely by continue predictor.
  goto <D.5505>;
  <D.5653>:
  D.5654 = p->thread_blocked;
  if (D.5654 != 0) goto <D.5655>; else goto <D.5656>;
  <D.5655>:
  // predicted unlikely by continue predictor.
  goto <D.5505>;
  <D.5656>:
  n_live_threads = n_live_threads + 1;
  D.5645 = p->id;
  result = pthread_kill (D.5645, 30);
  switch (result) <default: <D.5509>, case 0: <D.5508>, case 3: <D.5506>>
  <D.5506>:
  n_live_threads = n_live_threads + -1;
  goto <D.5507>;
  <D.5508>:
  goto <D.5507>;
  <D.5509>:
  GC_abort ("pthread_kill failed");
  <D.5507>:
  <D.5647>:
  <D.5505>:
  p = p->next;
  <D.5511>:
  if (p != 0B) goto <D.5510>; else goto <D.5512>;
  <D.5512>:
  i = i + 1;
  <D.5514>:
  if (i <= 127) goto <D.5513>; else goto <D.5515>;
  <D.5515>:
  i = 0;
  goto <D.5520>;
  <D.5519>:
  goto <D.5517>;
  <D.5516>:
  D.5657 = __errno_location ();
  D.5658 = *D.5657;
  if (D.5658 != 4) goto <D.5659>; else goto <D.5660>;
  <D.5659>:
  GC_err_printf ("Sem_wait returned %ld\n", code, 0, 0, 0, 0, 0);
  GC_abort ("sem_wait for handler failed");
  <D.5660>:
  <D.5517>:
  code = sem_wait (&GC_suspend_ack_sem);
  if (code != 0) goto <D.5516>; else goto <D.5518>;
  <D.5518>:
  i = i + 1;
  <D.5520>:
  if (i < n_live_threads) goto <D.5519>; else goto <D.5521>;
  <D.5521>:
  GC_notify_event.13 = GC_notify_event;
  if (GC_notify_event.13 != 0B) goto <D.5661>; else goto <D.5662>;
  <D.5661>:
  GC_notify_event.13 = GC_notify_event;
  GC_notify_event.13 (9);
  <D.5662>:
}


GC_stop_init ()
{
  pthread_stop_init ();
}


pthread_stop_init ()
{
  int D.5664;
  int D.5667;
  int D.5670;
  int D.5673;
  int D.5676;
  int D.5679;
  char * D.5682;
  char * D.5685;
  int GC_print_stats.14;
  int GC_retry_signals.15;
  struct sigaction act;

  try
    {
      D.5664 = sem_init (&GC_suspend_ack_sem, 0, 0);
      if (D.5664 != 0) goto <D.5665>; else goto <D.5666>;
      <D.5665>:
      GC_abort ("sem_init failed");
      <D.5666>:
      act.sa_flags = 268435456;
      D.5667 = sigfillset (&act.sa_mask);
      if (D.5667 != 0) goto <D.5668>; else goto <D.5669>;
      <D.5668>:
      GC_abort ("sigfillset() failed");
      <D.5669>:
      GC_remove_allowed_signals (&act.sa_mask);
      act.__sigaction_handler.sa_handler = GC_suspend_handler;
      D.5670 = sigaction (19, &act, 0B);
      if (D.5670 != 0) goto <D.5671>; else goto <D.5672>;
      <D.5671>:
      GC_abort ("Cannot set SIG_SUSPEND handler");
      <D.5672>:
      act.__sigaction_handler.sa_handler = GC_restart_handler;
      D.5673 = sigaction (30, &act, 0B);
      if (D.5673 != 0) goto <D.5674>; else goto <D.5675>;
      <D.5674>:
      GC_abort ("Cannot set SIG_THR_RESTART handler");
      <D.5675>:
      D.5676 = sigfillset (&suspend_handler_mask);
      if (D.5676 != 0) goto <D.5677>; else goto <D.5678>;
      <D.5677>:
      GC_abort ("sigfillset() failed");
      <D.5678>:
      GC_remove_allowed_signals (&suspend_handler_mask);
      D.5679 = sigdelset (&suspend_handler_mask, 30);
      if (D.5679 != 0) goto <D.5680>; else goto <D.5681>;
      <D.5680>:
      GC_abort ("sigdelset() failed");
      <D.5681>:
      D.5682 = getenv ("GC_RETRY_SIGNALS");
      if (D.5682 != 0B) goto <D.5683>; else goto <D.5684>;
      <D.5683>:
      GC_retry_signals = 1;
      <D.5684>:
      D.5685 = getenv ("GC_NO_RETRY_SIGNALS");
      if (D.5685 != 0B) goto <D.5686>; else goto <D.5687>;
      <D.5686>:
      GC_retry_signals = 0;
      <D.5687>:
      GC_print_stats.14 = GC_print_stats;
      if (GC_print_stats.14 != 0) goto <D.5689>; else goto <D.5690>;
      <D.5689>:
      GC_retry_signals.15 = GC_retry_signals;
      if (GC_retry_signals.15 != 0) goto <D.5692>; else goto <D.5693>;
      <D.5692>:
      GC_printf ("Will retry suspend signal if necessary.\n", 0, 0, 0, 0, 0, 0);
      <D.5693>:
      <D.5690>:
    }
  finally
    {
      act = {CLOBBER};
    }
}


