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


GC_new_thread (pthread_t id)
{
  int id.0;
  int first_thread_used.1;
  struct GC_Thread_Rep * D.6063;
  struct GC_Thread_Rep * D.6064;
  int hv;
  struct GC_Thread_Rep * result;
  static GC_bool first_thread_used = 0;

  id.0 = (int) id;
  hv = id.0 & 127;
  first_thread_used.1 = first_thread_used;
  if (first_thread_used.1 == 0) goto <D.6058>; else goto <D.6059>;
  <D.6058>:
  result = &first_thread;
  first_thread_used = 1;
  goto <D.6060>;
  <D.6059>:
  result = GC_generic_malloc_inner (48, 1);
  <D.6060>:
  if (result == 0B) goto <D.6061>; else goto <D.6062>;
  <D.6061>:
  D.6063 = 0B;
  return D.6063;
  <D.6062>:
  result->id = id;
  D.6064 = GC_threads[hv];
  result->next = D.6064;
  GC_threads[hv] = result;
  D.6063 = result;
  return D.6063;
}


GC_delete_thread (pthread_t id)
{
  int id.2;
  long unsigned int D.6067;
  int D.6068;
  struct GC_Thread_Rep * D.6071;
  int hv;
  register struct GC_Thread_Rep * p;
  register struct GC_Thread_Rep * prev;

  id.2 = (int) id;
  hv = id.2 & 127;
  p = GC_threads[hv];
  prev = 0B;
  goto <D.5891>;
  <D.5890>:
  prev = p;
  p = p->next;
  <D.5891>:
  D.6067 = p->id;
  D.6068 = pthread_equal (D.6067, id);
  if (D.6068 == 0) goto <D.5890>; else goto <D.5892>;
  <D.5892>:
  if (prev == 0B) goto <D.6069>; else goto <D.6070>;
  <D.6069>:
  D.6071 = p->next;
  GC_threads[hv] = D.6071;
  goto <D.6072>;
  <D.6070>:
  D.6071 = p->next;
  prev->next = D.6071;
  <D.6072>:
  GC_free_inner (p);
}


pthread_equal (pthread_t __thread1, pthread_t __thread2)
{
  int D.6073;
  _Bool D.6074;

  D.6074 = __thread1 == __thread2;
  D.6073 = (int) D.6074;
  return D.6073;
}


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

  id.3 = (int) id;
  hv = id.3 & 127;
  p = GC_threads[hv];
  prev = 0B;
  goto <D.5901>;
  <D.5900>:
  prev = p;
  p = p->next;
  <D.5901>:
  if (p != gc_id) goto <D.5900>; else goto <D.5902>;
  <D.5902>:
  if (prev == 0B) goto <D.6077>; else goto <D.6078>;
  <D.6077>:
  D.6079 = p->next;
  GC_threads[hv] = D.6079;
  goto <D.6080>;
  <D.6078>:
  D.6079 = p->next;
  prev->next = D.6079;
  <D.6080>:
  GC_free_inner (p);
}


GC_lookup_thread (pthread_t id)
{
  int id.4;
  long unsigned int D.6083;
  int D.6084;
  struct GC_Thread_Rep * D.6085;
  int hv;
  register struct GC_Thread_Rep * p;

  id.4 = (int) id;
  hv = id.4 & 127;
  p = GC_threads[hv];
  goto <D.5909>;
  <D.5908>:
  p = p->next;
  <D.5909>:
  if (p != 0B) goto <D.6082>; else goto <D.5910>;
  <D.6082>:
  D.6083 = p->id;
  D.6084 = pthread_equal (D.6083, id);
  if (D.6084 == 0) goto <D.5908>; else goto <D.5910>;
  <D.5910>:
  D.6085 = p;
  return D.6085;
}


GC_thread_is_registered ()
{
  int D.6087;
  long unsigned int D.6090;
  int D.6091;
  _Bool D.6092;
  void * ptr;

  D.6087 = _test_and_set (&GC_allocate_lock, 1);
  if (D.6087 != 0) goto <D.6088>; else goto <D.6089>;
  <D.6088>:
  GC_lock ();
  <D.6089>:
  D.6090 = pthread_self ();
  ptr = GC_lookup_thread (D.6090);
  GC_clear (&GC_allocate_lock);
  D.6092 = ptr != 0B;
  D.6091 = (int) D.6092;
  return D.6091;
}


_test_and_set (int * __p, int __v)
{
  int D.6094;
  int __r;
  int __t;

  __asm__ __volatile__("/* Inline test and set */
.set	push
	.set	mips2
	sync
	1:
	ll	%0,%3
	move	%1,%4
	beq	%0,%4,2f
	sc	%1,%2
	beqz	%1,1b
sync
	.set	pop
	2:
	/* End test and set */" : "=&r" __r, "=&r" __t, "=m" *__p : "m" *__p, "r" __v : "memory");
  D.6094 = __r;
  return D.6094;
}


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


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

  D.6096 = _test_and_set (&GC_allocate_lock, 1);
  if (D.6096 != 0) goto <D.6097>; else goto <D.6098>;
  <D.6097>:
  GC_lock ();
  <D.6098>:
  main_pthread_self.5 = pthread_self ();
  thread = GC_lookup_thread (main_pthread_self.5);
  if (thread != 0B) goto <D.6100>; else goto <D.6101>;
  <D.6100>:
  thread->stack = stack;
  thread->stack_size = stack_size;
  thread->altstack = altstack;
  thread->altstack_size = altstack_size;
  goto <D.6102>;
  <D.6101>:
  main_pthread_self.5 = pthread_self ();
  main_pthread_self = main_pthread_self.5;
  main_stack = stack;
  main_stack_size = stack_size;
  main_altstack = altstack;
  main_altstack_size = altstack_size;
  <D.6102>:
  GC_clear (&GC_allocate_lock);
}


GC_get_nprocs ()
{
  int D.6106;
  void (*<T32e>) (char *, GC_word) GC_current_warn_proc.6;
  int D.6108;
  char D.6109;
  unsigned int D.6112;
  char D.6113;
  unsigned int D.6116;
  char D.6117;
  unsigned int D.6120;
  char D.6121;
  sizetype D.6124;
  const char * D.6125;
  long unsigned int cpu_no.7;
  int D.6129;
  unsigned int D.6130;
  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.6103>; else goto <D.6105>;
      <D.6105>:
      D.6106 = read (f, &stat_buf, 4096);
      len = (size_t) D.6106;
      if (len <= 99) goto <D.6103>; else goto <D.6104>;
      <D.6103>:
      GC_current_warn_proc.6 = GC_current_warn_proc;
      GC_current_warn_proc.6 ("GC Warning: Couldn\'t read /proc/stat\n", 0);
      D.6108 = -1;
      return D.6108;
      <D.6104>:
      i = 0;
      goto <D.5931>;
      <D.5930>:
      D.6109 = stat_buf[i];
      if (D.6109 == 10) goto <D.6110>; else goto <D.6111>;
      <D.6110>:
      D.6112 = i + 1;
      D.6113 = stat_buf[D.6112];
      if (D.6113 == 99) goto <D.6114>; else goto <D.6115>;
      <D.6114>:
      D.6116 = i + 2;
      D.6117 = stat_buf[D.6116];
      if (D.6117 == 112) goto <D.6118>; else goto <D.6119>;
      <D.6118>:
      D.6120 = i + 3;
      D.6121 = stat_buf[D.6120];
      if (D.6121 == 117) goto <D.6122>; else goto <D.6123>;
      <D.6122>:
      {
        int cpu_no;

        D.6124 = i + 4;
        D.6125 = &stat_buf + D.6124;
        cpu_no = atoi (D.6125);
        cpu_no.7 = (long unsigned int) cpu_no;
        if (cpu_no.7 >= result) goto <D.6127>; else goto <D.6128>;
        <D.6127>:
        D.6129 = cpu_no + 1;
        result = (word) D.6129;
        <D.6128>:
      }
      <D.6123>:
      <D.6119>:
      <D.6115>:
      <D.6111>:
      i = i + 1;
      <D.5931>:
      D.6130 = len + 4294967196;
      if (D.6130 > i) goto <D.5930>; else goto <D.5932>;
      <D.5932>:
      close (f);
      D.6108 = (int) result;
      return D.6108;
    }
  finally
    {
      stat_buf = {CLOBBER};
    }
}


open (const char * __path, int __oflag)
{
  int D.6133;
  int D.6136;
  int D.6141;
  int D.6143;
  int D.6144;
  int D.6147;
  int D.6148;

  D.6133 = __builtin_va_arg_pack_len ();
  if (D.6133 > 1) goto <D.6134>; else goto <D.6135>;
  <D.6134>:
  __open_too_many_args ();
  <D.6135>:
  D.6136 = __builtin_constant_p (__oflag);
  if (D.6136 != 0) goto <D.6137>; else goto <D.6138>;
  <D.6137>:
  D.6141 = __oflag & 256;
  if (D.6141 != 0) goto <D.6139>; else goto <D.6142>;
  <D.6142>:
  D.6143 = __oflag & 4259840;
  if (D.6143 == 4259840) goto <D.6139>; else goto <D.6140>;
  <D.6139>:
  D.6144 = __builtin_va_arg_pack_len ();
  if (D.6144 <= 0) goto <D.6145>; else goto <D.6146>;
  <D.6145>:
  __open_missing_mode ();
  D.6147 = __open_2 (__path, __oflag);
  return D.6147;
  <D.6146>:
  <D.6140>:
  D.6147 = __open_alias (__path, __oflag, __builtin_va_arg_pack ());
  return D.6147;
  <D.6138>:
  D.6148 = __builtin_va_arg_pack_len ();
  if (D.6148 <= 0) goto <D.6149>; else goto <D.6150>;
  <D.6149>:
  D.6147 = __open_2 (__path, __oflag);
  return D.6147;
  <D.6150>:
  D.6147 = __open_alias (__path, __oflag, __builtin_va_arg_pack ());
  return D.6147;
}


read (int __fd, void * __buf, size_t __nbytes)
{
  unsigned int D.6152;
  int D.6155;
  ssize_t D.6158;
  unsigned int D.6159;
  unsigned int D.6160;
  unsigned int D.6163;

  D.6152 = __builtin_object_size (__buf, 0);
  if (D.6152 != 4294967295) goto <D.6153>; else goto <D.6154>;
  <D.6153>:
  D.6155 = __builtin_constant_p (__nbytes);
  if (D.6155 == 0) goto <D.6156>; else goto <D.6157>;
  <D.6156>:
  D.6159 = __builtin_object_size (__buf, 0);
  D.6158 = __read_chk (__fd, __buf, __nbytes, D.6159);
  return D.6158;
  <D.6157>:
  D.6160 = __builtin_object_size (__buf, 0);
  if (D.6160 < __nbytes) goto <D.6161>; else goto <D.6162>;
  <D.6161>:
  D.6163 = __builtin_object_size (__buf, 0);
  D.6158 = __read_chk_warn (__fd, __buf, __nbytes, D.6163);
  return D.6158;
  <D.6162>:
  <D.6154>:
  D.6158 = __read_alias (__fd, __buf, __nbytes);
  return D.6158;
}


atoi (const char * __nptr)
{
  int D.6165;

  D.6165 = strtol (__nptr, 0B, 10);
  return D.6165;
}


GC_wait_for_gc_completion (GC_bool wait_for_all)
{
  int GC_incremental.8;
  int D.6170;
  long unsigned int GC_gc_no.9;
  int D.6174;
  int D.6178;
  long unsigned int old_gc_no.10;

  GC_incremental.8 = GC_incremental;
  if (GC_incremental.8 != 0) goto <D.6168>; else goto <D.6169>;
  <D.6168>:
  D.6170 = GC_collection_in_progress ();
  if (D.6170 != 0) goto <D.6171>; else goto <D.6172>;
  <D.6171>:
  {
    int old_gc_no;

    GC_gc_no.9 = GC_gc_no;
    old_gc_no = (int) GC_gc_no.9;
    goto <D.5939>;
    <D.5938>:
    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.6174 = _test_and_set (&GC_allocate_lock, 1);
    if (D.6174 != 0) goto <D.6175>; else goto <D.6176>;
    <D.6175>:
    GC_lock ();
    <D.6176>:
    <D.5939>:
    GC_incremental.8 = GC_incremental;
    if (GC_incremental.8 != 0) goto <D.6177>; else goto <D.5940>;
    <D.6177>:
    D.6178 = GC_collection_in_progress ();
    if (D.6178 != 0) goto <D.6179>; else goto <D.5940>;
    <D.6179>:
    if (wait_for_all != 0) goto <D.5938>; else goto <D.6180>;
    <D.6180>:
    old_gc_no.10 = (long unsigned int) old_gc_no;
    GC_gc_no.9 = GC_gc_no;
    if (old_gc_no.10 == GC_gc_no.9) goto <D.5938>; else goto <D.5940>;
    <D.5940>:
  }
  <D.6172>:
  <D.6169>:
}


GC_thr_init ()
{
  int GC_thr_initialized.11;
  long unsigned int D.6185;
  long unsigned int main_pthread_self.12;
  void * main_stack.13;
  int main_stack_size.14;
  void * main_altstack.15;
  int main_altstack_size.16;
  int GC_nprocs.17;
  long int GC_nprocs.18;
  int GC_nprocs.19;
  void (*<T32e>) (char *, GC_word) GC_current_warn_proc.20;
  long unsigned int GC_nprocs.21;
  int dummy;
  struct GC_Thread_Rep * t;

  try
    {
      GC_thr_initialized.11 = GC_thr_initialized;
      if (GC_thr_initialized.11 != 0) goto <D.6183>; else goto <D.6184>;
      <D.6183>:
      return;
      <D.6184>:
      GC_thr_initialized = 1;
      D.6185 = pthread_self ();
      t = GC_new_thread (D.6185);
      t->stop_info.stack_ptr = &dummy;
      t->flags = 6;
      D.6185 = pthread_self ();
      main_pthread_self.12 = main_pthread_self;
      if (D.6185 == main_pthread_self.12) goto <D.6187>; else goto <D.6188>;
      <D.6187>:
      main_stack.13 = main_stack;
      t->stack = main_stack.13;
      main_stack_size.14 = main_stack_size;
      t->stack_size = main_stack_size.14;
      main_altstack.15 = main_altstack;
      t->altstack = main_altstack.15;
      main_altstack_size.16 = main_altstack_size;
      t->altstack_size = main_altstack_size.16;
      <D.6188>:
      GC_stop_init ();
      {
        char * nprocs_string;

        nprocs_string = getenv ("GC_NPROCS");
        GC_nprocs = -1;
        if (nprocs_string != 0B) goto <D.6193>; else goto <D.6194>;
        <D.6193>:
        GC_nprocs.17 = atoi (nprocs_string);
        GC_nprocs = GC_nprocs.17;
        <D.6194>:
      }
      GC_nprocs.18 = GC_nprocs;
      if (GC_nprocs.18 <= 0) goto <D.6197>; else goto <D.6198>;
      <D.6197>:
      GC_nprocs.19 = GC_get_nprocs ();
      GC_nprocs = GC_nprocs.19;
      <D.6198>:
      GC_nprocs.18 = GC_nprocs;
      if (GC_nprocs.18 <= 0) goto <D.6200>; else goto <D.6201>;
      <D.6200>:
      GC_current_warn_proc.20 = GC_current_warn_proc;
      GC_nprocs.18 = GC_nprocs;
      GC_nprocs.21 = (long unsigned int) GC_nprocs.18;
      GC_current_warn_proc.20 ("GC Warning: GC_get_nprocs() returned %ld\n", GC_nprocs.21);
      GC_nprocs = 2;
      goto <D.6204>;
      <D.6201>:
      <D.6204>:
    }
  finally
    {
      dummy = {CLOBBER};
    }
}


GC_init_parallel ()
{
  int parallel_initialized.22;
  int GC_is_initialized.23;

  parallel_initialized.22 = parallel_initialized;
  if (parallel_initialized.22 != 0) goto <D.6209>; else goto <D.6210>;
  <D.6209>:
  return;
  <D.6210>:
  parallel_initialized = 1;
  GC_is_initialized.23 = GC_is_initialized;
  if (GC_is_initialized.23 == 0) goto <D.6212>; else goto <D.6213>;
  <D.6212>:
  GC_init ();
  <D.6213>:
}


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

  try
    {
      if (set != 0B) goto <D.6217>; else goto <D.6218>;
      <D.6217>:
      if (how == 1) goto <D.6215>; else goto <D.6219>;
      <D.6219>:
      if (how == 3) goto <D.6215>; else goto <D.6216>;
      <D.6215>:
      fudged_set = *set;
      sigdelset (&fudged_set, 19);
      set = &fudged_set;
      <D.6216>:
      <D.6218>:
      D.6220 = pthread_sigmask (how, set, oset);
      return D.6220;
    }
  finally
    {
      fudged_set = {CLOBBER};
    }
}


GC_start_blocking ()
{
  int D.6223;
  long unsigned int D.6226;
  char * D.6227;
  char * D.6228;
  char * D.6229;
  struct GC_Thread_Rep * me;

  D.6223 = _test_and_set (&GC_allocate_lock, 1);
  if (D.6223 != 0) goto <D.6224>; else goto <D.6225>;
  <D.6224>:
  GC_lock ();
  <D.6225>:
  D.6226 = pthread_self ();
  me = GC_lookup_thread (D.6226);
  D.6227 = GC_approx_sp ();
  me->stop_info.stack_ptr = D.6227;
  D.6228 = me->stop_info.stack_ptr;
  D.6229 = D.6228 + 4294967168;
  me->stop_info.stack_ptr = D.6229;
  me->thread_blocked = 1;
  GC_clear (&GC_allocate_lock);
}


GC_end_blocking ()
{
  int D.6230;
  long unsigned int D.6233;
  struct GC_Thread_Rep * me;

  D.6230 = _test_and_set (&GC_allocate_lock, 1);
  if (D.6230 != 0) goto <D.6231>; else goto <D.6232>;
  <D.6231>:
  GC_lock ();
  <D.6232>:
  D.6233 = pthread_self ();
  me = GC_lookup_thread (D.6233);
  me->thread_blocked = 0;
  GC_clear (&GC_allocate_lock);
}


GC_sleep (unsigned int seconds)
{
  unsigned int D.6234;
  int D.6235;
  int result;

  GC_start_blocking ();
  D.6234 = sleep (seconds);
  result = (int) D.6234;
  GC_end_blocking ();
  D.6235 = result;
  return D.6235;
}


GC_thread_exit_proc (void * arg)
{
  int D.6237;
  long unsigned int D.6240;
  short int D.6241;
  unsigned short D.6242;
  int D.6243;
  int D.6244;
  short int D.6248;
  struct GC_Thread_Rep * me;

  D.6237 = _test_and_set (&GC_allocate_lock, 1);
  if (D.6237 != 0) goto <D.6238>; else goto <D.6239>;
  <D.6238>:
  GC_lock ();
  <D.6239>:
  D.6240 = pthread_self ();
  me = GC_lookup_thread (D.6240);
  D.6241 = me->flags;
  D.6242 = (unsigned short) D.6241;
  D.6243 = (int) D.6242;
  D.6244 = D.6243 & 2;
  if (D.6244 != 0) goto <D.6245>; else goto <D.6246>;
  <D.6245>:
  D.6240 = pthread_self ();
  GC_delete_thread (D.6240);
  goto <D.6247>;
  <D.6246>:
  D.6241 = me->flags;
  D.6248 = D.6241 | 1;
  me->flags = D.6248;
  <D.6247>:
  GC_wait_for_gc_completion (0);
  GC_clear (&GC_allocate_lock);
}


GC_pthread_join (pthread_t thread, void * * retval)
{
  int D.6249;
  int D.6254;
  int D.6257;
  int result;
  struct GC_Thread_Rep * thread_gc_id;

  D.6249 = _test_and_set (&GC_allocate_lock, 1);
  if (D.6249 != 0) goto <D.6250>; else goto <D.6251>;
  <D.6250>:
  GC_lock ();
  <D.6251>:
  thread_gc_id = GC_lookup_thread (thread);
  GC_clear (&GC_allocate_lock);
  result = pthread_join (thread, retval);
  if (result == 0) goto <D.6252>; else goto <D.6253>;
  <D.6252>:
  D.6254 = _test_and_set (&GC_allocate_lock, 1);
  if (D.6254 != 0) goto <D.6255>; else goto <D.6256>;
  <D.6255>:
  GC_lock ();
  <D.6256>:
  GC_delete_gc_thread (thread, thread_gc_id);
  GC_clear (&GC_allocate_lock);
  <D.6253>:
  D.6257 = result;
  return D.6257;
}


GC_pthread_detach (pthread_t thread)
{
  int D.6259;
  int D.6264;
  short int D.6267;
  short int D.6268;
  unsigned short D.6269;
  int D.6270;
  int D.6271;
  int D.6274;
  int result;
  struct GC_Thread_Rep * thread_gc_id;

  D.6259 = _test_and_set (&GC_allocate_lock, 1);
  if (D.6259 != 0) goto <D.6260>; else goto <D.6261>;
  <D.6260>:
  GC_lock ();
  <D.6261>:
  thread_gc_id = GC_lookup_thread (thread);
  GC_clear (&GC_allocate_lock);
  result = pthread_detach (thread);
  if (result == 0) goto <D.6262>; else goto <D.6263>;
  <D.6262>:
  D.6264 = _test_and_set (&GC_allocate_lock, 1);
  if (D.6264 != 0) goto <D.6265>; else goto <D.6266>;
  <D.6265>:
  GC_lock ();
  <D.6266>:
  D.6267 = thread_gc_id->flags;
  D.6268 = D.6267 | 2;
  thread_gc_id->flags = D.6268;
  D.6267 = thread_gc_id->flags;
  D.6269 = (unsigned short) D.6267;
  D.6270 = (int) D.6269;
  D.6271 = D.6270 & 1;
  if (D.6271 != 0) goto <D.6272>; else goto <D.6273>;
  <D.6272>:
  GC_delete_gc_thread (thread, thread_gc_id);
  <D.6273>:
  GC_clear (&GC_allocate_lock);
  <D.6263>:
  D.6274 = result;
  return D.6274;
}


GC_start_routine_head (void * arg, void * base_addr, void * (*ThreadStartFn) (void *) * start, void * * start_arg)
{
  int D.6276;
  long unsigned int D.6279;
  short int D.6280;
  long unsigned int GC_page_size.24;
  long unsigned int base_addr.25;
  long unsigned int D.6283;
  long unsigned int D.6284;
  long unsigned int D.6285;
  long unsigned int D.6286;
  char * D.6287;
  char * D.6288;
  char * D.6289;
  void * (*<T338>) (void *) D.6292;
  void * D.6295;
  long unsigned int D.6296;
  union sem_t * D.6299;
  void * D.6300;
  struct start_info * si;
  void * result;
  struct GC_Thread_Rep * me;
  pthread_t my_pthread;

  si = arg;
  my_pthread = pthread_self ();
  D.6276 = _test_and_set (&GC_allocate_lock, 1);
  if (D.6276 != 0) goto <D.6277>; else goto <D.6278>;
  <D.6277>:
  GC_lock ();
  <D.6278>:
  GC_in_thread_creation = 1;
  me = GC_new_thread (my_pthread);
  GC_in_thread_creation = 0;
  me->stop_info.stack_ptr = 0B;
  D.6279 = si->flags;
  D.6280 = (short int) D.6279;
  me->flags = D.6280;
  GC_page_size.24 = GC_page_size;
  base_addr.25 = (long unsigned int) base_addr;
  D.6283 = GC_page_size.24 + base_addr.25;
  D.6284 = D.6283 + 4294967295;
  GC_page_size.24 = GC_page_size;
  D.6285 = -GC_page_size.24;
  D.6286 = D.6284 & D.6285;
  D.6287 = (char *) D.6286;
  me->stack_end = D.6287;
  D.6288 = me->stack_end;
  D.6289 = D.6288 + 4294967280;
  me->stop_info.stack_ptr = D.6289;
  GC_clear (&GC_allocate_lock);
  if (start != 0B) goto <D.6290>; else goto <D.6291>;
  <D.6290>:
  D.6292 = si->start_routine;
  *start = D.6292;
  <D.6291>:
  if (start_arg != 0B) goto <D.6293>; else goto <D.6294>;
  <D.6293>:
  D.6295 = si->arg;
  *start_arg = D.6295;
  <D.6294>:
  D.6279 = si->flags;
  D.6296 = D.6279 & 8;
  if (D.6296 == 0) goto <D.6297>; else goto <D.6298>;
  <D.6297>:
  D.6299 = &si->registered;
  sem_post (D.6299);
  <D.6298>:
  D.6300 = me;
  return D.6300;
}


GC_thread_register_foreign (void * base_addr)
{
  int parallel_initialized.26;
  int D.6305;
  int GC_thr_initialized.27;
  int D.6311;
  _Bool D.6312;
  struct start_info si;
  struct GC_Thread_Rep * me;

  try
    {
      si = {};
      si.flags = 8;
      parallel_initialized.26 = parallel_initialized;
      if (parallel_initialized.26 == 0) goto <D.6303>; else goto <D.6304>;
      <D.6303>:
      GC_init_parallel ();
      <D.6304>:
      D.6305 = _test_and_set (&GC_allocate_lock, 1);
      if (D.6305 != 0) goto <D.6306>; else goto <D.6307>;
      <D.6306>:
      GC_lock ();
      <D.6307>:
      GC_thr_initialized.27 = GC_thr_initialized;
      if (GC_thr_initialized.27 == 0) goto <D.6309>; else goto <D.6310>;
      <D.6309>:
      GC_thr_init ();
      <D.6310>:
      GC_clear (&GC_allocate_lock);
      me = GC_start_routine_head (&si, base_addr, 0B, 0B);
      D.6312 = me != 0B;
      D.6311 = (int) D.6312;
      return D.6311;
    }
  finally
    {
      si = {CLOBBER};
    }
}


GC_start_routine (void * arg)
{
  long int D.6315;
  void * (*<T338>) (void *) start.28;
  void * start_arg.29;
  void * D.6322;
  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 (*<Tc3>) (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.6315 = __builtin_expect (__not_first_call, 0);
            if (D.6315 != 0) goto <D.6316>; else goto <D.6317>;
            <D.6316>:
            __cancel_routine (__cancel_arg);
            __pthread_unwind_next (&__cancel_buf);
            <D.6317>:
            __pthread_register_cancel (&__cancel_buf);
            start.28 = start;
            start_arg.29 = start_arg;
            result = start.28 (start_arg.29);
            me->status = result;
            __pthread_unregister_cancel (&__cancel_buf);
            if (1 != 0) goto <D.6320>; else goto <D.6321>;
            <D.6320>:
            __cancel_routine (__cancel_arg);
            <D.6321>:
          }
        finally
          {
            __cancel_buf = {CLOBBER};
          }
      }
      D.6322 = result;
      return D.6322;
    }
  finally
    {
      dummy = {CLOBBER};
      start = {CLOBBER};
      start_arg = {CLOBBER};
    }
}


GC_pthread_create (pthread_t * new_thread, const union pthread_attr_t * attr, void * (*<T338>) (void *) start_routine, void * arg)
{
  int D.6327;
  int parallel_initialized.30;
  int D.6335;
  union sem_t * D.6336;
  int D.6337;
  int GC_thr_initialized.31;
  int detachstate.32;
  int * D.6351;
  int D.6352;
  int D.6355;
  int D.6356;
  int result;
  int detachstate;
  word my_flags;
  struct start_info * si;

  try
    {
      my_flags = 0;
      D.6327 = _test_and_set (&GC_allocate_lock, 1);
      if (D.6327 != 0) goto <D.6328>; else goto <D.6329>;
      <D.6328>:
      GC_lock ();
      <D.6329>:
      si = GC_generic_malloc_inner (28, 1);
      GC_clear (&GC_allocate_lock);
      parallel_initialized.30 = parallel_initialized;
      if (parallel_initialized.30 == 0) goto <D.6331>; else goto <D.6332>;
      <D.6331>:
      GC_init_parallel ();
      <D.6332>:
      if (si == 0B) goto <D.6333>; else goto <D.6334>;
      <D.6333>:
      D.6335 = 12;
      return D.6335;
      <D.6334>:
      D.6336 = &si->registered;
      sem_init (D.6336, 0, 0);
      si->start_routine = start_routine;
      si->arg = arg;
      D.6337 = _test_and_set (&GC_allocate_lock, 1);
      if (D.6337 != 0) goto <D.6338>; else goto <D.6339>;
      <D.6338>:
      GC_lock ();
      <D.6339>:
      GC_thr_initialized.31 = GC_thr_initialized;
      if (GC_thr_initialized.31 == 0) goto <D.6341>; else goto <D.6342>;
      <D.6341>:
      GC_thr_init ();
      <D.6342>:
      if (attr == 0B) goto <D.6343>; else goto <D.6344>;
      <D.6343>:
      detachstate = 0;
      goto <D.6345>;
      <D.6344>:
      pthread_attr_getdetachstate (attr, &detachstate);
      <D.6345>:
      detachstate.32 = detachstate;
      if (detachstate.32 == 1) goto <D.6347>; else goto <D.6348>;
      <D.6347>:
      my_flags = my_flags | 2;
      <D.6348>:
      si->flags = my_flags;
      GC_clear (&GC_allocate_lock);
      result = pthread_create (new_thread, attr, GC_start_routine, si);
      if (result == 0) goto <D.6349>; else goto <D.6350>;
      <D.6349>:
      goto <D.6031>;
      <D.6030>:
      D.6351 = __errno_location ();
      D.6352 = *D.6351;
      if (D.6352 != 4) goto <D.6353>; else goto <D.6354>;
      <D.6353>:
      GC_abort ("sem_wait failed");
      <D.6354>:
      <D.6031>:
      D.6336 = &si->registered;
      D.6355 = sem_wait (D.6336);
      if (D.6355 != 0) goto <D.6030>; else goto <D.6032>;
      <D.6032>:
      <D.6350>:
      D.6336 = &si->registered;
      sem_destroy (D.6336);
      D.6356 = _test_and_set (&GC_allocate_lock, 1);
      if (D.6356 != 0) goto <D.6357>; else goto <D.6358>;
      <D.6357>:
      GC_lock ();
      <D.6358>:
      GC_free_inner (si);
      GC_clear (&GC_allocate_lock);
      D.6335 = result;
      return D.6335;
    }
  finally
    {
      detachstate = {CLOBBER};
    }
}


GC_pause ()
{
  int i;

  i = 0;
  goto <D.6037>;
  <D.6036>:
  __asm__ __volatile__(" " :  :  : "memory");
  i = i + 1;
  <D.6037>:
  if (i <= 9) goto <D.6036>; else goto <D.6038>;
  <D.6038>:
}


GC_lock ()
{
  int D.6361;
  int GC_collecting.33;
  long int GC_nprocs.34;
  unsigned int i.35;
  unsigned int D.6371;
  unsigned int GC_allocate_lock.36;
  int D.6374;
  int D.6377;
  int D.6385;
  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.6361 = _test_and_set (&GC_allocate_lock, 1);
  if (D.6361 == 0) goto <D.6362>; else goto <D.6363>;
  <D.6362>:
  return;
  <D.6363>:
  my_spin_max = spin_max;
  my_last_spins = last_spins;
  i = 0;
  goto <D.6051>;
  <D.6050>:
  GC_collecting.33 = GC_collecting;
  if (GC_collecting.33 != 0) goto yield; else goto <D.6365>;
  <D.6365>:
  GC_nprocs.34 = GC_nprocs;
  if (GC_nprocs.34 == 1) goto yield; else goto <D.6367>;
  <D.6367>:
  i.35 = (unsigned int) i;
  D.6371 = my_last_spins / 2;
  if (i.35 < D.6371) goto <D.6368>; else goto <D.6372>;
  <D.6372>:
  GC_allocate_lock.36 = GC_allocate_lock;
  if (GC_allocate_lock.36 != 0) goto <D.6368>; else goto <D.6369>;
  <D.6368>:
  GC_pause ();
  // predicted unlikely by continue predictor.
  goto <D.6049>;
  <D.6369>:
  D.6374 = _test_and_set (&GC_allocate_lock, 1);
  if (D.6374 == 0) goto <D.6375>; else goto <D.6376>;
  <D.6375>:
  i.35 = (unsigned int) i;
  last_spins = i.35;
  spin_max = 128;
  return;
  <D.6376>:
  <D.6049>:
  i = i + 1;
  <D.6051>:
  i.35 = (unsigned int) i;
  if (i.35 < my_spin_max) goto <D.6050>; else goto <D.6052>;
  <D.6052>:
  spin_max = 30;
  yield:
  i = 0;
  <D.6054>:
  D.6377 = _test_and_set (&GC_allocate_lock, 1);
  if (D.6377 == 0) goto <D.6378>; else goto <D.6379>;
  <D.6378>:
  return;
  <D.6379>:
  if (i <= 11) goto <D.6380>; else goto <D.6381>;
  <D.6380>:
  sched_yield ();
  goto <D.6382>;
  <D.6381>:
  {
    struct timespec ts;

    try
      {
        if (i > 24) goto <D.6383>; else goto <D.6384>;
        <D.6383>:
        i = 24;
        <D.6384>:
        ts.tv_sec = 0;
        D.6385 = 1 << i;
        ts.tv_nsec = D.6385;
        nanosleep (&ts, 0B);
      }
    finally
      {
        ts = {CLOBBER};
      }
  }
  <D.6382>:
  i = i + 1;
  goto <D.6054>;
}


