mono_wsq_init ()
{
  int wsq_tlskey_inited.0;

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


mono_native_tls_alloc (pthread_key_t * key, void * destructor)
{
  int D.16957;
  void (*<Tbf>) (void *) destructor.1;
  int D.16959;
  _Bool D.16960;

  destructor.1 = (void (*<Tbf>) (void *)) destructor;
  D.16959 = pthread_key_create (key, destructor.1);
  D.16960 = D.16959 == 0;
  D.16957 = (int) D.16960;
  return D.16957;
}


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.16963>; else goto <D.16964>;
  <D.16963>:
  return;
  <D.16964>:
  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.16970;
  struct MonoArray * * D.16973;
  void * D.16974;
  struct MonoClass * D.16912;
  struct MonoClass * tmp_klass.5;
  struct MonoClass * D.16978;
  struct MonoClass * tmp_klass.6;
  _Bool D.16980;
  long int D.16981;
  long int D.16982;
  struct MonoVTable * D.16985;
  struct MonoArray * D.16986;
  union MonoSemType * D.16987;
  unsigned int wsq_tlskey.7;
  int D.16989;
  struct MonoWSQ * wsq;
  struct MonoDomain * root;

  wsq_tlskey_inited.4 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.4 == 0) goto <D.16968>; else goto <D.16969>;
  <D.16968>:
  D.16970 = 0B;
  return D.16970;
  <D.16969>:
  wsq = monoeg_malloc0 (56);
  wsq->mask = 31;
  if (0 != 0) goto <D.16971>; else goto <D.16972>;
  <D.16971>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-wsq.c", 64, "sizeof (wsq->queue) == sizeof (MonoObject*)");
  <D.16972>:
  D.16973 = &wsq->queue;
  D.16974 = mono_gc_make_root_descr_all_refs (1);
  mono_gc_register_root (D.16973, 8, D.16974);
  root = mono_get_root_domain ();
  {
    static struct MonoClass * tmp_klass;

    {
      tmp_klass.5 = tmp_klass;
      if (tmp_klass.5 == 0B) goto <D.16976>; else goto <D.16977>;
      <D.16976>:
      D.16978 = mono_defaults.object_class;
      tmp_klass.6 = mono_array_class_get (D.16978, 1);
      tmp_klass = tmp_klass.6;
      tmp_klass.5 = tmp_klass;
      D.16980 = tmp_klass.5 == 0B;
      D.16981 = (long int) D.16980;
      D.16982 = __builtin_expect (D.16981, 0);
      if (D.16982 != 0) goto <D.16983>; else goto <D.16984>;
      <D.16983>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-wsq.c", 66, "tmp_klass");
      <D.16984>:
      <D.16977>:
    }
    D.16912 = tmp_klass;
  }
  D.16985 = mono_class_vtable (root, D.16912);
  D.16986 = mono_array_new_specific (D.16985, 32);
  wsq->queue = D.16986;
  D.16987 = &wsq->lock;
  sem_init (D.16987, 0, 1);
  wsq_tlskey.7 = wsq_tlskey;
  D.16989 = mono_native_tls_set_value (wsq_tlskey.7, wsq);
  if (D.16989 == 0) goto <D.16990>; else goto <D.16991>;
  <D.16990>:
  mono_wsq_destroy (wsq);
  wsq = 0B;
  <D.16991>:
  D.16970 = wsq;
  return D.16970;
}


mono_native_tls_set_value (pthread_key_t key, void * value)
{
  int D.16993;
  int D.16994;
  _Bool D.16995;

  D.16994 = pthread_setspecific (key, value);
  D.16995 = D.16994 == 0;
  D.16993 = (int) D.16995;
  return D.16993;
}


mono_wsq_destroy (struct MonoWSQ * wsq)
{
  struct MonoArray * D.17000;
  int D.17001;
  _Bool D.17002;
  long int D.17003;
  long int D.17004;
  struct MonoArray * * D.17007;
  union MonoSemType * D.17008;
  int wsq_tlskey_inited.8;
  unsigned int wsq_tlskey.9;
  void * D.17013;

  if (wsq == 0B) goto <D.16997>; else goto <D.16999>;
  <D.16999>:
  D.17000 = wsq->queue;
  if (D.17000 == 0B) goto <D.16997>; else goto <D.16998>;
  <D.16997>:
  return;
  <D.16998>:
  D.17001 = mono_wsq_count (wsq);
  D.17002 = D.17001 != 0;
  D.17003 = (long int) D.17002;
  D.17004 = __builtin_expect (D.17003, 0);
  if (D.17004 != 0) goto <D.17005>; else goto <D.17006>;
  <D.17005>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-wsq.c", 81, "mono_wsq_count (wsq) == 0");
  <D.17006>:
  D.17007 = &wsq->queue;
  mono_gc_deregister_root (D.17007);
  D.17008 = &wsq->lock;
  sem_destroy (D.17008);
  memset (wsq, 0, 56);
  wsq_tlskey_inited.8 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.8 != 0) goto <D.17010>; else goto <D.17011>;
  <D.17010>:
  wsq_tlskey.9 = wsq_tlskey;
  D.17013 = pthread_getspecific (wsq_tlskey.9);
  if (D.17013 == wsq) goto <D.17014>; else goto <D.17015>;
  <D.17014>:
  wsq_tlskey.9 = wsq_tlskey;
  mono_native_tls_set_value (wsq_tlskey.9, 0B);
  <D.17015>:
  <D.17011>:
  monoeg_g_free (wsq);
}


memset (void * __dest, int __ch, size_t __len)
{
  int D.17019;
  int D.17024;
  void * D.17026;
  long unsigned int D.17027;

  D.17019 = __builtin_constant_p (__len);
  if (D.17019 != 0) goto <D.17020>; else goto <D.17021>;
  <D.17020>:
  if (__len == 0) goto <D.17022>; else goto <D.17023>;
  <D.17022>:
  D.17024 = __builtin_constant_p (__ch);
  if (D.17024 == 0) goto <D.17017>; else goto <D.17025>;
  <D.17025>:
  if (__ch != 0) goto <D.17017>; else goto <D.17018>;
  <D.17017>:
  __warn_memset_zero_len ();
  D.17026 = __dest;
  return D.17026;
  <D.17018>:
  <D.17023>:
  <D.17021>:
  D.17027 = __builtin_object_size (__dest, 0);
  D.17026 = __builtin___memset_chk (__dest, __ch, __len, D.17027);
  return D.17026;
}


mono_wsq_count (struct MonoWSQ * wsq)
{
  gint D.17031;
  int D.17032;
  int D.17033;
  int D.17034;
  int D.17035;

  if (wsq == 0B) goto <D.17029>; else goto <D.17030>;
  <D.17029>:
  D.17031 = 0;
  return D.17031;
  <D.17030>:
  D.17032 = wsq->tail;
  D.17033 = wsq->head;
  D.17034 = D.17032 - D.17033;
  D.17035 = wsq->mask;
  D.17031 = D.17034 & D.17035;
  return D.17031;
}


mono_wsq_local_push (void * obj)
{
  int wsq_tlskey_inited.10;
  gboolean D.17041;
  unsigned int wsq_tlskey.11;
  int D.17045;
  int D.17046;
  int D.17047;
  struct MonoArray * D.17050;
  int D.17051;
  long unsigned int D.17052;
  int D.17053;
  union MonoSemType * D.17054;
  int D.17055;
  int D.17056;
  long unsigned int D.17059;
  struct MonoDomain * D.17060;
  struct MonoClass * D.16931;
  struct MonoClass * tmp_klass.12;
  struct MonoClass * D.17064;
  struct MonoClass * tmp_klass.13;
  _Bool D.17066;
  long int D.17067;
  long int D.17068;
  struct MonoVTable * D.17071;
  int D.17072;
  long unsigned int D.17073;
  long unsigned int D.17074;
  int D.17075;
  int D.17076;
  long unsigned int D.17077;
  char * D.17078;
  struct MonoObject * D.17079;
  char * D.17080;
  long unsigned int D.17081;
  long unsigned int D.17082;
  int D.17083;
  int D.17084;
  int tail;
  int head;
  int count;
  struct MonoWSQ * wsq;

  if (obj == 0B) goto <D.17037>; else goto <D.17039>;
  <D.17039>:
  wsq_tlskey_inited.10 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.10 == 0) goto <D.17037>; else goto <D.17038>;
  <D.17037>:
  D.17041 = 0;
  return D.17041;
  <D.17038>:
  wsq_tlskey.11 = wsq_tlskey;
  wsq = pthread_getspecific (wsq_tlskey.11);
  if (wsq == 0B) goto <D.17043>; else goto <D.17044>;
  <D.17043>:
  D.17041 = 0;
  return D.17041;
  <D.17044>:
  tail = wsq->tail;
  D.17045 = wsq->head;
  D.17046 = wsq->mask;
  D.17047 = D.17045 + D.17046;
  if (D.17047 > tail) goto <D.17048>; else goto <D.17049>;
  <D.17048>:
  {
    void * * __p;

    D.17050 = wsq->queue;
    D.17046 = wsq->mask;
    D.17051 = D.17046 & tail;
    D.17052 = (long unsigned int) D.17051;
    __p = mono_array_addr_with_size (D.17050, 8, D.17052);
    D.17050 = wsq->queue;
    mono_gc_wbarrier_set_arrayref (D.17050, __p, obj);
  }
  D.17053 = tail + 1;
  wsq->tail = D.17053;
  D.17041 = 1;
  return D.17041;
  <D.17049>:
  D.17054 = &wsq->lock;
  mono_sem_wait (D.17054, 0);
  head = wsq->head;
  D.17055 = wsq->tail;
  D.17056 = wsq->head;
  count = D.17055 - D.17056;
  D.17046 = wsq->mask;
  if (D.17046 <= count) goto <D.17057>; else goto <D.17058>;
  <D.17057>:
  {
    struct MonoArray * new_array;
    int length;
    int i;

    D.17050 = wsq->queue;
    D.17059 = mono_array_length (D.17050);
    length = (int) D.17059;
    D.17060 = mono_get_root_domain ();
    {
      static struct MonoClass * tmp_klass;

      {
        tmp_klass.12 = tmp_klass;
        if (tmp_klass.12 == 0B) goto <D.17062>; else goto <D.17063>;
        <D.17062>:
        D.17064 = mono_defaults.object_class;
        tmp_klass.13 = mono_array_class_get (D.17064, 1);
        tmp_klass = tmp_klass.13;
        tmp_klass.12 = tmp_klass;
        D.17066 = tmp_klass.12 == 0B;
        D.17067 = (long int) D.17066;
        D.17068 = __builtin_expect (D.17067, 0);
        if (D.17068 != 0) goto <D.17069>; else goto <D.17070>;
        <D.17069>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-wsq.c", 132, "tmp_klass");
        <D.17070>:
        <D.17063>:
      }
      D.16931 = tmp_klass;
    }
    D.17071 = mono_class_vtable (D.17060, D.16931);
    D.17072 = length * 2;
    D.17073 = (long unsigned int) D.17072;
    new_array = mono_array_new_specific (D.17071, D.17073);
    i = 0;
    goto <D.16934>;
    <D.16933>:
    {
      void * * __p;

      D.17074 = (long unsigned int) i;
      __p = mono_array_addr_with_size (new_array, 8, D.17074);
      D.17050 = wsq->queue;
      D.17075 = i + head;
      D.17046 = wsq->mask;
      D.17076 = D.17075 & D.17046;
      D.17077 = (long unsigned int) D.17076;
      D.17078 = mono_array_addr_with_size (D.17050, 8, D.17077);
      D.17079 = MEM[(struct MonoObject * *)D.17078];
      mono_gc_wbarrier_set_arrayref (new_array, __p, D.17079);
    }
    i = i + 1;
    <D.16934>:
    if (i < length) goto <D.16933>; else goto <D.16935>;
    <D.16935>:
    D.17050 = wsq->queue;
    D.17080 = mono_array_addr_with_size (D.17050, 8, 0);
    D.17081 = (long unsigned int) length;
    D.17082 = D.17081 * 8;
    mono_gc_bzero_aligned (D.17080, D.17082);
    wsq->queue = new_array;
    wsq->head = 0;
    tail = count;
    wsq->tail = tail;
    D.17046 = wsq->mask;
    D.17083 = D.17046 << 1;
    D.17084 = D.17083 | 1;
    wsq->mask = D.17084;
  }
  <D.17058>:
  {
    void * * __p;

    D.17050 = wsq->queue;
    D.17046 = wsq->mask;
    D.17051 = D.17046 & tail;
    D.17052 = (long unsigned int) D.17051;
    __p = mono_array_addr_with_size (D.17050, 8, D.17052);
    D.17050 = wsq->queue;
    mono_gc_wbarrier_set_arrayref (D.17050, __p, obj);
  }
  D.17053 = tail + 1;
  wsq->tail = D.17053;
  D.17054 = &wsq->lock;
  mono_sem_post (D.17054);
  D.17041 = 1;
  return D.17041;
}


mono_wsq_local_pop (void * * ptr)
{
  int wsq_tlskey_inited.14;
  gboolean D.17090;
  unsigned int wsq_tlskey.15;
  int D.17094;
  volatile gint * D.17097;
  int D.17098;
  struct MonoArray * D.17101;
  int D.17102;
  int D.17103;
  long unsigned int D.17104;
  char * D.17105;
  void * D.17106;
  union MonoSemType * D.17107;
  int D.17108;
  char * D.17111;
  void * D.17112;
  int D.17114;
  int tail;
  gboolean res;
  struct MonoWSQ * wsq;

  if (ptr == 0B) goto <D.17086>; else goto <D.17088>;
  <D.17088>:
  wsq_tlskey_inited.14 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.14 == 0) goto <D.17086>; else goto <D.17087>;
  <D.17086>:
  D.17090 = 0;
  return D.17090;
  <D.17087>:
  wsq_tlskey.15 = wsq_tlskey;
  wsq = pthread_getspecific (wsq_tlskey.15);
  if (wsq == 0B) goto <D.17092>; else goto <D.17093>;
  <D.17092>:
  D.17090 = 0;
  return D.17090;
  <D.17093>:
  tail = wsq->tail;
  D.17094 = wsq->head;
  if (D.17094 >= tail) goto <D.17095>; else goto <D.17096>;
  <D.17095>:
  D.17090 = 0;
  return D.17090;
  <D.17096>:
  tail = tail + -1;
  D.17097 = &wsq->tail;
  InterlockedExchange (D.17097, tail);
  D.17098 = wsq->head;
  if (D.17098 <= tail) goto <D.17099>; else goto <D.17100>;
  <D.17099>:
  D.17101 = wsq->queue;
  D.17102 = wsq->mask;
  D.17103 = D.17102 & tail;
  D.17104 = (long unsigned int) D.17103;
  D.17105 = mono_array_addr_with_size (D.17101, 8, D.17104);
  D.17106 = MEM[(void * *)D.17105];
  *ptr = D.17106;
  {
    void * * __p;

    D.17101 = wsq->queue;
    D.17102 = wsq->mask;
    D.17103 = D.17102 & tail;
    D.17104 = (long unsigned int) D.17103;
    __p = mono_array_addr_with_size (D.17101, 8, D.17104);
    *__p = 0B;
  }
  D.17090 = 1;
  return D.17090;
  <D.17100>:
  D.17107 = &wsq->lock;
  mono_sem_wait (D.17107, 0);
  D.17108 = wsq->head;
  if (D.17108 <= tail) goto <D.17109>; else goto <D.17110>;
  <D.17109>:
  D.17101 = wsq->queue;
  D.17102 = wsq->mask;
  D.17103 = D.17102 & tail;
  D.17104 = (long unsigned int) D.17103;
  D.17111 = mono_array_addr_with_size (D.17101, 8, D.17104);
  D.17112 = MEM[(void * *)D.17111];
  *ptr = D.17112;
  {
    void * * __p;

    D.17101 = wsq->queue;
    D.17102 = wsq->mask;
    D.17103 = D.17102 & tail;
    D.17104 = (long unsigned int) D.17103;
    __p = mono_array_addr_with_size (D.17101, 8, D.17104);
    *__p = 0B;
  }
  res = 1;
  goto <D.17113>;
  <D.17110>:
  D.17114 = tail + 1;
  wsq->tail = D.17114;
  res = 0;
  <D.17113>:
  D.17107 = &wsq->lock;
  mono_sem_post (D.17107);
  D.17090 = res;
  return D.17090;
}


InterlockedExchange (volatile gint32 * val, gint32 new_val)
{
  unsigned int old_val.16;
  unsigned int new_val.17;
  unsigned int D.17118;
  int D.17119;
  gint32 D.17120;
  gint32 old_val;

  <D.16813>:
  old_val = *val;
  old_val.16 = (unsigned int) old_val;
  new_val.17 = (unsigned int) new_val;
  D.17118 = __sync_val_compare_and_swap_4 (val, old_val.16, new_val.17);
  D.17119 = (int) D.17118;
  if (D.17119 != old_val) goto <D.16813>; else goto <D.16814>;
  <D.16814>:
  D.17120 = old_val;
  return D.17120;
}


mono_wsq_try_steal (struct MonoWSQ * wsq, void * * ptr, guint32 ms_timeout)
{
  void * D.17126;
  int wsq_tlskey_inited.18;
  unsigned int wsq_tlskey.19;
  void * D.17130;
  union MonoSemType * D.17133;
  int D.17134;
  volatile gint * D.17137;
  int D.17138;
  int D.17139;
  struct MonoArray * D.17142;
  int D.17143;
  int D.17144;
  long unsigned int D.17145;
  char * D.17146;
  void * D.17147;

  if (wsq == 0B) goto <D.17122>; else goto <D.17124>;
  <D.17124>:
  if (ptr == 0B) goto <D.17122>; else goto <D.17125>;
  <D.17125>:
  D.17126 = *ptr;
  if (D.17126 != 0B) goto <D.17122>; else goto <D.17127>;
  <D.17127>:
  wsq_tlskey_inited.18 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.18 == 0) goto <D.17122>; else goto <D.17123>;
  <D.17122>:
  return;
  <D.17123>:
  wsq_tlskey.19 = wsq_tlskey;
  D.17130 = pthread_getspecific (wsq_tlskey.19);
  if (D.17130 == wsq) goto <D.17131>; else goto <D.17132>;
  <D.17131>:
  return;
  <D.17132>:
  D.17133 = &wsq->lock;
  D.17134 = mono_sem_timedwait (D.17133, ms_timeout, 0);
  if (D.17134 == 0) goto <D.17135>; else goto <D.17136>;
  <D.17135>:
  {
    int head;

    head = wsq->head;
    D.17137 = &wsq->head;
    D.17138 = head + 1;
    InterlockedExchange (D.17137, D.17138);
    D.17139 = wsq->tail;
    if (D.17139 > head) goto <D.17140>; else goto <D.17141>;
    <D.17140>:
    D.17142 = wsq->queue;
    D.17143 = wsq->mask;
    D.17144 = D.17143 & head;
    D.17145 = (long unsigned int) D.17144;
    D.17146 = mono_array_addr_with_size (D.17142, 8, D.17145);
    D.17147 = MEM[(void * *)D.17146];
    *ptr = D.17147;
    {
      void * * __p;

      D.17142 = wsq->queue;
      D.17143 = wsq->mask;
      D.17144 = D.17143 & head;
      D.17145 = (long unsigned int) D.17144;
      __p = mono_array_addr_with_size (D.17142, 8, D.17145);
      *__p = 0B;
    }
    goto <D.17148>;
    <D.17141>:
    wsq->head = head;
    <D.17148>:
    D.17133 = &wsq->lock;
    mono_sem_post (D.17133);
  }
  <D.17136>:
}


