mono_cq_create ()
{
  struct MonoMList * * D.18635;
  void * D.18636;
  struct MonoMList * * D.18639;
  void * D.18640;
  struct MonoCQItem * D.18641;
  struct MonoMList * D.18642;
  struct MonoMList * D.18643;
  struct MonoCQ * D.18644;
  struct MonoCQ * cq;

  cq = monoeg_malloc0 (12);
  if (0 != 0) goto <D.18633>; else goto <D.18634>;
  <D.18633>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-cq.c", 70, "sizeof (cq->head) == sizeof (MonoObject*)");
  <D.18634>:
  D.18635 = &cq->head;
  D.18636 = mono_gc_make_root_descr_all_refs (1);
  mono_gc_register_root (D.18635, 4, D.18636);
  if (0 != 0) goto <D.18637>; else goto <D.18638>;
  <D.18637>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-cq.c", 71, "sizeof (cq->tail) == sizeof (MonoObject*)");
  <D.18638>:
  D.18639 = &cq->tail;
  D.18640 = mono_gc_make_root_descr_all_refs (1);
  mono_gc_register_root (D.18639, 4, D.18640);
  D.18641 = mono_cqitem_alloc ();
  D.18642 = mono_mlist_alloc (D.18641);
  cq->head = D.18642;
  D.18643 = cq->head;
  cq->tail = D.18643;
  D.18644 = cq;
  return D.18644;
}


mono_cqitem_alloc ()
{
  struct MonoVTable * monocq_item_vtable.0;
  struct MonoImage * D.18649;
  struct MonoVTable * monocq_item_vtable.1;
  _Bool D.18651;
  long int D.18652;
  long int D.18653;
  struct MonoArray * * D.18656;
  struct MonoClass * D.18657;
  struct MonoArray * D.18658;
  struct MonoArray * * D.18659;
  struct MonoClass * D.18660;
  struct MonoArray * D.18661;
  struct MonoCQItem * D.18662;
  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.18647>; else goto <D.18648>;
  <D.18647>:
  {
    struct MonoClass * klass;

    D.18649 = mono_defaults.corlib;
    klass = mono_class_from_name (D.18649, "System", "MonoCQItem");
    monocq_item_vtable.1 = mono_class_vtable (domain, klass);
    monocq_item_vtable = monocq_item_vtable.1;
    monocq_item_vtable.0 = monocq_item_vtable;
    D.18651 = monocq_item_vtable.0 == 0B;
    D.18652 = (long int) D.18651;
    D.18653 = __builtin_expect (D.18652, 0);
    if (D.18653 != 0) goto <D.18654>; else goto <D.18655>;
    <D.18654>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-cq.c", 56, "monocq_item_vtable");
    <D.18655>:
  }
  <D.18648>:
  monocq_item_vtable.0 = monocq_item_vtable;
  queue = mono_object_new_fast (monocq_item_vtable.0);
  D.18656 = &queue->array;
  D.18657 = mono_defaults.object_class;
  D.18658 = mono_array_new (domain, D.18657, 64);
  mono_gc_wbarrier_set_field (queue, D.18656, D.18658);
  D.18659 = &queue->array_state;
  D.18660 = mono_defaults.byte_class;
  D.18661 = mono_array_new (domain, D.18660, 64);
  mono_gc_wbarrier_set_field (queue, D.18659, D.18661);
  D.18662 = queue;
  return D.18662;
}


mono_cq_destroy (struct MonoCQ * cq)
{
  struct MonoMList * * D.18666;
  struct MonoMList * * D.18667;

  if (cq == 0B) goto <D.18664>; else goto <D.18665>;
  <D.18664>:
  return;
  <D.18665>:
  mono_gc_bzero_aligned (cq, 12);
  D.18666 = &cq->tail;
  mono_gc_deregister_root (D.18666);
  D.18667 = &cq->head;
  mono_gc_deregister_root (D.18667);
  monoeg_g_free (cq);
}


mono_cq_count (struct MonoCQ * cq)
{
  gint D.18671;

  if (cq == 0B) goto <D.18669>; else goto <D.18670>;
  <D.18669>:
  D.18671 = 0;
  return D.18671;
  <D.18670>:
  D.18671 = cq->count;
  return D.18671;
}


mono_cq_enqueue (struct MonoCQ * cq, struct MonoObject * obj)
{
  _Bool D.18673;
  _Bool D.18674;
  _Bool D.18675;
  int D.18678;
  volatile gint32 * D.18681;

  D.18673 = cq == 0B;
  D.18674 = obj == 0B;
  D.18675 = D.18673 | D.18674;
  if (D.18675 != 0) goto <D.18676>; else goto <D.18677>;
  <D.18676>:
  return;
  <D.18677>:
  <D.18602>:
  D.18678 = mono_cqitem_try_enqueue (cq, obj);
  if (D.18678 != 0) goto <D.18679>; else goto <D.18680>;
  <D.18679>:
  D.18681 = &cq->count;
  InterlockedIncrement (D.18681);
  goto <D.18601>;
  <D.18680>:
  SleepEx (0, 0);
  goto <D.18602>;
  <D.18601>:
}


mono_cqitem_try_enqueue (struct MonoCQ * cq, struct MonoObject * obj)
{
  gboolean D.18685;
  volatile gint32 * D.18686;
  int D.18687;
  int D.18688;
  struct MonoArray * D.18691;
  double[0:] * D.18692;
  unsigned int pos.2;
  unsigned int D.18694;
  struct MonoArray * D.18695;
  double[0:] * D.18696;
  sizetype pos.3;
  struct MonoCQItem * queue;
  struct MonoMList * tail;
  gint32 pos;

  tail = cq->tail;
  queue = tail->data;
  <D.18596>:
  pos = queue->last;
  if (pos > 63) goto <D.18683>; else goto <D.18684>;
  <D.18683>:
  D.18685 = 0;
  return D.18685;
  <D.18684>:
  D.18686 = &queue->last;
  D.18687 = pos + 1;
  D.18688 = InterlockedCompareExchange (D.18686, D.18687, pos);
  if (D.18688 == pos) goto <D.18689>; else goto <D.18690>;
  <D.18689>:
  {
    void * * __p;

    D.18691 = queue->array;
    D.18692 = &D.18691->vector;
    pos.2 = (unsigned int) pos;
    D.18694 = pos.2 * 4;
    __p = D.18692 + D.18694;
    D.18691 = queue->array;
    mono_gc_wbarrier_set_arrayref (D.18691, __p, obj);
  }
  mono_memory_write_barrier ();
  {
    char * __p;

    D.18695 = queue->array_state;
    D.18696 = &D.18695->vector;
    pos.3 = (sizetype) pos;
    __p = D.18696 + pos.3;
    *__p = 1;
  }
  if (pos == 63) goto <D.18698>; else goto <D.18699>;
  <D.18698>:
  mono_cq_add_node (cq);
  <D.18699>:
  D.18685 = 1;
  return D.18685;
  <D.18690>:
  goto <D.18596>;
  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.18701;
  unsigned int comp.4;
  unsigned int exch.5;
  unsigned int D.18704;

  comp.4 = (unsigned int) comp;
  exch.5 = (unsigned int) exch;
  D.18704 = __sync_val_compare_and_swap_4 (dest, comp.4, exch.5);
  D.18701 = (gint32) D.18704;
  return D.18701;
}


mono_memory_write_barrier ()
{
  mono_memory_barrier ();
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


mono_cq_add_node (struct MonoCQ * cq)
{
  struct MonoCQItem * D.18706;
  struct MonoMList * * D.18707;
  struct MonoMList * n;
  struct MonoMList * prev_tail;

  D.18706 = mono_cqitem_alloc ();
  n = mono_mlist_alloc (D.18706);
  prev_tail = cq->tail;
  D.18707 = &prev_tail->next;
  mono_gc_wbarrier_set_field (prev_tail, D.18707, n);
  mono_memory_write_barrier ();
  cq->tail = n;
}


InterlockedIncrement (volatile gint32 * val)
{
  gint32 D.18708;
  unsigned int D.18709;

  D.18709 = __sync_add_and_fetch_4 (val, 1);
  D.18708 = (gint32) D.18709;
  return D.18708;
}


mono_cq_dequeue (struct MonoCQ * cq, struct MonoObject * * result)
{
  int D.18711;
  volatile gint32 * D.18714;
  gboolean D.18715;
  int D.18716;

  goto <D.18628>;
  <D.18627>:
  D.18711 = mono_cqitem_try_dequeue (cq, result);
  if (D.18711 != 0) goto <D.18712>; else goto <D.18713>;
  <D.18712>:
  D.18714 = &cq->count;
  InterlockedDecrement (D.18714);
  D.18715 = 1;
  return D.18715;
  <D.18713>:
  SleepEx (0, 0);
  <D.18628>:
  D.18716 = cq->count;
  if (D.18716 > 0) goto <D.18627>; else goto <D.18629>;
  <D.18629>:
  D.18715 = 0;
  return D.18715;
}


mono_cqitem_try_dequeue (struct MonoCQ * cq, struct MonoObject * * obj)
{
  int D.18720;
  gboolean D.18722;
  volatile gint32 * D.18723;
  int D.18724;
  int D.18725;
  struct MonoArray * D.18728;
  unsigned int pos.6;
  char * D.18730;
  char D.18731;
  struct MonoArray * D.18732;
  char * D.18733;
  struct MonoObject * D.18734;
  struct MonoCQItem * queue;
  struct MonoMList * head;
  gint32 pos;

  head = cq->head;
  queue = head->data;
  <D.18622>:
  pos = queue->first;
  D.18720 = queue->last;
  if (D.18720 <= pos) goto <D.18718>; else goto <D.18721>;
  <D.18721>:
  if (pos > 63) goto <D.18718>; else goto <D.18719>;
  <D.18718>:
  D.18722 = 0;
  return D.18722;
  <D.18719>:
  D.18723 = &queue->first;
  D.18724 = pos + 1;
  D.18725 = InterlockedCompareExchange (D.18723, D.18724, pos);
  if (D.18725 == pos) goto <D.18726>; else goto <D.18727>;
  <D.18726>:
  goto <D.18618>;
  <D.18617>:
  SleepEx (0, 0);
  <D.18618>:
  D.18728 = queue->array_state;
  pos.6 = (unsigned int) pos;
  D.18730 = mono_array_addr_with_size (D.18728, 1, pos.6);
  D.18731 = *D.18730;
  if (D.18731 == 0) goto <D.18617>; else goto <D.18619>;
  <D.18619>:
  mono_memory_read_barrier ();
  D.18732 = queue->array;
  pos.6 = (unsigned int) pos;
  D.18733 = mono_array_addr_with_size (D.18732, 4, pos.6);
  D.18734 = MEM[(struct MonoObject * *)D.18733];
  *obj = D.18734;
  {
    struct MonoObject * * __p;

    D.18732 = queue->array;
    pos.6 = (unsigned int) pos;
    __p = mono_array_addr_with_size (D.18732, 4, pos.6);
    *__p = 0B;
  }
  {
    char * __p;

    D.18728 = queue->array_state;
    pos.6 = (unsigned int) pos;
    __p = mono_array_addr_with_size (D.18728, 1, pos.6);
    *__p = 0;
  }
  if (pos == 63) goto <D.18735>; else goto <D.18736>;
  <D.18735>:
  mono_cq_remove_node (cq);
  <D.18736>:
  D.18722 = 1;
  return D.18722;
  <D.18727>:
  goto <D.18622>;
  monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "mono-cq.c", 235);
}


mono_memory_read_barrier ()
{
  mono_memory_barrier ();
}


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

  old_head = cq->head;
  goto <D.18608>;
  <D.18607>:
  SleepEx (0, 0);
  <D.18608>:
  D.18738 = old_head->next;
  if (D.18738 == 0B) goto <D.18607>; else goto <D.18609>;
  <D.18609>:
  D.18738 = old_head->next;
  cq->head = D.18738;
  old_head = 0B;
}


InterlockedDecrement (volatile gint32 * val)
{
  gint32 D.18739;
  unsigned int D.18740;

  D.18740 = __sync_sub_and_fetch_4 (val, 1);
  D.18739 = (gint32) D.18740;
  return D.18739;
}


