mono_wsq_init ()
{
  int wsq_tlskey_inited.0;

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


mono_native_tls_alloc (pthread_key_t * key, void * destructor)
{
  int D.16043;
  void (*<Tc3>) (void *) destructor.1;
  int D.16045;
  _Bool D.16046;

  destructor.1 = (void (*<Tc3>) (void *)) destructor;
  D.16045 = pthread_key_create (key, destructor.1);
  D.16046 = D.16045 == 0;
  D.16043 = (int) D.16046;
  return D.16043;
}


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.16049>; else goto <D.16050>;
  <D.16049>:
  return;
  <D.16050>:
  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.16056;
  struct MonoArray * * D.16059;
  void * D.16060;
  struct MonoClass * D.15998;
  struct MonoClass * tmp_klass.5;
  struct MonoClass * D.16064;
  struct MonoClass * tmp_klass.6;
  _Bool D.16066;
  long int D.16067;
  long int D.16068;
  struct MonoVTable * D.16071;
  struct MonoArray * D.16072;
  union MonoSemType * D.16073;
  unsigned int wsq_tlskey.7;
  int D.16075;
  struct MonoWSQ * wsq;
  struct MonoDomain * root;

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

    {
      tmp_klass.5 = tmp_klass;
      if (tmp_klass.5 == 0B) goto <D.16062>; else goto <D.16063>;
      <D.16062>:
      D.16064 = mono_defaults.object_class;
      tmp_klass.6 = mono_array_class_get (D.16064, 1);
      tmp_klass = tmp_klass.6;
      tmp_klass.5 = tmp_klass;
      D.16066 = tmp_klass.5 == 0B;
      D.16067 = (long int) D.16066;
      D.16068 = __builtin_expect (D.16067, 0);
      if (D.16068 != 0) goto <D.16069>; else goto <D.16070>;
      <D.16069>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-wsq.c", 66, "tmp_klass");
      <D.16070>:
      <D.16063>:
    }
    D.15998 = tmp_klass;
  }
  D.16071 = mono_class_vtable (root, D.15998);
  D.16072 = mono_array_new_specific (D.16071, 32);
  wsq->queue = D.16072;
  D.16073 = &wsq->lock;
  sem_init (D.16073, 0, 1);
  wsq_tlskey.7 = wsq_tlskey;
  D.16075 = mono_native_tls_set_value (wsq_tlskey.7, wsq);
  if (D.16075 == 0) goto <D.16076>; else goto <D.16077>;
  <D.16076>:
  mono_wsq_destroy (wsq);
  wsq = 0B;
  <D.16077>:
  D.16056 = wsq;
  return D.16056;
}


mono_native_tls_set_value (pthread_key_t key, void * value)
{
  int D.16079;
  int D.16080;
  _Bool D.16081;

  D.16080 = pthread_setspecific (key, value);
  D.16081 = D.16080 == 0;
  D.16079 = (int) D.16081;
  return D.16079;
}


mono_wsq_destroy (struct MonoWSQ * wsq)
{
  struct MonoArray * D.16086;
  int D.16087;
  _Bool D.16088;
  long int D.16089;
  long int D.16090;
  struct MonoArray * * D.16093;
  union MonoSemType * D.16094;
  int wsq_tlskey_inited.8;
  unsigned int wsq_tlskey.9;
  void * D.16099;

  if (wsq == 0B) goto <D.16083>; else goto <D.16085>;
  <D.16085>:
  D.16086 = wsq->queue;
  if (D.16086 == 0B) goto <D.16083>; else goto <D.16084>;
  <D.16083>:
  return;
  <D.16084>:
  D.16087 = mono_wsq_count (wsq);
  D.16088 = D.16087 != 0;
  D.16089 = (long int) D.16088;
  D.16090 = __builtin_expect (D.16089, 0);
  if (D.16090 != 0) goto <D.16091>; else goto <D.16092>;
  <D.16091>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-wsq.c", 81, "mono_wsq_count (wsq) == 0");
  <D.16092>:
  D.16093 = &wsq->queue;
  mono_gc_deregister_root (D.16093);
  D.16094 = &wsq->lock;
  sem_destroy (D.16094);
  memset (wsq, 0, 32);
  wsq_tlskey_inited.8 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.8 != 0) goto <D.16096>; else goto <D.16097>;
  <D.16096>:
  wsq_tlskey.9 = wsq_tlskey;
  D.16099 = pthread_getspecific (wsq_tlskey.9);
  if (D.16099 == wsq) goto <D.16100>; else goto <D.16101>;
  <D.16100>:
  wsq_tlskey.9 = wsq_tlskey;
  mono_native_tls_set_value (wsq_tlskey.9, 0B);
  <D.16101>:
  <D.16097>:
  monoeg_g_free (wsq);
}


memset (void * __dest, int __ch, size_t __len)
{
  int D.16105;
  int D.16110;
  void * D.16112;
  unsigned int D.16113;

  D.16105 = __builtin_constant_p (__len);
  if (D.16105 != 0) goto <D.16106>; else goto <D.16107>;
  <D.16106>:
  if (__len == 0) goto <D.16108>; else goto <D.16109>;
  <D.16108>:
  D.16110 = __builtin_constant_p (__ch);
  if (D.16110 == 0) goto <D.16103>; else goto <D.16111>;
  <D.16111>:
  if (__ch != 0) goto <D.16103>; else goto <D.16104>;
  <D.16103>:
  __warn_memset_zero_len ();
  D.16112 = __dest;
  return D.16112;
  <D.16104>:
  <D.16109>:
  <D.16107>:
  D.16113 = __builtin_object_size (__dest, 0);
  D.16112 = __builtin___memset_chk (__dest, __ch, __len, D.16113);
  return D.16112;
}


mono_wsq_count (struct MonoWSQ * wsq)
{
  gint D.16117;
  int D.16118;
  int D.16119;
  int D.16120;
  int D.16121;

  if (wsq == 0B) goto <D.16115>; else goto <D.16116>;
  <D.16115>:
  D.16117 = 0;
  return D.16117;
  <D.16116>:
  D.16118 = wsq->tail;
  D.16119 = wsq->head;
  D.16120 = D.16118 - D.16119;
  D.16121 = wsq->mask;
  D.16117 = D.16120 & D.16121;
  return D.16117;
}


mono_wsq_local_push (void * obj)
{
  int wsq_tlskey_inited.10;
  gboolean D.16127;
  unsigned int wsq_tlskey.11;
  int D.16131;
  int D.16132;
  int D.16133;
  struct MonoArray * D.16136;
  int D.16137;
  unsigned int D.16138;
  int D.16139;
  union MonoSemType * D.16140;
  int D.16141;
  int D.16142;
  unsigned int D.16145;
  struct MonoDomain * D.16146;
  struct MonoClass * D.16017;
  struct MonoClass * tmp_klass.12;
  struct MonoClass * D.16150;
  struct MonoClass * tmp_klass.13;
  _Bool D.16152;
  long int D.16153;
  long int D.16154;
  struct MonoVTable * D.16157;
  int D.16158;
  unsigned int D.16159;
  unsigned int i.14;
  int D.16161;
  int D.16162;
  unsigned int D.16163;
  char * D.16164;
  struct MonoObject * D.16165;
  char * D.16166;
  unsigned int length.15;
  unsigned int D.16168;
  int D.16169;
  int D.16170;
  int tail;
  int head;
  int count;
  struct MonoWSQ * wsq;

  if (obj == 0B) goto <D.16123>; else goto <D.16125>;
  <D.16125>:
  wsq_tlskey_inited.10 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.10 == 0) goto <D.16123>; else goto <D.16124>;
  <D.16123>:
  D.16127 = 0;
  return D.16127;
  <D.16124>:
  wsq_tlskey.11 = wsq_tlskey;
  wsq = pthread_getspecific (wsq_tlskey.11);
  if (wsq == 0B) goto <D.16129>; else goto <D.16130>;
  <D.16129>:
  D.16127 = 0;
  return D.16127;
  <D.16130>:
  tail = wsq->tail;
  D.16131 = wsq->head;
  D.16132 = wsq->mask;
  D.16133 = D.16131 + D.16132;
  if (D.16133 > tail) goto <D.16134>; else goto <D.16135>;
  <D.16134>:
  {
    void * * __p;

    D.16136 = wsq->queue;
    D.16132 = wsq->mask;
    D.16137 = D.16132 & tail;
    D.16138 = (unsigned int) D.16137;
    __p = mono_array_addr_with_size (D.16136, 4, D.16138);
    D.16136 = wsq->queue;
    mono_gc_wbarrier_set_arrayref (D.16136, __p, obj);
  }
  D.16139 = tail + 1;
  wsq->tail = D.16139;
  D.16127 = 1;
  return D.16127;
  <D.16135>:
  D.16140 = &wsq->lock;
  mono_sem_wait (D.16140, 0);
  head = wsq->head;
  D.16141 = wsq->tail;
  D.16142 = wsq->head;
  count = D.16141 - D.16142;
  D.16132 = wsq->mask;
  if (D.16132 <= count) goto <D.16143>; else goto <D.16144>;
  <D.16143>:
  {
    struct MonoArray * new_array;
    int length;
    int i;

    D.16136 = wsq->queue;
    D.16145 = mono_array_length (D.16136);
    length = (int) D.16145;
    D.16146 = mono_get_root_domain ();
    {
      static struct MonoClass * tmp_klass;

      {
        tmp_klass.12 = tmp_klass;
        if (tmp_klass.12 == 0B) goto <D.16148>; else goto <D.16149>;
        <D.16148>:
        D.16150 = mono_defaults.object_class;
        tmp_klass.13 = mono_array_class_get (D.16150, 1);
        tmp_klass = tmp_klass.13;
        tmp_klass.12 = tmp_klass;
        D.16152 = tmp_klass.12 == 0B;
        D.16153 = (long int) D.16152;
        D.16154 = __builtin_expect (D.16153, 0);
        if (D.16154 != 0) goto <D.16155>; else goto <D.16156>;
        <D.16155>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-wsq.c", 132, "tmp_klass");
        <D.16156>:
        <D.16149>:
      }
      D.16017 = tmp_klass;
    }
    D.16157 = mono_class_vtable (D.16146, D.16017);
    D.16158 = length * 2;
    D.16159 = (unsigned int) D.16158;
    new_array = mono_array_new_specific (D.16157, D.16159);
    i = 0;
    goto <D.16020>;
    <D.16019>:
    {
      void * * __p;

      i.14 = (unsigned int) i;
      __p = mono_array_addr_with_size (new_array, 4, i.14);
      D.16136 = wsq->queue;
      D.16161 = i + head;
      D.16132 = wsq->mask;
      D.16162 = D.16161 & D.16132;
      D.16163 = (unsigned int) D.16162;
      D.16164 = mono_array_addr_with_size (D.16136, 4, D.16163);
      D.16165 = MEM[(struct MonoObject * *)D.16164];
      mono_gc_wbarrier_set_arrayref (new_array, __p, D.16165);
    }
    i = i + 1;
    <D.16020>:
    if (i < length) goto <D.16019>; else goto <D.16021>;
    <D.16021>:
    D.16136 = wsq->queue;
    D.16166 = mono_array_addr_with_size (D.16136, 4, 0);
    length.15 = (unsigned int) length;
    D.16168 = length.15 * 4;
    mono_gc_bzero_aligned (D.16166, D.16168);
    wsq->queue = new_array;
    wsq->head = 0;
    tail = count;
    wsq->tail = tail;
    D.16132 = wsq->mask;
    D.16169 = D.16132 << 1;
    D.16170 = D.16169 | 1;
    wsq->mask = D.16170;
  }
  <D.16144>:
  {
    void * * __p;

    D.16136 = wsq->queue;
    D.16132 = wsq->mask;
    D.16137 = D.16132 & tail;
    D.16138 = (unsigned int) D.16137;
    __p = mono_array_addr_with_size (D.16136, 4, D.16138);
    D.16136 = wsq->queue;
    mono_gc_wbarrier_set_arrayref (D.16136, __p, obj);
  }
  D.16139 = tail + 1;
  wsq->tail = D.16139;
  D.16140 = &wsq->lock;
  mono_sem_post (D.16140);
  D.16127 = 1;
  return D.16127;
}


mono_wsq_local_pop (void * * ptr)
{
  int wsq_tlskey_inited.16;
  gboolean D.16176;
  unsigned int wsq_tlskey.17;
  int D.16180;
  volatile gint * D.16183;
  int D.16184;
  struct MonoArray * D.16187;
  int D.16188;
  int D.16189;
  unsigned int D.16190;
  char * D.16191;
  void * D.16192;
  union MonoSemType * D.16193;
  int D.16194;
  char * D.16197;
  void * D.16198;
  int D.16200;
  int tail;
  gboolean res;
  struct MonoWSQ * wsq;

  if (ptr == 0B) goto <D.16172>; else goto <D.16174>;
  <D.16174>:
  wsq_tlskey_inited.16 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.16 == 0) goto <D.16172>; else goto <D.16173>;
  <D.16172>:
  D.16176 = 0;
  return D.16176;
  <D.16173>:
  wsq_tlskey.17 = wsq_tlskey;
  wsq = pthread_getspecific (wsq_tlskey.17);
  if (wsq == 0B) goto <D.16178>; else goto <D.16179>;
  <D.16178>:
  D.16176 = 0;
  return D.16176;
  <D.16179>:
  tail = wsq->tail;
  D.16180 = wsq->head;
  if (D.16180 >= tail) goto <D.16181>; else goto <D.16182>;
  <D.16181>:
  D.16176 = 0;
  return D.16176;
  <D.16182>:
  tail = tail + -1;
  D.16183 = &wsq->tail;
  InterlockedExchange (D.16183, tail);
  D.16184 = wsq->head;
  if (D.16184 <= tail) goto <D.16185>; else goto <D.16186>;
  <D.16185>:
  D.16187 = wsq->queue;
  D.16188 = wsq->mask;
  D.16189 = D.16188 & tail;
  D.16190 = (unsigned int) D.16189;
  D.16191 = mono_array_addr_with_size (D.16187, 4, D.16190);
  D.16192 = MEM[(void * *)D.16191];
  *ptr = D.16192;
  {
    void * * __p;

    D.16187 = wsq->queue;
    D.16188 = wsq->mask;
    D.16189 = D.16188 & tail;
    D.16190 = (unsigned int) D.16189;
    __p = mono_array_addr_with_size (D.16187, 4, D.16190);
    *__p = 0B;
  }
  D.16176 = 1;
  return D.16176;
  <D.16186>:
  D.16193 = &wsq->lock;
  mono_sem_wait (D.16193, 0);
  D.16194 = wsq->head;
  if (D.16194 <= tail) goto <D.16195>; else goto <D.16196>;
  <D.16195>:
  D.16187 = wsq->queue;
  D.16188 = wsq->mask;
  D.16189 = D.16188 & tail;
  D.16190 = (unsigned int) D.16189;
  D.16197 = mono_array_addr_with_size (D.16187, 4, D.16190);
  D.16198 = MEM[(void * *)D.16197];
  *ptr = D.16198;
  {
    void * * __p;

    D.16187 = wsq->queue;
    D.16188 = wsq->mask;
    D.16189 = D.16188 & tail;
    D.16190 = (unsigned int) D.16189;
    __p = mono_array_addr_with_size (D.16187, 4, D.16190);
    *__p = 0B;
  }
  res = 1;
  goto <D.16199>;
  <D.16196>:
  D.16200 = tail + 1;
  wsq->tail = D.16200;
  res = 0;
  <D.16199>:
  D.16193 = &wsq->lock;
  mono_sem_post (D.16193);
  D.16176 = res;
  return D.16176;
}


InterlockedExchange (volatile gint32 * val, gint32 new_val)
{
  unsigned int old_val.18;
  unsigned int new_val.19;
  unsigned int D.16204;
  int D.16205;
  gint32 D.16206;
  gint32 old_val;

  <D.15885>:
  old_val = *val;
  old_val.18 = (unsigned int) old_val;
  new_val.19 = (unsigned int) new_val;
  D.16204 = __sync_val_compare_and_swap_4 (val, old_val.18, new_val.19);
  D.16205 = (int) D.16204;
  if (D.16205 != old_val) goto <D.15885>; else goto <D.15886>;
  <D.15886>:
  D.16206 = old_val;
  return D.16206;
}


mono_wsq_try_steal (struct MonoWSQ * wsq, void * * ptr, guint32 ms_timeout)
{
  void * D.16212;
  int wsq_tlskey_inited.20;
  unsigned int wsq_tlskey.21;
  void * D.16216;
  union MonoSemType * D.16219;
  int D.16220;
  volatile gint * D.16223;
  int D.16224;
  int D.16225;
  struct MonoArray * D.16228;
  int D.16229;
  int D.16230;
  unsigned int D.16231;
  char * D.16232;
  void * D.16233;

  if (wsq == 0B) goto <D.16208>; else goto <D.16210>;
  <D.16210>:
  if (ptr == 0B) goto <D.16208>; else goto <D.16211>;
  <D.16211>:
  D.16212 = *ptr;
  if (D.16212 != 0B) goto <D.16208>; else goto <D.16213>;
  <D.16213>:
  wsq_tlskey_inited.20 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.20 == 0) goto <D.16208>; else goto <D.16209>;
  <D.16208>:
  return;
  <D.16209>:
  wsq_tlskey.21 = wsq_tlskey;
  D.16216 = pthread_getspecific (wsq_tlskey.21);
  if (D.16216 == wsq) goto <D.16217>; else goto <D.16218>;
  <D.16217>:
  return;
  <D.16218>:
  D.16219 = &wsq->lock;
  D.16220 = mono_sem_timedwait (D.16219, ms_timeout, 0);
  if (D.16220 == 0) goto <D.16221>; else goto <D.16222>;
  <D.16221>:
  {
    int head;

    head = wsq->head;
    D.16223 = &wsq->head;
    D.16224 = head + 1;
    InterlockedExchange (D.16223, D.16224);
    D.16225 = wsq->tail;
    if (D.16225 > head) goto <D.16226>; else goto <D.16227>;
    <D.16226>:
    D.16228 = wsq->queue;
    D.16229 = wsq->mask;
    D.16230 = D.16229 & head;
    D.16231 = (unsigned int) D.16230;
    D.16232 = mono_array_addr_with_size (D.16228, 4, D.16231);
    D.16233 = MEM[(void * *)D.16232];
    *ptr = D.16233;
    {
      void * * __p;

      D.16228 = wsq->queue;
      D.16229 = wsq->mask;
      D.16230 = D.16229 & head;
      D.16231 = (unsigned int) D.16230;
      __p = mono_array_addr_with_size (D.16228, 4, D.16231);
      *__p = 0B;
    }
    goto <D.16234>;
    <D.16227>:
    wsq->head = head;
    <D.16234>:
    D.16219 = &wsq->lock;
    mono_sem_post (D.16219);
  }
  <D.16222>:
}


