mono_cq_create ()
{
  struct MonoMList * * D.16050;
  void * D.16051;
  struct MonoMList * * D.16054;
  void * D.16055;
  struct MonoCQItem * D.16056;
  struct MonoMList * D.16057;
  struct MonoMList * D.16058;
  struct MonoCQ * D.16059;
  struct MonoCQ * cq;

  cq = monoeg_malloc0 (12);
  if (0 != 0) goto <D.16048>; else goto <D.16049>;
  <D.16048>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-cq.c", 70, "sizeof (cq->head) == sizeof (MonoObject*)");
  <D.16049>:
  D.16050 = &cq->head;
  D.16051 = mono_gc_make_root_descr_all_refs (1);
  mono_gc_register_root (D.16050, 4, D.16051);
  if (0 != 0) goto <D.16052>; else goto <D.16053>;
  <D.16052>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-cq.c", 71, "sizeof (cq->tail) == sizeof (MonoObject*)");
  <D.16053>:
  D.16054 = &cq->tail;
  D.16055 = mono_gc_make_root_descr_all_refs (1);
  mono_gc_register_root (D.16054, 4, D.16055);
  D.16056 = mono_cqitem_alloc ();
  D.16057 = mono_mlist_alloc (D.16056);
  cq->head = D.16057;
  D.16058 = cq->head;
  cq->tail = D.16058;
  D.16059 = cq;
  return D.16059;
}


mono_cqitem_alloc ()
{
  struct MonoVTable * monocq_item_vtable.0;
  struct MonoImage * D.16064;
  struct MonoVTable * monocq_item_vtable.1;
  _Bool D.16066;
  long int D.16067;
  long int D.16068;
  struct MonoArray * * D.16071;
  struct MonoClass * D.16072;
  struct MonoArray * D.16073;
  struct MonoArray * * D.16074;
  struct MonoClass * D.16075;
  struct MonoArray * D.16076;
  struct MonoCQItem * D.16077;
  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.16062>; else goto <D.16063>;
  <D.16062>:
  {
    struct MonoClass * klass;

    D.16064 = mono_defaults.corlib;
    klass = mono_class_from_name (D.16064, "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.16066 = monocq_item_vtable.0 == 0B;
    D.16067 = (long int) D.16066;
    D.16068 = __builtin_expect (D.16067, 0);
    if (D.16068 != 0) goto <D.16069>; else goto <D.16070>;
    <D.16069>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-cq.c", 56, "monocq_item_vtable");
    <D.16070>:
  }
  <D.16063>:
  monocq_item_vtable.0 = monocq_item_vtable;
  queue = mono_object_new_fast (monocq_item_vtable.0);
  D.16071 = &queue->array;
  D.16072 = mono_defaults.object_class;
  D.16073 = mono_array_new (domain, D.16072, 64);
  mono_gc_wbarrier_set_field (queue, D.16071, D.16073);
  D.16074 = &queue->array_state;
  D.16075 = mono_defaults.byte_class;
  D.16076 = mono_array_new (domain, D.16075, 64);
  mono_gc_wbarrier_set_field (queue, D.16074, D.16076);
  D.16077 = queue;
  return D.16077;
}


mono_cq_destroy (struct MonoCQ * cq)
{
  struct MonoMList * * D.16081;
  struct MonoMList * * D.16082;

  if (cq == 0B) goto <D.16079>; else goto <D.16080>;
  <D.16079>:
  return;
  <D.16080>:
  mono_gc_bzero_aligned (cq, 12);
  D.16081 = &cq->tail;
  mono_gc_deregister_root (D.16081);
  D.16082 = &cq->head;
  mono_gc_deregister_root (D.16082);
  monoeg_g_free (cq);
}


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

  if (cq == 0B) goto <D.16084>; else goto <D.16085>;
  <D.16084>:
  D.16086 = 0;
  return D.16086;
  <D.16085>:
  D.16086 = cq->count;
  return D.16086;
}


mono_cq_enqueue (struct MonoCQ * cq, struct MonoObject * obj)
{
  int D.16091;
  volatile gint32 * D.16094;

  if (cq == 0B) goto <D.16088>; else goto <D.16090>;
  <D.16090>:
  if (obj == 0B) goto <D.16088>; else goto <D.16089>;
  <D.16088>:
  return;
  <D.16089>:
  <D.16019>:
  D.16091 = mono_cqitem_try_enqueue (cq, obj);
  if (D.16091 != 0) goto <D.16092>; else goto <D.16093>;
  <D.16092>:
  D.16094 = &cq->count;
  InterlockedIncrement (D.16094);
  goto <D.16018>;
  <D.16093>:
  SleepEx (0, 0);
  goto <D.16019>;
  <D.16018>:
}


mono_cqitem_try_enqueue (struct MonoCQ * cq, struct MonoObject * obj)
{
  gboolean D.16098;
  volatile gint32 * D.16099;
  int D.16100;
  int D.16101;
  struct MonoArray * D.16104;
  double[0:] * D.16105;
  unsigned int pos.2;
  unsigned int D.16107;
  struct MonoArray * D.16108;
  double[0:] * D.16109;
  sizetype pos.3;
  struct MonoCQItem * queue;
  struct MonoMList * tail;
  gint32 pos;

  tail = cq->tail;
  queue = tail->data;
  <D.16013>:
  pos = queue->last;
  if (pos > 63) goto <D.16096>; else goto <D.16097>;
  <D.16096>:
  D.16098 = 0;
  return D.16098;
  <D.16097>:
  D.16099 = &queue->last;
  D.16100 = pos + 1;
  D.16101 = InterlockedCompareExchange (D.16099, D.16100, pos);
  if (D.16101 == pos) goto <D.16102>; else goto <D.16103>;
  <D.16102>:
  {
    void * * __p;

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

    D.16108 = queue->array_state;
    D.16109 = &D.16108->vector;
    pos.3 = (sizetype) pos;
    __p = D.16109 + pos.3;
    *__p = 1;
  }
  if (pos == 63) goto <D.16111>; else goto <D.16112>;
  <D.16111>:
  mono_cq_add_node (cq);
  <D.16112>:
  D.16098 = 1;
  return D.16098;
  <D.16103>:
  goto <D.16013>;
  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.16114;
  unsigned int comp.4;
  unsigned int exch.5;
  unsigned int D.16117;

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


mono_memory_write_barrier ()
{
  mono_memory_barrier ();
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


mono_cq_add_node (struct MonoCQ * cq)
{
  struct MonoCQItem * D.16119;
  struct MonoMList * * D.16120;
  struct MonoMList * n;
  struct MonoMList * prev_tail;

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


InterlockedIncrement (volatile gint32 * val)
{
  gint32 D.16121;
  unsigned int D.16122;

  D.16122 = __sync_add_and_fetch_4 (val, 1);
  D.16121 = (gint32) D.16122;
  return D.16121;
}


mono_cq_dequeue (struct MonoCQ * cq, struct MonoObject * * result)
{
  int D.16124;
  volatile gint32 * D.16127;
  gboolean D.16128;
  int D.16129;

  goto <D.16045>;
  <D.16044>:
  D.16124 = mono_cqitem_try_dequeue (cq, result);
  if (D.16124 != 0) goto <D.16125>; else goto <D.16126>;
  <D.16125>:
  D.16127 = &cq->count;
  InterlockedDecrement (D.16127);
  D.16128 = 1;
  return D.16128;
  <D.16126>:
  SleepEx (0, 0);
  <D.16045>:
  D.16129 = cq->count;
  if (D.16129 > 0) goto <D.16044>; else goto <D.16046>;
  <D.16046>:
  D.16128 = 0;
  return D.16128;
}


mono_cqitem_try_dequeue (struct MonoCQ * cq, struct MonoObject * * obj)
{
  int D.16133;
  gboolean D.16135;
  volatile gint32 * D.16136;
  int D.16137;
  int D.16138;
  struct MonoArray * D.16141;
  unsigned int pos.6;
  char * D.16143;
  char D.16144;
  struct MonoArray * D.16145;
  char * D.16146;
  struct MonoObject * D.16147;
  struct MonoCQItem * queue;
  struct MonoMList * head;
  gint32 pos;

  head = cq->head;
  queue = head->data;
  <D.16039>:
  pos = queue->first;
  D.16133 = queue->last;
  if (D.16133 <= pos) goto <D.16131>; else goto <D.16134>;
  <D.16134>:
  if (pos > 63) goto <D.16131>; else goto <D.16132>;
  <D.16131>:
  D.16135 = 0;
  return D.16135;
  <D.16132>:
  D.16136 = &queue->first;
  D.16137 = pos + 1;
  D.16138 = InterlockedCompareExchange (D.16136, D.16137, pos);
  if (D.16138 == pos) goto <D.16139>; else goto <D.16140>;
  <D.16139>:
  goto <D.16035>;
  <D.16034>:
  SleepEx (0, 0);
  <D.16035>:
  D.16141 = queue->array_state;
  pos.6 = (unsigned int) pos;
  D.16143 = mono_array_addr_with_size (D.16141, 1, pos.6);
  D.16144 = *D.16143;
  if (D.16144 == 0) goto <D.16034>; else goto <D.16036>;
  <D.16036>:
  mono_memory_read_barrier ();
  D.16145 = queue->array;
  pos.6 = (unsigned int) pos;
  D.16146 = mono_array_addr_with_size (D.16145, 4, pos.6);
  D.16147 = MEM[(struct MonoObject * *)D.16146];
  *obj = D.16147;
  {
    struct MonoObject * * __p;

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

    D.16141 = queue->array_state;
    pos.6 = (unsigned int) pos;
    __p = mono_array_addr_with_size (D.16141, 1, pos.6);
    *__p = 0;
  }
  if (pos == 63) goto <D.16148>; else goto <D.16149>;
  <D.16148>:
  mono_cq_remove_node (cq);
  <D.16149>:
  D.16135 = 1;
  return D.16135;
  <D.16140>:
  goto <D.16039>;
  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.16151;
  struct MonoMList * old_head;

  old_head = cq->head;
  goto <D.16025>;
  <D.16024>:
  SleepEx (0, 0);
  <D.16025>:
  D.16151 = old_head->next;
  if (D.16151 == 0B) goto <D.16024>; else goto <D.16026>;
  <D.16026>:
  D.16151 = old_head->next;
  cq->head = D.16151;
  old_head = 0B;
}


InterlockedDecrement (volatile gint32 * val)
{
  gint32 D.16152;
  unsigned int D.16153;

  D.16153 = __sync_sub_and_fetch_4 (val, 1);
  D.16152 = (gint32) D.16153;
  return D.16152;
}


