mono_wsq_init ()
{
  int wsq_tlskey_inited.0;

  wsq_tlskey_inited.0 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.0 != 0) goto <D.18625>; else goto <D.18626>;
  <D.18625>:
  return;
  <D.18626>:
  mono_native_tls_alloc (&wsq_tlskey, 0B);
  wsq_tlskey_inited = 1;
}


mono_native_tls_alloc (pthread_key_t * key, void * destructor)
{
  int D.18628;
  void (*<Tc1>) (void *) destructor.1;
  int D.18630;
  _Bool D.18631;

  destructor.1 = (void (*<Tc1>) (void *)) destructor;
  D.18630 = pthread_key_create (key, destructor.1);
  D.18631 = D.18630 == 0;
  D.18628 = (int) D.18631;
  return D.18628;
}


mono_wsq_cleanup ()
{
  int wsq_tlskey_inited.2;
  unsigned int wsq_tlskey.3;

  wsq_tlskey_inited.2 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.2 == 0) goto <D.18634>; else goto <D.18635>;
  <D.18634>:
  return;
  <D.18635>:
  wsq_tlskey.3 = wsq_tlskey;
  mono_native_tls_free (wsq_tlskey.3);
  wsq_tlskey_inited = 0;
}


mono_native_tls_free (pthread_key_t key)
{
  pthread_key_delete (key);
}


mono_wsq_create ()
{
  int wsq_tlskey_inited.4;
  struct MonoWSQ * D.18641;
  struct MonoArray * * D.18644;
  void * D.18645;
  struct MonoClass * D.18581;
  struct MonoClass * tmp_klass.5;
  struct MonoClass * D.18649;
  struct MonoClass * tmp_klass.6;
  _Bool D.18651;
  long int D.18652;
  long int D.18653;
  struct MonoVTable * D.18656;
  struct MonoArray * D.18657;
  union MonoSemType * D.18658;
  unsigned int wsq_tlskey.7;
  int D.18660;
  struct MonoWSQ * wsq;
  struct MonoDomain * root;

  wsq_tlskey_inited.4 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.4 == 0) goto <D.18639>; else goto <D.18640>;
  <D.18639>:
  D.18641 = 0B;
  return D.18641;
  <D.18640>:
  wsq = monoeg_malloc0 (32);
  wsq->mask = 31;
  if (0 != 0) goto <D.18642>; else goto <D.18643>;
  <D.18642>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-wsq.c", 64, "sizeof (wsq->queue) == sizeof (MonoObject*)");
  <D.18643>:
  D.18644 = &wsq->queue;
  D.18645 = mono_gc_make_root_descr_all_refs (1);
  mono_gc_register_root (D.18644, 4, D.18645);
  root = mono_get_root_domain ();
  {
    static struct MonoClass * tmp_klass;

    {
      tmp_klass.5 = tmp_klass;
      if (tmp_klass.5 == 0B) goto <D.18647>; else goto <D.18648>;
      <D.18647>:
      D.18649 = mono_defaults.object_class;
      tmp_klass.6 = mono_array_class_get (D.18649, 1);
      tmp_klass = tmp_klass.6;
      tmp_klass.5 = tmp_klass;
      D.18651 = tmp_klass.5 == 0B;
      D.18652 = (long int) D.18651;
      D.18653 = __builtin_expect (D.18652, 0);
      if (D.18653 != 0) goto <D.18654>; else goto <D.18655>;
      <D.18654>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-wsq.c", 66, "tmp_klass");
      <D.18655>:
      <D.18648>:
    }
    D.18581 = tmp_klass;
  }
  D.18656 = mono_class_vtable (root, D.18581);
  D.18657 = mono_array_new_specific (D.18656, 32);
  wsq->queue = D.18657;
  D.18658 = &wsq->lock;
  sem_init (D.18658, 0, 1);
  wsq_tlskey.7 = wsq_tlskey;
  D.18660 = mono_native_tls_set_value (wsq_tlskey.7, wsq);
  if (D.18660 == 0) goto <D.18661>; else goto <D.18662>;
  <D.18661>:
  mono_wsq_destroy (wsq);
  wsq = 0B;
  <D.18662>:
  D.18641 = wsq;
  return D.18641;
}


mono_native_tls_set_value (pthread_key_t key, void * value)
{
  int D.18664;
  int D.18665;
  _Bool D.18666;

  D.18665 = pthread_setspecific (key, value);
  D.18666 = D.18665 == 0;
  D.18664 = (int) D.18666;
  return D.18664;
}


mono_wsq_destroy (struct MonoWSQ * wsq)
{
  struct MonoArray * D.18671;
  int D.18672;
  _Bool D.18673;
  long int D.18674;
  long int D.18675;
  struct MonoArray * * D.18678;
  union MonoSemType * D.18679;
  int wsq_tlskey_inited.8;
  unsigned int wsq_tlskey.9;
  void * D.18684;

  if (wsq == 0B) goto <D.18668>; else goto <D.18670>;
  <D.18670>:
  D.18671 = wsq->queue;
  if (D.18671 == 0B) goto <D.18668>; else goto <D.18669>;
  <D.18668>:
  return;
  <D.18669>:
  D.18672 = mono_wsq_count (wsq);
  D.18673 = D.18672 != 0;
  D.18674 = (long int) D.18673;
  D.18675 = __builtin_expect (D.18674, 0);
  if (D.18675 != 0) goto <D.18676>; else goto <D.18677>;
  <D.18676>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-wsq.c", 81, "mono_wsq_count (wsq) == 0");
  <D.18677>:
  D.18678 = &wsq->queue;
  mono_gc_deregister_root (D.18678);
  D.18679 = &wsq->lock;
  sem_destroy (D.18679);
  memset (wsq, 0, 32);
  wsq_tlskey_inited.8 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.8 != 0) goto <D.18681>; else goto <D.18682>;
  <D.18681>:
  wsq_tlskey.9 = wsq_tlskey;
  D.18684 = pthread_getspecific (wsq_tlskey.9);
  if (D.18684 == wsq) goto <D.18685>; else goto <D.18686>;
  <D.18685>:
  wsq_tlskey.9 = wsq_tlskey;
  mono_native_tls_set_value (wsq_tlskey.9, 0B);
  <D.18686>:
  <D.18682>:
  monoeg_g_free (wsq);
}


memset (void * __dest, int __ch, size_t __len)
{
  int D.18690;
  int D.18695;
  void * D.18697;
  unsigned int D.18698;

  D.18690 = __builtin_constant_p (__len);
  if (D.18690 != 0) goto <D.18691>; else goto <D.18692>;
  <D.18691>:
  if (__len == 0) goto <D.18693>; else goto <D.18694>;
  <D.18693>:
  D.18695 = __builtin_constant_p (__ch);
  if (D.18695 == 0) goto <D.18688>; else goto <D.18696>;
  <D.18696>:
  if (__ch != 0) goto <D.18688>; else goto <D.18689>;
  <D.18688>:
  __warn_memset_zero_len ();
  D.18697 = __dest;
  return D.18697;
  <D.18689>:
  <D.18694>:
  <D.18692>:
  D.18698 = __builtin_object_size (__dest, 0);
  D.18697 = __builtin___memset_chk (__dest, __ch, __len, D.18698);
  return D.18697;
}


mono_wsq_count (struct MonoWSQ * wsq)
{
  gint D.18702;
  int D.18703;
  int D.18704;
  int D.18705;
  int D.18706;

  if (wsq == 0B) goto <D.18700>; else goto <D.18701>;
  <D.18700>:
  D.18702 = 0;
  return D.18702;
  <D.18701>:
  D.18703 = wsq->tail;
  D.18704 = wsq->head;
  D.18705 = D.18703 - D.18704;
  D.18706 = wsq->mask;
  D.18702 = D.18705 & D.18706;
  return D.18702;
}


mono_wsq_local_push (void * obj)
{
  int wsq_tlskey_inited.10;
  gboolean D.18712;
  unsigned int wsq_tlskey.11;
  int D.18716;
  int D.18717;
  int D.18718;
  struct MonoArray * D.18721;
  int D.18722;
  unsigned int D.18723;
  int D.18724;
  union MonoSemType * D.18725;
  int D.18726;
  int D.18727;
  unsigned int D.18730;
  struct MonoDomain * D.18731;
  struct MonoClass * D.18600;
  struct MonoClass * tmp_klass.12;
  struct MonoClass * D.18735;
  struct MonoClass * tmp_klass.13;
  _Bool D.18737;
  long int D.18738;
  long int D.18739;
  struct MonoVTable * D.18742;
  int D.18743;
  unsigned int D.18744;
  unsigned int i.14;
  int D.18746;
  int D.18747;
  unsigned int D.18748;
  char * D.18749;
  struct MonoObject * D.18750;
  char * D.18751;
  unsigned int length.15;
  unsigned int D.18753;
  int D.18754;
  int D.18755;
  int tail;
  int head;
  int count;
  struct MonoWSQ * wsq;

  if (obj == 0B) goto <D.18708>; else goto <D.18710>;
  <D.18710>:
  wsq_tlskey_inited.10 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.10 == 0) goto <D.18708>; else goto <D.18709>;
  <D.18708>:
  D.18712 = 0;
  return D.18712;
  <D.18709>:
  wsq_tlskey.11 = wsq_tlskey;
  wsq = pthread_getspecific (wsq_tlskey.11);
  if (wsq == 0B) goto <D.18714>; else goto <D.18715>;
  <D.18714>:
  D.18712 = 0;
  return D.18712;
  <D.18715>:
  tail = wsq->tail;
  D.18716 = wsq->head;
  D.18717 = wsq->mask;
  D.18718 = D.18716 + D.18717;
  if (D.18718 > tail) goto <D.18719>; else goto <D.18720>;
  <D.18719>:
  {
    void * * __p;

    D.18721 = wsq->queue;
    D.18717 = wsq->mask;
    D.18722 = D.18717 & tail;
    D.18723 = (unsigned int) D.18722;
    __p = mono_array_addr_with_size (D.18721, 4, D.18723);
    D.18721 = wsq->queue;
    mono_gc_wbarrier_set_arrayref (D.18721, __p, obj);
  }
  D.18724 = tail + 1;
  wsq->tail = D.18724;
  D.18712 = 1;
  return D.18712;
  <D.18720>:
  D.18725 = &wsq->lock;
  mono_sem_wait (D.18725, 0);
  head = wsq->head;
  D.18726 = wsq->tail;
  D.18727 = wsq->head;
  count = D.18726 - D.18727;
  D.18717 = wsq->mask;
  if (D.18717 <= count) goto <D.18728>; else goto <D.18729>;
  <D.18728>:
  {
    struct MonoArray * new_array;
    int length;
    int i;

    D.18721 = wsq->queue;
    D.18730 = mono_array_length (D.18721);
    length = (int) D.18730;
    D.18731 = mono_get_root_domain ();
    {
      static struct MonoClass * tmp_klass;

      {
        tmp_klass.12 = tmp_klass;
        if (tmp_klass.12 == 0B) goto <D.18733>; else goto <D.18734>;
        <D.18733>:
        D.18735 = mono_defaults.object_class;
        tmp_klass.13 = mono_array_class_get (D.18735, 1);
        tmp_klass = tmp_klass.13;
        tmp_klass.12 = tmp_klass;
        D.18737 = tmp_klass.12 == 0B;
        D.18738 = (long int) D.18737;
        D.18739 = __builtin_expect (D.18738, 0);
        if (D.18739 != 0) goto <D.18740>; else goto <D.18741>;
        <D.18740>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-wsq.c", 132, "tmp_klass");
        <D.18741>:
        <D.18734>:
      }
      D.18600 = tmp_klass;
    }
    D.18742 = mono_class_vtable (D.18731, D.18600);
    D.18743 = length * 2;
    D.18744 = (unsigned int) D.18743;
    new_array = mono_array_new_specific (D.18742, D.18744);
    i = 0;
    goto <D.18603>;
    <D.18602>:
    {
      void * * __p;

      i.14 = (unsigned int) i;
      __p = mono_array_addr_with_size (new_array, 4, i.14);
      D.18721 = wsq->queue;
      D.18746 = i + head;
      D.18717 = wsq->mask;
      D.18747 = D.18746 & D.18717;
      D.18748 = (unsigned int) D.18747;
      D.18749 = mono_array_addr_with_size (D.18721, 4, D.18748);
      D.18750 = MEM[(struct MonoObject * *)D.18749];
      mono_gc_wbarrier_set_arrayref (new_array, __p, D.18750);
    }
    i = i + 1;
    <D.18603>:
    if (i < length) goto <D.18602>; else goto <D.18604>;
    <D.18604>:
    D.18721 = wsq->queue;
    D.18751 = mono_array_addr_with_size (D.18721, 4, 0);
    length.15 = (unsigned int) length;
    D.18753 = length.15 * 4;
    mono_gc_bzero_aligned (D.18751, D.18753);
    wsq->queue = new_array;
    wsq->head = 0;
    tail = count;
    wsq->tail = tail;
    D.18717 = wsq->mask;
    D.18754 = D.18717 << 1;
    D.18755 = D.18754 | 1;
    wsq->mask = D.18755;
  }
  <D.18729>:
  {
    void * * __p;

    D.18721 = wsq->queue;
    D.18717 = wsq->mask;
    D.18722 = D.18717 & tail;
    D.18723 = (unsigned int) D.18722;
    __p = mono_array_addr_with_size (D.18721, 4, D.18723);
    D.18721 = wsq->queue;
    mono_gc_wbarrier_set_arrayref (D.18721, __p, obj);
  }
  D.18724 = tail + 1;
  wsq->tail = D.18724;
  D.18725 = &wsq->lock;
  mono_sem_post (D.18725);
  D.18712 = 1;
  return D.18712;
}


mono_wsq_local_pop (void * * ptr)
{
  int wsq_tlskey_inited.16;
  gboolean D.18761;
  unsigned int wsq_tlskey.17;
  int D.18765;
  volatile gint * D.18768;
  int D.18769;
  struct MonoArray * D.18772;
  int D.18773;
  int D.18774;
  unsigned int D.18775;
  char * D.18776;
  void * D.18777;
  union MonoSemType * D.18778;
  int D.18779;
  char * D.18782;
  void * D.18783;
  int D.18785;
  int tail;
  gboolean res;
  struct MonoWSQ * wsq;

  if (ptr == 0B) goto <D.18757>; else goto <D.18759>;
  <D.18759>:
  wsq_tlskey_inited.16 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.16 == 0) goto <D.18757>; else goto <D.18758>;
  <D.18757>:
  D.18761 = 0;
  return D.18761;
  <D.18758>:
  wsq_tlskey.17 = wsq_tlskey;
  wsq = pthread_getspecific (wsq_tlskey.17);
  if (wsq == 0B) goto <D.18763>; else goto <D.18764>;
  <D.18763>:
  D.18761 = 0;
  return D.18761;
  <D.18764>:
  tail = wsq->tail;
  D.18765 = wsq->head;
  if (D.18765 >= tail) goto <D.18766>; else goto <D.18767>;
  <D.18766>:
  D.18761 = 0;
  return D.18761;
  <D.18767>:
  tail = tail + -1;
  D.18768 = &wsq->tail;
  InterlockedExchange (D.18768, tail);
  D.18769 = wsq->head;
  if (D.18769 <= tail) goto <D.18770>; else goto <D.18771>;
  <D.18770>:
  D.18772 = wsq->queue;
  D.18773 = wsq->mask;
  D.18774 = D.18773 & tail;
  D.18775 = (unsigned int) D.18774;
  D.18776 = mono_array_addr_with_size (D.18772, 4, D.18775);
  D.18777 = MEM[(void * *)D.18776];
  *ptr = D.18777;
  {
    void * * __p;

    D.18772 = wsq->queue;
    D.18773 = wsq->mask;
    D.18774 = D.18773 & tail;
    D.18775 = (unsigned int) D.18774;
    __p = mono_array_addr_with_size (D.18772, 4, D.18775);
    *__p = 0B;
  }
  D.18761 = 1;
  return D.18761;
  <D.18771>:
  D.18778 = &wsq->lock;
  mono_sem_wait (D.18778, 0);
  D.18779 = wsq->head;
  if (D.18779 <= tail) goto <D.18780>; else goto <D.18781>;
  <D.18780>:
  D.18772 = wsq->queue;
  D.18773 = wsq->mask;
  D.18774 = D.18773 & tail;
  D.18775 = (unsigned int) D.18774;
  D.18782 = mono_array_addr_with_size (D.18772, 4, D.18775);
  D.18783 = MEM[(void * *)D.18782];
  *ptr = D.18783;
  {
    void * * __p;

    D.18772 = wsq->queue;
    D.18773 = wsq->mask;
    D.18774 = D.18773 & tail;
    D.18775 = (unsigned int) D.18774;
    __p = mono_array_addr_with_size (D.18772, 4, D.18775);
    *__p = 0B;
  }
  res = 1;
  goto <D.18784>;
  <D.18781>:
  D.18785 = tail + 1;
  wsq->tail = D.18785;
  res = 0;
  <D.18784>:
  D.18778 = &wsq->lock;
  mono_sem_post (D.18778);
  D.18761 = res;
  return D.18761;
}


InterlockedExchange (volatile gint32 * val, gint32 new_val)
{
  unsigned int old_val.18;
  unsigned int new_val.19;
  unsigned int D.18789;
  int D.18790;
  gint32 D.18791;
  gint32 old_val;

  <D.18468>:
  old_val = *val;
  old_val.18 = (unsigned int) old_val;
  new_val.19 = (unsigned int) new_val;
  D.18789 = __sync_val_compare_and_swap_4 (val, old_val.18, new_val.19);
  D.18790 = (int) D.18789;
  if (D.18790 != old_val) goto <D.18468>; else goto <D.18469>;
  <D.18469>:
  D.18791 = old_val;
  return D.18791;
}


mono_wsq_try_steal (struct MonoWSQ * wsq, void * * ptr, guint32 ms_timeout)
{
  _Bool D.18795;
  _Bool D.18796;
  _Bool D.18797;
  void * D.18799;
  int wsq_tlskey_inited.20;
  unsigned int wsq_tlskey.21;
  void * D.18803;
  union MonoSemType * D.18806;
  int D.18807;
  volatile gint * D.18810;
  int D.18811;
  int D.18812;
  struct MonoArray * D.18815;
  int D.18816;
  int D.18817;
  unsigned int D.18818;
  char * D.18819;
  void * D.18820;

  D.18795 = wsq == 0B;
  D.18796 = ptr == 0B;
  D.18797 = D.18795 | D.18796;
  if (D.18797 != 0) goto <D.18793>; else goto <D.18798>;
  <D.18798>:
  D.18799 = *ptr;
  if (D.18799 != 0B) goto <D.18793>; else goto <D.18800>;
  <D.18800>:
  wsq_tlskey_inited.20 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.20 == 0) goto <D.18793>; else goto <D.18794>;
  <D.18793>:
  return;
  <D.18794>:
  wsq_tlskey.21 = wsq_tlskey;
  D.18803 = pthread_getspecific (wsq_tlskey.21);
  if (D.18803 == wsq) goto <D.18804>; else goto <D.18805>;
  <D.18804>:
  return;
  <D.18805>:
  D.18806 = &wsq->lock;
  D.18807 = mono_sem_timedwait (D.18806, ms_timeout, 0);
  if (D.18807 == 0) goto <D.18808>; else goto <D.18809>;
  <D.18808>:
  {
    int head;

    head = wsq->head;
    D.18810 = &wsq->head;
    D.18811 = head + 1;
    InterlockedExchange (D.18810, D.18811);
    D.18812 = wsq->tail;
    if (D.18812 > head) goto <D.18813>; else goto <D.18814>;
    <D.18813>:
    D.18815 = wsq->queue;
    D.18816 = wsq->mask;
    D.18817 = D.18816 & head;
    D.18818 = (unsigned int) D.18817;
    D.18819 = mono_array_addr_with_size (D.18815, 4, D.18818);
    D.18820 = MEM[(void * *)D.18819];
    *ptr = D.18820;
    {
      void * * __p;

      D.18815 = wsq->queue;
      D.18816 = wsq->mask;
      D.18817 = D.18816 & head;
      D.18818 = (unsigned int) D.18817;
      __p = mono_array_addr_with_size (D.18815, 4, D.18818);
      *__p = 0B;
    }
    goto <D.18821>;
    <D.18814>:
    wsq->head = head;
    <D.18821>:
    D.18806 = &wsq->lock;
    mono_sem_post (D.18806);
  }
  <D.18809>:
}


