GC_thread_deregister_foreign (void * data)
{
  short int D.6626;
  int D.6627;
  int D.6628;
  int D.6631;
  long unsigned int D.6634;
  struct GC_Thread_Rep * me;

  me = data;
  D.6626 = me->flags;
  D.6627 = (int) D.6626;
  D.6628 = D.6627 & 8;
  if (D.6628 != 0) goto <D.6629>; else goto <D.6630>;
  <D.6629>:
  D.6631 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.6631 != 0) goto <D.6632>; else goto <D.6633>;
  <D.6632>:
  GC_lock ();
  <D.6633>:
  GC_destroy_thread_local (me);
  D.6634 = me->id;
  GC_delete_gc_thread (D.6634, me);
  pthread_mutex_unlock (&GC_allocate_ml);
  <D.6630>:
}


GC_init_thread_local (struct GC_Thread_Rep * p)
{
  int keys_initialized.0;
  int D.6638;
  unsigned int GC_thread_key.1;
  int D.6642;
  int i;

  keys_initialized.0 = keys_initialized;
  if (keys_initialized.0 == 0) goto <D.6636>; else goto <D.6637>;
  <D.6636>:
  D.6638 = pthread_key_create (&GC_thread_key, GC_thread_deregister_foreign);
  if (D.6638 != 0) goto <D.6639>; else goto <D.6640>;
  <D.6639>:
  GC_abort ("Failed to create key for local allocator");
  <D.6640>:
  keys_initialized = 1;
  <D.6637>:
  GC_thread_key.1 = GC_thread_key;
  D.6642 = GC_setspecific (GC_thread_key.1, p);
  if (D.6642 != 0) goto <D.6643>; else goto <D.6644>;
  <D.6643>:
  GC_abort ("Failed to set thread specific allocation pointers");
  <D.6644>:
  i = 1;
  goto <D.6318>;
  <D.6317>:
  p->ptrfree_freelists[i] = 1B;
  p->normal_freelists[i] = 1B;
  p->gcj_freelists[i] = 1B;
  i = i + 1;
  <D.6318>:
  if (i <= 64) goto <D.6317>; else goto <D.6319>;
  <D.6319>:
  p->ptrfree_freelists[0] = &size_zero_object;
  p->normal_freelists[0] = &size_zero_object;
  p->gcj_freelists[0] = -1B;
}


GC_setspecific (GC_key_t key, void * value)
{
  int D.6645;

  GC_thread_tls = value;
  D.6645 = pthread_setspecific (key, value);
  return D.6645;
}


GC_destroy_thread_local (struct GC_Thread_Rep * p)
{
  char *[65] * D.6647;
  char *[65] * D.6648;
  char * * GC_gcjobjfreelist.2;
  char *[65] * D.6650;

  D.6647 = &p->ptrfree_freelists;
  return_freelists (D.6647, &GC_arrays._aobjfreelist);
  D.6648 = &p->normal_freelists;
  return_freelists (D.6648, &GC_arrays._objfreelist);
  GC_gcjobjfreelist.2 = GC_gcjobjfreelist;
  D.6650 = &p->gcj_freelists;
  return_freelists (D.6650, GC_gcjobjfreelist.2);
}


return_freelists (char * * fl, char * * gfl)
{
  long unsigned int D.6651;
  long unsigned int D.6652;
  long unsigned int q.3;
  long unsigned int D.6656;
  char * * D.6657;
  char * D.6658;
  char * * D.6662;
  char * D.6663;
  int i;
  char * q;
  char * * qptr;
  size_t nwords;

  i = 1;
  goto <D.6301>;
  <D.6300>:
  nwords = (size_t) i;
  D.6651 = (long unsigned int) i;
  D.6652 = D.6651 * 8;
  qptr = fl + D.6652;
  q = *qptr;
  q.3 = (long unsigned int) q;
  if (q.3 > 4095) goto <D.6654>; else goto <D.6655>;
  <D.6654>:
  D.6656 = nwords * 8;
  D.6657 = gfl + D.6656;
  D.6658 = *D.6657;
  if (D.6658 == 0B) goto <D.6659>; else goto <D.6660>;
  <D.6659>:
  D.6656 = nwords * 8;
  D.6657 = gfl + D.6656;
  *D.6657 = q;
  goto <D.6661>;
  <D.6660>:
  goto <D.6298>;
  <D.6297>:
  qptr = q;
  q = *qptr;
  <D.6298>:
  q.3 = (long unsigned int) q;
  if (q.3 > 4095) goto <D.6297>; else goto <D.6299>;
  <D.6299>:
  D.6656 = nwords * 8;
  D.6657 = gfl + D.6656;
  D.6658 = *D.6657;
  *qptr = D.6658;
  D.6656 = nwords * 8;
  D.6657 = gfl + D.6656;
  D.6651 = (long unsigned int) i;
  D.6652 = D.6651 * 8;
  D.6662 = fl + D.6652;
  D.6663 = *D.6662;
  *D.6657 = D.6663;
  <D.6661>:
  <D.6655>:
  D.6651 = (long unsigned int) i;
  D.6652 = D.6651 * 8;
  D.6662 = fl + D.6652;
  *D.6662 = 4096B;
  i = i + 1;
  <D.6301>:
  if (i <= 64) goto <D.6300>; else goto <D.6302>;
  <D.6302>:
}


GC_local_malloc (size_t bytes)
{
  int GC_all_interior_pointers.4;
  long unsigned int D.6665;
  long unsigned int D.6666;
  _Bool D.6667;
  long int D.6668;
  long int D.6669;
  void * D.6672;
  long unsigned int D.6673;
  long unsigned int D.6674;
  sizetype D.6675;
  long unsigned int my_entry.5;
  _Bool D.6677;
  long int D.6678;
  long int D.6679;
  long unsigned int D.6682;
  sizetype D.6685;
  char * D.6686;
  int D.6687;
  int D.6688;
  char * D.6689;
  void * (*<T397>) (size_t) GC_oom_fn.6;

  GC_all_interior_pointers.4 = GC_all_interior_pointers;
  D.6665 = (long unsigned int) GC_all_interior_pointers.4;
  D.6666 = D.6665 + bytes;
  D.6667 = D.6666 > 512;
  D.6668 = (long int) D.6667;
  D.6669 = __builtin_expect (D.6668, 0);
  if (D.6669 != 0) goto <D.6670>; else goto <D.6671>;
  <D.6670>:
  D.6672 = GC_malloc (bytes);
  return D.6672;
  <D.6671>:
  {
    int index;
    char * * my_fl;
    char * my_entry;
    void * tsd;

    GC_all_interior_pointers.4 = GC_all_interior_pointers;
    D.6665 = (long unsigned int) GC_all_interior_pointers.4;
    D.6666 = D.6665 + bytes;
    D.6673 = D.6666 + 7;
    D.6674 = D.6673 / 8;
    index = (int) D.6674;
    tsd = GC_thread_tls;
    D.6675 = (sizetype) index;
    my_fl = &MEM[(struct GC_Thread_Rep *)tsd].normal_freelists[D.6675];
    my_entry = *my_fl;
    my_entry.5 = (long unsigned int) my_entry;
    D.6677 = my_entry.5 > 4095;
    D.6678 = (long int) D.6677;
    D.6679 = __builtin_expect (D.6678, 1);
    if (D.6679 != 0) goto <D.6680>; else goto <D.6681>;
    <D.6680>:
    {
      char * next;
      void * result;

      next = MEM[(char * *)my_entry];
      result = my_entry;
      *my_fl = next;
      MEM[(char * *)my_entry] = 0B;
      D.6672 = result;
      return D.6672;
    }
    <D.6681>:
    my_entry.5 = (long unsigned int) my_entry;
    D.6682 = my_entry.5 + 18446744073709551615;
    if (D.6682 <= 511) goto <D.6683>; else goto <D.6684>;
    <D.6683>:
    D.6675 = (sizetype) index;
    D.6685 = D.6675 + 1;
    D.6686 = my_entry + D.6685;
    *my_fl = D.6686;
    D.6672 = GC_malloc (bytes);
    return D.6672;
    <D.6684>:
    D.6687 = index * 8;
    GC_all_interior_pointers.4 = GC_all_interior_pointers;
    D.6688 = D.6687 - GC_all_interior_pointers.4;
    GC_generic_malloc_many (D.6688, 1, my_fl);
    D.6689 = *my_fl;
    if (D.6689 == 0B) goto <D.6690>; else goto <D.6691>;
    <D.6690>:
    GC_oom_fn.6 = GC_oom_fn;
    D.6672 = GC_oom_fn.6 (bytes);
    return D.6672;
    <D.6691>:
    D.6672 = GC_local_malloc (bytes);
    return D.6672;
  }
}


GC_local_malloc_atomic (size_t bytes)
{
  int GC_all_interior_pointers.7;
  long unsigned int D.6695;
  long unsigned int D.6696;
  _Bool D.6697;
  long int D.6698;
  long int D.6699;
  void * D.6702;
  long unsigned int D.6703;
  long unsigned int D.6704;
  void * GC_thread_tls.8;
  sizetype D.6706;
  long unsigned int my_entry.9;
  _Bool D.6708;
  long int D.6709;
  long int D.6710;
  char * D.6713;
  long unsigned int D.6714;
  sizetype D.6717;
  char * D.6718;
  int D.6719;
  int D.6720;
  char * D.6721;
  void * (*<T397>) (size_t) GC_oom_fn.10;

  GC_all_interior_pointers.7 = GC_all_interior_pointers;
  D.6695 = (long unsigned int) GC_all_interior_pointers.7;
  D.6696 = D.6695 + bytes;
  D.6697 = D.6696 > 512;
  D.6698 = (long int) D.6697;
  D.6699 = __builtin_expect (D.6698, 0);
  if (D.6699 != 0) goto <D.6700>; else goto <D.6701>;
  <D.6700>:
  D.6702 = GC_malloc_atomic (bytes);
  return D.6702;
  <D.6701>:
  {
    int index;
    char * * my_fl;
    char * my_entry;

    GC_all_interior_pointers.7 = GC_all_interior_pointers;
    D.6695 = (long unsigned int) GC_all_interior_pointers.7;
    D.6696 = D.6695 + bytes;
    D.6703 = D.6696 + 7;
    D.6704 = D.6703 / 8;
    index = (int) D.6704;
    GC_thread_tls.8 = GC_thread_tls;
    D.6706 = (sizetype) index;
    my_fl = &MEM[(struct GC_Thread_Rep *)GC_thread_tls.8].ptrfree_freelists[D.6706];
    my_entry = *my_fl;
    my_entry.9 = (long unsigned int) my_entry;
    D.6708 = my_entry.9 > 4095;
    D.6709 = (long int) D.6708;
    D.6710 = __builtin_expect (D.6709, 1);
    if (D.6710 != 0) goto <D.6711>; else goto <D.6712>;
    <D.6711>:
    {
      void * result;

      result = my_entry;
      D.6713 = MEM[(char * *)my_entry];
      *my_fl = D.6713;
      D.6702 = result;
      return D.6702;
    }
    <D.6712>:
    my_entry.9 = (long unsigned int) my_entry;
    D.6714 = my_entry.9 + 18446744073709551615;
    if (D.6714 <= 511) goto <D.6715>; else goto <D.6716>;
    <D.6715>:
    D.6706 = (sizetype) index;
    D.6717 = D.6706 + 1;
    D.6718 = my_entry + D.6717;
    *my_fl = D.6718;
    D.6702 = GC_malloc_atomic (bytes);
    return D.6702;
    <D.6716>:
    D.6719 = index * 8;
    GC_all_interior_pointers.7 = GC_all_interior_pointers;
    D.6720 = D.6719 - GC_all_interior_pointers.7;
    GC_generic_malloc_many (D.6720, 0, my_fl);
    D.6721 = *my_fl;
    if (D.6721 == 0B) goto <D.6722>; else goto <D.6723>;
    <D.6722>:
    GC_oom_fn.10 = GC_oom_fn;
    D.6702 = GC_oom_fn.10 (bytes);
    return D.6702;
    <D.6723>:
    D.6702 = GC_local_malloc_atomic (bytes);
    return D.6702;
  }
}


GC_local_gcj_malloc (size_t bytes, void * ptr_to_struct_containing_descr)
{
  int GC_all_interior_pointers.11;
  long unsigned int D.6727;
  long unsigned int D.6728;
  _Bool D.6729;
  long int D.6730;
  long int D.6731;
  void * D.6734;
  long unsigned int D.6735;
  long unsigned int D.6736;
  void * GC_thread_tls.12;
  sizetype D.6738;
  long unsigned int my_entry.13;
  _Bool D.6740;
  long int D.6741;
  long int D.6742;
  char * D.6745;
  long unsigned int D.6746;
  int GC_incremental.14;
  sizetype D.6752;
  char * D.6753;
  int GC_gcj_kind.15;
  int D.6755;
  int D.6756;
  char * D.6757;
  void * (*<T397>) (size_t) GC_oom_fn.16;

  GC_all_interior_pointers.11 = GC_all_interior_pointers;
  D.6727 = (long unsigned int) GC_all_interior_pointers.11;
  D.6728 = D.6727 + bytes;
  D.6729 = D.6728 > 512;
  D.6730 = (long int) D.6729;
  D.6731 = __builtin_expect (D.6730, 0);
  if (D.6731 != 0) goto <D.6732>; else goto <D.6733>;
  <D.6732>:
  D.6734 = GC_gcj_malloc (bytes, ptr_to_struct_containing_descr);
  return D.6734;
  <D.6733>:
  {
    int index;
    char * * my_fl;
    char * my_entry;

    GC_all_interior_pointers.11 = GC_all_interior_pointers;
    D.6727 = (long unsigned int) GC_all_interior_pointers.11;
    D.6728 = D.6727 + bytes;
    D.6735 = D.6728 + 7;
    D.6736 = D.6735 / 8;
    index = (int) D.6736;
    GC_thread_tls.12 = GC_thread_tls;
    D.6738 = (sizetype) index;
    my_fl = &MEM[(struct GC_Thread_Rep *)GC_thread_tls.12].gcj_freelists[D.6738];
    my_entry = *my_fl;
    my_entry.13 = (long unsigned int) my_entry;
    D.6740 = my_entry.13 > 4095;
    D.6741 = (long int) D.6740;
    D.6742 = __builtin_expect (D.6741, 1);
    if (D.6742 != 0) goto <D.6743>; else goto <D.6744>;
    <D.6743>:
    {
      void * result;

      result = my_entry;
      D.6745 = MEM[(char * *)my_entry];
      MEM[(char * volatile *)my_fl] = D.6745;
      MEM[(void * volatile *)result] = ptr_to_struct_containing_descr;
      D.6734 = result;
      return D.6734;
    }
    <D.6744>:
    my_entry.13 = (long unsigned int) my_entry;
    D.6746 = my_entry.13 + 18446744073709551615;
    if (D.6746 <= 511) goto <D.6747>; else goto <D.6748>;
    <D.6747>:
    GC_incremental.14 = GC_incremental;
    if (GC_incremental.14 == 0) goto <D.6750>; else goto <D.6751>;
    <D.6750>:
    D.6738 = (sizetype) index;
    D.6752 = D.6738 + 1;
    D.6753 = my_entry + D.6752;
    *my_fl = D.6753;
    <D.6751>:
    D.6734 = GC_gcj_malloc (bytes, ptr_to_struct_containing_descr);
    return D.6734;
    <D.6748>:
    GC_gcj_kind.15 = GC_gcj_kind;
    D.6755 = index * 8;
    GC_all_interior_pointers.11 = GC_all_interior_pointers;
    D.6756 = D.6755 - GC_all_interior_pointers.11;
    GC_generic_malloc_many (D.6756, GC_gcj_kind.15, my_fl);
    D.6757 = *my_fl;
    if (D.6757 == 0B) goto <D.6758>; else goto <D.6759>;
    <D.6758>:
    GC_oom_fn.16 = GC_oom_fn;
    D.6734 = GC_oom_fn.16 (bytes);
    return D.6734;
    <D.6759>:
    D.6734 = GC_local_gcj_malloc (bytes, ptr_to_struct_containing_descr);
    return D.6734;
  }
}


GC_local_gcj_fast_malloc (size_t lw, void * ptr_to_struct_containing_descr)
{
  void * GC_thread_tls.17;
  long unsigned int my_entry.18;
  _Bool D.6764;
  long int D.6765;
  long int D.6766;
  char * D.6769;
  void * D.6770;
  long unsigned int D.6771;
  int GC_incremental.19;
  sizetype D.6777;
  char * D.6778;
  int GC_gcj_kind.20;
  long unsigned int D.6780;
  int GC_all_interior_pointers.21;
  long unsigned int D.6782;
  long unsigned int D.6783;
  char * D.6784;
  void * (*<T397>) (size_t) GC_oom_fn.22;
  char * * my_fl;
  char * my_entry;

  GC_thread_tls.17 = GC_thread_tls;
  my_fl = &MEM[(struct GC_Thread_Rep *)GC_thread_tls.17].gcj_freelists[lw];
  my_entry = *my_fl;
  my_entry.18 = (long unsigned int) my_entry;
  D.6764 = my_entry.18 > 4095;
  D.6765 = (long int) D.6764;
  D.6766 = __builtin_expect (D.6765, 1);
  if (D.6766 != 0) goto <D.6767>; else goto <D.6768>;
  <D.6767>:
  {
    void * result;

    result = my_entry;
    D.6769 = MEM[(char * *)my_entry];
    MEM[(char * volatile *)my_fl] = D.6769;
    MEM[(void * volatile *)result] = ptr_to_struct_containing_descr;
    D.6770 = result;
    return D.6770;
  }
  <D.6768>:
  my_entry.18 = (long unsigned int) my_entry;
  D.6771 = my_entry.18 + 18446744073709551615;
  if (D.6771 <= 511) goto <D.6772>; else goto <D.6773>;
  <D.6772>:
  GC_incremental.19 = GC_incremental;
  if (GC_incremental.19 == 0) goto <D.6775>; else goto <D.6776>;
  <D.6775>:
  D.6777 = lw + 1;
  D.6778 = my_entry + D.6777;
  *my_fl = D.6778;
  <D.6776>:
  D.6770 = GC_gcj_fast_malloc (lw, ptr_to_struct_containing_descr);
  return D.6770;
  <D.6773>:
  GC_gcj_kind.20 = GC_gcj_kind;
  D.6780 = lw * 8;
  GC_all_interior_pointers.21 = GC_all_interior_pointers;
  D.6782 = (long unsigned int) GC_all_interior_pointers.21;
  D.6783 = D.6780 - D.6782;
  GC_generic_malloc_many (D.6783, GC_gcj_kind.20, my_fl);
  D.6784 = *my_fl;
  if (D.6784 == 0B) goto <D.6785>; else goto <D.6786>;
  <D.6785>:
  GC_oom_fn.22 = GC_oom_fn;
  D.6780 = lw * 8;
  GC_all_interior_pointers.21 = GC_all_interior_pointers;
  D.6782 = (long unsigned int) GC_all_interior_pointers.21;
  D.6783 = D.6780 - D.6782;
  D.6770 = GC_oom_fn.22 (D.6783);
  return D.6770;
  <D.6786>:
  D.6770 = GC_local_gcj_fast_malloc (lw, ptr_to_struct_containing_descr);
  return D.6770;
}


GC_mark_thread (void * id)
{
  long unsigned int id.23;
  char * D.6790;
  long unsigned int GC_mark_no.24;
  long unsigned int D.6795;
  word my_mark_no;

  my_mark_no = 0;
  id.23 = (long unsigned int) id;
  D.6790 = GC_approx_sp ();
  marker_sp[id.23] = D.6790;
  <D.6387>:
  GC_mark_no.24 = GC_mark_no;
  if (my_mark_no < GC_mark_no.24) goto <D.6791>; else goto <D.6794>;
  <D.6794>:
  GC_mark_no.24 = GC_mark_no;
  D.6795 = GC_mark_no.24 + 2;
  if (D.6795 < my_mark_no) goto <D.6791>; else goto <D.6792>;
  <D.6791>:
  my_mark_no = GC_mark_no;
  <D.6792>:
  GC_help_marker (my_mark_no);
  my_mark_no = my_mark_no + 1;
  goto <D.6387>;
}


GC_push_thread_structures ()
{
  unsigned char * D.6796;
  char * D.6797;
  unsigned char * D.6798;

  GC_push_all (&GC_threads, &MEM[(void *)&GC_threads + 1024B]);
  D.6796 = get_gc_thread_key_addr ();
  D.6797 = D.6796 + 8;
  D.6798 = get_gc_thread_key_addr ();
  GC_push_all (D.6798, D.6797);
}


get_gc_thread_key_addr ()
{
  unsigned char * D.6799;

  D.6799 = &GC_thread_key;
  return D.6799;
}


GC_mark_thread_local_free_lists ()
{
  long unsigned int q.25;
  int i;
  int j;
  struct GC_Thread_Rep * p;
  char * q;

  i = 0;
  goto <D.6419>;
  <D.6418>:
  p = GC_threads[i];
  goto <D.6416>;
  <D.6415>:
  j = 1;
  goto <D.6413>;
  <D.6412>:
  q = p->ptrfree_freelists[j];
  q.25 = (long unsigned int) q;
  if (q.25 > 4096) goto <D.6802>; else goto <D.6803>;
  <D.6802>:
  GC_set_fl_marks (q);
  <D.6803>:
  q = p->normal_freelists[j];
  q.25 = (long unsigned int) q;
  if (q.25 > 4096) goto <D.6804>; else goto <D.6805>;
  <D.6804>:
  GC_set_fl_marks (q);
  <D.6805>:
  q = p->gcj_freelists[j];
  q.25 = (long unsigned int) q;
  if (q.25 > 4096) goto <D.6806>; else goto <D.6807>;
  <D.6806>:
  GC_set_fl_marks (q);
  <D.6807>:
  j = j + 1;
  <D.6413>:
  if (j <= 64) goto <D.6412>; else goto <D.6414>;
  <D.6414>:
  p = p->next;
  <D.6416>:
  if (p != 0B) goto <D.6415>; else goto <D.6417>;
  <D.6417>:
  i = i + 1;
  <D.6419>:
  if (i <= 127) goto <D.6418>; else goto <D.6420>;
  <D.6420>:
}


GC_new_thread (pthread_t id)
{
  int D.6808;
  int first_thread_used.26;
  struct GC_Thread_Rep * D.6815;
  struct GC_Thread_Rep * D.6816;
  int hv;
  struct GC_Thread_Rep * result;
  static GC_bool first_thread_used = 0;

  D.6808 = (int) id;
  hv = D.6808 & 127;
  first_thread_used.26 = first_thread_used;
  if (first_thread_used.26 == 0) goto <D.6810>; else goto <D.6811>;
  <D.6810>:
  result = &first_thread;
  first_thread_used = 1;
  goto <D.6812>;
  <D.6811>:
  result = GC_generic_malloc_inner (1656, 1);
  <D.6812>:
  if (result == 0B) goto <D.6813>; else goto <D.6814>;
  <D.6813>:
  D.6815 = 0B;
  return D.6815;
  <D.6814>:
  result->id = id;
  D.6816 = GC_threads[hv];
  result->next = D.6816;
  GC_threads[hv] = result;
  D.6815 = result;
  return D.6815;
}


GC_delete_thread (pthread_t id)
{
  int D.6818;
  long unsigned int D.6819;
  int D.6820;
  struct GC_Thread_Rep * D.6823;
  int hv;
  register struct GC_Thread_Rep * p;
  register struct GC_Thread_Rep * prev;

  D.6818 = (int) id;
  hv = D.6818 & 127;
  p = GC_threads[hv];
  prev = 0B;
  goto <D.6435>;
  <D.6434>:
  prev = p;
  p = p->next;
  <D.6435>:
  D.6819 = p->id;
  D.6820 = pthread_equal (D.6819, id);
  if (D.6820 == 0) goto <D.6434>; else goto <D.6436>;
  <D.6436>:
  if (prev == 0B) goto <D.6821>; else goto <D.6822>;
  <D.6821>:
  D.6823 = p->next;
  GC_threads[hv] = D.6823;
  goto <D.6824>;
  <D.6822>:
  D.6823 = p->next;
  prev->next = D.6823;
  <D.6824>:
  GC_free_inner (p);
}


pthread_equal (pthread_t __thread1, pthread_t __thread2)
{
  int D.6825;
  _Bool D.6826;

  D.6826 = __thread1 == __thread2;
  D.6825 = (int) D.6826;
  return D.6825;
}


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

  D.6828 = (int) id;
  hv = D.6828 & 127;
  p = GC_threads[hv];
  prev = 0B;
  goto <D.6445>;
  <D.6444>:
  prev = p;
  p = p->next;
  <D.6445>:
  if (p != gc_id) goto <D.6444>; else goto <D.6446>;
  <D.6446>:
  if (prev == 0B) goto <D.6829>; else goto <D.6830>;
  <D.6829>:
  D.6831 = p->next;
  GC_threads[hv] = D.6831;
  goto <D.6832>;
  <D.6830>:
  D.6831 = p->next;
  prev->next = D.6831;
  <D.6832>:
  GC_free_inner (p);
}


GC_lookup_thread (pthread_t id)
{
  int D.6833;
  long unsigned int D.6835;
  int D.6836;
  struct GC_Thread_Rep * D.6837;
  int hv;
  register struct GC_Thread_Rep * p;

  D.6833 = (int) id;
  hv = D.6833 & 127;
  p = GC_threads[hv];
  goto <D.6453>;
  <D.6452>:
  p = p->next;
  <D.6453>:
  if (p != 0B) goto <D.6834>; else goto <D.6454>;
  <D.6834>:
  D.6835 = p->id;
  D.6836 = pthread_equal (D.6835, id);
  if (D.6836 == 0) goto <D.6452>; else goto <D.6454>;
  <D.6454>:
  D.6837 = p;
  return D.6837;
}


GC_thread_is_registered ()
{
  int D.6839;
  long unsigned int D.6842;
  int D.6843;
  _Bool D.6844;
  void * ptr;

  D.6839 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.6839 != 0) goto <D.6840>; else goto <D.6841>;
  <D.6840>:
  GC_lock ();
  <D.6841>:
  D.6842 = pthread_self ();
  ptr = GC_lookup_thread (D.6842);
  pthread_mutex_unlock (&GC_allocate_ml);
  D.6844 = ptr != 0B;
  D.6843 = (int) D.6844;
  return D.6843;
}


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

  D.6846 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.6846 != 0) goto <D.6847>; else goto <D.6848>;
  <D.6847>:
  GC_lock ();
  <D.6848>:
  main_pthread_self.27 = pthread_self ();
  thread = GC_lookup_thread (main_pthread_self.27);
  if (thread != 0B) goto <D.6850>; else goto <D.6851>;
  <D.6850>:
  thread->stack = stack;
  thread->stack_size = stack_size;
  thread->altstack = altstack;
  thread->altstack_size = altstack_size;
  goto <D.6852>;
  <D.6851>:
  main_pthread_self.27 = pthread_self ();
  main_pthread_self = main_pthread_self.27;
  main_stack = stack;
  main_stack_size = stack_size;
  main_altstack = altstack;
  main_altstack_size = altstack_size;
  <D.6852>:
  pthread_mutex_unlock (&GC_allocate_ml);
}


GC_get_nprocs ()
{
  long int D.6856;
  void (*<T41a>) (char *, GC_word) GC_current_warn_proc.28;
  int D.6858;
  char D.6859;
  long unsigned int D.6862;
  char D.6863;
  long unsigned int D.6866;
  char D.6867;
  long unsigned int D.6870;
  char D.6871;
  sizetype D.6874;
  const char * D.6875;
  long unsigned int D.6876;
  int D.6879;
  long unsigned int D.6880;
  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.6853>; else goto <D.6855>;
      <D.6855>:
      D.6856 = read (f, &stat_buf, 4096);
      len = (size_t) D.6856;
      if (len <= 99) goto <D.6853>; else goto <D.6854>;
      <D.6853>:
      GC_current_warn_proc.28 = GC_current_warn_proc;
      GC_current_warn_proc.28 ("GC Warning: Couldn\'t read /proc/stat\n", 0);
      D.6858 = -1;
      return D.6858;
      <D.6854>:
      i = 0;
      goto <D.6475>;
      <D.6474>:
      D.6859 = stat_buf[i];
      if (D.6859 == 10) goto <D.6860>; else goto <D.6861>;
      <D.6860>:
      D.6862 = i + 1;
      D.6863 = stat_buf[D.6862];
      if (D.6863 == 99) goto <D.6864>; else goto <D.6865>;
      <D.6864>:
      D.6866 = i + 2;
      D.6867 = stat_buf[D.6866];
      if (D.6867 == 112) goto <D.6868>; else goto <D.6869>;
      <D.6868>:
      D.6870 = i + 3;
      D.6871 = stat_buf[D.6870];
      if (D.6871 == 117) goto <D.6872>; else goto <D.6873>;
      <D.6872>:
      {
        int cpu_no;

        D.6874 = i + 4;
        D.6875 = &stat_buf + D.6874;
        cpu_no = atoi (D.6875);
        D.6876 = (long unsigned int) cpu_no;
        if (D.6876 >= result) goto <D.6877>; else goto <D.6878>;
        <D.6877>:
        D.6879 = cpu_no + 1;
        result = (word) D.6879;
        <D.6878>:
      }
      <D.6873>:
      <D.6869>:
      <D.6865>:
      <D.6861>:
      i = i + 1;
      <D.6475>:
      D.6880 = len + 18446744073709551516;
      if (D.6880 > i) goto <D.6474>; else goto <D.6476>;
      <D.6476>:
      close (f);
      D.6858 = (int) result;
      return D.6858;
    }
  finally
    {
      stat_buf = {CLOBBER};
    }
}


open (const char * __path, int __oflag)
{
  int D.6883;
  int D.6886;
  int D.6891;
  int D.6893;
  int D.6894;
  int D.6897;
  int D.6898;

  D.6883 = __builtin_va_arg_pack_len ();
  if (D.6883 > 1) goto <D.6884>; else goto <D.6885>;
  <D.6884>:
  __open_too_many_args ();
  <D.6885>:
  D.6886 = __builtin_constant_p (__oflag);
  if (D.6886 != 0) goto <D.6887>; else goto <D.6888>;
  <D.6887>:
  D.6891 = __oflag & 64;
  if (D.6891 != 0) goto <D.6889>; else goto <D.6892>;
  <D.6892>:
  D.6893 = __oflag & 4259840;
  if (D.6893 == 4259840) goto <D.6889>; else goto <D.6890>;
  <D.6889>:
  D.6894 = __builtin_va_arg_pack_len ();
  if (D.6894 <= 0) goto <D.6895>; else goto <D.6896>;
  <D.6895>:
  __open_missing_mode ();
  D.6897 = __open_2 (__path, __oflag);
  return D.6897;
  <D.6896>:
  <D.6890>:
  D.6897 = __open_alias (__path, __oflag, __builtin_va_arg_pack ());
  return D.6897;
  <D.6888>:
  D.6898 = __builtin_va_arg_pack_len ();
  if (D.6898 <= 0) goto <D.6899>; else goto <D.6900>;
  <D.6899>:
  D.6897 = __open_2 (__path, __oflag);
  return D.6897;
  <D.6900>:
  D.6897 = __open_alias (__path, __oflag, __builtin_va_arg_pack ());
  return D.6897;
}


read (int __fd, void * __buf, size_t __nbytes)
{
  long unsigned int D.6902;
  int D.6905;
  ssize_t D.6908;
  long unsigned int D.6909;
  long unsigned int D.6910;
  long unsigned int D.6913;

  D.6902 = __builtin_object_size (__buf, 0);
  if (D.6902 != 18446744073709551615) goto <D.6903>; else goto <D.6904>;
  <D.6903>:
  D.6905 = __builtin_constant_p (__nbytes);
  if (D.6905 == 0) goto <D.6906>; else goto <D.6907>;
  <D.6906>:
  D.6909 = __builtin_object_size (__buf, 0);
  D.6908 = __read_chk (__fd, __buf, __nbytes, D.6909);
  return D.6908;
  <D.6907>:
  D.6910 = __builtin_object_size (__buf, 0);
  if (D.6910 < __nbytes) goto <D.6911>; else goto <D.6912>;
  <D.6911>:
  D.6913 = __builtin_object_size (__buf, 0);
  D.6908 = __read_chk_warn (__fd, __buf, __nbytes, D.6913);
  return D.6908;
  <D.6912>:
  <D.6904>:
  D.6908 = __read_alias (__fd, __buf, __nbytes);
  return D.6908;
}


atoi (const char * __nptr)
{
  int D.6915;
  long int D.6916;

  D.6916 = strtol (__nptr, 0B, 10);
  D.6915 = (int) D.6916;
  return D.6915;
}


GC_wait_for_gc_completion (GC_bool wait_for_all)
{
  int GC_incremental.29;
  int D.6921;
  long unsigned int GC_gc_no.30;
  int D.6925;
  int D.6929;
  long unsigned int D.6932;

  GC_incremental.29 = GC_incremental;
  if (GC_incremental.29 != 0) goto <D.6919>; else goto <D.6920>;
  <D.6919>:
  D.6921 = GC_collection_in_progress ();
  if (D.6921 != 0) goto <D.6922>; else goto <D.6923>;
  <D.6922>:
  {
    int old_gc_no;

    GC_gc_no.30 = GC_gc_no;
    old_gc_no = (int) GC_gc_no.30;
    goto <D.6483>;
    <D.6482>:
    GC_collecting = 1;
    GC_in_thread_creation = 1;
    GC_collect_a_little_inner (1);
    GC_in_thread_creation = 0;
    GC_collecting = 0;
    pthread_mutex_unlock (&GC_allocate_ml);
    sched_yield ();
    D.6925 = pthread_mutex_trylock (&GC_allocate_ml);
    if (D.6925 != 0) goto <D.6926>; else goto <D.6927>;
    <D.6926>:
    GC_lock ();
    <D.6927>:
    <D.6483>:
    GC_incremental.29 = GC_incremental;
    if (GC_incremental.29 != 0) goto <D.6928>; else goto <D.6484>;
    <D.6928>:
    D.6929 = GC_collection_in_progress ();
    if (D.6929 != 0) goto <D.6930>; else goto <D.6484>;
    <D.6930>:
    if (wait_for_all != 0) goto <D.6482>; else goto <D.6931>;
    <D.6931>:
    D.6932 = (long unsigned int) old_gc_no;
    GC_gc_no.30 = GC_gc_no;
    if (D.6932 == GC_gc_no.30) goto <D.6482>; else goto <D.6484>;
    <D.6484>:
  }
  <D.6923>:
  <D.6920>:
}


GC_thr_init ()
{
  int GC_thr_initialized.31;
  long unsigned int D.6936;
  long unsigned int main_pthread_self.32;
  void * main_stack.33;
  int main_stack_size.34;
  void * main_altstack.35;
  int main_altstack_size.36;
  int D.6946;
  long int GC_nprocs.37;
  long int GC_nprocs.38;
  int D.6951;
  long int GC_nprocs.39;
  void (*<T41a>) (char *, GC_word) GC_current_warn_proc.40;
  long unsigned int GC_nprocs.41;
  int D.6960;
  long int GC_markers.42;
  long int GC_markers.43;
  int GC_print_stats.44;
  int GC_parallel.45;
  int dummy;
  struct GC_Thread_Rep * t;

  try
    {
      GC_thr_initialized.31 = GC_thr_initialized;
      if (GC_thr_initialized.31 != 0) goto <D.6934>; else goto <D.6935>;
      <D.6934>:
      return;
      <D.6935>:
      GC_thr_initialized = 1;
      D.6936 = pthread_self ();
      t = GC_new_thread (D.6936);
      t->stop_info.stack_ptr = &dummy;
      t->flags = 6;
      D.6936 = pthread_self ();
      main_pthread_self.32 = main_pthread_self;
      if (D.6936 == main_pthread_self.32) goto <D.6938>; else goto <D.6939>;
      <D.6938>:
      main_stack.33 = main_stack;
      t->stack = main_stack.33;
      main_stack_size.34 = main_stack_size;
      t->stack_size = main_stack_size.34;
      main_altstack.35 = main_altstack;
      t->altstack = main_altstack.35;
      main_altstack_size.36 = main_altstack_size;
      t->altstack_size = main_altstack_size.36;
      <D.6939>:
      GC_stop_init ();
      {
        char * nprocs_string;

        nprocs_string = getenv ("GC_NPROCS");
        GC_nprocs = -1;
        if (nprocs_string != 0B) goto <D.6944>; else goto <D.6945>;
        <D.6944>:
        D.6946 = atoi (nprocs_string);
        GC_nprocs.37 = (long int) D.6946;
        GC_nprocs = GC_nprocs.37;
        <D.6945>:
      }
      GC_nprocs.38 = GC_nprocs;
      if (GC_nprocs.38 <= 0) goto <D.6949>; else goto <D.6950>;
      <D.6949>:
      D.6951 = GC_get_nprocs ();
      GC_nprocs.39 = (long int) D.6951;
      GC_nprocs = GC_nprocs.39;
      <D.6950>:
      GC_nprocs.38 = GC_nprocs;
      if (GC_nprocs.38 <= 0) goto <D.6953>; else goto <D.6954>;
      <D.6953>:
      GC_current_warn_proc.40 = GC_current_warn_proc;
      GC_nprocs.38 = GC_nprocs;
      GC_nprocs.41 = (long unsigned int) GC_nprocs.38;
      GC_current_warn_proc.40 ("GC Warning: GC_get_nprocs() returned %ld\n", GC_nprocs.41);
      GC_nprocs = 2;
      GC_markers = 1;
      goto <D.6957>;
      <D.6954>:
      {
        char * markers_string;

        markers_string = getenv ("GC_MARKERS");
        if (markers_string != 0B) goto <D.6958>; else goto <D.6959>;
        <D.6958>:
        D.6960 = atoi (markers_string);
        GC_markers.42 = (long int) D.6960;
        GC_markers = GC_markers.42;
        goto <D.6962>;
        <D.6959>:
        GC_nprocs.38 = GC_nprocs;
        GC_markers = GC_nprocs.38;
        GC_markers.43 = GC_markers;
        if (GC_markers.43 > 16) goto <D.6964>; else goto <D.6965>;
        <D.6964>:
        GC_markers = 16;
        <D.6965>:
        <D.6962>:
      }
      <D.6957>:
      GC_print_stats.44 = GC_print_stats;
      if (GC_print_stats.44 != 0) goto <D.6967>; else goto <D.6968>;
      <D.6967>:
      GC_markers.43 = GC_markers;
      GC_nprocs.38 = GC_nprocs;
      GC_printf ("Number of processors = %ld, number of marker threads = %ld\n", GC_nprocs.38, GC_markers.43, 0, 0, 0, 0);
      <D.6968>:
      GC_markers.43 = GC_markers;
      if (GC_markers.43 == 1) goto <D.6969>; else goto <D.6970>;
      <D.6969>:
      GC_parallel = 0;
      GC_print_stats.44 = GC_print_stats;
      if (GC_print_stats.44 != 0) goto <D.6971>; else goto <D.6972>;
      <D.6971>:
      GC_printf ("Single marker thread, turning off parallel marking\n", 0, 0, 0, 0, 0, 0);
      <D.6972>:
      goto <D.6973>;
      <D.6970>:
      GC_parallel = 1;
      GC_time_limit = 999999;
      <D.6973>:
      GC_parallel.45 = GC_parallel;
      if (GC_parallel.45 != 0) goto <D.6975>; else goto <D.6976>;
      <D.6975>:
      start_mark_threads ();
      <D.6976>:
    }
  finally
    {
      dummy = {CLOBBER};
    }
}


start_mark_threads ()
{
  long int GC_markers.46;
  void (*<T41a>) (char *, GC_word) GC_current_warn_proc.47;
  int D.6984;
  int D.6987;
  int GC_print_stats.48;
  long int D.6993;
  long unsigned int D.6994;
  void * D.6995;
  long unsigned int D.6996;
  pthread_t * D.6997;
  int D.6998;
  int * D.7001;
  int D.7002;
  long unsigned int D.7003;
  long int D.7004;
  unsigned int i;
  union pthread_attr_t attr;

  try
    {
      GC_markers.46 = GC_markers;
      if (GC_markers.46 > 16) goto <D.6981>; else goto <D.6982>;
      <D.6981>:
      GC_current_warn_proc.47 = GC_current_warn_proc;
      GC_current_warn_proc.47 ("GC Warning: Limiting number of mark threads\n", 0);
      GC_markers = 16;
      <D.6982>:
      D.6984 = pthread_attr_init (&attr);
      if (D.6984 != 0) goto <D.6985>; else goto <D.6986>;
      <D.6985>:
      GC_abort ("pthread_attr_init failed");
      <D.6986>:
      D.6987 = pthread_attr_setdetachstate (&attr, 1);
      if (D.6987 != 0) goto <D.6988>; else goto <D.6989>;
      <D.6988>:
      GC_abort ("pthread_attr_setdetachstate failed");
      <D.6989>:
      GC_print_stats.48 = GC_print_stats;
      if (GC_print_stats.48 != 0) goto <D.6991>; else goto <D.6992>;
      <D.6991>:
      GC_markers.46 = GC_markers;
      D.6993 = GC_markers.46 + -1;
      GC_printf ("Starting %ld marker threads\n", D.6993, 0, 0, 0, 0, 0);
      <D.6992>:
      i = 0;
      goto <D.6395>;
      <D.6394>:
      D.6994 = (long unsigned int) i;
      D.6995 = (void *) D.6994;
      D.6994 = (long unsigned int) i;
      D.6996 = D.6994 * 8;
      D.6997 = &GC_mark_threads + D.6996;
      D.6998 = pthread_create (D.6997, &attr, GC_mark_thread, D.6995);
      if (D.6998 != 0) goto <D.6999>; else goto <D.7000>;
      <D.6999>:
      GC_current_warn_proc.47 = GC_current_warn_proc;
      D.7001 = __errno_location ();
      D.7002 = *D.7001;
      D.7003 = (long unsigned int) D.7002;
      GC_current_warn_proc.47 ("GC Warning: Marker thread creation failed, errno = %ld.\n", D.7003);
      <D.7000>:
      i = i + 1;
      <D.6395>:
      D.7004 = (long int) i;
      GC_markers.46 = GC_markers;
      D.6993 = GC_markers.46 + -1;
      if (D.7004 < D.6993) goto <D.6394>; else goto <D.6396>;
      <D.6396>:
    }
  finally
    {
      attr = {CLOBBER};
    }
}


GC_init_parallel ()
{
  int parallel_initialized.49;
  int GC_is_initialized.50;
  int D.7011;
  long unsigned int D.7014;
  struct GC_Thread_Rep * D.7015;

  parallel_initialized.49 = parallel_initialized;
  if (parallel_initialized.49 != 0) goto <D.7006>; else goto <D.7007>;
  <D.7006>:
  return;
  <D.7007>:
  parallel_initialized = 1;
  GC_is_initialized.50 = GC_is_initialized;
  if (GC_is_initialized.50 == 0) goto <D.7009>; else goto <D.7010>;
  <D.7009>:
  GC_init ();
  <D.7010>:
  D.7011 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.7011 != 0) goto <D.7012>; else goto <D.7013>;
  <D.7012>:
  GC_lock ();
  <D.7013>:
  D.7014 = pthread_self ();
  D.7015 = GC_lookup_thread (D.7014);
  GC_init_thread_local (D.7015);
  pthread_mutex_unlock (&GC_allocate_ml);
}


GC_pthread_sigmask (int how, const struct sigset_t * set, struct sigset_t * oset)
{
  _Bool D.7019;
  _Bool D.7020;
  _Bool D.7021;
  int D.7024;
  struct sigset_t fudged_set;

  try
    {
      if (set != 0B) goto <D.7017>; else goto <D.7018>;
      <D.7017>:
      D.7019 = how == 0;
      D.7020 = how == 2;
      D.7021 = D.7019 | D.7020;
      if (D.7021 != 0) goto <D.7022>; else goto <D.7023>;
      <D.7022>:
      fudged_set = *set;
      sigdelset (&fudged_set, 30);
      set = &fudged_set;
      <D.7023>:
      <D.7018>:
      D.7024 = pthread_sigmask (how, set, oset);
      return D.7024;
    }
  finally
    {
      fudged_set = {CLOBBER};
    }
}


GC_start_blocking ()
{
  int D.7027;
  long unsigned int D.7030;
  char * D.7031;
  char * D.7032;
  char * D.7033;
  struct GC_Thread_Rep * me;

  D.7027 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.7027 != 0) goto <D.7028>; else goto <D.7029>;
  <D.7028>:
  GC_lock ();
  <D.7029>:
  D.7030 = pthread_self ();
  me = GC_lookup_thread (D.7030);
  D.7031 = GC_approx_sp ();
  me->stop_info.stack_ptr = D.7031;
  D.7032 = me->stop_info.stack_ptr;
  D.7033 = D.7032 + 18446744073709551488;
  me->stop_info.stack_ptr = D.7033;
  me->thread_blocked = 1;
  pthread_mutex_unlock (&GC_allocate_ml);
}


GC_end_blocking ()
{
  int D.7034;
  long unsigned int D.7037;
  struct GC_Thread_Rep * me;

  D.7034 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.7034 != 0) goto <D.7035>; else goto <D.7036>;
  <D.7035>:
  GC_lock ();
  <D.7036>:
  D.7037 = pthread_self ();
  me = GC_lookup_thread (D.7037);
  me->thread_blocked = 0;
  pthread_mutex_unlock (&GC_allocate_ml);
}


GC_sleep (unsigned int seconds)
{
  unsigned int D.7038;
  int D.7039;
  int result;

  GC_start_blocking ();
  D.7038 = sleep (seconds);
  result = (int) D.7038;
  GC_end_blocking ();
  D.7039 = result;
  return D.7039;
}


GC_thread_exit_proc (void * arg)
{
  int D.7041;
  long unsigned int D.7044;
  short int D.7045;
  int D.7046;
  int D.7047;
  unsigned int GC_thread_key.51;
  int D.7051;
  short int D.7055;
  struct GC_Thread_Rep * me;

  D.7041 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.7041 != 0) goto <D.7042>; else goto <D.7043>;
  <D.7042>:
  GC_lock ();
  <D.7043>:
  D.7044 = pthread_self ();
  me = GC_lookup_thread (D.7044);
  GC_destroy_thread_local (me);
  D.7045 = me->flags;
  D.7046 = (int) D.7045;
  D.7047 = D.7046 & 2;
  if (D.7047 != 0) goto <D.7048>; else goto <D.7049>;
  <D.7048>:
  GC_thread_key.51 = GC_thread_key;
  D.7051 = GC_setspecific (GC_thread_key.51, 0B);
  if (D.7051 != 0) goto <D.7052>; else goto <D.7053>;
  <D.7052>:
  GC_abort ("Failed to set thread specific allocation pointers");
  <D.7053>:
  D.7044 = pthread_self ();
  GC_delete_thread (D.7044);
  goto <D.7054>;
  <D.7049>:
  D.7045 = me->flags;
  D.7055 = D.7045 | 1;
  me->flags = D.7055;
  <D.7054>:
  GC_wait_for_gc_completion (0);
  pthread_mutex_unlock (&GC_allocate_ml);
}


GC_pthread_join (pthread_t thread, void * * retval)
{
  int D.7056;
  int D.7061;
  int D.7064;
  int result;
  struct GC_Thread_Rep * thread_gc_id;

  D.7056 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.7056 != 0) goto <D.7057>; else goto <D.7058>;
  <D.7057>:
  GC_lock ();
  <D.7058>:
  thread_gc_id = GC_lookup_thread (thread);
  pthread_mutex_unlock (&GC_allocate_ml);
  result = pthread_join (thread, retval);
  if (result == 0) goto <D.7059>; else goto <D.7060>;
  <D.7059>:
  D.7061 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.7061 != 0) goto <D.7062>; else goto <D.7063>;
  <D.7062>:
  GC_lock ();
  <D.7063>:
  GC_delete_gc_thread (thread, thread_gc_id);
  pthread_mutex_unlock (&GC_allocate_ml);
  <D.7060>:
  D.7064 = result;
  return D.7064;
}


GC_pthread_detach (pthread_t thread)
{
  int D.7066;
  int D.7071;
  short int D.7074;
  short int D.7075;
  int D.7076;
  int D.7077;
  int D.7080;
  int result;
  struct GC_Thread_Rep * thread_gc_id;

  D.7066 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.7066 != 0) goto <D.7067>; else goto <D.7068>;
  <D.7067>:
  GC_lock ();
  <D.7068>:
  thread_gc_id = GC_lookup_thread (thread);
  pthread_mutex_unlock (&GC_allocate_ml);
  result = pthread_detach (thread);
  if (result == 0) goto <D.7069>; else goto <D.7070>;
  <D.7069>:
  D.7071 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.7071 != 0) goto <D.7072>; else goto <D.7073>;
  <D.7072>:
  GC_lock ();
  <D.7073>:
  D.7074 = thread_gc_id->flags;
  D.7075 = D.7074 | 2;
  thread_gc_id->flags = D.7075;
  D.7074 = thread_gc_id->flags;
  D.7076 = (int) D.7074;
  D.7077 = D.7076 & 1;
  if (D.7077 != 0) goto <D.7078>; else goto <D.7079>;
  <D.7078>:
  GC_delete_gc_thread (thread, thread_gc_id);
  <D.7079>:
  pthread_mutex_unlock (&GC_allocate_ml);
  <D.7070>:
  D.7080 = result;
  return D.7080;
}


GC_start_routine_head (void * arg, void * base_addr, void * (*ThreadStartFn) (void *) * start, void * * start_arg)
{
  int D.7082;
  long unsigned int D.7085;
  short int D.7086;
  long unsigned int GC_page_size.52;
  long unsigned int base_addr.53;
  long unsigned int D.7089;
  long unsigned int D.7090;
  long unsigned int D.7091;
  long unsigned int D.7092;
  char * D.7093;
  char * D.7094;
  char * D.7095;
  void * (*<T424>) (void *) D.7098;
  void * D.7101;
  long unsigned int D.7102;
  union sem_t * D.7105;
  int D.7106;
  void * D.7109;
  struct start_info * si;
  void * result;
  struct GC_Thread_Rep * me;
  pthread_t my_pthread;

  si = arg;
  my_pthread = pthread_self ();
  D.7082 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.7082 != 0) goto <D.7083>; else goto <D.7084>;
  <D.7083>:
  GC_lock ();
  <D.7084>:
  GC_in_thread_creation = 1;
  me = GC_new_thread (my_pthread);
  GC_in_thread_creation = 0;
  me->stop_info.stack_ptr = 0B;
  D.7085 = si->flags;
  D.7086 = (short int) D.7085;
  me->flags = D.7086;
  GC_page_size.52 = GC_page_size;
  base_addr.53 = (long unsigned int) base_addr;
  D.7089 = GC_page_size.52 + base_addr.53;
  D.7090 = D.7089 + 18446744073709551615;
  GC_page_size.52 = GC_page_size;
  D.7091 = -GC_page_size.52;
  D.7092 = D.7090 & D.7091;
  D.7093 = (char *) D.7092;
  me->stack_end = D.7093;
  D.7094 = me->stack_end;
  D.7095 = D.7094 + 18446744073709551600;
  me->stop_info.stack_ptr = D.7095;
  pthread_mutex_unlock (&GC_allocate_ml);
  if (start != 0B) goto <D.7096>; else goto <D.7097>;
  <D.7096>:
  D.7098 = si->start_routine;
  *start = D.7098;
  <D.7097>:
  if (start_arg != 0B) goto <D.7099>; else goto <D.7100>;
  <D.7099>:
  D.7101 = si->arg;
  *start_arg = D.7101;
  <D.7100>:
  D.7085 = si->flags;
  D.7102 = D.7085 & 8;
  if (D.7102 == 0) goto <D.7103>; else goto <D.7104>;
  <D.7103>:
  D.7105 = &si->registered;
  sem_post (D.7105);
  <D.7104>:
  D.7106 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.7106 != 0) goto <D.7107>; else goto <D.7108>;
  <D.7107>:
  GC_lock ();
  <D.7108>:
  GC_init_thread_local (me);
  pthread_mutex_unlock (&GC_allocate_ml);
  D.7109 = me;
  return D.7109;
}


GC_thread_register_foreign (void * base_addr)
{
  int parallel_initialized.54;
  int D.7114;
  int GC_thr_initialized.55;
  int D.7120;
  _Bool D.7121;
  struct start_info si;
  struct GC_Thread_Rep * me;

  try
    {
      si = {};
      si.flags = 8;
      parallel_initialized.54 = parallel_initialized;
      if (parallel_initialized.54 == 0) goto <D.7112>; else goto <D.7113>;
      <D.7112>:
      GC_init_parallel ();
      <D.7113>:
      D.7114 = pthread_mutex_trylock (&GC_allocate_ml);
      if (D.7114 != 0) goto <D.7115>; else goto <D.7116>;
      <D.7115>:
      GC_lock ();
      <D.7116>:
      GC_thr_initialized.55 = GC_thr_initialized;
      if (GC_thr_initialized.55 == 0) goto <D.7118>; else goto <D.7119>;
      <D.7118>:
      GC_thr_init ();
      <D.7119>:
      pthread_mutex_unlock (&GC_allocate_ml);
      me = GC_start_routine_head (&si, base_addr, 0B, 0B);
      D.7121 = me != 0B;
      D.7120 = (int) D.7121;
      return D.7120;
    }
  finally
    {
      si = {CLOBBER};
    }
}


GC_start_routine (void * arg)
{
  long int D.7124;
  long int D.7125;
  void * (*<T424>) (void *) start.56;
  void * start_arg.57;
  void * D.7132;
  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 (*<Tc2>) (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.7124 = (long int) __not_first_call;
            D.7125 = __builtin_expect (D.7124, 0);
            if (D.7125 != 0) goto <D.7126>; else goto <D.7127>;
            <D.7126>:
            __cancel_routine (__cancel_arg);
            __pthread_unwind_next (&__cancel_buf);
            <D.7127>:
            __pthread_register_cancel (&__cancel_buf);
            start.56 = start;
            start_arg.57 = start_arg;
            result = start.56 (start_arg.57);
            me->status = result;
            __pthread_unregister_cancel (&__cancel_buf);
            if (1 != 0) goto <D.7130>; else goto <D.7131>;
            <D.7130>:
            __cancel_routine (__cancel_arg);
            <D.7131>:
          }
        finally
          {
            __cancel_buf = {CLOBBER};
          }
      }
      D.7132 = result;
      return D.7132;
    }
  finally
    {
      dummy = {CLOBBER};
      start = {CLOBBER};
      start_arg = {CLOBBER};
    }
}


GC_pthread_create (pthread_t * new_thread, const union pthread_attr_t * attr, void * (*<T424>) (void *) start_routine, void * arg)
{
  int D.7137;
  int parallel_initialized.58;
  int D.7145;
  union sem_t * D.7146;
  int D.7147;
  int GC_thr_initialized.59;
  int detachstate.60;
  int * D.7161;
  int D.7162;
  int D.7165;
  int D.7166;
  int result;
  int detachstate;
  word my_flags;
  struct start_info * si;

  try
    {
      my_flags = 0;
      D.7137 = pthread_mutex_trylock (&GC_allocate_ml);
      if (D.7137 != 0) goto <D.7138>; else goto <D.7139>;
      <D.7138>:
      GC_lock ();
      <D.7139>:
      si = GC_generic_malloc_inner (56, 1);
      pthread_mutex_unlock (&GC_allocate_ml);
      parallel_initialized.58 = parallel_initialized;
      if (parallel_initialized.58 == 0) goto <D.7141>; else goto <D.7142>;
      <D.7141>:
      GC_init_parallel ();
      <D.7142>:
      if (si == 0B) goto <D.7143>; else goto <D.7144>;
      <D.7143>:
      D.7145 = 12;
      return D.7145;
      <D.7144>:
      D.7146 = &si->registered;
      sem_init (D.7146, 0, 0);
      si->start_routine = start_routine;
      si->arg = arg;
      D.7147 = pthread_mutex_trylock (&GC_allocate_ml);
      if (D.7147 != 0) goto <D.7148>; else goto <D.7149>;
      <D.7148>:
      GC_lock ();
      <D.7149>:
      GC_thr_initialized.59 = GC_thr_initialized;
      if (GC_thr_initialized.59 == 0) goto <D.7151>; else goto <D.7152>;
      <D.7151>:
      GC_thr_init ();
      <D.7152>:
      if (attr == 0B) goto <D.7153>; else goto <D.7154>;
      <D.7153>:
      detachstate = 0;
      goto <D.7155>;
      <D.7154>:
      pthread_attr_getdetachstate (attr, &detachstate);
      <D.7155>:
      detachstate.60 = detachstate;
      if (detachstate.60 == 1) goto <D.7157>; else goto <D.7158>;
      <D.7157>:
      my_flags = my_flags | 2;
      <D.7158>:
      si->flags = my_flags;
      pthread_mutex_unlock (&GC_allocate_ml);
      result = pthread_create (new_thread, attr, GC_start_routine, si);
      if (result == 0) goto <D.7159>; else goto <D.7160>;
      <D.7159>:
      goto <D.6576>;
      <D.6575>:
      D.7161 = __errno_location ();
      D.7162 = *D.7161;
      if (D.7162 != 4) goto <D.7163>; else goto <D.7164>;
      <D.7163>:
      GC_abort ("sem_wait failed");
      <D.7164>:
      <D.6576>:
      D.7146 = &si->registered;
      D.7165 = sem_wait (D.7146);
      if (D.7165 != 0) goto <D.6575>; else goto <D.6577>;
      <D.6577>:
      <D.7160>:
      D.7146 = &si->registered;
      sem_destroy (D.7146);
      D.7166 = pthread_mutex_trylock (&GC_allocate_ml);
      if (D.7166 != 0) goto <D.7167>; else goto <D.7168>;
      <D.7167>:
      GC_lock ();
      <D.7168>:
      GC_free_inner (si);
      pthread_mutex_unlock (&GC_allocate_ml);
      D.7145 = result;
      return D.7145;
    }
  finally
    {
      detachstate = {CLOBBER};
    }
}


GC_pause ()
{
  int i;

  i = 0;
  goto <D.6582>;
  <D.6581>:
  __asm__ __volatile__(" " :  :  : "memory");
  i = i + 1;
  <D.6582>:
  if (i <= 9) goto <D.6581>; else goto <D.6583>;
  <D.6583>:
}


GC_generic_lock (union pthread_mutex_t * lock)
{
  int D.7171;
  long unsigned int GC_unlocked_count.61;
  long unsigned int GC_unlocked_count.62;
  int D.7176;
  long unsigned int GC_spin_count.63;
  long unsigned int GC_spin_count.64;
  long unsigned int GC_block_count.65;
  long unsigned int GC_block_count.66;
  unsigned int pause_length;
  unsigned int i;

  pause_length = 1;
  D.7171 = pthread_mutex_trylock (lock);
  if (D.7171 == 0) goto <D.7172>; else goto <D.7173>;
  <D.7172>:
  GC_unlocked_count.61 = GC_unlocked_count;
  GC_unlocked_count.62 = GC_unlocked_count.61 + 1;
  GC_unlocked_count = GC_unlocked_count.62;
  return;
  <D.7173>:
  goto <D.6601>;
  <D.6600>:
  i = 0;
  goto <D.6594>;
  <D.6593>:
  GC_pause ();
  i = i + 1;
  <D.6594>:
  if (i < pause_length) goto <D.6593>; else goto <D.6595>;
  <D.6595>:
  D.7176 = pthread_mutex_trylock (lock);
  switch (D.7176) <default: <D.6599>, case 0: <D.6596>, case 16: <D.6597>>
  <D.6596>:
  GC_spin_count.63 = GC_spin_count;
  GC_spin_count.64 = GC_spin_count.63 + 1;
  GC_spin_count = GC_spin_count.64;
  return;
  <D.6597>:
  goto <D.6598>;
  <D.6599>:
  GC_abort ("Unexpected error from pthread_mutex_trylock");
  <D.6598>:
  pause_length = pause_length << 1;
  <D.6601>:
  if (pause_length <= 128) goto <D.6600>; else goto <D.6602>;
  <D.6602>:
  GC_block_count.65 = GC_block_count;
  GC_block_count.66 = GC_block_count.65 + 1;
  GC_block_count = GC_block_count.66;
  pthread_mutex_lock (lock);
}


GC_lock ()
{
  long int GC_nprocs.67;
  int GC_collecting.68;

  GC_nprocs.67 = GC_nprocs;
  if (GC_nprocs.67 == 1) goto <D.7183>; else goto <D.7187>;
  <D.7187>:
  GC_collecting.68 = GC_collecting;
  if (GC_collecting.68 != 0) goto <D.7183>; else goto <D.7184>;
  <D.7183>:
  pthread_mutex_lock (&GC_allocate_ml);
  goto <D.7185>;
  <D.7184>:
  GC_generic_lock (&GC_allocate_ml);
  <D.7185>:
}


GC_acquire_mark_lock ()
{
  GC_generic_lock (&mark_mutex);
}


GC_release_mark_lock ()
{
  int D.7189;

  D.7189 = pthread_mutex_unlock (&mark_mutex);
  if (D.7189 != 0) goto <D.7190>; else goto <D.7191>;
  <D.7190>:
  GC_abort ("pthread_mutex_unlock failed");
  <D.7191>:
}


GC_wait_builder ()
{
  int D.7192;

  D.7192 = pthread_cond_wait (&builder_cv, &mark_mutex);
  if (D.7192 != 0) goto <D.7193>; else goto <D.7194>;
  <D.7193>:
  GC_abort ("pthread_cond_wait failed");
  <D.7194>:
}


GC_wait_for_reclaim ()
{
  long unsigned int GC_fl_builder_count.69;

  GC_acquire_mark_lock ();
  goto <D.6616>;
  <D.6615>:
  GC_wait_builder ();
  <D.6616>:
  GC_fl_builder_count.69 = GC_fl_builder_count;
  if (GC_fl_builder_count.69 != 0) goto <D.6615>; else goto <D.6617>;
  <D.6617>:
  GC_release_mark_lock ();
}


GC_notify_all_builder ()
{
  int D.7196;

  D.7196 = pthread_cond_broadcast (&builder_cv);
  if (D.7196 != 0) goto <D.7197>; else goto <D.7198>;
  <D.7197>:
  GC_abort ("pthread_cond_broadcast failed");
  <D.7198>:
}


GC_wait_marker ()
{
  int D.7199;

  D.7199 = pthread_cond_wait (&mark_cv, &mark_mutex);
  if (D.7199 != 0) goto <D.7200>; else goto <D.7201>;
  <D.7200>:
  GC_abort ("pthread_cond_wait failed");
  <D.7201>:
}


GC_notify_all_marker ()
{
  int D.7202;

  D.7202 = pthread_cond_broadcast (&mark_cv);
  if (D.7202 != 0) goto <D.7203>; else goto <D.7204>;
  <D.7203>:
  GC_abort ("pthread_cond_broadcast failed");
  <D.7204>:
}


