GC_push_thread_structures ()
{
  GC_push_all (&GC_threads, &MEM[(void *)&GC_threads + 1024B]);
}


GC_new_thread (pthread_t id)
{
  int D.6962;
  int first_thread_used.0;
  struct GC_Thread_Rep * D.6969;
  struct GC_Thread_Rep * D.6970;
  int hv;
  struct GC_Thread_Rep * result;
  static GC_bool first_thread_used = 0;

  D.6962 = (int) id;
  hv = D.6962 & 127;
  first_thread_used.0 = first_thread_used;
  if (first_thread_used.0 == 0) goto <D.6964>; else goto <D.6965>;
  <D.6964>:
  result = &first_thread;
  first_thread_used = 1;
  goto <D.6966>;
  <D.6965>:
  result = GC_generic_malloc_inner (96, 1);
  <D.6966>:
  if (result == 0B) goto <D.6967>; else goto <D.6968>;
  <D.6967>:
  D.6969 = 0B;
  return D.6969;
  <D.6968>:
  result->id = id;
  D.6970 = GC_threads[hv];
  result->next = D.6970;
  GC_threads[hv] = result;
  D.6969 = result;
  return D.6969;
}


GC_delete_thread (pthread_t id)
{
  int D.6972;
  long unsigned int D.6973;
  int D.6974;
  struct GC_Thread_Rep * D.6977;
  int hv;
  register struct GC_Thread_Rep * p;
  register struct GC_Thread_Rep * prev;

  D.6972 = (int) id;
  hv = D.6972 & 127;
  p = GC_threads[hv];
  prev = 0B;
  goto <D.6797>;
  <D.6796>:
  prev = p;
  p = p->next;
  <D.6797>:
  D.6973 = p->id;
  D.6974 = pthread_equal (D.6973, id);
  if (D.6974 == 0) goto <D.6796>; else goto <D.6798>;
  <D.6798>:
  if (prev == 0B) goto <D.6975>; else goto <D.6976>;
  <D.6975>:
  D.6977 = p->next;
  GC_threads[hv] = D.6977;
  goto <D.6978>;
  <D.6976>:
  D.6977 = p->next;
  prev->next = D.6977;
  <D.6978>:
  GC_free_inner (p);
}


pthread_equal (pthread_t __thread1, pthread_t __thread2)
{
  int D.6979;
  _Bool D.6980;

  D.6980 = __thread1 == __thread2;
  D.6979 = (int) D.6980;
  return D.6979;
}


GC_delete_gc_thread (pthread_t id, struct GC_Thread_Rep * gc_id)
{
  int D.6982;
  struct GC_Thread_Rep * D.6985;
  int hv;
  register struct GC_Thread_Rep * p;
  register struct GC_Thread_Rep * prev;

  D.6982 = (int) id;
  hv = D.6982 & 127;
  p = GC_threads[hv];
  prev = 0B;
  goto <D.6807>;
  <D.6806>:
  prev = p;
  p = p->next;
  <D.6807>:
  if (p != gc_id) goto <D.6806>; else goto <D.6808>;
  <D.6808>:
  if (prev == 0B) goto <D.6983>; else goto <D.6984>;
  <D.6983>:
  D.6985 = p->next;
  GC_threads[hv] = D.6985;
  goto <D.6986>;
  <D.6984>:
  D.6985 = p->next;
  prev->next = D.6985;
  <D.6986>:
  GC_free_inner (p);
}


GC_lookup_thread (pthread_t id)
{
  int D.6987;
  long unsigned int D.6989;
  int D.6990;
  struct GC_Thread_Rep * D.6991;
  int hv;
  register struct GC_Thread_Rep * p;

  D.6987 = (int) id;
  hv = D.6987 & 127;
  p = GC_threads[hv];
  goto <D.6815>;
  <D.6814>:
  p = p->next;
  <D.6815>:
  if (p != 0B) goto <D.6988>; else goto <D.6816>;
  <D.6988>:
  D.6989 = p->id;
  D.6990 = pthread_equal (D.6989, id);
  if (D.6990 == 0) goto <D.6814>; else goto <D.6816>;
  <D.6816>:
  D.6991 = p;
  return D.6991;
}


GC_thread_is_registered ()
{
  int D.6993;
  long unsigned int D.6996;
  int D.6997;
  _Bool D.6998;
  void * ptr;

  D.6993 = GC_test_and_set (&GC_allocate_lock);
  if (D.6993 != 0) goto <D.6994>; else goto <D.6995>;
  <D.6994>:
  GC_lock ();
  <D.6995>:
  D.6996 = pthread_self ();
  ptr = GC_lookup_thread (D.6996);
  GC_clear (&GC_allocate_lock);
  D.6998 = ptr != 0B;
  D.6997 = (int) D.6998;
  return D.6997;
}


GC_test_and_set (volatile unsigned int * addr)
{
  int D.7000;
  int oldval;
  int temp;

  temp = 1;
  __asm__ __volatile__("1:	lwarx %0,0,%1
	cmpwi %0, 0
	bne 2f
	stwcx. %2,0,%1
	bne- 1b
	sync
2:	
" : "=&r" oldval : "r" addr, "r" temp : "memory", "cr0");
  D.7000 = oldval;
  return D.7000;
}


GC_clear (volatile unsigned int * addr)
{
  __asm__ __volatile__("lwsync" :  :  : "memory");
  *addr = 0;
}


GC_register_altstack (void * stack, int stack_size, void * altstack, int altstack_size)
{
  int D.7002;
  long unsigned int main_pthread_self.1;
  struct GC_Thread_Rep * thread;

  D.7002 = GC_test_and_set (&GC_allocate_lock);
  if (D.7002 != 0) goto <D.7003>; else goto <D.7004>;
  <D.7003>:
  GC_lock ();
  <D.7004>:
  main_pthread_self.1 = pthread_self ();
  thread = GC_lookup_thread (main_pthread_self.1);
  if (thread != 0B) goto <D.7006>; else goto <D.7007>;
  <D.7006>:
  thread->stack = stack;
  thread->stack_size = stack_size;
  thread->altstack = altstack;
  thread->altstack_size = altstack_size;
  goto <D.7008>;
  <D.7007>:
  main_pthread_self.1 = pthread_self ();
  main_pthread_self = main_pthread_self.1;
  main_stack = stack;
  main_stack_size = stack_size;
  main_altstack = altstack;
  main_altstack_size = altstack_size;
  <D.7008>:
  GC_clear (&GC_allocate_lock);
}


GC_get_nprocs ()
{
  long int D.7012;
  void (*<T41b>) (char *, GC_word) GC_current_warn_proc.2;
  int D.7014;
  char D.7015;
  long unsigned int D.7018;
  char D.7019;
  long unsigned int D.7022;
  char D.7023;
  long unsigned int D.7026;
  char D.7027;
  sizetype D.7030;
  const char * D.7031;
  long unsigned int D.7032;
  int D.7035;
  long unsigned int D.7036;
  char stat_buf[4096];
  int f;
  word result;
  size_t i;
  size_t len;

  try
    {
      result = 1;
      len = 0;
      f = open ("/proc/stat", 0);
      if (f < 0) goto <D.7009>; else goto <D.7011>;
      <D.7011>:
      D.7012 = read (f, &stat_buf, 4096);
      len = (size_t) D.7012;
      if (len <= 99) goto <D.7009>; else goto <D.7010>;
      <D.7009>:
      GC_current_warn_proc.2 = GC_current_warn_proc;
      GC_current_warn_proc.2 ("GC Warning: Couldn\'t read /proc/stat\n", 0);
      D.7014 = -1;
      return D.7014;
      <D.7010>:
      i = 0;
      goto <D.6837>;
      <D.6836>:
      D.7015 = stat_buf[i];
      if (D.7015 == 10) goto <D.7016>; else goto <D.7017>;
      <D.7016>:
      D.7018 = i + 1;
      D.7019 = stat_buf[D.7018];
      if (D.7019 == 99) goto <D.7020>; else goto <D.7021>;
      <D.7020>:
      D.7022 = i + 2;
      D.7023 = stat_buf[D.7022];
      if (D.7023 == 112) goto <D.7024>; else goto <D.7025>;
      <D.7024>:
      D.7026 = i + 3;
      D.7027 = stat_buf[D.7026];
      if (D.7027 == 117) goto <D.7028>; else goto <D.7029>;
      <D.7028>:
      {
        int cpu_no;

        D.7030 = i + 4;
        D.7031 = &stat_buf + D.7030;
        cpu_no = atoi (D.7031);
        D.7032 = (long unsigned int) cpu_no;
        if (D.7032 >= result) goto <D.7033>; else goto <D.7034>;
        <D.7033>:
        D.7035 = cpu_no + 1;
        result = (word) D.7035;
        <D.7034>:
      }
      <D.7029>:
      <D.7025>:
      <D.7021>:
      <D.7017>:
      i = i + 1;
      <D.6837>:
      D.7036 = len + 18446744073709551516;
      if (D.7036 > i) goto <D.6836>; else goto <D.6838>;
      <D.6838>:
      close (f);
      D.7014 = (int) result;
      return D.7014;
    }
  finally
    {
      stat_buf = {CLOBBER};
    }
}


open (const char * __path, int __oflag)
{
  int D.7039;
  int D.7042;
  int D.7047;
  int D.7049;
  int D.7050;
  int D.7053;
  int D.7054;

  D.7039 = __builtin_va_arg_pack_len ();
  if (D.7039 > 1) goto <D.7040>; else goto <D.7041>;
  <D.7040>:
  __open_too_many_args ();
  <D.7041>:
  D.7042 = __builtin_constant_p (__oflag);
  if (D.7042 != 0) goto <D.7043>; else goto <D.7044>;
  <D.7043>:
  D.7047 = __oflag & 64;
  if (D.7047 != 0) goto <D.7045>; else goto <D.7048>;
  <D.7048>:
  D.7049 = __oflag & 4259840;
  if (D.7049 == 4259840) goto <D.7045>; else goto <D.7046>;
  <D.7045>:
  D.7050 = __builtin_va_arg_pack_len ();
  if (D.7050 <= 0) goto <D.7051>; else goto <D.7052>;
  <D.7051>:
  __open_missing_mode ();
  D.7053 = __open_2 (__path, __oflag);
  return D.7053;
  <D.7052>:
  <D.7046>:
  D.7053 = __open_alias (__path, __oflag, __builtin_va_arg_pack ());
  return D.7053;
  <D.7044>:
  D.7054 = __builtin_va_arg_pack_len ();
  if (D.7054 <= 0) goto <D.7055>; else goto <D.7056>;
  <D.7055>:
  D.7053 = __open_2 (__path, __oflag);
  return D.7053;
  <D.7056>:
  D.7053 = __open_alias (__path, __oflag, __builtin_va_arg_pack ());
  return D.7053;
}


read (int __fd, void * __buf, size_t __nbytes)
{
  long unsigned int D.7058;
  int D.7061;
  ssize_t D.7064;
  long unsigned int D.7065;
  long unsigned int D.7066;
  long unsigned int D.7069;

  D.7058 = __builtin_object_size (__buf, 0);
  if (D.7058 != 18446744073709551615) goto <D.7059>; else goto <D.7060>;
  <D.7059>:
  D.7061 = __builtin_constant_p (__nbytes);
  if (D.7061 == 0) goto <D.7062>; else goto <D.7063>;
  <D.7062>:
  D.7065 = __builtin_object_size (__buf, 0);
  D.7064 = __read_chk (__fd, __buf, __nbytes, D.7065);
  return D.7064;
  <D.7063>:
  D.7066 = __builtin_object_size (__buf, 0);
  if (D.7066 < __nbytes) goto <D.7067>; else goto <D.7068>;
  <D.7067>:
  D.7069 = __builtin_object_size (__buf, 0);
  D.7064 = __read_chk_warn (__fd, __buf, __nbytes, D.7069);
  return D.7064;
  <D.7068>:
  <D.7060>:
  D.7064 = __read_alias (__fd, __buf, __nbytes);
  return D.7064;
}


atoi (const char * __nptr)
{
  int D.7071;
  long int D.7072;

  D.7072 = strtol (__nptr, 0B, 10);
  D.7071 = (int) D.7072;
  return D.7071;
}


GC_wait_for_gc_completion (GC_bool wait_for_all)
{
  int GC_incremental.3;
  int D.7077;
  long unsigned int GC_gc_no.4;
  int D.7081;
  int D.7085;
  long unsigned int D.7088;

  GC_incremental.3 = GC_incremental;
  if (GC_incremental.3 != 0) goto <D.7075>; else goto <D.7076>;
  <D.7075>:
  D.7077 = GC_collection_in_progress ();
  if (D.7077 != 0) goto <D.7078>; else goto <D.7079>;
  <D.7078>:
  {
    int old_gc_no;

    GC_gc_no.4 = GC_gc_no;
    old_gc_no = (int) GC_gc_no.4;
    goto <D.6845>;
    <D.6844>:
    GC_collecting = 1;
    GC_in_thread_creation = 1;
    GC_collect_a_little_inner (1);
    GC_in_thread_creation = 0;
    GC_collecting = 0;
    GC_clear (&GC_allocate_lock);
    sched_yield ();
    D.7081 = GC_test_and_set (&GC_allocate_lock);
    if (D.7081 != 0) goto <D.7082>; else goto <D.7083>;
    <D.7082>:
    GC_lock ();
    <D.7083>:
    <D.6845>:
    GC_incremental.3 = GC_incremental;
    if (GC_incremental.3 != 0) goto <D.7084>; else goto <D.6846>;
    <D.7084>:
    D.7085 = GC_collection_in_progress ();
    if (D.7085 != 0) goto <D.7086>; else goto <D.6846>;
    <D.7086>:
    if (wait_for_all != 0) goto <D.6844>; else goto <D.7087>;
    <D.7087>:
    D.7088 = (long unsigned int) old_gc_no;
    GC_gc_no.4 = GC_gc_no;
    if (D.7088 == GC_gc_no.4) goto <D.6844>; else goto <D.6846>;
    <D.6846>:
  }
  <D.7079>:
  <D.7076>:
}


GC_thr_init ()
{
  int GC_thr_initialized.5;
  long unsigned int D.7092;
  long unsigned int main_pthread_self.6;
  void * main_stack.7;
  int main_stack_size.8;
  void * main_altstack.9;
  int main_altstack_size.10;
  int D.7102;
  long int GC_nprocs.11;
  long int GC_nprocs.12;
  int D.7107;
  long int GC_nprocs.13;
  void (*<T41b>) (char *, GC_word) GC_current_warn_proc.14;
  long unsigned int GC_nprocs.15;
  int dummy;
  struct GC_Thread_Rep * t;

  try
    {
      GC_thr_initialized.5 = GC_thr_initialized;
      if (GC_thr_initialized.5 != 0) goto <D.7090>; else goto <D.7091>;
      <D.7090>:
      return;
      <D.7091>:
      GC_thr_initialized = 1;
      D.7092 = pthread_self ();
      t = GC_new_thread (D.7092);
      t->stop_info.stack_ptr = &dummy;
      t->flags = 6;
      D.7092 = pthread_self ();
      main_pthread_self.6 = main_pthread_self;
      if (D.7092 == main_pthread_self.6) goto <D.7094>; else goto <D.7095>;
      <D.7094>:
      main_stack.7 = main_stack;
      t->stack = main_stack.7;
      main_stack_size.8 = main_stack_size;
      t->stack_size = main_stack_size.8;
      main_altstack.9 = main_altstack;
      t->altstack = main_altstack.9;
      main_altstack_size.10 = main_altstack_size;
      t->altstack_size = main_altstack_size.10;
      <D.7095>:
      GC_stop_init ();
      {
        char * nprocs_string;

        nprocs_string = getenv ("GC_NPROCS");
        GC_nprocs = -1;
        if (nprocs_string != 0B) goto <D.7100>; else goto <D.7101>;
        <D.7100>:
        D.7102 = atoi (nprocs_string);
        GC_nprocs.11 = (long int) D.7102;
        GC_nprocs = GC_nprocs.11;
        <D.7101>:
      }
      GC_nprocs.12 = GC_nprocs;
      if (GC_nprocs.12 <= 0) goto <D.7105>; else goto <D.7106>;
      <D.7105>:
      D.7107 = GC_get_nprocs ();
      GC_nprocs.13 = (long int) D.7107;
      GC_nprocs = GC_nprocs.13;
      <D.7106>:
      GC_nprocs.12 = GC_nprocs;
      if (GC_nprocs.12 <= 0) goto <D.7109>; else goto <D.7110>;
      <D.7109>:
      GC_current_warn_proc.14 = GC_current_warn_proc;
      GC_nprocs.12 = GC_nprocs;
      GC_nprocs.15 = (long unsigned int) GC_nprocs.12;
      GC_current_warn_proc.14 ("GC Warning: GC_get_nprocs() returned %ld\n", GC_nprocs.15);
      GC_nprocs = 2;
      goto <D.7113>;
      <D.7110>:
      <D.7113>:
    }
  finally
    {
      dummy = {CLOBBER};
    }
}


GC_init_parallel ()
{
  int parallel_initialized.16;
  int GC_is_initialized.17;

  parallel_initialized.16 = parallel_initialized;
  if (parallel_initialized.16 != 0) goto <D.7118>; else goto <D.7119>;
  <D.7118>:
  return;
  <D.7119>:
  parallel_initialized = 1;
  GC_is_initialized.17 = GC_is_initialized;
  if (GC_is_initialized.17 == 0) goto <D.7121>; else goto <D.7122>;
  <D.7121>:
  GC_init ();
  <D.7122>:
}


GC_pthread_sigmask (int how, const struct sigset_t * set, struct sigset_t * oset)
{
  int D.7129;
  struct sigset_t fudged_set;

  try
    {
      if (set != 0B) goto <D.7126>; else goto <D.7127>;
      <D.7126>:
      if (how == 0) goto <D.7124>; else goto <D.7128>;
      <D.7128>:
      if (how == 2) goto <D.7124>; else goto <D.7125>;
      <D.7124>:
      fudged_set = *set;
      sigdelset (&fudged_set, 30);
      set = &fudged_set;
      <D.7125>:
      <D.7127>:
      D.7129 = pthread_sigmask (how, set, oset);
      return D.7129;
    }
  finally
    {
      fudged_set = {CLOBBER};
    }
}


GC_start_blocking ()
{
  int D.7132;
  long unsigned int D.7135;
  char * D.7136;
  char * D.7137;
  char * D.7138;
  struct GC_Thread_Rep * me;

  D.7132 = GC_test_and_set (&GC_allocate_lock);
  if (D.7132 != 0) goto <D.7133>; else goto <D.7134>;
  <D.7133>:
  GC_lock ();
  <D.7134>:
  D.7135 = pthread_self ();
  me = GC_lookup_thread (D.7135);
  D.7136 = GC_approx_sp ();
  me->stop_info.stack_ptr = D.7136;
  D.7137 = me->stop_info.stack_ptr;
  D.7138 = D.7137 + 18446744073709551488;
  me->stop_info.stack_ptr = D.7138;
  me->thread_blocked = 1;
  GC_clear (&GC_allocate_lock);
}


GC_end_blocking ()
{
  int D.7139;
  long unsigned int D.7142;
  struct GC_Thread_Rep * me;

  D.7139 = GC_test_and_set (&GC_allocate_lock);
  if (D.7139 != 0) goto <D.7140>; else goto <D.7141>;
  <D.7140>:
  GC_lock ();
  <D.7141>:
  D.7142 = pthread_self ();
  me = GC_lookup_thread (D.7142);
  me->thread_blocked = 0;
  GC_clear (&GC_allocate_lock);
}


GC_sleep (unsigned int seconds)
{
  unsigned int D.7143;
  int D.7144;
  int result;

  GC_start_blocking ();
  D.7143 = sleep (seconds);
  result = (int) D.7143;
  GC_end_blocking ();
  D.7144 = result;
  return D.7144;
}


GC_thread_exit_proc (void * arg)
{
  int D.7146;
  long unsigned int D.7149;
  short int D.7150;
  unsigned short D.7151;
  int D.7152;
  int D.7153;
  short int D.7157;
  struct GC_Thread_Rep * me;

  D.7146 = GC_test_and_set (&GC_allocate_lock);
  if (D.7146 != 0) goto <D.7147>; else goto <D.7148>;
  <D.7147>:
  GC_lock ();
  <D.7148>:
  D.7149 = pthread_self ();
  me = GC_lookup_thread (D.7149);
  D.7150 = me->flags;
  D.7151 = (unsigned short) D.7150;
  D.7152 = (int) D.7151;
  D.7153 = D.7152 & 2;
  if (D.7153 != 0) goto <D.7154>; else goto <D.7155>;
  <D.7154>:
  D.7149 = pthread_self ();
  GC_delete_thread (D.7149);
  goto <D.7156>;
  <D.7155>:
  D.7150 = me->flags;
  D.7157 = D.7150 | 1;
  me->flags = D.7157;
  <D.7156>:
  GC_wait_for_gc_completion (0);
  GC_clear (&GC_allocate_lock);
}


GC_pthread_join (pthread_t thread, void * * retval)
{
  int D.7158;
  int D.7163;
  int D.7166;
  int result;
  struct GC_Thread_Rep * thread_gc_id;

  D.7158 = GC_test_and_set (&GC_allocate_lock);
  if (D.7158 != 0) goto <D.7159>; else goto <D.7160>;
  <D.7159>:
  GC_lock ();
  <D.7160>:
  thread_gc_id = GC_lookup_thread (thread);
  GC_clear (&GC_allocate_lock);
  result = pthread_join (thread, retval);
  if (result == 0) goto <D.7161>; else goto <D.7162>;
  <D.7161>:
  D.7163 = GC_test_and_set (&GC_allocate_lock);
  if (D.7163 != 0) goto <D.7164>; else goto <D.7165>;
  <D.7164>:
  GC_lock ();
  <D.7165>:
  GC_delete_gc_thread (thread, thread_gc_id);
  GC_clear (&GC_allocate_lock);
  <D.7162>:
  D.7166 = result;
  return D.7166;
}


GC_pthread_detach (pthread_t thread)
{
  int D.7168;
  int D.7173;
  short int D.7176;
  short int D.7177;
  unsigned short D.7178;
  int D.7179;
  int D.7180;
  int D.7183;
  int result;
  struct GC_Thread_Rep * thread_gc_id;

  D.7168 = GC_test_and_set (&GC_allocate_lock);
  if (D.7168 != 0) goto <D.7169>; else goto <D.7170>;
  <D.7169>:
  GC_lock ();
  <D.7170>:
  thread_gc_id = GC_lookup_thread (thread);
  GC_clear (&GC_allocate_lock);
  result = pthread_detach (thread);
  if (result == 0) goto <D.7171>; else goto <D.7172>;
  <D.7171>:
  D.7173 = GC_test_and_set (&GC_allocate_lock);
  if (D.7173 != 0) goto <D.7174>; else goto <D.7175>;
  <D.7174>:
  GC_lock ();
  <D.7175>:
  D.7176 = thread_gc_id->flags;
  D.7177 = D.7176 | 2;
  thread_gc_id->flags = D.7177;
  D.7176 = thread_gc_id->flags;
  D.7178 = (unsigned short) D.7176;
  D.7179 = (int) D.7178;
  D.7180 = D.7179 & 1;
  if (D.7180 != 0) goto <D.7181>; else goto <D.7182>;
  <D.7181>:
  GC_delete_gc_thread (thread, thread_gc_id);
  <D.7182>:
  GC_clear (&GC_allocate_lock);
  <D.7172>:
  D.7183 = result;
  return D.7183;
}


GC_start_routine_head (void * arg, void * base_addr, void * (*ThreadStartFn) (void *) * start, void * * start_arg)
{
  int D.7185;
  long unsigned int D.7188;
  short int D.7189;
  long unsigned int GC_page_size.18;
  long unsigned int base_addr.19;
  long unsigned int D.7192;
  long unsigned int D.7193;
  long unsigned int D.7194;
  long unsigned int D.7195;
  char * D.7196;
  char * D.7197;
  char * D.7198;
  void * (*<T425>) (void *) D.7201;
  void * D.7204;
  long unsigned int D.7205;
  union sem_t * D.7208;
  void * D.7209;
  struct start_info * si;
  void * result;
  struct GC_Thread_Rep * me;
  pthread_t my_pthread;

  si = arg;
  my_pthread = pthread_self ();
  D.7185 = GC_test_and_set (&GC_allocate_lock);
  if (D.7185 != 0) goto <D.7186>; else goto <D.7187>;
  <D.7186>:
  GC_lock ();
  <D.7187>:
  GC_in_thread_creation = 1;
  me = GC_new_thread (my_pthread);
  GC_in_thread_creation = 0;
  me->stop_info.stack_ptr = 0B;
  D.7188 = si->flags;
  D.7189 = (short int) D.7188;
  me->flags = D.7189;
  GC_page_size.18 = GC_page_size;
  base_addr.19 = (long unsigned int) base_addr;
  D.7192 = GC_page_size.18 + base_addr.19;
  D.7193 = D.7192 + 18446744073709551615;
  GC_page_size.18 = GC_page_size;
  D.7194 = -GC_page_size.18;
  D.7195 = D.7193 & D.7194;
  D.7196 = (char *) D.7195;
  me->stack_end = D.7196;
  D.7197 = me->stack_end;
  D.7198 = D.7197 + 18446744073709551600;
  me->stop_info.stack_ptr = D.7198;
  GC_clear (&GC_allocate_lock);
  if (start != 0B) goto <D.7199>; else goto <D.7200>;
  <D.7199>:
  D.7201 = si->start_routine;
  *start = D.7201;
  <D.7200>:
  if (start_arg != 0B) goto <D.7202>; else goto <D.7203>;
  <D.7202>:
  D.7204 = si->arg;
  *start_arg = D.7204;
  <D.7203>:
  D.7188 = si->flags;
  D.7205 = D.7188 & 8;
  if (D.7205 == 0) goto <D.7206>; else goto <D.7207>;
  <D.7206>:
  D.7208 = &si->registered;
  sem_post (D.7208);
  <D.7207>:
  D.7209 = me;
  return D.7209;
}


GC_thread_register_foreign (void * base_addr)
{
  int parallel_initialized.20;
  int D.7214;
  int GC_thr_initialized.21;
  int D.7220;
  _Bool D.7221;
  struct start_info si;
  struct GC_Thread_Rep * me;

  try
    {
      si = {};
      si.flags = 8;
      parallel_initialized.20 = parallel_initialized;
      if (parallel_initialized.20 == 0) goto <D.7212>; else goto <D.7213>;
      <D.7212>:
      GC_init_parallel ();
      <D.7213>:
      D.7214 = GC_test_and_set (&GC_allocate_lock);
      if (D.7214 != 0) goto <D.7215>; else goto <D.7216>;
      <D.7215>:
      GC_lock ();
      <D.7216>:
      GC_thr_initialized.21 = GC_thr_initialized;
      if (GC_thr_initialized.21 == 0) goto <D.7218>; else goto <D.7219>;
      <D.7218>:
      GC_thr_init ();
      <D.7219>:
      GC_clear (&GC_allocate_lock);
      me = GC_start_routine_head (&si, base_addr, 0B, 0B);
      D.7221 = me != 0B;
      D.7220 = (int) D.7221;
      return D.7220;
    }
  finally
    {
      si = {CLOBBER};
    }
}


GC_start_routine (void * arg)
{
  long int D.7224;
  long int D.7225;
  void * (*<T425>) (void *) start.22;
  void * start_arg.23;
  void * D.7232;
  int dummy;
  struct start_info * si;
  void * result;
  struct GC_Thread_Rep * me;
  void * (*ThreadStartFn) (void *) start;
  void * start_arg;

  try
    {
      si = arg;
      me = GC_start_routine_head (arg, &dummy, &start, &start_arg);
      {
        struct __pthread_unwind_buf_t __cancel_buf;
        void (*<Tbf>) (void *) __cancel_routine;
        void * __cancel_arg;
        int __not_first_call;

        try
          {
            __cancel_routine = GC_thread_exit_proc;
            __cancel_arg = 0B;
            __not_first_call = __sigsetjmp (&__cancel_buf.__cancel_jmp_buf, 0);
            D.7224 = (long int) __not_first_call;
            D.7225 = __builtin_expect (D.7224, 0);
            if (D.7225 != 0) goto <D.7226>; else goto <D.7227>;
            <D.7226>:
            __cancel_routine (__cancel_arg);
            __pthread_unwind_next (&__cancel_buf);
            <D.7227>:
            __pthread_register_cancel (&__cancel_buf);
            start.22 = start;
            start_arg.23 = start_arg;
            result = start.22 (start_arg.23);
            me->status = result;
            __pthread_unregister_cancel (&__cancel_buf);
            if (1 != 0) goto <D.7230>; else goto <D.7231>;
            <D.7230>:
            __cancel_routine (__cancel_arg);
            <D.7231>:
          }
        finally
          {
            __cancel_buf = {CLOBBER};
          }
      }
      D.7232 = result;
      return D.7232;
    }
  finally
    {
      dummy = {CLOBBER};
      start = {CLOBBER};
      start_arg = {CLOBBER};
    }
}


GC_pthread_create (pthread_t * new_thread, const union pthread_attr_t * attr, void * (*<T425>) (void *) start_routine, void * arg)
{
  int D.7237;
  int parallel_initialized.24;
  int D.7245;
  union sem_t * D.7246;
  int D.7247;
  int GC_thr_initialized.25;
  int detachstate.26;
  int * D.7261;
  int D.7262;
  int D.7265;
  int D.7266;
  int result;
  int detachstate;
  word my_flags;
  struct start_info * si;

  try
    {
      my_flags = 0;
      D.7237 = GC_test_and_set (&GC_allocate_lock);
      if (D.7237 != 0) goto <D.7238>; else goto <D.7239>;
      <D.7238>:
      GC_lock ();
      <D.7239>:
      si = GC_generic_malloc_inner (56, 1);
      GC_clear (&GC_allocate_lock);
      parallel_initialized.24 = parallel_initialized;
      if (parallel_initialized.24 == 0) goto <D.7241>; else goto <D.7242>;
      <D.7241>:
      GC_init_parallel ();
      <D.7242>:
      if (si == 0B) goto <D.7243>; else goto <D.7244>;
      <D.7243>:
      D.7245 = 12;
      return D.7245;
      <D.7244>:
      D.7246 = &si->registered;
      sem_init (D.7246, 0, 0);
      si->start_routine = start_routine;
      si->arg = arg;
      D.7247 = GC_test_and_set (&GC_allocate_lock);
      if (D.7247 != 0) goto <D.7248>; else goto <D.7249>;
      <D.7248>:
      GC_lock ();
      <D.7249>:
      GC_thr_initialized.25 = GC_thr_initialized;
      if (GC_thr_initialized.25 == 0) goto <D.7251>; else goto <D.7252>;
      <D.7251>:
      GC_thr_init ();
      <D.7252>:
      if (attr == 0B) goto <D.7253>; else goto <D.7254>;
      <D.7253>:
      detachstate = 0;
      goto <D.7255>;
      <D.7254>:
      pthread_attr_getdetachstate (attr, &detachstate);
      <D.7255>:
      detachstate.26 = detachstate;
      if (detachstate.26 == 1) goto <D.7257>; else goto <D.7258>;
      <D.7257>:
      my_flags = my_flags | 2;
      <D.7258>:
      si->flags = my_flags;
      GC_clear (&GC_allocate_lock);
      result = pthread_create (new_thread, attr, GC_start_routine, si);
      if (result == 0) goto <D.7259>; else goto <D.7260>;
      <D.7259>:
      goto <D.6937>;
      <D.6936>:
      D.7261 = __errno_location ();
      D.7262 = *D.7261;
      if (D.7262 != 4) goto <D.7263>; else goto <D.7264>;
      <D.7263>:
      GC_abort ("sem_wait failed");
      <D.7264>:
      <D.6937>:
      D.7246 = &si->registered;
      D.7265 = sem_wait (D.7246);
      if (D.7265 != 0) goto <D.6936>; else goto <D.6938>;
      <D.6938>:
      <D.7260>:
      D.7246 = &si->registered;
      sem_destroy (D.7246);
      D.7266 = GC_test_and_set (&GC_allocate_lock);
      if (D.7266 != 0) goto <D.7267>; else goto <D.7268>;
      <D.7267>:
      GC_lock ();
      <D.7268>:
      GC_free_inner (si);
      GC_clear (&GC_allocate_lock);
      D.7245 = result;
      return D.7245;
    }
  finally
    {
      detachstate = {CLOBBER};
    }
}


GC_pause ()
{
  int i;

  i = 0;
  goto <D.6943>;
  <D.6942>:
  __asm__ __volatile__(" " :  :  : "memory");
  i = i + 1;
  <D.6943>:
  if (i <= 9) goto <D.6942>; else goto <D.6944>;
  <D.6944>:
}


GC_lock ()
{
  int D.7271;
  int GC_collecting.27;
  long int GC_nprocs.28;
  unsigned int i.29;
  unsigned int D.7281;
  unsigned int GC_allocate_lock.30;
  int D.7284;
  int D.7287;
  int D.7295;
  long int D.7296;
  static unsigned int spin_max = 30;
  unsigned int my_spin_max;
  static unsigned int last_spins = 0;
  unsigned int my_last_spins;
  int i;
  void yield = <<< error >>>;

  D.7271 = GC_test_and_set (&GC_allocate_lock);
  if (D.7271 == 0) goto <D.7272>; else goto <D.7273>;
  <D.7272>:
  return;
  <D.7273>:
  my_spin_max = spin_max;
  my_last_spins = last_spins;
  i = 0;
  goto <D.6957>;
  <D.6956>:
  GC_collecting.27 = GC_collecting;
  if (GC_collecting.27 != 0) goto yield; else goto <D.7275>;
  <D.7275>:
  GC_nprocs.28 = GC_nprocs;
  if (GC_nprocs.28 == 1) goto yield; else goto <D.7277>;
  <D.7277>:
  i.29 = (unsigned int) i;
  D.7281 = my_last_spins / 2;
  if (i.29 < D.7281) goto <D.7278>; else goto <D.7282>;
  <D.7282>:
  GC_allocate_lock.30 = GC_allocate_lock;
  if (GC_allocate_lock.30 != 0) goto <D.7278>; else goto <D.7279>;
  <D.7278>:
  GC_pause ();
  // predicted unlikely by continue predictor.
  goto <D.6955>;
  <D.7279>:
  D.7284 = GC_test_and_set (&GC_allocate_lock);
  if (D.7284 == 0) goto <D.7285>; else goto <D.7286>;
  <D.7285>:
  i.29 = (unsigned int) i;
  last_spins = i.29;
  spin_max = 128;
  return;
  <D.7286>:
  <D.6955>:
  i = i + 1;
  <D.6957>:
  i.29 = (unsigned int) i;
  if (i.29 < my_spin_max) goto <D.6956>; else goto <D.6958>;
  <D.6958>:
  spin_max = 30;
  yield:
  i = 0;
  <D.6960>:
  D.7287 = GC_test_and_set (&GC_allocate_lock);
  if (D.7287 == 0) goto <D.7288>; else goto <D.7289>;
  <D.7288>:
  return;
  <D.7289>:
  if (i <= 11) goto <D.7290>; else goto <D.7291>;
  <D.7290>:
  sched_yield ();
  goto <D.7292>;
  <D.7291>:
  {
    struct timespec ts;

    try
      {
        if (i > 24) goto <D.7293>; else goto <D.7294>;
        <D.7293>:
        i = 24;
        <D.7294>:
        ts.tv_sec = 0;
        D.7295 = 1 << i;
        D.7296 = (long int) D.7295;
        ts.tv_nsec = D.7296;
        nanosleep (&ts, 0B);
      }
    finally
      {
        ts = {CLOBBER};
      }
  }
  <D.7292>:
  i = i + 1;
  goto <D.6960>;
}


