mono_cq_create ()
{
  void * D.16070;
  struct MonoMList * * D.16071;
  void * D.16074;
  struct MonoMList * * D.16075;
  struct MonoCQItem * D.16076;
  struct MonoMList * D.16077;
  struct MonoMList * D.16078;
  struct MonoCQ * D.16079;
  struct MonoCQ * cq;

  cq = monoeg_malloc0 (12);
  if (0 != 0) goto <D.16068>; else goto <D.16069>;
  <D.16068>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-cq.c", 70, "sizeof (cq->head) == sizeof (MonoObject*)");
  <D.16069>:
  D.16070 = mono_gc_make_root_descr_all_refs (1);
  D.16071 = &cq->head;
  mono_gc_register_root (D.16071, 4, D.16070);
  if (0 != 0) goto <D.16072>; else goto <D.16073>;
  <D.16072>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-cq.c", 71, "sizeof (cq->tail) == sizeof (MonoObject*)");
  <D.16073>:
  D.16074 = mono_gc_make_root_descr_all_refs (1);
  D.16075 = &cq->tail;
  mono_gc_register_root (D.16075, 4, D.16074);
  D.16076 = mono_cqitem_alloc ();
  D.16077 = mono_mlist_alloc (D.16076);
  cq->head = D.16077;
  D.16078 = cq->head;
  cq->tail = D.16078;
  D.16079 = cq;
  return D.16079;
}


mono_cqitem_alloc ()
{
  struct MonoVTable * monocq_item_vtable.0;
  struct MonoImage * D.16084;
  struct MonoVTable * monocq_item_vtable.1;
  _Bool D.16086;
  long int D.16087;
  long int D.16088;
  struct MonoClass * D.16091;
  struct MonoArray * D.16092;
  struct MonoArray * * D.16093;
  struct MonoClass * D.16094;
  struct MonoArray * D.16095;
  struct MonoArray * * D.16096;
  struct MonoCQItem * D.16097;
  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.16082>; else goto <D.16083>;
  <D.16082>:
  {
    struct MonoClass * klass;

    D.16084 = mono_defaults.corlib;
    klass = mono_class_from_name (D.16084, "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.16086 = monocq_item_vtable.0 == 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-cq.c", 56, "monocq_item_vtable");
    <D.16090>:
  }
  <D.16083>:
  monocq_item_vtable.0 = monocq_item_vtable;
  queue = mono_object_new_fast (monocq_item_vtable.0);
  D.16091 = mono_defaults.object_class;
  D.16092 = mono_array_new (domain, D.16091, 64);
  D.16093 = &queue->array;
  mono_gc_wbarrier_set_field (queue, D.16093, D.16092);
  D.16094 = mono_defaults.byte_class;
  D.16095 = mono_array_new (domain, D.16094, 64);
  D.16096 = &queue->array_state;
  mono_gc_wbarrier_set_field (queue, D.16096, D.16095);
  D.16097 = queue;
  return D.16097;
}


mono_cq_destroy (struct MonoCQ * cq)
{
  struct MonoMList * * D.16101;
  struct MonoMList * * D.16102;

  if (cq == 0B) goto <D.16099>; else goto <D.16100>;
  <D.16099>:
  return;
  <D.16100>:
  mono_gc_bzero_aligned (cq, 12);
  D.16101 = &cq->tail;
  mono_gc_deregister_root (D.16101);
  D.16102 = &cq->head;
  mono_gc_deregister_root (D.16102);
  monoeg_g_free (cq);
}


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

  if (cq == 0B) goto <D.16104>; else goto <D.16105>;
  <D.16104>:
  D.16106 = 0;
  return D.16106;
  <D.16105>:
  D.16106 = cq->count;
  return D.16106;
}


mono_cq_enqueue (struct MonoCQ * cq, struct MonoObject * obj)
{
  _Bool D.16108;
  _Bool D.16109;
  _Bool D.16110;
  int D.16113;
  volatile gint32 * D.16116;

  D.16108 = cq == 0B;
  D.16109 = obj == 0B;
  D.16110 = D.16108 | D.16109;
  if (D.16110 != 0) goto <D.16111>; else goto <D.16112>;
  <D.16111>:
  return;
  <D.16112>:
  <D.16039>:
  D.16113 = mono_cqitem_try_enqueue (cq, obj);
  if (D.16113 != 0) goto <D.16114>; else goto <D.16115>;
  <D.16114>:
  D.16116 = &cq->count;
  InterlockedIncrement (D.16116);
  goto <D.16038>;
  <D.16115>:
  SleepEx (0, 0);
  goto <D.16039>;
  <D.16038>:
}


mono_cqitem_try_enqueue (struct MonoCQ * cq, struct MonoObject * obj)
{
  gboolean D.16120;
  int D.16121;
  volatile gint32 * D.16122;
  int D.16123;
  struct MonoArray * D.16126;
  double[0:] * D.16127;
  unsigned int pos.2;
  unsigned int D.16129;
  struct MonoArray * D.16130;
  double[0:] * D.16131;
  sizetype pos.3;
  struct MonoCQItem * queue;
  struct MonoMList * tail;
  gint32 pos;

  tail = cq->tail;
  queue = tail->data;
  <D.16033>:
  pos = queue->last;
  if (pos > 63) goto <D.16118>; else goto <D.16119>;
  <D.16118>:
  D.16120 = 0;
  return D.16120;
  <D.16119>:
  D.16121 = pos + 1;
  D.16122 = &queue->last;
  D.16123 = InterlockedCompareExchange (D.16122, D.16121, pos);
  if (D.16123 == pos) goto <D.16124>; else goto <D.16125>;
  <D.16124>:
  {
    void * * __p;

    D.16126 = queue->array;
    D.16127 = &D.16126->vector;
    pos.2 = (unsigned int) pos;
    D.16129 = pos.2 * 4;
    __p = D.16127 + D.16129;
    D.16126 = queue->array;
    mono_gc_wbarrier_set_arrayref (D.16126, __p, obj);
  }
  {
    char * __p;

    D.16130 = queue->array_state;
    D.16131 = &D.16130->vector;
    pos.3 = (sizetype) pos;
    __p = D.16131 + pos.3;
    *__p = 1;
  }
  if (pos == 63) goto <D.16133>; else goto <D.16134>;
  <D.16133>:
  mono_cq_add_node (cq);
  <D.16134>:
  D.16120 = 1;
  return D.16120;
  <D.16125>:
  goto <D.16033>;
  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.16136;
  unsigned int exch.4;
  unsigned int comp.5;
  unsigned int D.16139;

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


mono_cq_add_node (struct MonoCQ * cq)
{
  struct MonoCQItem * D.16141;
  struct MonoMList * * D.16142;
  struct MonoMList * n;
  struct MonoMList * prev_tail;

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


InterlockedIncrement (volatile gint32 * val)
{
  gint32 D.16143;
  unsigned int D.16144;

  D.16144 = __sync_add_and_fetch_4 (val, 1);
  D.16143 = (gint32) D.16144;
  return D.16143;
}


mono_cq_dequeue (struct MonoCQ * cq, struct MonoObject * * result)
{
  int D.16146;
  volatile gint32 * D.16149;
  gboolean D.16150;
  int D.16151;

  goto <D.16065>;
  <D.16064>:
  D.16146 = mono_cqitem_try_dequeue (cq, result);
  if (D.16146 != 0) goto <D.16147>; else goto <D.16148>;
  <D.16147>:
  D.16149 = &cq->count;
  InterlockedDecrement (D.16149);
  D.16150 = 1;
  return D.16150;
  <D.16148>:
  SleepEx (0, 0);
  <D.16065>:
  D.16151 = cq->count;
  if (D.16151 > 0) goto <D.16064>; else goto <D.16066>;
  <D.16066>:
  D.16150 = 0;
  return D.16150;
}


mono_cqitem_try_dequeue (struct MonoCQ * cq, struct MonoObject * * obj)
{
  int D.16155;
  gboolean D.16157;
  int D.16158;
  volatile gint32 * D.16159;
  int D.16160;
  unsigned int pos.6;
  struct MonoArray * D.16164;
  char * D.16165;
  char D.16166;
  struct MonoArray * D.16167;
  char * D.16168;
  struct MonoObject * D.16169;
  struct MonoCQItem * queue;
  struct MonoMList * head;
  gint32 pos;

  head = cq->head;
  queue = head->data;
  <D.16059>:
  pos = queue->first;
  D.16155 = queue->last;
  if (D.16155 <= pos) goto <D.16153>; else goto <D.16156>;
  <D.16156>:
  if (pos > 63) goto <D.16153>; else goto <D.16154>;
  <D.16153>:
  D.16157 = 0;
  return D.16157;
  <D.16154>:
  D.16158 = pos + 1;
  D.16159 = &queue->first;
  D.16160 = InterlockedCompareExchange (D.16159, D.16158, pos);
  if (D.16160 == pos) goto <D.16161>; else goto <D.16162>;
  <D.16161>:
  goto <D.16055>;
  <D.16054>:
  SleepEx (0, 0);
  <D.16055>:
  pos.6 = (unsigned int) pos;
  D.16164 = queue->array_state;
  D.16165 = mono_array_addr_with_size (D.16164, 1, pos.6);
  D.16166 = *D.16165;
  if (D.16166 == 0) goto <D.16054>; else goto <D.16056>;
  <D.16056>:
  pos.6 = (unsigned int) pos;
  D.16167 = queue->array;
  D.16168 = mono_array_addr_with_size (D.16167, 4, pos.6);
  D.16169 = MEM[(struct MonoObject * *)D.16168];
  *obj = D.16169;
  {
    struct MonoObject * * __p;

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

    pos.6 = (unsigned int) pos;
    D.16164 = queue->array_state;
    __p = mono_array_addr_with_size (D.16164, 1, pos.6);
    *__p = 0;
  }
  if (pos == 63) goto <D.16170>; else goto <D.16171>;
  <D.16170>:
  mono_cq_remove_node (cq);
  <D.16171>:
  D.16157 = 1;
  return D.16157;
  <D.16162>:
  goto <D.16059>;
  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.16173;
  struct MonoMList * old_head;

  old_head = cq->head;
  goto <D.16045>;
  <D.16044>:
  SleepEx (0, 0);
  <D.16045>:
  D.16173 = old_head->next;
  if (D.16173 == 0B) goto <D.16044>; else goto <D.16046>;
  <D.16046>:
  D.16173 = old_head->next;
  cq->head = D.16173;
  old_head = 0B;
}


InterlockedDecrement (volatile gint32 * val)
{
  gint32 D.16174;
  unsigned int D.16175;

  D.16175 = __sync_sub_and_fetch_4 (val, 1);
  D.16174 = (gint32) D.16175;
  return D.16174;
}


