mono_cq_create ()
{
  struct MonoMList * * D.16964;
  void * D.16965;
  struct MonoMList * * D.16968;
  void * D.16969;
  struct MonoCQItem * D.16970;
  struct MonoMList * D.16971;
  struct MonoMList * D.16972;
  struct MonoCQ * D.16973;
  struct MonoCQ * cq;

  cq = monoeg_malloc0 (24);
  if (0 != 0) goto <D.16962>; else goto <D.16963>;
  <D.16962>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-cq.c", 70, "sizeof (cq->head) == sizeof (MonoObject*)");
  <D.16963>:
  D.16964 = &cq->head;
  D.16965 = mono_gc_make_root_descr_all_refs (1);
  mono_gc_register_root (D.16964, 8, D.16965);
  if (0 != 0) goto <D.16966>; else goto <D.16967>;
  <D.16966>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-cq.c", 71, "sizeof (cq->tail) == sizeof (MonoObject*)");
  <D.16967>:
  D.16968 = &cq->tail;
  D.16969 = mono_gc_make_root_descr_all_refs (1);
  mono_gc_register_root (D.16968, 8, D.16969);
  D.16970 = mono_cqitem_alloc ();
  D.16971 = mono_mlist_alloc (D.16970);
  cq->head = D.16971;
  D.16972 = cq->head;
  cq->tail = D.16972;
  D.16973 = cq;
  return D.16973;
}


mono_cqitem_alloc ()
{
  struct MonoVTable * monocq_item_vtable.0;
  struct MonoImage * D.16978;
  struct MonoVTable * monocq_item_vtable.1;
  _Bool D.16980;
  long int D.16981;
  long int D.16982;
  struct MonoArray * * D.16985;
  struct MonoClass * D.16986;
  struct MonoArray * D.16987;
  struct MonoArray * * D.16988;
  struct MonoClass * D.16989;
  struct MonoArray * D.16990;
  struct MonoCQItem * D.16991;
  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.16976>; else goto <D.16977>;
  <D.16976>:
  {
    struct MonoClass * klass;

    D.16978 = mono_defaults.corlib;
    klass = mono_class_from_name (D.16978, "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.16980 = monocq_item_vtable.0 == 0B;
    D.16981 = (long int) D.16980;
    D.16982 = __builtin_expect (D.16981, 0);
    if (D.16982 != 0) goto <D.16983>; else goto <D.16984>;
    <D.16983>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-cq.c", 56, "monocq_item_vtable");
    <D.16984>:
  }
  <D.16977>:
  monocq_item_vtable.0 = monocq_item_vtable;
  queue = mono_object_new_fast (monocq_item_vtable.0);
  D.16985 = &queue->array;
  D.16986 = mono_defaults.object_class;
  D.16987 = mono_array_new (domain, D.16986, 64);
  mono_gc_wbarrier_set_field (queue, D.16985, D.16987);
  D.16988 = &queue->array_state;
  D.16989 = mono_defaults.byte_class;
  D.16990 = mono_array_new (domain, D.16989, 64);
  mono_gc_wbarrier_set_field (queue, D.16988, D.16990);
  D.16991 = queue;
  return D.16991;
}


mono_cq_destroy (struct MonoCQ * cq)
{
  struct MonoMList * * D.16995;
  struct MonoMList * * D.16996;

  if (cq == 0B) goto <D.16993>; else goto <D.16994>;
  <D.16993>:
  return;
  <D.16994>:
  mono_gc_bzero_aligned (cq, 24);
  D.16995 = &cq->tail;
  mono_gc_deregister_root (D.16995);
  D.16996 = &cq->head;
  mono_gc_deregister_root (D.16996);
  monoeg_g_free (cq);
}


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

  if (cq == 0B) goto <D.16998>; else goto <D.16999>;
  <D.16998>:
  D.17000 = 0;
  return D.17000;
  <D.16999>:
  D.17000 = cq->count;
  return D.17000;
}


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

  if (cq == 0B) goto <D.17002>; else goto <D.17004>;
  <D.17004>:
  if (obj == 0B) goto <D.17002>; else goto <D.17003>;
  <D.17002>:
  return;
  <D.17003>:
  <D.16933>:
  D.17005 = mono_cqitem_try_enqueue (cq, obj);
  if (D.17005 != 0) goto <D.17006>; else goto <D.17007>;
  <D.17006>:
  D.17008 = &cq->count;
  InterlockedIncrement (D.17008);
  goto <D.16932>;
  <D.17007>:
  SleepEx (0, 0);
  goto <D.16933>;
  <D.16932>:
}


mono_cqitem_try_enqueue (struct MonoCQ * cq, struct MonoObject * obj)
{
  gboolean D.17012;
  volatile gint32 * D.17013;
  int D.17014;
  int D.17015;
  struct MonoArray * D.17018;
  sizetype D.17019;
  struct MonoArray * D.17020;
  double[0:] * D.17021;
  struct MonoCQItem * queue;
  struct MonoMList * tail;
  gint32 pos;

  tail = cq->tail;
  queue = tail->data;
  <D.16927>:
  pos = queue->last;
  if (pos > 63) goto <D.17010>; else goto <D.17011>;
  <D.17010>:
  D.17012 = 0;
  return D.17012;
  <D.17011>:
  D.17013 = &queue->last;
  D.17014 = pos + 1;
  D.17015 = InterlockedCompareExchange (D.17013, D.17014, pos);
  if (D.17015 == pos) goto <D.17016>; else goto <D.17017>;
  <D.17016>:
  {
    void * * __p;

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

    D.17020 = queue->array_state;
    D.17021 = &D.17020->vector;
    D.17019 = (sizetype) pos;
    __p = D.17021 + D.17019;
    *__p = 1;
  }
  if (pos == 63) goto <D.17022>; else goto <D.17023>;
  <D.17022>:
  mono_cq_add_node (cq);
  <D.17023>:
  D.17012 = 1;
  return D.17012;
  <D.17017>:
  goto <D.16927>;
  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.17025;
  unsigned int comp.2;
  unsigned int exch.3;
  unsigned int D.17028;

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


mono_memory_write_barrier ()
{
  mono_memory_barrier ();
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


mono_cq_add_node (struct MonoCQ * cq)
{
  struct MonoCQItem * D.17030;
  struct MonoMList * * D.17031;
  struct MonoMList * n;
  struct MonoMList * prev_tail;

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


InterlockedIncrement (volatile gint32 * val)
{
  gint32 D.17032;
  unsigned int D.17033;

  D.17033 = __sync_add_and_fetch_4 (val, 1);
  D.17032 = (gint32) D.17033;
  return D.17032;
}


mono_cq_dequeue (struct MonoCQ * cq, struct MonoObject * * result)
{
  int D.17035;
  volatile gint32 * D.17038;
  gboolean D.17039;
  int D.17040;

  goto <D.16959>;
  <D.16958>:
  D.17035 = mono_cqitem_try_dequeue (cq, result);
  if (D.17035 != 0) goto <D.17036>; else goto <D.17037>;
  <D.17036>:
  D.17038 = &cq->count;
  InterlockedDecrement (D.17038);
  D.17039 = 1;
  return D.17039;
  <D.17037>:
  SleepEx (0, 0);
  <D.16959>:
  D.17040 = cq->count;
  if (D.17040 > 0) goto <D.16958>; else goto <D.16960>;
  <D.16960>:
  D.17039 = 0;
  return D.17039;
}


mono_cqitem_try_dequeue (struct MonoCQ * cq, struct MonoObject * * obj)
{
  int D.17044;
  gboolean D.17046;
  volatile gint32 * D.17047;
  int D.17048;
  int D.17049;
  struct MonoArray * D.17052;
  long unsigned int D.17053;
  char * D.17054;
  char D.17055;
  struct MonoArray * D.17056;
  char * D.17057;
  struct MonoObject * D.17058;
  struct MonoCQItem * queue;
  struct MonoMList * head;
  gint32 pos;

  head = cq->head;
  queue = head->data;
  <D.16953>:
  pos = queue->first;
  D.17044 = queue->last;
  if (D.17044 <= pos) goto <D.17042>; else goto <D.17045>;
  <D.17045>:
  if (pos > 63) goto <D.17042>; else goto <D.17043>;
  <D.17042>:
  D.17046 = 0;
  return D.17046;
  <D.17043>:
  D.17047 = &queue->first;
  D.17048 = pos + 1;
  D.17049 = InterlockedCompareExchange (D.17047, D.17048, pos);
  if (D.17049 == pos) goto <D.17050>; else goto <D.17051>;
  <D.17050>:
  goto <D.16949>;
  <D.16948>:
  SleepEx (0, 0);
  <D.16949>:
  D.17052 = queue->array_state;
  D.17053 = (long unsigned int) pos;
  D.17054 = mono_array_addr_with_size (D.17052, 1, D.17053);
  D.17055 = *D.17054;
  if (D.17055 == 0) goto <D.16948>; else goto <D.16950>;
  <D.16950>:
  mono_memory_read_barrier ();
  D.17056 = queue->array;
  D.17053 = (long unsigned int) pos;
  D.17057 = mono_array_addr_with_size (D.17056, 8, D.17053);
  D.17058 = MEM[(struct MonoObject * *)D.17057];
  *obj = D.17058;
  {
    struct MonoObject * * __p;

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

    D.17052 = queue->array_state;
    D.17053 = (long unsigned int) pos;
    __p = mono_array_addr_with_size (D.17052, 1, D.17053);
    *__p = 0;
  }
  if (pos == 63) goto <D.17059>; else goto <D.17060>;
  <D.17059>:
  mono_cq_remove_node (cq);
  <D.17060>:
  D.17046 = 1;
  return D.17046;
  <D.17051>:
  goto <D.16953>;
  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.17062;
  struct MonoMList * old_head;

  old_head = cq->head;
  goto <D.16939>;
  <D.16938>:
  SleepEx (0, 0);
  <D.16939>:
  D.17062 = old_head->next;
  if (D.17062 == 0B) goto <D.16938>; else goto <D.16940>;
  <D.16940>:
  D.17062 = old_head->next;
  cq->head = D.17062;
  old_head = 0B;
}


InterlockedDecrement (volatile gint32 * val)
{
  gint32 D.17063;
  unsigned int D.17064;

  D.17064 = __sync_sub_and_fetch_4 (val, 1);
  D.17063 = (gint32) D.17064;
  return D.17063;
}


