__attribute__((visibility ("hidden")))
mono_cq_create ()
{
  struct MonoMList * * D.16578;
  void * D.16579;
  struct MonoMList * * D.16582;
  void * D.16583;
  struct MonoCQItem * D.16584;
  struct MonoMList * D.16585;
  struct MonoMList * D.16586;
  struct MonoCQ * D.16587;
  struct MonoCQ * cq;

  cq = monoeg_malloc0 (24);
  if (0 != 0) goto <D.16576>; else goto <D.16577>;
  <D.16576>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-cq.c", 70, "sizeof (cq->head) == sizeof (MonoObject*)");
  <D.16577>:
  D.16578 = &cq->head;
  D.16579 = mono_gc_make_root_descr_all_refs (1);
  mono_gc_register_root (D.16578, 8, D.16579);
  if (0 != 0) goto <D.16580>; else goto <D.16581>;
  <D.16580>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-cq.c", 71, "sizeof (cq->tail) == sizeof (MonoObject*)");
  <D.16581>:
  D.16582 = &cq->tail;
  D.16583 = mono_gc_make_root_descr_all_refs (1);
  mono_gc_register_root (D.16582, 8, D.16583);
  D.16584 = mono_cqitem_alloc ();
  D.16585 = mono_mlist_alloc (D.16584);
  cq->head = D.16585;
  D.16586 = cq->head;
  cq->tail = D.16586;
  D.16587 = cq;
  return D.16587;
}


mono_cqitem_alloc ()
{
  struct MonoVTable * monocq_item_vtable.0;
  struct MonoImage * D.16592;
  struct MonoVTable * D.16593;
  _Bool D.16594;
  long int D.16595;
  long int D.16596;
  struct MonoArray * * D.16599;
  struct MonoClass * D.16600;
  struct MonoArray * D.16601;
  struct MonoArray * * D.16602;
  struct MonoClass * D.16603;
  struct MonoArray * D.16604;
  struct MonoCQItem * D.16605;
  struct MonoCQItem * queue;
  struct MonoDomain * domain;

  domain = mono_get_root_domain ();
  monocq_item_vtable.0 = monocq_item_vtable;
  if (monocq_item_vtable.0 == 0B) goto <D.16590>; else goto <D.16591>;
  <D.16590>:
  {
    struct MonoClass * klass;

    D.16592 = mono_defaults.corlib;
    klass = mono_class_from_name (D.16592, "System", "MonoCQItem");
    D.16593 = mono_class_vtable (domain, klass);
    monocq_item_vtable = D.16593;
    monocq_item_vtable.0 = monocq_item_vtable;
    D.16594 = monocq_item_vtable.0 == 0B;
    D.16595 = (long int) D.16594;
    D.16596 = __builtin_expect (D.16595, 0);
    if (D.16596 != 0) goto <D.16597>; else goto <D.16598>;
    <D.16597>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-cq.c", 56, "monocq_item_vtable");
    <D.16598>:
  }
  <D.16591>:
  monocq_item_vtable.0 = monocq_item_vtable;
  queue = mono_object_new_fast (monocq_item_vtable.0);
  D.16599 = &queue->array;
  D.16600 = mono_defaults.object_class;
  D.16601 = mono_array_new (domain, D.16600, 64);
  mono_gc_wbarrier_set_field (queue, D.16599, D.16601);
  D.16602 = &queue->array_state;
  D.16603 = mono_defaults.byte_class;
  D.16604 = mono_array_new (domain, D.16603, 64);
  mono_gc_wbarrier_set_field (queue, D.16602, D.16604);
  D.16605 = queue;
  return D.16605;
}


__attribute__((visibility ("hidden")))
mono_cq_destroy (struct MonoCQ * cq)
{
  struct MonoMList * * D.16609;
  struct MonoMList * * D.16610;

  if (cq == 0B) goto <D.16607>; else goto <D.16608>;
  <D.16607>:
  return;
  <D.16608>:
  mono_gc_bzero_aligned (cq, 24);
  D.16609 = &cq->tail;
  mono_gc_deregister_root (D.16609);
  D.16610 = &cq->head;
  mono_gc_deregister_root (D.16610);
  monoeg_g_free (cq);
}


__attribute__((visibility ("hidden")))
mono_cq_count (struct MonoCQ * cq)
{
  gint D.16614;

  if (cq == 0B) goto <D.16612>; else goto <D.16613>;
  <D.16612>:
  D.16614 = 0;
  return D.16614;
  <D.16613>:
  D.16614 = cq->count;
  return D.16614;
}


__attribute__((visibility ("hidden")))
mono_cq_enqueue (struct MonoCQ * cq, struct MonoObject * obj)
{
  int D.16619;
  volatile gint32 * D.16622;

  if (cq == 0B) goto <D.16616>; else goto <D.16618>;
  <D.16618>:
  if (obj == 0B) goto <D.16616>; else goto <D.16617>;
  <D.16616>:
  return;
  <D.16617>:
  <D.16547>:
  D.16619 = mono_cqitem_try_enqueue (cq, obj);
  if (D.16619 != 0) goto <D.16620>; else goto <D.16621>;
  <D.16620>:
  D.16622 = &cq->count;
  InterlockedIncrement (D.16622);
  goto <D.16546>;
  <D.16621>:
  SleepEx (0, 0);
  goto <D.16547>;
  <D.16546>:
}


mono_cqitem_try_enqueue (struct MonoCQ * cq, struct MonoObject * obj)
{
  gboolean D.16626;
  volatile gint32 * D.16627;
  int D.16628;
  int D.16629;
  struct MonoArray * D.16632;
  double[0:] * D.16633;
  long unsigned int D.16634;
  long unsigned int D.16635;
  struct MonoArray * D.16636;
  double[0:] * D.16637;
  sizetype D.16638;
  struct MonoCQItem * queue;
  struct MonoMList * tail;
  gint32 pos;

  tail = cq->tail;
  queue = tail->data;
  <D.16541>:
  pos = queue->last;
  if (pos > 63) goto <D.16624>; else goto <D.16625>;
  <D.16624>:
  D.16626 = 0;
  return D.16626;
  <D.16625>:
  D.16627 = &queue->last;
  D.16628 = pos + 1;
  D.16629 = InterlockedCompareExchange (D.16627, D.16628, pos);
  if (D.16629 == pos) goto <D.16630>; else goto <D.16631>;
  <D.16630>:
  {
    void * * __p;

    D.16632 = queue->array;
    D.16633 = &D.16632->vector;
    D.16634 = (long unsigned int) pos;
    D.16635 = D.16634 * 8;
    __p = D.16633 + D.16635;
    D.16632 = queue->array;
    mono_gc_wbarrier_set_arrayref (D.16632, __p, obj);
  }
  {
    char * __p;

    D.16636 = queue->array_state;
    D.16637 = &D.16636->vector;
    D.16638 = (sizetype) pos;
    __p = D.16637 + D.16638;
    *__p = 1;
  }
  if (pos == 63) goto <D.16639>; else goto <D.16640>;
  <D.16639>:
  mono_cq_add_node (cq);
  <D.16640>:
  D.16626 = 1;
  return D.16626;
  <D.16631>:
  goto <D.16541>;
  monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "mono-cq.c", 145);
}


InterlockedCompareExchange (volatile gint32 * dest, gint32 exch, gint32 comp)
{
  gint32 D.16642;
  unsigned int comp.1;
  unsigned int exch.2;
  unsigned int D.16645;

  comp.1 = (unsigned int) comp;
  exch.2 = (unsigned int) exch;
  D.16645 = __sync_val_compare_and_swap_4 (dest, comp.1, exch.2);
  D.16642 = (gint32) D.16645;
  return D.16642;
}


mono_cq_add_node (struct MonoCQ * cq)
{
  struct MonoCQItem * D.16647;
  struct MonoMList * * D.16648;
  struct MonoMList * n;
  struct MonoMList * prev_tail;

  D.16647 = mono_cqitem_alloc ();
  n = mono_mlist_alloc (D.16647);
  prev_tail = cq->tail;
  D.16648 = &prev_tail->next;
  mono_gc_wbarrier_set_field (prev_tail, D.16648, n);
  cq->tail = n;
}


InterlockedIncrement (volatile gint32 * val)
{
  gint32 D.16649;
  unsigned int D.16650;

  D.16650 = __sync_add_and_fetch_4 (val, 1);
  D.16649 = (gint32) D.16650;
  return D.16649;
}


__attribute__((visibility ("hidden")))
mono_cq_dequeue (struct MonoCQ * cq, struct MonoObject * * result)
{
  int D.16652;
  volatile gint32 * D.16655;
  gboolean D.16656;
  int D.16657;

  goto <D.16573>;
  <D.16572>:
  D.16652 = mono_cqitem_try_dequeue (cq, result);
  if (D.16652 != 0) goto <D.16653>; else goto <D.16654>;
  <D.16653>:
  D.16655 = &cq->count;
  InterlockedDecrement (D.16655);
  D.16656 = 1;
  return D.16656;
  <D.16654>:
  SleepEx (0, 0);
  <D.16573>:
  D.16657 = cq->count;
  if (D.16657 > 0) goto <D.16572>; else goto <D.16574>;
  <D.16574>:
  D.16656 = 0;
  return D.16656;
}


mono_cqitem_try_dequeue (struct MonoCQ * cq, struct MonoObject * * obj)
{
  int D.16661;
  gboolean D.16663;
  volatile gint32 * D.16664;
  int D.16665;
  int D.16666;
  struct MonoArray * D.16669;
  long unsigned int D.16670;
  char * D.16671;
  char D.16672;
  struct MonoArray * D.16673;
  char * D.16674;
  struct MonoObject * D.16675;
  struct MonoCQItem * queue;
  struct MonoMList * head;
  gint32 pos;

  head = cq->head;
  queue = head->data;
  <D.16567>:
  pos = queue->first;
  D.16661 = queue->last;
  if (D.16661 <= pos) goto <D.16659>; else goto <D.16662>;
  <D.16662>:
  if (pos > 63) goto <D.16659>; else goto <D.16660>;
  <D.16659>:
  D.16663 = 0;
  return D.16663;
  <D.16660>:
  D.16664 = &queue->first;
  D.16665 = pos + 1;
  D.16666 = InterlockedCompareExchange (D.16664, D.16665, pos);
  if (D.16666 == pos) goto <D.16667>; else goto <D.16668>;
  <D.16667>:
  goto <D.16563>;
  <D.16562>:
  SleepEx (0, 0);
  <D.16563>:
  D.16669 = queue->array_state;
  D.16670 = (long unsigned int) pos;
  D.16671 = mono_array_addr_with_size (D.16669, 1, D.16670);
  D.16672 = *D.16671;
  if (D.16672 == 0) goto <D.16562>; else goto <D.16564>;
  <D.16564>:
  D.16673 = queue->array;
  D.16670 = (long unsigned int) pos;
  D.16674 = mono_array_addr_with_size (D.16673, 8, D.16670);
  D.16675 = MEM[(struct MonoObject * *)D.16674];
  *obj = D.16675;
  {
    struct MonoObject * * __p;

    D.16673 = queue->array;
    D.16670 = (long unsigned int) pos;
    __p = mono_array_addr_with_size (D.16673, 8, D.16670);
    *__p = 0B;
  }
  {
    char * __p;

    D.16669 = queue->array_state;
    D.16670 = (long unsigned int) pos;
    __p = mono_array_addr_with_size (D.16669, 1, D.16670);
    *__p = 0;
  }
  if (pos == 63) goto <D.16676>; else goto <D.16677>;
  <D.16676>:
  mono_cq_remove_node (cq);
  <D.16677>:
  D.16663 = 1;
  return D.16663;
  <D.16668>:
  goto <D.16567>;
  monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "mono-cq.c", 235);
}


mono_cq_remove_node (struct MonoCQ * cq)
{
  struct MonoMList * D.16679;
  struct MonoMList * old_head;

  old_head = cq->head;
  goto <D.16553>;
  <D.16552>:
  SleepEx (0, 0);
  <D.16553>:
  D.16679 = old_head->next;
  if (D.16679 == 0B) goto <D.16552>; else goto <D.16554>;
  <D.16554>:
  D.16679 = old_head->next;
  cq->head = D.16679;
  old_head = 0B;
}


InterlockedDecrement (volatile gint32 * val)
{
  gint32 D.16680;
  unsigned int D.16681;

  D.16681 = __sync_sub_and_fetch_4 (val, 1);
  D.16680 = (gint32) D.16681;
  return D.16680;
}


