mono_wsq_init ()
{
  int wsq_tlskey_inited.0;

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


mono_native_tls_alloc (pthread_key_t * key, void * destructor)
{
  int D.16063;
  void (*<Tbf>) (void *) destructor.1;
  int D.16065;
  _Bool D.16066;

  destructor.1 = (void (*<Tbf>) (void *)) destructor;
  D.16065 = pthread_key_create (key, destructor.1);
  D.16066 = D.16065 == 0;
  D.16063 = (int) D.16066;
  return D.16063;
}


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.16069>; else goto <D.16070>;
  <D.16069>:
  return;
  <D.16070>:
  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.16076;
  void * D.16079;
  struct MonoArray * * D.16080;
  struct MonoClass * D.16018;
  struct MonoClass * tmp_klass.5;
  struct MonoClass * D.16084;
  struct MonoClass * tmp_klass.6;
  _Bool D.16086;
  long int D.16087;
  long int D.16088;
  struct MonoVTable * D.16091;
  struct MonoArray * D.16092;
  union MonoSemType * D.16093;
  unsigned int wsq_tlskey.7;
  int D.16095;
  struct MonoWSQ * wsq;
  struct MonoDomain * root;

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

    {
      tmp_klass.5 = tmp_klass;
      if (tmp_klass.5 == 0B) goto <D.16082>; else goto <D.16083>;
      <D.16082>:
      D.16084 = mono_defaults.object_class;
      tmp_klass.6 = mono_array_class_get (D.16084, 1);
      tmp_klass = tmp_klass.6;
      tmp_klass.5 = tmp_klass;
      D.16086 = tmp_klass.5 == 0B;
      D.16087 = (long int) D.16086;
      D.16088 = __builtin_expect (D.16087, 0);
      if (D.16088 != 0) goto <D.16089>; else goto <D.16090>;
      <D.16089>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-wsq.c", 66, "tmp_klass");
      <D.16090>:
      <D.16083>:
    }
    D.16018 = tmp_klass;
  }
  D.16091 = mono_class_vtable (root, D.16018);
  D.16092 = mono_array_new_specific (D.16091, 32);
  wsq->queue = D.16092;
  D.16093 = &wsq->lock;
  sem_init (D.16093, 0, 1);
  wsq_tlskey.7 = wsq_tlskey;
  D.16095 = mono_native_tls_set_value (wsq_tlskey.7, wsq);
  if (D.16095 == 0) goto <D.16096>; else goto <D.16097>;
  <D.16096>:
  mono_wsq_destroy (wsq);
  wsq = 0B;
  <D.16097>:
  D.16076 = wsq;
  return D.16076;
}


mono_native_tls_set_value (pthread_key_t key, void * value)
{
  int D.16099;
  int D.16100;
  _Bool D.16101;

  D.16100 = pthread_setspecific (key, value);
  D.16101 = D.16100 == 0;
  D.16099 = (int) D.16101;
  return D.16099;
}


mono_wsq_destroy (struct MonoWSQ * wsq)
{
  struct MonoArray * D.16106;
  int D.16107;
  _Bool D.16108;
  long int D.16109;
  long int D.16110;
  struct MonoArray * * D.16113;
  union MonoSemType * D.16114;
  int wsq_tlskey_inited.8;
  unsigned int wsq_tlskey.9;
  void * D.16119;

  if (wsq == 0B) goto <D.16103>; else goto <D.16105>;
  <D.16105>:
  D.16106 = wsq->queue;
  if (D.16106 == 0B) goto <D.16103>; else goto <D.16104>;
  <D.16103>:
  return;
  <D.16104>:
  D.16107 = mono_wsq_count (wsq);
  D.16108 = D.16107 != 0;
  D.16109 = (long int) D.16108;
  D.16110 = __builtin_expect (D.16109, 0);
  if (D.16110 != 0) goto <D.16111>; else goto <D.16112>;
  <D.16111>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-wsq.c", 81, "mono_wsq_count (wsq) == 0");
  <D.16112>:
  D.16113 = &wsq->queue;
  mono_gc_deregister_root (D.16113);
  D.16114 = &wsq->lock;
  sem_destroy (D.16114);
  memset (wsq, 0, 32);
  wsq_tlskey_inited.8 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.8 != 0) goto <D.16116>; else goto <D.16117>;
  <D.16116>:
  wsq_tlskey.9 = wsq_tlskey;
  D.16119 = pthread_getspecific (wsq_tlskey.9);
  if (D.16119 == wsq) goto <D.16120>; else goto <D.16121>;
  <D.16120>:
  wsq_tlskey.9 = wsq_tlskey;
  mono_native_tls_set_value (wsq_tlskey.9, 0B);
  <D.16121>:
  <D.16117>:
  monoeg_g_free (wsq);
}


memset (void * __dest, int __ch, size_t __len)
{
  int D.16125;
  int D.16130;
  void * D.16132;
  unsigned int D.16133;

  D.16125 = __builtin_constant_p (__len);
  if (D.16125 != 0) goto <D.16126>; else goto <D.16127>;
  <D.16126>:
  if (__len == 0) goto <D.16128>; else goto <D.16129>;
  <D.16128>:
  D.16130 = __builtin_constant_p (__ch);
  if (D.16130 == 0) goto <D.16123>; else goto <D.16131>;
  <D.16131>:
  if (__ch != 0) goto <D.16123>; else goto <D.16124>;
  <D.16123>:
  __warn_memset_zero_len ();
  D.16132 = __dest;
  return D.16132;
  <D.16124>:
  <D.16129>:
  <D.16127>:
  D.16133 = __builtin_object_size (__dest, 0);
  D.16132 = __builtin___memset_chk (__dest, __ch, __len, D.16133);
  return D.16132;
}


mono_wsq_count (struct MonoWSQ * wsq)
{
  gint D.16137;
  int D.16138;
  int D.16139;
  int D.16140;
  int D.16141;

  if (wsq == 0B) goto <D.16135>; else goto <D.16136>;
  <D.16135>:
  D.16137 = 0;
  return D.16137;
  <D.16136>:
  D.16138 = wsq->tail;
  D.16139 = wsq->head;
  D.16140 = D.16138 - D.16139;
  D.16141 = wsq->mask;
  D.16137 = D.16140 & D.16141;
  return D.16137;
}


mono_wsq_local_push (void * obj)
{
  int wsq_tlskey_inited.10;
  gboolean D.16147;
  unsigned int wsq_tlskey.11;
  int D.16151;
  int D.16152;
  int D.16153;
  int D.16156;
  unsigned int D.16157;
  struct MonoArray * D.16158;
  int D.16159;
  union MonoSemType * D.16160;
  int D.16161;
  int D.16162;
  unsigned int D.16165;
  int D.16166;
  unsigned int D.16167;
  struct MonoClass * D.16037;
  struct MonoClass * tmp_klass.12;
  struct MonoClass * D.16171;
  struct MonoClass * tmp_klass.13;
  _Bool D.16173;
  long int D.16174;
  long int D.16175;
  struct MonoDomain * D.16178;
  struct MonoVTable * D.16179;
  unsigned int i.14;
  int D.16181;
  int D.16182;
  unsigned int D.16183;
  char * D.16184;
  struct MonoObject * D.16185;
  unsigned int length.15;
  unsigned int D.16187;
  char * D.16188;
  int D.16189;
  int D.16190;
  int tail;
  int head;
  int count;
  struct MonoWSQ * wsq;

  if (obj == 0B) goto <D.16143>; else goto <D.16145>;
  <D.16145>:
  wsq_tlskey_inited.10 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.10 == 0) goto <D.16143>; else goto <D.16144>;
  <D.16143>:
  D.16147 = 0;
  return D.16147;
  <D.16144>:
  wsq_tlskey.11 = wsq_tlskey;
  wsq = pthread_getspecific (wsq_tlskey.11);
  if (wsq == 0B) goto <D.16149>; else goto <D.16150>;
  <D.16149>:
  D.16147 = 0;
  return D.16147;
  <D.16150>:
  tail = wsq->tail;
  D.16151 = wsq->head;
  D.16152 = wsq->mask;
  D.16153 = D.16151 + D.16152;
  if (D.16153 > tail) goto <D.16154>; else goto <D.16155>;
  <D.16154>:
  {
    void * * __p;

    D.16152 = wsq->mask;
    D.16156 = D.16152 & tail;
    D.16157 = (unsigned int) D.16156;
    D.16158 = wsq->queue;
    __p = mono_array_addr_with_size (D.16158, 4, D.16157);
    D.16158 = wsq->queue;
    mono_gc_wbarrier_set_arrayref (D.16158, __p, obj);
  }
  D.16159 = tail + 1;
  wsq->tail = D.16159;
  D.16147 = 1;
  return D.16147;
  <D.16155>:
  D.16160 = &wsq->lock;
  mono_sem_wait (D.16160, 0);
  head = wsq->head;
  D.16161 = wsq->tail;
  D.16162 = wsq->head;
  count = D.16161 - D.16162;
  D.16152 = wsq->mask;
  if (D.16152 <= count) goto <D.16163>; else goto <D.16164>;
  <D.16163>:
  {
    struct MonoArray * new_array;
    int length;
    int i;

    D.16158 = wsq->queue;
    D.16165 = mono_array_length (D.16158);
    length = (int) D.16165;
    D.16166 = length * 2;
    D.16167 = (unsigned int) D.16166;
    {
      static struct MonoClass * tmp_klass;

      {
        tmp_klass.12 = tmp_klass;
        if (tmp_klass.12 == 0B) goto <D.16169>; else goto <D.16170>;
        <D.16169>:
        D.16171 = mono_defaults.object_class;
        tmp_klass.13 = mono_array_class_get (D.16171, 1);
        tmp_klass = tmp_klass.13;
        tmp_klass.12 = tmp_klass;
        D.16173 = tmp_klass.12 == 0B;
        D.16174 = (long int) D.16173;
        D.16175 = __builtin_expect (D.16174, 0);
        if (D.16175 != 0) goto <D.16176>; else goto <D.16177>;
        <D.16176>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-wsq.c", 132, "tmp_klass");
        <D.16177>:
        <D.16170>:
      }
      D.16037 = tmp_klass;
    }
    D.16178 = mono_get_root_domain ();
    D.16179 = mono_class_vtable (D.16178, D.16037);
    new_array = mono_array_new_specific (D.16179, D.16167);
    i = 0;
    goto <D.16040>;
    <D.16039>:
    {
      void * * __p;

      i.14 = (unsigned int) i;
      __p = mono_array_addr_with_size (new_array, 4, i.14);
      D.16181 = i + head;
      D.16152 = wsq->mask;
      D.16182 = D.16181 & D.16152;
      D.16183 = (unsigned int) D.16182;
      D.16158 = wsq->queue;
      D.16184 = mono_array_addr_with_size (D.16158, 4, D.16183);
      D.16185 = MEM[(struct MonoObject * *)D.16184];
      mono_gc_wbarrier_set_arrayref (new_array, __p, D.16185);
    }
    i = i + 1;
    <D.16040>:
    if (i < length) goto <D.16039>; else goto <D.16041>;
    <D.16041>:
    length.15 = (unsigned int) length;
    D.16187 = length.15 * 4;
    D.16158 = wsq->queue;
    D.16188 = mono_array_addr_with_size (D.16158, 4, 0);
    mono_gc_bzero_aligned (D.16188, D.16187);
    wsq->queue = new_array;
    wsq->head = 0;
    tail = count;
    wsq->tail = tail;
    D.16152 = wsq->mask;
    D.16189 = D.16152 << 1;
    D.16190 = D.16189 | 1;
    wsq->mask = D.16190;
  }
  <D.16164>:
  {
    void * * __p;

    D.16152 = wsq->mask;
    D.16156 = D.16152 & tail;
    D.16157 = (unsigned int) D.16156;
    D.16158 = wsq->queue;
    __p = mono_array_addr_with_size (D.16158, 4, D.16157);
    D.16158 = wsq->queue;
    mono_gc_wbarrier_set_arrayref (D.16158, __p, obj);
  }
  D.16159 = tail + 1;
  wsq->tail = D.16159;
  D.16160 = &wsq->lock;
  mono_sem_post (D.16160);
  D.16147 = 1;
  return D.16147;
}


mono_wsq_local_pop (void * * ptr)
{
  int wsq_tlskey_inited.16;
  gboolean D.16196;
  unsigned int wsq_tlskey.17;
  int D.16200;
  volatile gint * D.16203;
  int D.16204;
  int D.16207;
  int D.16208;
  unsigned int D.16209;
  struct MonoArray * D.16210;
  char * D.16211;
  void * D.16212;
  union MonoSemType * D.16213;
  int D.16214;
  char * D.16217;
  void * D.16218;
  int D.16220;
  int tail;
  gboolean res;
  struct MonoWSQ * wsq;

  if (ptr == 0B) goto <D.16192>; else goto <D.16194>;
  <D.16194>:
  wsq_tlskey_inited.16 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.16 == 0) goto <D.16192>; else goto <D.16193>;
  <D.16192>:
  D.16196 = 0;
  return D.16196;
  <D.16193>:
  wsq_tlskey.17 = wsq_tlskey;
  wsq = pthread_getspecific (wsq_tlskey.17);
  if (wsq == 0B) goto <D.16198>; else goto <D.16199>;
  <D.16198>:
  D.16196 = 0;
  return D.16196;
  <D.16199>:
  tail = wsq->tail;
  D.16200 = wsq->head;
  if (D.16200 >= tail) goto <D.16201>; else goto <D.16202>;
  <D.16201>:
  D.16196 = 0;
  return D.16196;
  <D.16202>:
  tail = tail + -1;
  D.16203 = &wsq->tail;
  InterlockedExchange (D.16203, tail);
  D.16204 = wsq->head;
  if (D.16204 <= tail) goto <D.16205>; else goto <D.16206>;
  <D.16205>:
  D.16207 = wsq->mask;
  D.16208 = D.16207 & tail;
  D.16209 = (unsigned int) D.16208;
  D.16210 = wsq->queue;
  D.16211 = mono_array_addr_with_size (D.16210, 4, D.16209);
  D.16212 = MEM[(void * *)D.16211];
  *ptr = D.16212;
  {
    void * * __p;

    D.16207 = wsq->mask;
    D.16208 = D.16207 & tail;
    D.16209 = (unsigned int) D.16208;
    D.16210 = wsq->queue;
    __p = mono_array_addr_with_size (D.16210, 4, D.16209);
    *__p = 0B;
  }
  D.16196 = 1;
  return D.16196;
  <D.16206>:
  D.16213 = &wsq->lock;
  mono_sem_wait (D.16213, 0);
  D.16214 = wsq->head;
  if (D.16214 <= tail) goto <D.16215>; else goto <D.16216>;
  <D.16215>:
  D.16207 = wsq->mask;
  D.16208 = D.16207 & tail;
  D.16209 = (unsigned int) D.16208;
  D.16210 = wsq->queue;
  D.16217 = mono_array_addr_with_size (D.16210, 4, D.16209);
  D.16218 = MEM[(void * *)D.16217];
  *ptr = D.16218;
  {
    void * * __p;

    D.16207 = wsq->mask;
    D.16208 = D.16207 & tail;
    D.16209 = (unsigned int) D.16208;
    D.16210 = wsq->queue;
    __p = mono_array_addr_with_size (D.16210, 4, D.16209);
    *__p = 0B;
  }
  res = 1;
  goto <D.16219>;
  <D.16216>:
  D.16220 = tail + 1;
  wsq->tail = D.16220;
  res = 0;
  <D.16219>:
  D.16213 = &wsq->lock;
  mono_sem_post (D.16213);
  D.16196 = res;
  return D.16196;
}


InterlockedExchange (volatile gint32 * val, gint32 new_val)
{
  unsigned int new_val.18;
  unsigned int old_val.19;
  unsigned int D.16224;
  int D.16225;
  gint32 D.16226;
  gint32 old_val;

  <D.15919>:
  old_val = *val;
  new_val.18 = (unsigned int) new_val;
  old_val.19 = (unsigned int) old_val;
  D.16224 = __sync_val_compare_and_swap_4 (val, old_val.19, new_val.18);
  D.16225 = (int) D.16224;
  if (D.16225 != old_val) goto <D.15919>; else goto <D.15920>;
  <D.15920>:
  D.16226 = old_val;
  return D.16226;
}


mono_wsq_try_steal (struct MonoWSQ * wsq, void * * ptr, guint32 ms_timeout)
{
  _Bool D.16230;
  _Bool D.16231;
  _Bool D.16232;
  void * D.16234;
  int wsq_tlskey_inited.20;
  unsigned int wsq_tlskey.21;
  void * D.16238;
  union MonoSemType * D.16241;
  int D.16242;
  int D.16245;
  volatile gint * D.16246;
  int D.16247;
  int D.16250;
  int D.16251;
  unsigned int D.16252;
  struct MonoArray * D.16253;
  char * D.16254;
  void * D.16255;

  D.16230 = wsq == 0B;
  D.16231 = ptr == 0B;
  D.16232 = D.16230 | D.16231;
  if (D.16232 != 0) goto <D.16228>; else goto <D.16233>;
  <D.16233>:
  D.16234 = *ptr;
  if (D.16234 != 0B) goto <D.16228>; else goto <D.16235>;
  <D.16235>:
  wsq_tlskey_inited.20 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.20 == 0) goto <D.16228>; else goto <D.16229>;
  <D.16228>:
  return;
  <D.16229>:
  wsq_tlskey.21 = wsq_tlskey;
  D.16238 = pthread_getspecific (wsq_tlskey.21);
  if (D.16238 == wsq) goto <D.16239>; else goto <D.16240>;
  <D.16239>:
  return;
  <D.16240>:
  D.16241 = &wsq->lock;
  D.16242 = mono_sem_timedwait (D.16241, ms_timeout, 0);
  if (D.16242 == 0) goto <D.16243>; else goto <D.16244>;
  <D.16243>:
  {
    int head;

    head = wsq->head;
    D.16245 = head + 1;
    D.16246 = &wsq->head;
    InterlockedExchange (D.16246, D.16245);
    D.16247 = wsq->tail;
    if (D.16247 > head) goto <D.16248>; else goto <D.16249>;
    <D.16248>:
    D.16250 = wsq->mask;
    D.16251 = D.16250 & head;
    D.16252 = (unsigned int) D.16251;
    D.16253 = wsq->queue;
    D.16254 = mono_array_addr_with_size (D.16253, 4, D.16252);
    D.16255 = MEM[(void * *)D.16254];
    *ptr = D.16255;
    {
      void * * __p;

      D.16250 = wsq->mask;
      D.16251 = D.16250 & head;
      D.16252 = (unsigned int) D.16251;
      D.16253 = wsq->queue;
      __p = mono_array_addr_with_size (D.16253, 4, D.16252);
      *__p = 0B;
    }
    goto <D.16256>;
    <D.16249>:
    wsq->head = head;
    <D.16256>:
    D.16241 = &wsq->lock;
    mono_sem_post (D.16241);
  }
  <D.16244>:
}


