mono_wsq_init ()
{
  int wsq_tlskey_inited.0;

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


mono_native_tls_alloc (pthread_key_t * key, void * destructor)
{
  int D.16427;
  void (*<Tc2>) (void *) destructor.1;
  int D.16429;
  _Bool D.16430;

  destructor.1 = (void (*<Tc2>) (void *)) destructor;
  D.16429 = pthread_key_create (key, destructor.1);
  D.16430 = D.16429 == 0;
  D.16427 = (int) D.16430;
  return D.16427;
}


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.16433>; else goto <D.16434>;
  <D.16433>:
  return;
  <D.16434>:
  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.16440;
  void * D.16443;
  struct MonoArray * * D.16444;
  struct MonoClass * D.16382;
  struct MonoClass * tmp_klass.5;
  struct MonoClass * D.16448;
  struct MonoClass * tmp_klass.6;
  _Bool D.16450;
  long int D.16451;
  long int D.16452;
  struct MonoVTable * D.16455;
  struct MonoArray * D.16456;
  union MonoSemType * D.16457;
  unsigned int wsq_tlskey.7;
  int D.16459;
  struct MonoWSQ * wsq;
  struct MonoDomain * root;

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

    {
      tmp_klass.5 = tmp_klass;
      if (tmp_klass.5 == 0B) goto <D.16446>; else goto <D.16447>;
      <D.16446>:
      D.16448 = mono_defaults.object_class;
      tmp_klass.6 = mono_array_class_get (D.16448, 1);
      tmp_klass = tmp_klass.6;
      tmp_klass.5 = tmp_klass;
      D.16450 = tmp_klass.5 == 0B;
      D.16451 = (long int) D.16450;
      D.16452 = __builtin_expect (D.16451, 0);
      if (D.16452 != 0) goto <D.16453>; else goto <D.16454>;
      <D.16453>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-wsq.c", 66, "tmp_klass");
      <D.16454>:
      <D.16447>:
    }
    D.16382 = tmp_klass;
  }
  D.16455 = mono_class_vtable (root, D.16382);
  D.16456 = mono_array_new_specific (D.16455, 32);
  wsq->queue = D.16456;
  D.16457 = &wsq->lock;
  sem_init (D.16457, 0, 1);
  wsq_tlskey.7 = wsq_tlskey;
  D.16459 = mono_native_tls_set_value (wsq_tlskey.7, wsq);
  if (D.16459 == 0) goto <D.16460>; else goto <D.16461>;
  <D.16460>:
  mono_wsq_destroy (wsq);
  wsq = 0B;
  <D.16461>:
  D.16440 = wsq;
  return D.16440;
}


mono_native_tls_set_value (pthread_key_t key, void * value)
{
  int D.16463;
  int D.16464;
  _Bool D.16465;

  D.16464 = pthread_setspecific (key, value);
  D.16465 = D.16464 == 0;
  D.16463 = (int) D.16465;
  return D.16463;
}


mono_wsq_destroy (struct MonoWSQ * wsq)
{
  struct MonoArray * D.16470;
  int D.16471;
  _Bool D.16472;
  long int D.16473;
  long int D.16474;
  struct MonoArray * * D.16477;
  union MonoSemType * D.16478;
  int wsq_tlskey_inited.8;
  unsigned int wsq_tlskey.9;
  void * D.16483;

  if (wsq == 0B) goto <D.16467>; else goto <D.16469>;
  <D.16469>:
  D.16470 = wsq->queue;
  if (D.16470 == 0B) goto <D.16467>; else goto <D.16468>;
  <D.16467>:
  return;
  <D.16468>:
  D.16471 = mono_wsq_count (wsq);
  D.16472 = D.16471 != 0;
  D.16473 = (long int) D.16472;
  D.16474 = __builtin_expect (D.16473, 0);
  if (D.16474 != 0) goto <D.16475>; else goto <D.16476>;
  <D.16475>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-wsq.c", 81, "mono_wsq_count (wsq) == 0");
  <D.16476>:
  D.16477 = &wsq->queue;
  mono_gc_deregister_root (D.16477);
  D.16478 = &wsq->lock;
  sem_destroy (D.16478);
  memset (wsq, 0, 56);
  wsq_tlskey_inited.8 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.8 != 0) goto <D.16480>; else goto <D.16481>;
  <D.16480>:
  wsq_tlskey.9 = wsq_tlskey;
  D.16483 = pthread_getspecific (wsq_tlskey.9);
  if (D.16483 == wsq) goto <D.16484>; else goto <D.16485>;
  <D.16484>:
  wsq_tlskey.9 = wsq_tlskey;
  mono_native_tls_set_value (wsq_tlskey.9, 0B);
  <D.16485>:
  <D.16481>:
  monoeg_g_free (wsq);
}


memset (void * __dest, int __ch, size_t __len)
{
  int D.16489;
  int D.16494;
  void * D.16496;
  long unsigned int D.16497;

  D.16489 = __builtin_constant_p (__len);
  if (D.16489 != 0) goto <D.16490>; else goto <D.16491>;
  <D.16490>:
  if (__len == 0) goto <D.16492>; else goto <D.16493>;
  <D.16492>:
  D.16494 = __builtin_constant_p (__ch);
  if (D.16494 == 0) goto <D.16487>; else goto <D.16495>;
  <D.16495>:
  if (__ch != 0) goto <D.16487>; else goto <D.16488>;
  <D.16487>:
  __warn_memset_zero_len ();
  D.16496 = __dest;
  return D.16496;
  <D.16488>:
  <D.16493>:
  <D.16491>:
  D.16497 = __builtin_object_size (__dest, 0);
  D.16496 = __builtin___memset_chk (__dest, __ch, __len, D.16497);
  return D.16496;
}


mono_wsq_count (struct MonoWSQ * wsq)
{
  gint D.16501;
  int D.16502;
  int D.16503;
  int D.16504;
  int D.16505;

  if (wsq == 0B) goto <D.16499>; else goto <D.16500>;
  <D.16499>:
  D.16501 = 0;
  return D.16501;
  <D.16500>:
  D.16502 = wsq->tail;
  D.16503 = wsq->head;
  D.16504 = D.16502 - D.16503;
  D.16505 = wsq->mask;
  D.16501 = D.16504 & D.16505;
  return D.16501;
}


mono_wsq_local_push (void * obj)
{
  int wsq_tlskey_inited.10;
  gboolean D.16511;
  unsigned int wsq_tlskey.11;
  int D.16515;
  int D.16516;
  int D.16517;
  int D.16520;
  long unsigned int D.16521;
  struct MonoArray * D.16522;
  int D.16523;
  union MonoSemType * D.16524;
  int D.16525;
  int D.16526;
  long unsigned int D.16529;
  int D.16530;
  long unsigned int D.16531;
  struct MonoClass * D.16401;
  struct MonoClass * tmp_klass.12;
  struct MonoClass * D.16535;
  struct MonoClass * tmp_klass.13;
  _Bool D.16537;
  long int D.16538;
  long int D.16539;
  struct MonoDomain * D.16542;
  struct MonoVTable * D.16543;
  long unsigned int D.16544;
  int D.16545;
  int D.16546;
  long unsigned int D.16547;
  char * D.16548;
  struct MonoObject * D.16549;
  long unsigned int D.16550;
  long unsigned int D.16551;
  char * D.16552;
  int D.16553;
  int D.16554;
  int tail;
  int head;
  int count;
  struct MonoWSQ * wsq;

  if (obj == 0B) goto <D.16507>; else goto <D.16509>;
  <D.16509>:
  wsq_tlskey_inited.10 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.10 == 0) goto <D.16507>; else goto <D.16508>;
  <D.16507>:
  D.16511 = 0;
  return D.16511;
  <D.16508>:
  wsq_tlskey.11 = wsq_tlskey;
  wsq = pthread_getspecific (wsq_tlskey.11);
  if (wsq == 0B) goto <D.16513>; else goto <D.16514>;
  <D.16513>:
  D.16511 = 0;
  return D.16511;
  <D.16514>:
  tail = wsq->tail;
  D.16515 = wsq->head;
  D.16516 = wsq->mask;
  D.16517 = D.16515 + D.16516;
  if (D.16517 > tail) goto <D.16518>; else goto <D.16519>;
  <D.16518>:
  {
    void * * __p;

    D.16516 = wsq->mask;
    D.16520 = D.16516 & tail;
    D.16521 = (long unsigned int) D.16520;
    D.16522 = wsq->queue;
    __p = mono_array_addr_with_size (D.16522, 8, D.16521);
    D.16522 = wsq->queue;
    mono_gc_wbarrier_set_arrayref (D.16522, __p, obj);
  }
  D.16523 = tail + 1;
  wsq->tail = D.16523;
  D.16511 = 1;
  return D.16511;
  <D.16519>:
  D.16524 = &wsq->lock;
  mono_sem_wait (D.16524, 0);
  head = wsq->head;
  D.16525 = wsq->tail;
  D.16526 = wsq->head;
  count = D.16525 - D.16526;
  D.16516 = wsq->mask;
  if (D.16516 <= count) goto <D.16527>; else goto <D.16528>;
  <D.16527>:
  {
    struct MonoArray * new_array;
    int length;
    int i;

    D.16522 = wsq->queue;
    D.16529 = mono_array_length (D.16522);
    length = (int) D.16529;
    D.16530 = length * 2;
    D.16531 = (long unsigned int) D.16530;
    {
      static struct MonoClass * tmp_klass;

      {
        tmp_klass.12 = tmp_klass;
        if (tmp_klass.12 == 0B) goto <D.16533>; else goto <D.16534>;
        <D.16533>:
        D.16535 = mono_defaults.object_class;
        tmp_klass.13 = mono_array_class_get (D.16535, 1);
        tmp_klass = tmp_klass.13;
        tmp_klass.12 = tmp_klass;
        D.16537 = tmp_klass.12 == 0B;
        D.16538 = (long int) D.16537;
        D.16539 = __builtin_expect (D.16538, 0);
        if (D.16539 != 0) goto <D.16540>; else goto <D.16541>;
        <D.16540>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-wsq.c", 132, "tmp_klass");
        <D.16541>:
        <D.16534>:
      }
      D.16401 = tmp_klass;
    }
    D.16542 = mono_get_root_domain ();
    D.16543 = mono_class_vtable (D.16542, D.16401);
    new_array = mono_array_new_specific (D.16543, D.16531);
    i = 0;
    goto <D.16404>;
    <D.16403>:
    {
      void * * __p;

      D.16544 = (long unsigned int) i;
      __p = mono_array_addr_with_size (new_array, 8, D.16544);
      D.16545 = i + head;
      D.16516 = wsq->mask;
      D.16546 = D.16545 & D.16516;
      D.16547 = (long unsigned int) D.16546;
      D.16522 = wsq->queue;
      D.16548 = mono_array_addr_with_size (D.16522, 8, D.16547);
      D.16549 = MEM[(struct MonoObject * *)D.16548];
      mono_gc_wbarrier_set_arrayref (new_array, __p, D.16549);
    }
    i = i + 1;
    <D.16404>:
    if (i < length) goto <D.16403>; else goto <D.16405>;
    <D.16405>:
    D.16550 = (long unsigned int) length;
    D.16551 = D.16550 * 8;
    D.16522 = wsq->queue;
    D.16552 = mono_array_addr_with_size (D.16522, 8, 0);
    mono_gc_bzero_aligned (D.16552, D.16551);
    wsq->queue = new_array;
    wsq->head = 0;
    tail = count;
    wsq->tail = tail;
    D.16516 = wsq->mask;
    D.16553 = D.16516 << 1;
    D.16554 = D.16553 | 1;
    wsq->mask = D.16554;
  }
  <D.16528>:
  {
    void * * __p;

    D.16516 = wsq->mask;
    D.16520 = D.16516 & tail;
    D.16521 = (long unsigned int) D.16520;
    D.16522 = wsq->queue;
    __p = mono_array_addr_with_size (D.16522, 8, D.16521);
    D.16522 = wsq->queue;
    mono_gc_wbarrier_set_arrayref (D.16522, __p, obj);
  }
  D.16523 = tail + 1;
  wsq->tail = D.16523;
  D.16524 = &wsq->lock;
  mono_sem_post (D.16524);
  D.16511 = 1;
  return D.16511;
}


mono_wsq_local_pop (void * * ptr)
{
  int wsq_tlskey_inited.14;
  gboolean D.16560;
  unsigned int wsq_tlskey.15;
  int D.16564;
  volatile gint * D.16567;
  int D.16568;
  int D.16571;
  int D.16572;
  long unsigned int D.16573;
  struct MonoArray * D.16574;
  char * D.16575;
  void * D.16576;
  union MonoSemType * D.16577;
  int D.16578;
  char * D.16581;
  void * D.16582;
  int D.16584;
  int tail;
  gboolean res;
  struct MonoWSQ * wsq;

  if (ptr == 0B) goto <D.16556>; else goto <D.16558>;
  <D.16558>:
  wsq_tlskey_inited.14 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.14 == 0) goto <D.16556>; else goto <D.16557>;
  <D.16556>:
  D.16560 = 0;
  return D.16560;
  <D.16557>:
  wsq_tlskey.15 = wsq_tlskey;
  wsq = pthread_getspecific (wsq_tlskey.15);
  if (wsq == 0B) goto <D.16562>; else goto <D.16563>;
  <D.16562>:
  D.16560 = 0;
  return D.16560;
  <D.16563>:
  tail = wsq->tail;
  D.16564 = wsq->head;
  if (D.16564 >= tail) goto <D.16565>; else goto <D.16566>;
  <D.16565>:
  D.16560 = 0;
  return D.16560;
  <D.16566>:
  tail = tail + -1;
  D.16567 = &wsq->tail;
  InterlockedExchange (D.16567, tail);
  D.16568 = wsq->head;
  if (D.16568 <= tail) goto <D.16569>; else goto <D.16570>;
  <D.16569>:
  D.16571 = wsq->mask;
  D.16572 = D.16571 & tail;
  D.16573 = (long unsigned int) D.16572;
  D.16574 = wsq->queue;
  D.16575 = mono_array_addr_with_size (D.16574, 8, D.16573);
  D.16576 = MEM[(void * *)D.16575];
  *ptr = D.16576;
  {
    void * * __p;

    D.16571 = wsq->mask;
    D.16572 = D.16571 & tail;
    D.16573 = (long unsigned int) D.16572;
    D.16574 = wsq->queue;
    __p = mono_array_addr_with_size (D.16574, 8, D.16573);
    *__p = 0B;
  }
  D.16560 = 1;
  return D.16560;
  <D.16570>:
  D.16577 = &wsq->lock;
  mono_sem_wait (D.16577, 0);
  D.16578 = wsq->head;
  if (D.16578 <= tail) goto <D.16579>; else goto <D.16580>;
  <D.16579>:
  D.16571 = wsq->mask;
  D.16572 = D.16571 & tail;
  D.16573 = (long unsigned int) D.16572;
  D.16574 = wsq->queue;
  D.16581 = mono_array_addr_with_size (D.16574, 8, D.16573);
  D.16582 = MEM[(void * *)D.16581];
  *ptr = D.16582;
  {
    void * * __p;

    D.16571 = wsq->mask;
    D.16572 = D.16571 & tail;
    D.16573 = (long unsigned int) D.16572;
    D.16574 = wsq->queue;
    __p = mono_array_addr_with_size (D.16574, 8, D.16573);
    *__p = 0B;
  }
  res = 1;
  goto <D.16583>;
  <D.16580>:
  D.16584 = tail + 1;
  wsq->tail = D.16584;
  res = 0;
  <D.16583>:
  D.16577 = &wsq->lock;
  mono_sem_post (D.16577);
  D.16560 = res;
  return D.16560;
}


InterlockedExchange (volatile gint32 * val, gint32 new_val)
{
  unsigned int new_val.16;
  unsigned int old_val.17;
  unsigned int D.16588;
  int D.16589;
  gint32 D.16590;
  gint32 old_val;

  <D.16283>:
  old_val = *val;
  new_val.16 = (unsigned int) new_val;
  old_val.17 = (unsigned int) old_val;
  D.16588 = __sync_val_compare_and_swap_4 (val, old_val.17, new_val.16);
  D.16589 = (int) D.16588;
  if (D.16589 != old_val) goto <D.16283>; else goto <D.16284>;
  <D.16284>:
  D.16590 = old_val;
  return D.16590;
}


mono_wsq_try_steal (struct MonoWSQ * wsq, void * * ptr, guint32 ms_timeout)
{
  _Bool D.16594;
  _Bool D.16595;
  _Bool D.16596;
  void * D.16598;
  int wsq_tlskey_inited.18;
  unsigned int wsq_tlskey.19;
  void * D.16602;
  union MonoSemType * D.16605;
  int D.16606;
  int D.16609;
  volatile gint * D.16610;
  int D.16611;
  int D.16614;
  int D.16615;
  long unsigned int D.16616;
  struct MonoArray * D.16617;
  char * D.16618;
  void * D.16619;

  D.16594 = wsq == 0B;
  D.16595 = ptr == 0B;
  D.16596 = D.16594 | D.16595;
  if (D.16596 != 0) goto <D.16592>; else goto <D.16597>;
  <D.16597>:
  D.16598 = *ptr;
  if (D.16598 != 0B) goto <D.16592>; else goto <D.16599>;
  <D.16599>:
  wsq_tlskey_inited.18 = wsq_tlskey_inited;
  if (wsq_tlskey_inited.18 == 0) goto <D.16592>; else goto <D.16593>;
  <D.16592>:
  return;
  <D.16593>:
  wsq_tlskey.19 = wsq_tlskey;
  D.16602 = pthread_getspecific (wsq_tlskey.19);
  if (D.16602 == wsq) goto <D.16603>; else goto <D.16604>;
  <D.16603>:
  return;
  <D.16604>:
  D.16605 = &wsq->lock;
  D.16606 = mono_sem_timedwait (D.16605, ms_timeout, 0);
  if (D.16606 == 0) goto <D.16607>; else goto <D.16608>;
  <D.16607>:
  {
    int head;

    head = wsq->head;
    D.16609 = head + 1;
    D.16610 = &wsq->head;
    InterlockedExchange (D.16610, D.16609);
    D.16611 = wsq->tail;
    if (D.16611 > head) goto <D.16612>; else goto <D.16613>;
    <D.16612>:
    D.16614 = wsq->mask;
    D.16615 = D.16614 & head;
    D.16616 = (long unsigned int) D.16615;
    D.16617 = wsq->queue;
    D.16618 = mono_array_addr_with_size (D.16617, 8, D.16616);
    D.16619 = MEM[(void * *)D.16618];
    *ptr = D.16619;
    {
      void * * __p;

      D.16614 = wsq->mask;
      D.16615 = D.16614 & head;
      D.16616 = (long unsigned int) D.16615;
      D.16617 = wsq->queue;
      __p = mono_array_addr_with_size (D.16617, 8, D.16616);
      *__p = 0B;
    }
    goto <D.16620>;
    <D.16613>:
    wsq->head = head;
    <D.16620>:
    D.16605 = &wsq->lock;
    mono_sem_post (D.16605);
  }
  <D.16608>:
}


