mono_cq_create ()
{
  void * D.16434;
  struct MonoMList * * D.16435;
  void * D.16438;
  struct MonoMList * * D.16439;
  struct MonoCQItem * D.16440;
  struct MonoMList * D.16441;
  struct MonoMList * D.16442;
  struct MonoCQ * D.16443;
  struct MonoCQ * cq;

  cq = monoeg_malloc0 (24);
  if (0 != 0) goto <D.16432>; else goto <D.16433>;
  <D.16432>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-cq.c", 70, "sizeof (cq->head) == sizeof (MonoObject*)");
  <D.16433>:
  D.16434 = mono_gc_make_root_descr_all_refs (1);
  D.16435 = &cq->head;
  mono_gc_register_root (D.16435, 8, D.16434);
  if (0 != 0) goto <D.16436>; else goto <D.16437>;
  <D.16436>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-cq.c", 71, "sizeof (cq->tail) == sizeof (MonoObject*)");
  <D.16437>:
  D.16438 = mono_gc_make_root_descr_all_refs (1);
  D.16439 = &cq->tail;
  mono_gc_register_root (D.16439, 8, D.16438);
  D.16440 = mono_cqitem_alloc ();
  D.16441 = mono_mlist_alloc (D.16440);
  cq->head = D.16441;
  D.16442 = cq->head;
  cq->tail = D.16442;
  D.16443 = cq;
  return D.16443;
}


mono_cqitem_alloc ()
{
  struct MonoVTable * monocq_item_vtable.0;
  struct MonoImage * D.16448;
  struct MonoVTable * monocq_item_vtable.1;
  _Bool D.16450;
  long int D.16451;
  long int D.16452;
  struct MonoClass * D.16455;
  struct MonoArray * D.16456;
  struct MonoArray * * D.16457;
  struct MonoClass * D.16458;
  struct MonoArray * D.16459;
  struct MonoArray * * D.16460;
  struct MonoCQItem * D.16461;
  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.16446>; else goto <D.16447>;
  <D.16446>:
  {
    struct MonoClass * klass;

    D.16448 = mono_defaults.corlib;
    klass = mono_class_from_name (D.16448, "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.16450 = monocq_item_vtable.0 == 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-cq.c", 56, "monocq_item_vtable");
    <D.16454>:
  }
  <D.16447>:
  monocq_item_vtable.0 = monocq_item_vtable;
  queue = mono_object_new_fast (monocq_item_vtable.0);
  D.16455 = mono_defaults.object_class;
  D.16456 = mono_array_new (domain, D.16455, 64);
  D.16457 = &queue->array;
  mono_gc_wbarrier_set_field (queue, D.16457, D.16456);
  D.16458 = mono_defaults.byte_class;
  D.16459 = mono_array_new (domain, D.16458, 64);
  D.16460 = &queue->array_state;
  mono_gc_wbarrier_set_field (queue, D.16460, D.16459);
  D.16461 = queue;
  return D.16461;
}


mono_cq_destroy (struct MonoCQ * cq)
{
  struct MonoMList * * D.16465;
  struct MonoMList * * D.16466;

  if (cq == 0B) goto <D.16463>; else goto <D.16464>;
  <D.16463>:
  return;
  <D.16464>:
  mono_gc_bzero_aligned (cq, 24);
  D.16465 = &cq->tail;
  mono_gc_deregister_root (D.16465);
  D.16466 = &cq->head;
  mono_gc_deregister_root (D.16466);
  monoeg_g_free (cq);
}


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

  if (cq == 0B) goto <D.16468>; else goto <D.16469>;
  <D.16468>:
  D.16470 = 0;
  return D.16470;
  <D.16469>:
  D.16470 = cq->count;
  return D.16470;
}


mono_cq_enqueue (struct MonoCQ * cq, struct MonoObject * obj)
{
  _Bool D.16472;
  _Bool D.16473;
  _Bool D.16474;
  int D.16477;
  volatile gint32 * D.16480;

  D.16472 = cq == 0B;
  D.16473 = obj == 0B;
  D.16474 = D.16472 | D.16473;
  if (D.16474 != 0) goto <D.16475>; else goto <D.16476>;
  <D.16475>:
  return;
  <D.16476>:
  <D.16403>:
  D.16477 = mono_cqitem_try_enqueue (cq, obj);
  if (D.16477 != 0) goto <D.16478>; else goto <D.16479>;
  <D.16478>:
  D.16480 = &cq->count;
  InterlockedIncrement (D.16480);
  goto <D.16402>;
  <D.16479>:
  SleepEx (0, 0);
  goto <D.16403>;
  <D.16402>:
}


mono_cqitem_try_enqueue (struct MonoCQ * cq, struct MonoObject * obj)
{
  gboolean D.16484;
  int D.16485;
  volatile gint32 * D.16486;
  int D.16487;
  struct MonoArray * D.16490;
  sizetype D.16491;
  struct MonoArray * D.16492;
  double[0:] * D.16493;
  struct MonoCQItem * queue;
  struct MonoMList * tail;
  gint32 pos;

  tail = cq->tail;
  queue = tail->data;
  <D.16397>:
  pos = queue->last;
  if (pos > 63) goto <D.16482>; else goto <D.16483>;
  <D.16482>:
  D.16484 = 0;
  return D.16484;
  <D.16483>:
  D.16485 = pos + 1;
  D.16486 = &queue->last;
  D.16487 = InterlockedCompareExchange (D.16486, D.16485, pos);
  if (D.16487 == pos) goto <D.16488>; else goto <D.16489>;
  <D.16488>:
  {
    void * * __p;

    D.16490 = queue->array;
    D.16491 = (sizetype) pos;
    __p = &D.16490->vector[D.16491];
    D.16490 = queue->array;
    mono_gc_wbarrier_set_arrayref (D.16490, __p, obj);
  }
  {
    char * __p;

    D.16492 = queue->array_state;
    D.16493 = &D.16492->vector;
    D.16491 = (sizetype) pos;
    __p = D.16493 + D.16491;
    *__p = 1;
  }
  if (pos == 63) goto <D.16494>; else goto <D.16495>;
  <D.16494>:
  mono_cq_add_node (cq);
  <D.16495>:
  D.16484 = 1;
  return D.16484;
  <D.16489>:
  goto <D.16397>;
  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.16497;
  unsigned int exch.2;
  unsigned int comp.3;
  unsigned int D.16500;

  exch.2 = (unsigned int) exch;
  comp.3 = (unsigned int) comp;
  D.16500 = __sync_val_compare_and_swap_4 (dest, comp.3, exch.2);
  D.16497 = (gint32) D.16500;
  return D.16497;
}


mono_cq_add_node (struct MonoCQ * cq)
{
  struct MonoCQItem * D.16502;
  struct MonoMList * * D.16503;
  struct MonoMList * n;
  struct MonoMList * prev_tail;

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


InterlockedIncrement (volatile gint32 * val)
{
  gint32 D.16504;
  unsigned int D.16505;

  D.16505 = __sync_add_and_fetch_4 (val, 1);
  D.16504 = (gint32) D.16505;
  return D.16504;
}


mono_cq_dequeue (struct MonoCQ * cq, struct MonoObject * * result)
{
  int D.16507;
  volatile gint32 * D.16510;
  gboolean D.16511;
  int D.16512;

  goto <D.16429>;
  <D.16428>:
  D.16507 = mono_cqitem_try_dequeue (cq, result);
  if (D.16507 != 0) goto <D.16508>; else goto <D.16509>;
  <D.16508>:
  D.16510 = &cq->count;
  InterlockedDecrement (D.16510);
  D.16511 = 1;
  return D.16511;
  <D.16509>:
  SleepEx (0, 0);
  <D.16429>:
  D.16512 = cq->count;
  if (D.16512 > 0) goto <D.16428>; else goto <D.16430>;
  <D.16430>:
  D.16511 = 0;
  return D.16511;
}


mono_cqitem_try_dequeue (struct MonoCQ * cq, struct MonoObject * * obj)
{
  int D.16516;
  gboolean D.16518;
  int D.16519;
  volatile gint32 * D.16520;
  int D.16521;
  long unsigned int D.16524;
  struct MonoArray * D.16525;
  char * D.16526;
  char D.16527;
  struct MonoArray * D.16528;
  char * D.16529;
  struct MonoObject * D.16530;
  struct MonoCQItem * queue;
  struct MonoMList * head;
  gint32 pos;

  head = cq->head;
  queue = head->data;
  <D.16423>:
  pos = queue->first;
  D.16516 = queue->last;
  if (D.16516 <= pos) goto <D.16514>; else goto <D.16517>;
  <D.16517>:
  if (pos > 63) goto <D.16514>; else goto <D.16515>;
  <D.16514>:
  D.16518 = 0;
  return D.16518;
  <D.16515>:
  D.16519 = pos + 1;
  D.16520 = &queue->first;
  D.16521 = InterlockedCompareExchange (D.16520, D.16519, pos);
  if (D.16521 == pos) goto <D.16522>; else goto <D.16523>;
  <D.16522>:
  goto <D.16419>;
  <D.16418>:
  SleepEx (0, 0);
  <D.16419>:
  D.16524 = (long unsigned int) pos;
  D.16525 = queue->array_state;
  D.16526 = mono_array_addr_with_size (D.16525, 1, D.16524);
  D.16527 = *D.16526;
  if (D.16527 == 0) goto <D.16418>; else goto <D.16420>;
  <D.16420>:
  D.16524 = (long unsigned int) pos;
  D.16528 = queue->array;
  D.16529 = mono_array_addr_with_size (D.16528, 8, D.16524);
  D.16530 = MEM[(struct MonoObject * *)D.16529];
  *obj = D.16530;
  {
    struct MonoObject * * __p;

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

    D.16524 = (long unsigned int) pos;
    D.16525 = queue->array_state;
    __p = mono_array_addr_with_size (D.16525, 1, D.16524);
    *__p = 0;
  }
  if (pos == 63) goto <D.16531>; else goto <D.16532>;
  <D.16531>:
  mono_cq_remove_node (cq);
  <D.16532>:
  D.16518 = 1;
  return D.16518;
  <D.16523>:
  goto <D.16423>;
  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.16534;
  struct MonoMList * old_head;

  old_head = cq->head;
  goto <D.16409>;
  <D.16408>:
  SleepEx (0, 0);
  <D.16409>:
  D.16534 = old_head->next;
  if (D.16534 == 0B) goto <D.16408>; else goto <D.16410>;
  <D.16410>:
  D.16534 = old_head->next;
  cq->head = D.16534;
  old_head = 0B;
}


InterlockedDecrement (volatile gint32 * val)
{
  gint32 D.16535;
  unsigned int D.16536;

  D.16536 = __sync_sub_and_fetch_4 (val, 1);
  D.16535 = (gint32) D.16536;
  return D.16535;
}


