__attribute__((visibility ("hidden")))
mono_thread_pool_remove_socket (int sock)
{
  int D.19138;
  _Bool D.19143;
  long int D.19144;
  long int D.19145;
  struct MonoGHashTable * D.19148;
  _Bool D.19153;
  long int D.19154;
  long int D.19155;
  long int D.19158;
  const void * D.19159;
  void * list.0;
  struct MonoMList * list.1;
  _Bool D.19166;
  long int D.19167;
  long int D.19168;
  int D.19171;
  struct MonoMList * list;
  struct MonoSocketAsyncResult * state;
  struct MonoObject * ares;

  try
    {
      D.19138 = socket_io_data.inited;
      if (D.19138 == 0) goto <D.19139>; else goto <D.19140>;
      <D.19139>:
      return;
      <D.19140>:
      {
        int ret;

        ret = pthread_mutex_lock (&socket_io_data.io_lock.mutex);
        if (ret != 0) goto <D.19141>; else goto <D.19142>;
        <D.19141>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.19142>:
        D.19143 = ret != 0;
        D.19144 = (long int) D.19143;
        D.19145 = __builtin_expect (D.19144, 0);
        if (D.19145 != 0) goto <D.19146>; else goto <D.19147>;
        <D.19146>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 446, "ret == 0");
        <D.19147>:
      }
      D.19148 = socket_io_data.sock_to_state;
      if (D.19148 == 0B) goto <D.19149>; else goto <D.19150>;
      <D.19149>:
      {
        int ret;

        ret = pthread_mutex_unlock (&socket_io_data.io_lock.mutex);
        if (ret != 0) goto <D.19151>; else goto <D.19152>;
        <D.19151>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.19152>:
        D.19153 = ret != 0;
        D.19154 = (long int) D.19153;
        D.19155 = __builtin_expect (D.19154, 0);
        if (D.19155 != 0) goto <D.19156>; else goto <D.19157>;
        <D.19156>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 448, "ret == 0");
        <D.19157>:
      }
      return;
      <D.19150>:
      D.19148 = socket_io_data.sock_to_state;
      D.19158 = (long int) sock;
      D.19159 = (const void *) D.19158;
      list.0 = mono_g_hash_table_lookup (D.19148, D.19159);
      list = list.0;
      list.1 = list;
      if (list.1 != 0B) goto <D.19162>; else goto <D.19163>;
      <D.19162>:
      D.19148 = socket_io_data.sock_to_state;
      D.19158 = (long int) sock;
      D.19159 = (const void *) D.19158;
      mono_g_hash_table_remove (D.19148, D.19159);
      <D.19163>:
      {
        int ret;

        ret = pthread_mutex_unlock (&socket_io_data.io_lock.mutex);
        if (ret != 0) goto <D.19164>; else goto <D.19165>;
        <D.19164>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.19165>:
        D.19166 = ret != 0;
        D.19167 = (long int) D.19166;
        D.19168 = __builtin_expect (D.19167, 0);
        if (D.19168 != 0) goto <D.19169>; else goto <D.19170>;
        <D.19169>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 454, "ret == 0");
        <D.19170>:
      }
      goto <D.18761>;
      <D.18760>:
      list.1 = list;
      state = mono_mlist_get_data (list.1);
      D.19171 = state->operation;
      if (D.19171 == 2) goto <D.19172>; else goto <D.19173>;
      <D.19172>:
      state->operation = 6;
      goto <D.19174>;
      <D.19173>:
      D.19171 = state->operation;
      if (D.19171 == 4) goto <D.19175>; else goto <D.19176>;
      <D.19175>:
      state->operation = 7;
      <D.19176>:
      <D.19174>:
      ares = get_io_event (&list, 1);
      threadpool_append_job (&async_io_tp, ares);
      list.1 = list;
      if (list.1 != 0B) goto <D.19177>; else goto <D.19178>;
      <D.19177>:
      ares = get_io_event (&list, 4);
      threadpool_append_job (&async_io_tp, ares);
      <D.19178>:
      <D.18761>:
      list.1 = list;
      if (list.1 != 0B) goto <D.18760>; else goto <D.18762>;
      <D.18762>:
    }
  finally
    {
      list = {CLOBBER};
    }
}


get_io_event (struct MonoMList * * list, gint event)
{
  int D.19182;
  struct MonoMList * D.19188;
  struct MonoMList * D.19190;
  struct MonoMList * D.19191;
  struct MonoObject * D.19192;
  struct MonoObject * state;
  struct MonoMList * current;
  struct MonoMList * prev;

  current = *list;
  prev = 0B;
  state = 0B;
  goto <D.18750>;
  <D.18749>:
  state = mono_mlist_get_data (current);
  D.19182 = get_event_from_state (state);
  if (D.19182 == event) goto <D.18748>; else goto <D.19183>;
  <D.19183>:
  state = 0B;
  prev = current;
  current = mono_mlist_next (current);
  <D.18750>:
  if (current != 0B) goto <D.18749>; else goto <D.18748>;
  <D.18748>:
  if (current != 0B) goto <D.19184>; else goto <D.19185>;
  <D.19184>:
  if (prev != 0B) goto <D.19186>; else goto <D.19187>;
  <D.19186>:
  D.19188 = mono_mlist_next (current);
  mono_mlist_set_next (prev, D.19188);
  goto <D.19189>;
  <D.19187>:
  D.19190 = *list;
  D.19191 = mono_mlist_next (D.19190);
  *list = D.19191;
  <D.19189>:
  <D.19185>:
  D.19192 = state;
  return D.19192;
}


get_event_from_state (struct MonoSocketAsyncResult * state)
{
  int D.19194;
  int D.19195;

  D.19194 = state->operation;
  switch (D.19194) <default: <D.18724>, case 0: <D.18711>, case 1: <D.18721>, case 2: <D.18712>, case 3: <D.18714>, case 4: <D.18718>, case 5: <D.18720>, case 6: <D.18713>, case 7: <D.18719>, case 8: <D.18715>, case 10: <D.18723>, case 11: <D.18716>, case 12: <D.18717>, case 13: <D.18722>>
  <D.18711>:
  <D.18712>:
  <D.18713>:
  <D.18714>:
  <D.18715>:
  <D.18716>:
  <D.18717>:
  D.19195 = 1;
  return D.19195;
  <D.18718>:
  <D.18719>:
  <D.18720>:
  <D.18721>:
  <D.18722>:
  <D.18723>:
  D.19195 = 4;
  return D.19195;
  <D.18724>:
  monoeg_g_log (0B, 32, "get_event_from_state: unknown value in switch!!!");
  D.19195 = 0;
  return D.19195;
}


threadpool_append_job (struct ThreadPool * tp, struct MonoObject * ar)
{
  threadpool_append_jobs (tp, &ar, 1);
}


threadpool_append_jobs (struct ThreadPool * tp, struct MonoObject * * jobs, gint njobs)
{
  int D.19197;
  int D.19200;
  volatile gint * D.19203;
  int D.19204;
  int D.19207;
  struct MonoDomain * D.19210;
  int D.19211;
  struct MonoDomain * D.19214;
  long unsigned int D.19215;
  long unsigned int D.19216;
  struct MonoObject * * D.19217;
  struct MonoVTable * D.19221;
  struct MonoDomain * D.19222;
  int D.19223;
  int D.19226;
  int D.19227;
  long int D.19230;
  void * D.19231;
  int D.19234;
  struct MonoCQ * D.19237;
  int D.19238;
  int iftmp.2;
  int D.19241;
  static int job_counter;
  struct MonoObject * ar;
  gint i;

  D.19197 = mono_runtime_is_shutting_down ();
  if (D.19197 != 0) goto <D.19198>; else goto <D.19199>;
  <D.19198>:
  return;
  <D.19199>:
  D.19200 = tp->pool_status;
  if (D.19200 == 0) goto <D.19201>; else goto <D.19202>;
  <D.19201>:
  D.19203 = &tp->pool_status;
  D.19204 = InterlockedCompareExchange (D.19203, 1, 0);
  if (D.19204 == 0) goto <D.19205>; else goto <D.19206>;
  <D.19205>:
  D.19207 = tp->is_io;
  if (D.19207 == 0) goto <D.19208>; else goto <D.19209>;
  <D.19208>:
  D.19210 = mono_get_root_domain ();
  mono_thread_create_internal (D.19210, monitor_thread, 0B, 1, 0, 262144);
  threadpool_start_thread (tp);
  <D.19209>:
  D.19211 = mono_config_is_server_mode ();
  if (D.19211 != 0) goto <D.19212>; else goto <D.19213>;
  <D.19212>:
  D.19214 = mono_get_root_domain ();
  mono_thread_create_internal (D.19214, threadpool_start_idle_threads, tp, 1, 0, 262144);
  <D.19213>:
  <D.19206>:
  <D.19202>:
  i = 0;
  goto <D.18934>;
  <D.18933>:
  D.19215 = (long unsigned int) i;
  D.19216 = D.19215 * 8;
  D.19217 = jobs + D.19216;
  ar = *D.19217;
  if (ar == 0B) goto <D.19218>; else goto <D.19220>;
  <D.19220>:
  D.19221 = ar->vtable;
  D.19222 = D.19221->domain;
  D.19223 = mono_domain_is_unloading (D.19222);
  if (D.19223 != 0) goto <D.19218>; else goto <D.19219>;
  <D.19218>:
  // predicted unlikely by continue predictor.
  goto <D.18931>;
  <D.19219>:
  D.19207 = tp->is_io;
  if (D.19207 == 0) goto <D.19224>; else goto <D.19225>;
  <D.19224>:
  D.19226 = InterlockedIncrement (&job_counter);
  D.19227 = D.19226 % 10;
  if (D.19227 == 0) goto <D.19228>; else goto <D.19229>;
  <D.19228>:
  {
    struct MonoAsyncResult * o;

    o = ar;
    D.19230 = mono_100ns_ticks ();
    o->add_time = D.19230;
  }
  <D.19229>:
  <D.19225>:
  threadpool_jobs_inc (ar);
  D.19231 = tp->pc_nitems;
  mono_perfcounter_update_value (D.19231, 1, 1);
  D.19207 = tp->is_io;
  if (D.19207 == 0) goto <D.19232>; else goto <D.19233>;
  <D.19232>:
  D.19234 = mono_wsq_local_push (ar);
  if (D.19234 != 0) goto <D.19235>; else goto <D.19236>;
  <D.19235>:
  // predicted unlikely by continue predictor.
  goto <D.18931>;
  <D.19236>:
  <D.19233>:
  D.19237 = tp->queue;
  mono_cq_enqueue (D.19237, ar);
  <D.18931>:
  i = i + 1;
  <D.18934>:
  if (i < njobs) goto <D.18933>; else goto <D.18935>;
  <D.18935>:
  i = 0;
  goto <D.18937>;
  <D.18936>:
  pulse_on_new_job (tp);
  i = i + 1;
  <D.18937>:
  D.19238 = tp->waiting;
  if (D.19238 > 0) goto <D.19239>; else goto <D.18938>;
  <D.19239>:
  D.19241 = tp->max_threads;
  if (D.19241 <= njobs) goto <D.19242>; else goto <D.19243>;
  <D.19242>:
  iftmp.2 = tp->max_threads;
  goto <D.19244>;
  <D.19243>:
  iftmp.2 = njobs;
  <D.19244>:
  if (iftmp.2 > i) goto <D.18936>; else goto <D.18938>;
  <D.18938>:
}


threadpool_start_idle_threads (struct ThreadPool * tp)
{
  guint32 iftmp.3;
  int D.19247;
  int D.19251;
  volatile gint * D.19254;
  int D.19255;
  int D.19256;
  void * D.19258;
  struct MonoDomain * D.19259;
  void (*<Tce2>) (void *) D.19260;
  int n;
  guint32 stack_size;

  D.19247 = tp->is_io;
  if (D.19247 == 0) goto <D.19248>; else goto <D.19249>;
  <D.19248>:
  iftmp.3 = 0;
  goto <D.19250>;
  <D.19249>:
  iftmp.3 = 262144;
  <D.19250>:
  stack_size = iftmp.3;
  <D.18812>:
  <D.18811>:
  n = tp->nthreads;
  D.19251 = tp->min_threads;
  if (D.19251 <= n) goto <D.19252>; else goto <D.19253>;
  <D.19252>:
  return;
  <D.19253>:
  D.19254 = &tp->nthreads;
  D.19255 = n + 1;
  D.19256 = InterlockedCompareExchange (D.19254, D.19255, n);
  if (D.19256 == n) goto <D.18810>; else goto <D.19257>;
  <D.19257>:
  goto <D.18811>;
  <D.18810>:
  D.19258 = tp->pc_nthreads;
  mono_perfcounter_update_value (D.19258, 1, 1);
  D.19259 = mono_get_root_domain ();
  D.19260 = tp->async_invoke;
  mono_thread_create_internal (D.19259, D.19260, tp, 1, 0, stack_size);
  SleepEx (100, 1);
  goto <D.18812>;
}


monitor_thread (void * unused)
{
  struct MonoDomain * D.19262;
  struct MonoString * D.19263;
  unsigned int D.19264;
  unsigned int D.19266;
  unsigned int D.19267;
  int D.19268;
  unsigned int D.19270;
  unsigned int D.19271;
  int i.4;
  int D.19276;
  int suspended.5;
  int D.19281;
  struct MonoCQ * D.19284;
  int D.19285;
  _Bool D.19286;
  int D.19289;
  _Bool D.19294;
  long int D.19295;
  long int D.19296;
  struct GPtrArray * wsqs.6;
  void * * D.19300;
  long unsigned int D.19301;
  long unsigned int D.19302;
  void * * D.19303;
  int D.19304;
  unsigned int D.19308;
  unsigned int i.7;
  _Bool D.19312;
  long int D.19313;
  long int D.19314;
  struct ThreadPool * pools[2];
  struct MonoInternalThread * thread;
  guint32 ms;
  gboolean need_one;
  int i;

  try
    {
      pools[0] = &async_tp;
      pools[1] = &async_io_tp;
      thread = mono_thread_internal_current ();
      D.19262 = mono_domain_get ();
      D.19263 = mono_string_new (D.19262, "Threadpool monitor");
      ves_icall_System_Threading_Thread_SetName_internal (thread, D.19263);
      <D.18854>:
      ms = 500;
      i = 10;
      <D.18840>:
      {
        guint32 ts;

        ts = mono_msec_ticks ();
        D.19264 = SleepEx (ms, 1);
        if (D.19264 == 0) goto <D.18839>; else goto <D.19265>;
        <D.19265>:
        D.19266 = mono_msec_ticks ();
        D.19267 = D.19266 - ts;
        ms = ms - D.19267;
        D.19268 = mono_runtime_is_shutting_down ();
        if (D.19268 != 0) goto <D.18839>; else goto <D.19269>;
        <D.19269>:
        D.19270 = thread->state;
        D.19271 = D.19270 & 3;
        if (D.19271 != 0) goto <D.19272>; else goto <D.19273>;
        <D.19272>:
        mono_thread_interruption_checkpoint ();
        <D.19273>:
      }
      if (ms != 0) goto <D.19274>; else goto <D.18839>;
      <D.19274>:
      i.4 = i;
      i = i.4 + -1;
      if (i.4 != 0) goto <D.18840>; else goto <D.18839>;
      <D.18839>:
      D.19276 = mono_runtime_is_shutting_down ();
      if (D.19276 != 0) goto <D.18841>; else goto <D.19277>;
      <D.19277>:
      suspended.5 = suspended;
      if (suspended.5 != 0) goto <D.19279>; else goto <D.19280>;
      <D.19279>:
      // predicted unlikely by continue predictor.
      goto <D.18842>;
      <D.19280>:
      i = 0;
      goto <D.18852>;
      <D.18851>:
      {
        struct ThreadPool * tp;

        tp = pools[i];
        D.19281 = tp->waiting;
        if (D.19281 > 0) goto <D.19282>; else goto <D.19283>;
        <D.19282>:
        // predicted unlikely by continue predictor.
        goto <D.18844>;
        <D.19283>:
        D.19284 = tp->queue;
        D.19285 = mono_cq_count (D.19284);
        D.19286 = D.19285 > 0;
        need_one = (gboolean) D.19286;
        if (need_one == 0) goto <D.19287>; else goto <D.19288>;
        <D.19287>:
        D.19289 = tp->is_io;
        if (D.19289 == 0) goto <D.19290>; else goto <D.19291>;
        <D.19290>:
        {
          int ret;

          ret = pthread_mutex_lock (&wsqs_lock.mutex);
          if (ret != 0) goto <D.19292>; else goto <D.19293>;
          <D.19292>:
          monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
          <D.19293>:
          D.19294 = ret != 0;
          D.19295 = (long int) D.19294;
          D.19296 = __builtin_expect (D.19295, 0);
          if (D.19296 != 0) goto <D.19297>; else goto <D.19298>;
          <D.19297>:
          monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 801, "ret == 0");
          <D.19298>:
        }
        i = 0;
        goto <D.18849>;
        <D.18848>:
        {
          struct MonoWSQ * wsq;

          wsqs.6 = wsqs;
          D.19300 = wsqs.6->pdata;
          D.19301 = (long unsigned int) i;
          D.19302 = D.19301 * 8;
          D.19303 = D.19300 + D.19302;
          wsq = *D.19303;
          D.19304 = mono_wsq_count (wsq);
          if (D.19304 != 0) goto <D.19305>; else goto <D.19306>;
          <D.19305>:
          need_one = 1;
          goto <D.18847>;
          <D.19306>:
        }
        i = i + 1;
        <D.18849>:
        wsqs.6 = wsqs;
        if (wsqs.6 != 0B) goto <D.19307>; else goto <D.18847>;
        <D.19307>:
        wsqs.6 = wsqs;
        D.19308 = wsqs.6->len;
        i.7 = (unsigned int) i;
        if (D.19308 > i.7) goto <D.18848>; else goto <D.18847>;
        <D.18847>:
        {
          int ret;

          ret = pthread_mutex_unlock (&wsqs_lock.mutex);
          if (ret != 0) goto <D.19310>; else goto <D.19311>;
          <D.19310>:
          monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
          <D.19311>:
          D.19312 = ret != 0;
          D.19313 = (long int) D.19312;
          D.19314 = __builtin_expect (D.19313, 0);
          if (D.19314 != 0) goto <D.19315>; else goto <D.19316>;
          <D.19315>:
          monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 810, "ret == 0");
          <D.19316>:
        }
        <D.19291>:
        <D.19288>:
        if (need_one != 0) goto <D.19317>; else goto <D.19318>;
        <D.19317>:
        threadpool_start_thread (tp);
        <D.19318>:
      }
      <D.18844>:
      i = i + 1;
      <D.18852>:
      if (i <= 1) goto <D.18851>; else goto <D.18853>;
      <D.18853>:
      <D.18842>:
      goto <D.18854>;
      <D.18841>:
    }
  finally
    {
      pools = {CLOBBER};
    }
}


InterlockedCompareExchange (volatile gint32 * dest, gint32 exch, gint32 comp)
{
  gint32 D.19319;
  unsigned int comp.8;
  unsigned int exch.9;
  unsigned int D.19322;

  comp.8 = (unsigned int) comp;
  exch.9 = (unsigned int) exch;
  D.19322 = __sync_val_compare_and_swap_4 (dest, comp.8, exch.9);
  D.19319 = (gint32) D.19322;
  return D.19319;
}


threadpool_start_thread (struct ThreadPool * tp)
{
  guint32 iftmp.10;
  int D.19325;
  volatile gint * D.19329;
  int D.19330;
  int D.19331;
  void * D.19334;
  struct MonoDomain * D.19335;
  void (*<Tce2>) (void *) D.19336;
  gboolean D.19337;
  int D.19338;
  int D.19340;
  gint n;
  guint32 stack_size;

  D.19325 = tp->is_io;
  if (D.19325 == 0) goto <D.19326>; else goto <D.19327>;
  <D.19326>:
  iftmp.10 = 0;
  goto <D.19328>;
  <D.19327>:
  iftmp.10 = 262144;
  <D.19328>:
  stack_size = iftmp.10;
  goto <D.18911>;
  <D.18910>:
  D.19329 = &tp->nthreads;
  D.19330 = n + 1;
  D.19331 = InterlockedCompareExchange (D.19329, D.19330, n);
  if (D.19331 == n) goto <D.19332>; else goto <D.19333>;
  <D.19332>:
  D.19334 = tp->pc_nthreads;
  mono_perfcounter_update_value (D.19334, 1, 1);
  D.19335 = mono_get_root_domain ();
  D.19336 = tp->async_invoke;
  mono_thread_create_internal (D.19335, D.19336, tp, 1, 0, stack_size);
  D.19337 = 1;
  return D.19337;
  <D.19333>:
  <D.18911>:
  D.19338 = mono_runtime_is_shutting_down ();
  if (D.19338 == 0) goto <D.19339>; else goto <D.18912>;
  <D.19339>:
  n = tp->nthreads;
  D.19340 = tp->max_threads;
  if (n < D.19340) goto <D.18910>; else goto <D.18912>;
  <D.18912>:
  D.19337 = 0;
  return D.19337;
}


InterlockedIncrement (volatile gint32 * val)
{
  gint32 D.19342;
  unsigned int D.19343;

  D.19343 = __sync_add_and_fetch_4 (val, 1);
  D.19342 = (gint32) D.19343;
  return D.19342;
}


threadpool_jobs_inc (struct MonoObject * obj)
{
  struct MonoVTable * D.19347;
  struct MonoDomain * D.19348;
  volatile int * D.19349;

  if (obj != 0B) goto <D.19345>; else goto <D.19346>;
  <D.19345>:
  D.19347 = obj->vtable;
  D.19348 = D.19347->domain;
  D.19349 = &D.19348->threadpool_jobs;
  InterlockedIncrement (D.19349);
  <D.19346>:
}


pulse_on_new_job (struct ThreadPool * tp)
{
  int D.19350;
  union MonoSemType * D.19353;

  D.19350 = tp->waiting;
  if (D.19350 != 0) goto <D.19351>; else goto <D.19352>;
  <D.19351>:
  D.19353 = &tp->new_job;
  mono_sem_post (D.19353);
  <D.19352>:
}


__attribute__((visibility ("hidden")))
mono_thread_pool_init_tls ()
{
  mono_wsq_init ();
}


__attribute__((visibility ("hidden")))
mono_thread_pool_init ()
{
  int tp_inited.11;
  int tp_inited.12;
  int D.19362;
  const gchar * D.19365;
  const gchar * D.19368;
  int D.19371;
  int D.19372;
  int D.19373;
  int D.19374;
  int D.19375;
  struct MonoImage * D.19376;
  struct MonoClass * D.19377;
  struct MonoClass * async_call_klass.13;
  _Bool D.19379;
  long int D.19380;
  long int D.19381;
  unsigned int D.19384;
  struct GPtrArray * D.19385;
  void * D.19386;
  void * D.19387;
  _Bool D.19388;
  long int D.19389;
  long int D.19390;
  void * D.19393;
  void * D.19394;
  _Bool D.19395;
  long int D.19396;
  long int D.19397;
  void * D.19400;
  void * D.19401;
  _Bool D.19402;
  long int D.19403;
  long int D.19404;
  void * D.19407;
  void * D.19408;
  _Bool D.19409;
  long int D.19410;
  long int D.19411;
  gint threads_per_cpu;
  gint thread_count;
  gint cpu_count;
  int result;

  threads_per_cpu = 1;
  cpu_count = mono_cpu_count ();
  tp_inited.11 = tp_inited;
  if (tp_inited.11 == 2) goto <D.19355>; else goto <D.19356>;
  <D.19355>:
  return;
  <D.19356>:
  result = InterlockedCompareExchange (&tp_inited, 1, 0);
  if (result == 1) goto <D.19357>; else goto <D.19358>;
  <D.19357>:
  <D.18865>:
  SleepEx (1, 0);
  tp_inited.12 = tp_inited;
  if (tp_inited.12 == 2) goto <D.19360>; else goto <D.19361>;
  <D.19360>:
  return;
  <D.19361>:
  goto <D.18865>;
  <D.19358>:
  D.19362 = mono_gc_is_moving ();
  if (D.19362 == 0) goto <D.19363>; else goto <D.19364>;
  <D.19363>:
  mono_gc_register_root (&socket_io_data.sock_to_state, 8, 0B);
  <D.19364>:
  InitializeCriticalSection (&socket_io_data.io_lock);
  D.19365 = monoeg_g_getenv ("MONO_THREADS_PER_CPU");
  if (D.19365 != 0B) goto <D.19366>; else goto <D.19367>;
  <D.19366>:
  D.19368 = monoeg_g_getenv ("MONO_THREADS_PER_CPU");
  threads_per_cpu = atoi (D.19368);
  if (threads_per_cpu <= 0) goto <D.19369>; else goto <D.19370>;
  <D.19369>:
  threads_per_cpu = 1;
  <D.19370>:
  <D.19367>:
  D.19371 = cpu_count * 100;
  D.19372 = cpu_count * threads_per_cpu;
  thread_count = MIN_EXPR <D.19371, D.19372>;
  D.19371 = cpu_count * 100;
  D.19373 = MAX_EXPR <D.19371, thread_count>;
  threadpool_init (&async_tp, thread_count, D.19373, async_invoke_thread);
  D.19374 = cpu_count * 2;
  D.19375 = cpu_count * 4;
  threadpool_init (&async_io_tp, D.19374, D.19375, async_invoke_thread);
  async_io_tp.is_io = 1;
  D.19376 = mono_defaults.corlib;
  D.19377 = mono_class_from_name (D.19376, "System", "MonoAsyncCall");
  async_call_klass = D.19377;
  async_call_klass.13 = async_call_klass;
  D.19379 = async_call_klass.13 == 0B;
  D.19380 = (long int) D.19379;
  D.19381 = __builtin_expect (D.19380, 0);
  if (D.19381 != 0) goto <D.19382>; else goto <D.19383>;
  <D.19382>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 858, "async_call_klass");
  <D.19383>:
  InitializeCriticalSection (&wsqs_lock);
  D.19371 = cpu_count * 100;
  D.19373 = MAX_EXPR <D.19371, thread_count>;
  D.19384 = (unsigned int) D.19373;
  D.19385 = monoeg_g_ptr_array_sized_new (D.19384);
  wsqs = D.19385;
  D.19386 = init_perf_counter ("Mono Threadpool", "Work Items Added");
  async_tp.pc_nitems = D.19386;
  D.19387 = async_tp.pc_nitems;
  D.19388 = D.19387 == 0B;
  D.19389 = (long int) D.19388;
  D.19390 = __builtin_expect (D.19389, 0);
  if (D.19390 != 0) goto <D.19391>; else goto <D.19392>;
  <D.19391>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 865, "async_tp.pc_nitems");
  <D.19392>:
  D.19393 = init_perf_counter ("Mono Threadpool", "IO Work Items Added");
  async_io_tp.pc_nitems = D.19393;
  D.19394 = async_io_tp.pc_nitems;
  D.19395 = D.19394 == 0B;
  D.19396 = (long int) D.19395;
  D.19397 = __builtin_expect (D.19396, 0);
  if (D.19397 != 0) goto <D.19398>; else goto <D.19399>;
  <D.19398>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 868, "async_io_tp.pc_nitems");
  <D.19399>:
  D.19400 = init_perf_counter ("Mono Threadpool", "# of Threads");
  async_tp.pc_nthreads = D.19400;
  D.19401 = async_tp.pc_nthreads;
  D.19402 = D.19401 == 0B;
  D.19403 = (long int) D.19402;
  D.19404 = __builtin_expect (D.19403, 0);
  if (D.19404 != 0) goto <D.19405>; else goto <D.19406>;
  <D.19405>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 871, "async_tp.pc_nthreads");
  <D.19406>:
  D.19407 = init_perf_counter ("Mono Threadpool", "# of IO Threads");
  async_io_tp.pc_nthreads = D.19407;
  D.19408 = async_io_tp.pc_nthreads;
  D.19409 = D.19408 == 0B;
  D.19410 = (long int) D.19409;
  D.19411 = __builtin_expect (D.19410, 0);
  if (D.19411 != 0) goto <D.19412>; else goto <D.19413>;
  <D.19412>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 874, "async_io_tp.pc_nthreads");
  <D.19413>:
  tp_inited = 2;
}


async_invoke_thread (void * data)
{
  int D.19415;
  void (*<Tce2>) (void *) tp_start_func.14;
  void * tp_hooks_user_data.15;
  volatile gint * D.19424;
  struct MonoVTable * D.19425;
  void * data.16;
  struct MonoVTable * D.19427;
  int D.19428;
  _Bool D.19429;
  int D.19432;
  void * D.19433;
  long int D.19434;
  unsigned int D.19435;
  struct MonoArray * D.19436;
  int D.19437;
  int D.19438;
  int D.19439;
  gint * D.19440;
  int D.19441;
  int D.19442;
  _Bool D.19444;
  long int D.19445;
  long int D.19446;
  int D.19452;
  int D.19454;
  volatile gint * D.19455;
  int D.19456;
  volatile gint * D.19459;
  int D.19460;
  void (*<Tce2>) (void *) tp_item_begin_func.17;
  void * tp_item_user_data.18;
  long int D.19469;
  void (*<Tce2>) (void *) tp_item_end_func.19;
  unsigned char D.19481;
  struct MonoDelegate * D.19484;
  struct MonoDomain * D.19487;
  volatile gint * D.19488;
  int D.19494;
  volatile gint * D.19495;
  volatile gint * D.19498;
  int D.19499;
  struct MonoCQ * D.19501;
  int D.19502;
  union MonoSemType * D.19504;
  volatile gint * D.19505;
  int D.19506;
  int D.19514;
  volatile gint * D.19521;
  int D.19526;
  volatile gint * D.19531;
  int D.19532;
  int D.19533;
  void * D.19534;
  void (*<Tce2>) (void *) tp_finish_func.20;
  struct MonoDomain * domain;
  struct MonoWSQ * wsq;
  struct ThreadPool * tp;
  gboolean must_die;

  tp = data;
  wsq = 0B;
  D.19415 = tp->is_io;
  if (D.19415 == 0) goto <D.19416>; else goto <D.19417>;
  <D.19416>:
  wsq = add_wsq ();
  <D.19417>:
  set_tp_thread_info (tp);
  tp_start_func.14 = tp_start_func;
  if (tp_start_func.14 != 0B) goto <D.19419>; else goto <D.19420>;
  <D.19419>:
  tp_start_func.14 = tp_start_func;
  tp_hooks_user_data.15 = tp_hooks_user_data;
  tp_start_func.14 (tp_hooks_user_data.15);
  <D.19420>:
  data = 0B;
  <D.19090>:
  {
    struct MonoAsyncResult * ar;
    struct MonoClass * klass;
    gboolean is_io_task;
    gboolean is_socket;
    int n_naps;

    n_naps = 0;
    is_io_task = 0;
    ar = data;
    if (ar != 0B) goto <D.19422>; else goto <D.19423>;
    <D.19422>:
    D.19424 = &tp->busy_threads;
    InterlockedIncrement (D.19424);
    D.19425 = MEM[(struct MonoObject *)ar].vtable;
    domain = D.19425->domain;
    data.16 = data;
    D.19427 = MEM[(struct MonoObject *)data.16].vtable;
    klass = D.19427->klass;
    D.19428 = is_corlib_asyncresult (domain, klass);
    D.19429 = D.19428 == 0;
    is_io_task = (gboolean) D.19429;
    is_socket = 0;
    if (is_io_task != 0) goto <D.19430>; else goto <D.19431>;
    <D.19430>:
    {
      struct MonoSocketAsyncResult * state;

      state = data;
      is_socket = is_socketasyncresult (domain, klass);
      ar = state->ares;
      D.19432 = state->operation;
      switch (D.19432) <default: <D.19443>, case 2: <D.19072>, case 4: <D.19074>>
      <D.19072>:
      D.19433 = state->handle;
      D.19434 = (long int) D.19433;
      D.19435 = (unsigned int) D.19434;
      D.19436 = state->buffer;
      D.19437 = state->offset;
      D.19438 = state->size;
      D.19439 = state->socket_flags;
      D.19440 = &state->error;
      D.19441 = ves_icall_System_Net_Sockets_Socket_Receive_internal (D.19435, D.19436, D.19437, D.19438, D.19439, D.19440);
      state->total = D.19441;
      goto <D.19073>;
      <D.19074>:
      D.19433 = state->handle;
      D.19434 = (long int) D.19433;
      D.19435 = (unsigned int) D.19434;
      D.19436 = state->buffer;
      D.19437 = state->offset;
      D.19438 = state->size;
      D.19439 = state->socket_flags;
      D.19440 = &state->error;
      D.19442 = ves_icall_System_Net_Sockets_Socket_Send_internal (D.19435, D.19436, D.19437, D.19438, D.19439, D.19440);
      state->total = D.19442;
      goto <D.19073>;
      <D.19443>:
      <D.19073>:
    }
    <D.19431>:
    D.19444 = domain == 0B;
    D.19445 = (long int) D.19444;
    D.19446 = __builtin_expect (D.19445, 0);
    if (D.19446 != 0) goto <D.19447>; else goto <D.19448>;
    <D.19447>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 1492, "domain");
    <D.19448>:
    D.19452 = mono_domain_is_unloading (domain);
    if (D.19452 != 0) goto <D.19449>; else goto <D.19453>;
    <D.19453>:
    D.19454 = mono_runtime_is_shutting_down ();
    if (D.19454 != 0) goto <D.19449>; else goto <D.19450>;
    <D.19449>:
    threadpool_jobs_dec (ar);
    data = 0B;
    ar = 0B;
    D.19455 = &tp->busy_threads;
    InterlockedDecrement (D.19455);
    goto <D.19451>;
    <D.19450>:
    mono_thread_push_appdomain_ref (domain);
    D.19456 = threadpool_jobs_dec (ar);
    if (D.19456 != 0) goto <D.19457>; else goto <D.19458>;
    <D.19457>:
    data = 0B;
    ar = 0B;
    mono_thread_pop_appdomain_ref ();
    D.19459 = &tp->busy_threads;
    InterlockedDecrement (D.19459);
    // predicted unlikely by continue predictor.
    goto <D.19075>;
    <D.19458>:
    D.19460 = mono_domain_set (domain, 0);
    if (D.19460 != 0) goto <D.19461>; else goto <D.19462>;
    <D.19461>:
    {
      struct MonoObject * exc;

      tp_item_begin_func.17 = tp_item_begin_func;
      if (tp_item_begin_func.17 != 0B) goto <D.19464>; else goto <D.19465>;
      <D.19464>:
      tp_item_begin_func.17 = tp_item_begin_func;
      tp_item_user_data.18 = tp_item_user_data;
      tp_item_begin_func.17 (tp_item_user_data.18);
      <D.19465>:
      if (is_io_task == 0) goto <D.19467>; else goto <D.19468>;
      <D.19467>:
      D.19469 = ar->add_time;
      if (D.19469 > 0) goto <D.19470>; else goto <D.19471>;
      <D.19470>:
      D.19469 = ar->add_time;
      process_idle_times (tp, D.19469);
      <D.19471>:
      <D.19468>:
      exc = mono_async_invoke (tp, ar);
      tp_item_end_func.19 = tp_item_end_func;
      if (tp_item_end_func.19 != 0B) goto <D.19473>; else goto <D.19474>;
      <D.19473>:
      tp_item_end_func.19 = tp_item_end_func;
      tp_item_user_data.18 = tp_item_user_data;
      tp_item_end_func.19 (tp_item_user_data.18);
      <D.19474>:
      if (exc != 0B) goto <D.19475>; else goto <D.19476>;
      <D.19475>:
      mono_internal_thread_unhandled_exception (exc);
      <D.19476>:
      if (is_socket != 0) goto <D.19477>; else goto <D.19478>;
      <D.19477>:
      D.19415 = tp->is_io;
      if (D.19415 != 0) goto <D.19479>; else goto <D.19480>;
      <D.19479>:
      {
        struct MonoSocketAsyncResult * state;

        state = data;
        D.19481 = state->completed;
        if (D.19481 != 0) goto <D.19482>; else goto <D.19483>;
        <D.19482>:
        D.19484 = state->callback;
        if (D.19484 != 0B) goto <D.19485>; else goto <D.19486>;
        <D.19485>:
        {
          struct MonoAsyncResult * cb_ares;

          D.19484 = state->callback;
          cb_ares = create_simple_asyncresult (D.19484, state);
          icall_append_job (cb_ares);
        }
        <D.19486>:
        <D.19483>:
      }
      <D.19480>:
      <D.19478>:
      D.19487 = mono_get_root_domain ();
      mono_domain_set (D.19487, 1);
    }
    <D.19462>:
    mono_thread_pop_appdomain_ref ();
    D.19488 = &tp->busy_threads;
    InterlockedDecrement (D.19488);
    clear_thread_state ();
    <D.19451>:
    <D.19423>:
    ar = 0B;
    data = 0B;
    must_die = should_i_die (tp);
    if (must_die == 0) goto <D.19491>; else goto <D.19492>;
    <D.19491>:
    D.19415 = tp->is_io;
    if (D.19415 != 0) goto <D.19489>; else goto <D.19493>;
    <D.19493>:
    D.19494 = mono_wsq_local_pop (&data);
    if (D.19494 == 0) goto <D.19489>; else goto <D.19490>;
    <D.19489>:
    dequeue_or_steal (tp, &data, wsq);
    <D.19490>:
    <D.19492>:
    n_naps = 0;
    goto <D.19085>;
    <D.19084>:
    {
      gboolean res;

      D.19495 = &tp->waiting;
      InterlockedIncrement (D.19495);
      dequeue_or_steal (tp, &data, wsq);
      data.16 = data;
      if (data.16 != 0B) goto <D.19496>; else goto <D.19497>;
      <D.19496>:
      D.19498 = &tp->waiting;
      InterlockedDecrement (D.19498);
      goto <D.19080>;
      <D.19497>:
      mono_gc_set_skip_thread (1);
      goto <D.19083>;
      <D.19082>:
      D.19499 = mono_runtime_is_shutting_down ();
      if (D.19499 != 0) goto <D.19081>; else goto <D.19500>;
      <D.19500>:
      check_for_interruption_critical ();
      <D.19083>:
      D.19501 = tp->queue;
      D.19502 = mono_cq_count (D.19501);
      if (D.19502 == 0) goto <D.19503>; else goto <D.19081>;
      <D.19503>:
      D.19504 = &tp->new_job;
      res = mono_sem_timedwait (D.19504, 2000, 1);
      if (res == -1) goto <D.19082>; else goto <D.19081>;
      <D.19081>:
      D.19505 = &tp->waiting;
      InterlockedDecrement (D.19505);
      mono_gc_set_skip_thread (0);
      D.19506 = mono_runtime_is_shutting_down ();
      if (D.19506 != 0) goto <D.19080>; else goto <D.19507>;
      <D.19507>:
      must_die = should_i_die (tp);
      dequeue_or_steal (tp, &data, wsq);
      n_naps = n_naps + 1;
    }
    <D.19085>:
    if (must_die == 0) goto <D.19508>; else goto <D.19080>;
    <D.19508>:
    data.16 = data;
    if (data.16 == 0B) goto <D.19509>; else goto <D.19080>;
    <D.19509>:
    if (n_naps <= 3) goto <D.19084>; else goto <D.19080>;
    <D.19080>:
    data.16 = data;
    if (data.16 == 0B) goto <D.19510>; else goto <D.19511>;
    <D.19510>:
    D.19415 = tp->is_io;
    if (D.19415 == 0) goto <D.19512>; else goto <D.19513>;
    <D.19512>:
    D.19514 = mono_runtime_is_shutting_down ();
    if (D.19514 == 0) goto <D.19515>; else goto <D.19516>;
    <D.19515>:
    mono_wsq_local_pop (&data);
    data.16 = data;
    if (data.16 != 0B) goto <D.19517>; else goto <D.19518>;
    <D.19517>:
    if (must_die != 0) goto <D.19519>; else goto <D.19520>;
    <D.19519>:
    D.19521 = &tp->destroy_thread;
    InterlockedCompareExchange (D.19521, 1, 0);
    pulse_on_new_job (tp);
    <D.19520>:
    <D.19518>:
    <D.19516>:
    <D.19513>:
    <D.19511>:
    data.16 = data;
    if (data.16 == 0B) goto <D.19522>; else goto <D.19523>;
    <D.19522>:
    {
      gint nt;
      gboolean down;

      <D.19089>:
      nt = tp->nthreads;
      down = mono_runtime_is_shutting_down ();
      if (down == 0) goto <D.19524>; else goto <D.19525>;
      <D.19524>:
      D.19526 = tp->min_threads;
      if (D.19526 >= nt) goto <D.19088>; else goto <D.19527>;
      <D.19527>:
      <D.19525>:
      if (down != 0) goto <D.19528>; else goto <D.19530>;
      <D.19530>:
      D.19531 = &tp->nthreads;
      D.19532 = nt + -1;
      D.19533 = InterlockedCompareExchange (D.19531, D.19532, nt);
      if (D.19533 == nt) goto <D.19528>; else goto <D.19529>;
      <D.19528>:
      D.19534 = tp->pc_nthreads;
      mono_perfcounter_update_value (D.19534, 1, -1);
      D.19415 = tp->is_io;
      if (D.19415 == 0) goto <D.19535>; else goto <D.19536>;
      <D.19535>:
      remove_wsq (wsq);
      <D.19536>:
      fire_profiler_thread_end ();
      tp_finish_func.20 = tp_finish_func;
      if (tp_finish_func.20 != 0B) goto <D.19538>; else goto <D.19539>;
      <D.19538>:
      tp_finish_func.20 = tp_finish_func;
      tp_hooks_user_data.15 = tp_hooks_user_data;
      tp_finish_func.20 (tp_hooks_user_data.15);
      <D.19539>:
      return;
      <D.19529>:
      goto <D.19089>;
      <D.19088>:
    }
    <D.19523>:
  }
  <D.19075>:
  goto <D.19090>;
  monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "threadpool.c", 1616);
}


add_wsq ()
{
  _Bool D.19543;
  long int D.19544;
  long int D.19545;
  struct GPtrArray * wsqs.21;
  _Bool D.19553;
  long int D.19554;
  long int D.19555;
  struct MonoWSQ * D.19558;
  void * * D.19559;
  long unsigned int D.19560;
  long unsigned int D.19561;
  void * * D.19562;
  void * D.19563;
  _Bool D.19568;
  long int D.19569;
  long int D.19570;
  unsigned int D.19573;
  unsigned int i.22;
  _Bool D.19577;
  long int D.19578;
  long int D.19579;
  int i;
  struct MonoWSQ * wsq;

  {
    int ret;

    ret = pthread_mutex_lock (&wsqs_lock.mutex);
    if (ret != 0) goto <D.19541>; else goto <D.19542>;
    <D.19541>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.19542>:
    D.19543 = ret != 0;
    D.19544 = (long int) D.19543;
    D.19545 = __builtin_expect (D.19544, 0);
    if (D.19545 != 0) goto <D.19546>; else goto <D.19547>;
    <D.19546>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 1221, "ret == 0");
    <D.19547>:
  }
  wsq = mono_wsq_create ();
  wsqs.21 = wsqs;
  if (wsqs.21 == 0B) goto <D.19549>; else goto <D.19550>;
  <D.19549>:
  {
    int ret;

    ret = pthread_mutex_unlock (&wsqs_lock.mutex);
    if (ret != 0) goto <D.19551>; else goto <D.19552>;
    <D.19551>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.19552>:
    D.19553 = ret != 0;
    D.19554 = (long int) D.19553;
    D.19555 = __builtin_expect (D.19554, 0);
    if (D.19555 != 0) goto <D.19556>; else goto <D.19557>;
    <D.19556>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 1224, "ret == 0");
    <D.19557>:
  }
  D.19558 = 0B;
  return D.19558;
  <D.19550>:
  i = 0;
  goto <D.18990>;
  <D.18989>:
  wsqs.21 = wsqs;
  D.19559 = wsqs.21->pdata;
  D.19560 = (long unsigned int) i;
  D.19561 = D.19560 * 8;
  D.19562 = D.19559 + D.19561;
  D.19563 = *D.19562;
  if (D.19563 == 0B) goto <D.19564>; else goto <D.19565>;
  <D.19564>:
  wsqs.21 = wsqs;
  D.19559 = wsqs.21->pdata;
  D.19560 = (long unsigned int) i;
  D.19561 = D.19560 * 8;
  D.19562 = D.19559 + D.19561;
  *D.19562 = wsq;
  {
    int ret;

    ret = pthread_mutex_unlock (&wsqs_lock.mutex);
    if (ret != 0) goto <D.19566>; else goto <D.19567>;
    <D.19566>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.19567>:
    D.19568 = ret != 0;
    D.19569 = (long int) D.19568;
    D.19570 = __builtin_expect (D.19569, 0);
    if (D.19570 != 0) goto <D.19571>; else goto <D.19572>;
    <D.19571>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 1230, "ret == 0");
    <D.19572>:
  }
  D.19558 = wsq;
  return D.19558;
  <D.19565>:
  i = i + 1;
  <D.18990>:
  wsqs.21 = wsqs;
  D.19573 = wsqs.21->len;
  i.22 = (unsigned int) i;
  if (D.19573 > i.22) goto <D.18989>; else goto <D.18991>;
  <D.18991>:
  wsqs.21 = wsqs;
  monoeg_g_ptr_array_add (wsqs.21, wsq);
  {
    int ret;

    ret = pthread_mutex_unlock (&wsqs_lock.mutex);
    if (ret != 0) goto <D.19575>; else goto <D.19576>;
    <D.19575>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.19576>:
    D.19577 = ret != 0;
    D.19578 = (long int) D.19577;
    D.19579 = __builtin_expect (D.19578, 0);
    if (D.19579 != 0) goto <D.19580>; else goto <D.19581>;
    <D.19580>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 1235, "ret == 0");
    <D.19581>:
  }
  D.19558 = wsq;
  return D.19558;
}


set_tp_thread_info (struct ThreadPool * tp)
{
  long unsigned int D.19583;
  const gchar * iftmp.23;
  int D.19585;
  struct MonoDomain * D.19589;
  struct MonoString * D.19590;
  const gchar * name;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  D.19583 = thread->tid;
  mono_profiler_thread_start (D.19583);
  D.19585 = tp->is_io;
  if (D.19585 != 0) goto <D.19586>; else goto <D.19587>;
  <D.19586>:
  iftmp.23 = "IO Threadpool worker";
  goto <D.19588>;
  <D.19587>:
  iftmp.23 = "Threadpool worker";
  <D.19588>:
  name = iftmp.23;
  D.19589 = mono_domain_get ();
  D.19590 = mono_string_new (D.19589, name);
  mono_thread_set_name_internal (thread, D.19590, 0);
}


is_corlib_asyncresult (struct MonoDomain * domain, struct MonoClass * klass)
{
  struct MonoClass * D.19591;
  gboolean D.19594;
  _Bool D.19595;
  int D.19596;
  const char * D.19599;
  int D.19600;
  const char * D.19603;
  int D.19604;

  D.19591 = domain->corlib_asyncresult_class;
  if (D.19591 != 0B) goto <D.19592>; else goto <D.19593>;
  <D.19592>:
  D.19591 = domain->corlib_asyncresult_class;
  D.19595 = D.19591 == klass;
  D.19594 = (gboolean) D.19595;
  return D.19594;
  <D.19593>:
  D.19596 = is_corlib_type (domain, klass);
  if (D.19596 != 0) goto <D.19597>; else goto <D.19598>;
  <D.19597>:
  D.19599 = klass->name;
  D.19600 = strcmp ("AsyncResult", D.19599);
  if (D.19600 == 0) goto <D.19601>; else goto <D.19602>;
  <D.19601>:
  D.19603 = klass->name_space;
  D.19604 = strcmp ("System.Runtime.Remoting.Messaging", D.19603);
  if (D.19604 == 0) goto <D.19605>; else goto <D.19606>;
  <D.19605>:
  domain->corlib_asyncresult_class = klass;
  D.19594 = 1;
  return D.19594;
  <D.19606>:
  <D.19602>:
  <D.19598>:
  D.19594 = 0;
  return D.19594;
}


is_corlib_type (struct MonoDomain * domain, struct MonoClass * klass)
{
  gboolean D.19608;
  struct MonoImage * D.19609;
  struct MonoImage * D.19610;
  _Bool D.19611;

  D.19609 = klass->image;
  D.19610 = mono_defaults.corlib;
  D.19611 = D.19609 == D.19610;
  D.19608 = (gboolean) D.19611;
  return D.19608;
}


__attribute__((__gnu_inline__, nothrow, leaf, pure))
strcmp (const char * __s1, const char * __s2)
{
  int iftmp.24;
  int iftmp.25;
  int D.19621;
  char * __p1;
  char * __p2;
  int __ret;

  __p1 = __s1;
  __p2 = __s2;
  __asm__ __volatile__("   slr   0,0
0: clst  %1,%2
   jo    0b
   ipm   %0
   srl   %0,28" : "=d" __ret, "=&a" __p1, "=&a" __p2 : "1" __p1, "2" __p2 : "0", "memory", "cc");
  if (__ret != 0) goto <D.19614>; else goto <D.19615>;
  <D.19614>:
  if (__ret == 1) goto <D.19617>; else goto <D.19618>;
  <D.19617>:
  iftmp.25 = -1;
  goto <D.19619>;
  <D.19618>:
  iftmp.25 = 1;
  <D.19619>:
  iftmp.24 = iftmp.25;
  goto <D.19620>;
  <D.19615>:
  iftmp.24 = 0;
  <D.19620>:
  __ret = iftmp.24;
  D.19621 = __ret;
  return D.19621;
}


is_socketasyncresult (struct MonoDomain * domain, struct MonoClass * klass)
{
  gboolean D.19623;
  int iftmp.26;
  struct MonoClass * D.19627;
  int D.19629;
  const char * D.19631;
  int D.19632;

  D.19627 = klass->nested_in;
  if (D.19627 != 0B) goto <D.19628>; else goto <D.19625>;
  <D.19628>:
  D.19627 = klass->nested_in;
  D.19629 = is_socket (domain, D.19627);
  if (D.19629 != 0) goto <D.19630>; else goto <D.19625>;
  <D.19630>:
  D.19631 = klass->name;
  D.19632 = strcmp (D.19631, "SocketAsyncResult");
  if (D.19632 == 0) goto <D.19633>; else goto <D.19625>;
  <D.19633>:
  iftmp.26 = 1;
  goto <D.19626>;
  <D.19625>:
  iftmp.26 = 0;
  <D.19626>:
  D.19623 = iftmp.26;
  return D.19623;
}


is_socket (struct MonoDomain * domain, struct MonoClass * klass)
{
  struct MonoClass * D.19635;
  gboolean D.19638;
  _Bool D.19639;
  int D.19640;
  const char * D.19643;
  int D.19644;
  const char * D.19647;
  int D.19648;

  D.19635 = domain->socket_class;
  if (D.19635 != 0B) goto <D.19636>; else goto <D.19637>;
  <D.19636>:
  D.19635 = domain->socket_class;
  D.19639 = D.19635 == klass;
  D.19638 = (gboolean) D.19639;
  return D.19638;
  <D.19637>:
  D.19640 = is_socket_type (domain, klass);
  if (D.19640 != 0) goto <D.19641>; else goto <D.19642>;
  <D.19641>:
  D.19643 = klass->name;
  D.19644 = strcmp ("Socket", D.19643);
  if (D.19644 == 0) goto <D.19645>; else goto <D.19646>;
  <D.19645>:
  D.19647 = klass->name_space;
  D.19648 = strcmp ("System.Net.Sockets", D.19647);
  if (D.19648 == 0) goto <D.19649>; else goto <D.19650>;
  <D.19649>:
  domain->socket_class = klass;
  D.19638 = 1;
  return D.19638;
  <D.19650>:
  <D.19646>:
  <D.19642>:
  D.19638 = 0;
  return D.19638;
}


is_socket_type (struct MonoDomain * domain, struct MonoClass * klass)
{
  gboolean D.19652;

  D.19652 = is_system_type (domain, klass);
  return D.19652;
}


is_system_type (struct MonoDomain * domain, struct MonoClass * klass)
{
  struct MonoImage * D.19654;
  struct MonoImage * D.19657;
  gboolean D.19658;
  struct MonoImage * D.19659;
  _Bool D.19660;

  D.19654 = domain->system_image;
  if (D.19654 == 0B) goto <D.19655>; else goto <D.19656>;
  <D.19655>:
  D.19657 = mono_image_loaded ("System");
  domain->system_image = D.19657;
  <D.19656>:
  D.19659 = klass->image;
  D.19654 = domain->system_image;
  D.19660 = D.19659 == D.19654;
  D.19658 = (gboolean) D.19660;
  return D.19658;
}


threadpool_jobs_dec (struct MonoObject * obj)
{
  gboolean D.19664;
  struct MonoVTable * D.19665;
  volatile int * D.19666;
  void * D.19669;
  struct MonoDomain * domain;
  int remaining_jobs;

  if (obj == 0B) goto <D.19662>; else goto <D.19663>;
  <D.19662>:
  D.19664 = 0;
  return D.19664;
  <D.19663>:
  D.19665 = obj->vtable;
  domain = D.19665->domain;
  D.19666 = &domain->threadpool_jobs;
  remaining_jobs = InterlockedDecrement (D.19666);
  if (remaining_jobs == 0) goto <D.19667>; else goto <D.19668>;
  <D.19667>:
  D.19669 = domain->cleanup_semaphore;
  if (D.19669 != 0B) goto <D.19670>; else goto <D.19671>;
  <D.19670>:
  D.19669 = domain->cleanup_semaphore;
  ReleaseSemaphore (D.19669, 1, 0B);
  D.19664 = 1;
  return D.19664;
  <D.19671>:
  <D.19668>:
  D.19664 = 0;
  return D.19664;
}


process_idle_times (struct ThreadPool * tp, gint64 t)
{
  int D.19675;
  volatile gint * D.19677;
  int D.19678;
  int D.19680;
  long int D.19683;
  long int D.19684;
  int D.19685;
  int D.19686;
  long int D.19687;
  long int D.19691;
  long int D.19694;
  long int D.19695;
  long int D.19700;
  int D.19701;
  long int D.19702;
  long int D.19703;
  long int D.19707;
  long int D.19708;
  long int D.19709;
  long int D.19714;
  int D.19724;
  int D.19727;
  int D.19732;
  volatile gint * D.19735;
  int D.19736;
  gint64 ticks;
  gint64 avg;
  gboolean compute_avg;
  gint new_threads;
  gint64 per1;

  D.19675 = tp->ignore_times;
  if (D.19675 != 0) goto <D.19673>; else goto <D.19676>;
  <D.19676>:
  if (t <= 0) goto <D.19673>; else goto <D.19674>;
  <D.19673>:
  return;
  <D.19674>:
  compute_avg = 0;
  ticks = mono_100ns_ticks ();
  t = ticks - t;
  <D.19035>:
  D.19677 = &tp->sp_lock;
  D.19678 = InterlockedCompareExchange (D.19677, 1, 0);
  if (D.19678 == 0) goto <D.19034>; else goto <D.19679>;
  <D.19679>:
  goto <D.19035>;
  <D.19034>:
  D.19680 = tp->ignore_times;
  if (D.19680 != 0) goto <D.19681>; else goto <D.19682>;
  <D.19681>:
  tp->sp_lock = 0;
  return;
  <D.19682>:
  D.19683 = tp->time_sum;
  D.19684 = D.19683 + t;
  tp->time_sum = D.19684;
  D.19685 = tp->n_sum;
  D.19686 = D.19685 + 1;
  tp->n_sum = D.19686;
  D.19687 = tp->last_check;
  if (D.19687 == 0) goto <D.19688>; else goto <D.19689>;
  <D.19688>:
  tp->last_check = ticks;
  goto <D.19690>;
  <D.19689>:
  D.19691 = tp->last_check;
  if (D.19691 > 0) goto <D.19692>; else goto <D.19693>;
  <D.19692>:
  D.19694 = tp->last_check;
  D.19695 = ticks - D.19694;
  if (D.19695 > 5000000) goto <D.19696>; else goto <D.19697>;
  <D.19696>:
  tp->ignore_times = 1;
  compute_avg = 1;
  <D.19697>:
  <D.19693>:
  <D.19690>:
  tp->sp_lock = 0;
  if (compute_avg == 0) goto <D.19698>; else goto <D.19699>;
  <D.19698>:
  return;
  <D.19699>:
  tp->last_check = ticks;
  new_threads = 0;
  D.19700 = tp->time_sum;
  D.19701 = tp->n_sum;
  D.19702 = (long int) D.19701;
  avg = D.19700 / D.19702;
  D.19703 = tp->averages[1];
  if (D.19703 == 0) goto <D.19704>; else goto <D.19705>;
  <D.19704>:
  tp->averages[1] = avg;
  goto <D.19706>;
  <D.19705>:
  D.19703 = tp->averages[1];
  D.19707 = avg - D.19703;
  D.19708 = ABS_EXPR <D.19707>;
  D.19709 = D.19708 * 100;
  D.19703 = tp->averages[1];
  per1 = D.19709 / D.19703;
  if (per1 > 5) goto <D.19710>; else goto <D.19711>;
  <D.19710>:
  D.19703 = tp->averages[1];
  if (D.19703 < avg) goto <D.19712>; else goto <D.19713>;
  <D.19712>:
  D.19703 = tp->averages[1];
  D.19714 = tp->averages[0];
  if (D.19703 < D.19714) goto <D.19715>; else goto <D.19716>;
  <D.19715>:
  new_threads = -1;
  goto <D.19717>;
  <D.19716>:
  new_threads = 1;
  <D.19717>:
  goto <D.19718>;
  <D.19713>:
  D.19703 = tp->averages[1];
  if (D.19703 > avg) goto <D.19719>; else goto <D.19720>;
  <D.19719>:
  D.19703 = tp->averages[1];
  D.19714 = tp->averages[0];
  if (D.19703 < D.19714) goto <D.19721>; else goto <D.19722>;
  <D.19721>:
  new_threads = 1;
  <D.19722>:
  <D.19720>:
  <D.19718>:
  goto <D.19723>;
  <D.19711>:
  {
    int min;
    int n;

    min = tp->min_threads;
    n = tp->nthreads;
    D.19724 = n - min;
    if (D.19724 < min) goto <D.19725>; else goto <D.19726>;
    <D.19725>:
    D.19727 = tp->busy_threads;
    if (D.19727 == n) goto <D.19728>; else goto <D.19729>;
    <D.19728>:
    new_threads = 1;
    <D.19729>:
    <D.19726>:
  }
  <D.19723>:
  <D.19706>:
  tp->time_sum = 0;
  tp->n_sum = 0;
  D.19703 = tp->averages[1];
  tp->averages[0] = D.19703;
  tp->averages[1] = avg;
  tp->ignore_times = 0;
  if (new_threads == -1) goto <D.19730>; else goto <D.19731>;
  <D.19730>:
  D.19732 = tp->destroy_thread;
  if (D.19732 == 0) goto <D.19733>; else goto <D.19734>;
  <D.19733>:
  D.19735 = &tp->destroy_thread;
  D.19736 = InterlockedCompareExchange (D.19735, 1, 0);
  if (D.19736 == 0) goto <D.19737>; else goto <D.19738>;
  <D.19737>:
  pulse_on_new_job (tp);
  <D.19738>:
  <D.19734>:
  <D.19731>:
}


mono_async_invoke (struct ThreadPool * tp, struct MonoAsyncResult * ares)
{
  struct MonoAsyncResult * ares.27;
  struct MonoObject * D.19741;
  struct MonoObject * * D.19744;
  struct MonoObject * D.19745;
  struct MonoObject * pa.28;
  struct MonoObject * D.19750;
  struct MonoMethod * D.19751;
  struct MonoMethodMessage * D.19753;
  struct MonoObject * * D.19754;
  struct MonoObject * * D.19755;
  struct MonoObject * exc.29;
  struct MonoArray * * D.19757;
  struct MonoArray * out_args.30;
  struct MonoObject * D.19759;
  struct MonoMethod * D.19767;
  struct MonoDelegate * D.19769;
  struct MonoObject * cb_exc.31;
  struct MonoObject * D.19771;
  struct MonoObject * D.19774;
  struct ASyncCall * ac;
  struct MonoObject * res;
  struct MonoObject * exc;
  struct MonoArray * out_args;
  void * wait_event;
  struct MonoInternalThread * thread;

  try
    {
      ares.27 = ares;
      ac = ares.27->object_data;
      exc = 0B;
      out_args = 0B;
      wait_event = 0B;
      thread = mono_thread_internal_current ();
      ares.27 = ares;
      D.19741 = ares.27->execution_context;
      if (D.19741 != 0B) goto <D.19742>; else goto <D.19743>;
      <D.19742>:
      ares.27 = ares;
      ares.27 = ares;
      D.19744 = &ares.27->original_context;
      D.19745 = mono_thread_get_execution_context ();
      mono_gc_wbarrier_set_field (ares.27, D.19744, D.19745);
      ares.27 = ares;
      D.19741 = ares.27->execution_context;
      mono_thread_set_execution_context (D.19741);
      goto <D.19746>;
      <D.19743>:
      ares.27 = ares;
      ares.27->original_context = 0B;
      <D.19746>:
      if (ac == 0B) goto <D.19747>; else goto <D.19748>;
      <D.19747>:
      {
        void * pa;

        try
          {
            ares.27 = ares;
            pa.28 = ares.27->async_state;
            pa = pa.28;
            ares.27 = ares;
            D.19750 = ares.27->async_delegate;
            D.19751 = MEM[(struct MonoDelegate *)D.19750].method;
            thread->async_invoke_method = D.19751;
            ares.27 = ares;
            D.19750 = ares.27->async_delegate;
            res = mono_runtime_delegate_invoke (D.19750, &pa, &exc);
            thread->async_invoke_method = 0B;
          }
        finally
          {
            pa = {CLOBBER};
          }
      }
      goto <D.19752>;
      <D.19748>:
      {
        struct MonoObject * cb_exc;

        try
          {
            cb_exc = 0B;
            D.19753 = ac->msg;
            D.19753->exc = 0B;
            ares.27 = ares;
            D.19750 = ares.27->async_delegate;
            D.19753 = ac->msg;
            res = mono_message_invoke (D.19750, D.19753, &exc, &out_args);
            D.19754 = &ac->res;
            mono_gc_wbarrier_set_field (ac, D.19754, res);
            D.19753 = ac->msg;
            D.19755 = &D.19753->exc;
            exc.29 = exc;
            mono_gc_wbarrier_set_field (ac, D.19755, exc.29);
            D.19757 = &ac->out_args;
            out_args.30 = out_args;
            mono_gc_wbarrier_set_field (ac, D.19757, out_args.30);
            ares.27 = ares;
            mono_monitor_enter (ares.27);
            ares.27 = ares;
            ares.27->completed = 1;
            ares.27 = ares;
            D.19759 = ares.27->handle;
            if (D.19759 != 0B) goto <D.19760>; else goto <D.19761>;
            <D.19760>:
            ares.27 = ares;
            D.19759 = ares.27->handle;
            wait_event = mono_wait_handle_get_handle (D.19759);
            <D.19761>:
            ares.27 = ares;
            mono_monitor_exit (ares.27);
            if (wait_event != 0B) goto <D.19762>; else goto <D.19763>;
            <D.19762>:
            SetEvent (wait_event);
            <D.19763>:
            if (ac != 0B) goto <D.19766>; else goto <D.19764>;
            <D.19766>:
            D.19767 = ac->cb_method;
            if (D.19767 != 0B) goto <D.19768>; else goto <D.19764>;
            <D.19768>:
            {
              void * pa;

              pa = &ares;
              cb_exc = 0B;
              D.19767 = ac->cb_method;
              thread->async_invoke_method = D.19767;
              D.19767 = ac->cb_method;
              D.19769 = ac->cb_target;
              mono_runtime_invoke (D.19767, D.19769, pa, &cb_exc);
              thread->async_invoke_method = 0B;
              cb_exc.31 = cb_exc;
              exc = cb_exc.31;
            }
            goto <D.19765>;
            <D.19764>:
            exc = 0B;
            <D.19765>:
          }
        finally
          {
            cb_exc = {CLOBBER};
          }
      }
      <D.19752>:
      ares.27 = ares;
      D.19771 = ares.27->original_context;
      if (D.19771 != 0B) goto <D.19772>; else goto <D.19773>;
      <D.19772>:
      ares.27 = ares;
      D.19771 = ares.27->original_context;
      mono_thread_set_execution_context (D.19771);
      ares.27 = ares;
      ares.27->original_context = 0B;
      <D.19773>:
      D.19774 = exc;
      return D.19774;
    }
  finally
    {
      exc = {CLOBBER};
      out_args = {CLOBBER};
    }
}


create_simple_asyncresult (struct MonoObject * target, struct MonoObject * state)
{
  struct MonoClass * D.19777;
  struct MonoObject * * D.19778;
  struct MonoObject * * D.19779;
  struct MonoAsyncResult * D.19780;
  struct MonoDomain * domain;
  struct MonoAsyncResult * ares;

  domain = mono_domain_get ();
  D.19777 = mono_defaults.asyncresult_class;
  ares = mono_object_new (domain, D.19777);
  D.19778 = &ares->async_delegate;
  mono_gc_wbarrier_set_field (ares, D.19778, target);
  D.19779 = &ares->async_state;
  mono_gc_wbarrier_set_field (ares, D.19779, state);
  D.19780 = ares;
  return D.19780;
}


clear_thread_state ()
{
  int D.19782;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  mono_thread_clr_state (thread, 4294967291);
  D.19782 = mono_thread_test_state (thread, 4);
  if (D.19782 == 0) goto <D.19783>; else goto <D.19784>;
  <D.19783>:
  ves_icall_System_Threading_Thread_SetState (thread, 4);
  <D.19784>:
}


check_for_interruption_critical ()
{
  unsigned int D.19785;
  unsigned int D.19786;
  struct MonoInternalThread * thread;

  mono_gc_set_skip_thread (0);
  thread = mono_thread_internal_current ();
  D.19785 = thread->state;
  D.19786 = D.19785 & 3;
  if (D.19786 != 0) goto <D.19787>; else goto <D.19788>;
  <D.19787>:
  mono_thread_interruption_checkpoint ();
  <D.19788>:
  mono_gc_set_skip_thread (1);
}


InterlockedDecrement (volatile gint32 * val)
{
  gint32 D.19789;
  unsigned int D.19790;

  D.19790 = __sync_sub_and_fetch_4 (val, 1);
  D.19789 = (gint32) D.19790;
  return D.19789;
}


should_i_die (struct ThreadPool * tp)
{
  int D.19792;
  volatile gint * D.19795;
  int D.19796;
  int D.19799;
  int D.19800;
  _Bool D.19801;
  gboolean D.19802;
  gboolean result;

  result = 0;
  D.19792 = tp->destroy_thread;
  if (D.19792 == 1) goto <D.19793>; else goto <D.19794>;
  <D.19793>:
  D.19795 = &tp->destroy_thread;
  D.19796 = InterlockedCompareExchange (D.19795, 0, 1);
  if (D.19796 == 1) goto <D.19797>; else goto <D.19798>;
  <D.19797>:
  D.19799 = tp->nthreads;
  D.19800 = tp->min_threads;
  D.19801 = D.19799 > D.19800;
  result = (gboolean) D.19801;
  <D.19798>:
  <D.19794>:
  D.19802 = result;
  return D.19802;
}


dequeue_or_steal (struct ThreadPool * tp, void * * data, struct MonoWSQ * local_wsq)
{
  int D.19804;
  gboolean D.19807;
  struct MonoCQ * D.19808;
  int D.19809;
  void * D.19812;
  _Bool D.19815;

  D.19804 = mono_runtime_is_shutting_down ();
  if (D.19804 != 0) goto <D.19805>; else goto <D.19806>;
  <D.19805>:
  D.19807 = 0;
  return D.19807;
  <D.19806>:
  D.19808 = tp->queue;
  mono_cq_dequeue (D.19808, data);
  D.19809 = tp->is_io;
  if (D.19809 == 0) goto <D.19810>; else goto <D.19811>;
  <D.19810>:
  D.19812 = *data;
  if (D.19812 == 0B) goto <D.19813>; else goto <D.19814>;
  <D.19813>:
  try_steal (local_wsq, data, 0);
  <D.19814>:
  <D.19811>:
  D.19812 = *data;
  D.19815 = D.19812 != 0B;
  D.19807 = (gboolean) D.19815;
  return D.19807;
}


try_steal (struct MonoWSQ * local_wsq, void * * data, gboolean retry)
{
  struct GPtrArray * wsqs.32;
  void * D.19822;
  int D.19823;
  _Bool D.19828;
  long int D.19829;
  long int D.19830;
  void * * D.19833;
  long unsigned int D.19834;
  long unsigned int D.19835;
  void * * D.19836;
  int D.19840;
  void * D.19841;
  unsigned int ms.33;
  _Bool D.19847;
  long int D.19848;
  long int D.19849;
  unsigned int D.19853;
  unsigned int i.34;
  _Bool D.19857;
  long int D.19858;
  long int D.19859;
  int i;
  int ms;

  wsqs.32 = wsqs;
  if (wsqs.32 == 0B) goto <D.19817>; else goto <D.19820>;
  <D.19820>:
  if (data == 0B) goto <D.19817>; else goto <D.19821>;
  <D.19821>:
  D.19822 = *data;
  if (D.19822 != 0B) goto <D.19817>; else goto <D.19818>;
  <D.19817>:
  return;
  <D.19818>:
  ms = 0;
  <D.19018>:
  D.19823 = mono_runtime_is_shutting_down ();
  if (D.19823 != 0) goto <D.19824>; else goto <D.19825>;
  <D.19824>:
  return;
  <D.19825>:
  {
    int ret;

    ret = pthread_mutex_lock (&wsqs_lock.mutex);
    if (ret != 0) goto <D.19826>; else goto <D.19827>;
    <D.19826>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.19827>:
    D.19828 = ret != 0;
    D.19829 = (long int) D.19828;
    D.19830 = __builtin_expect (D.19829, 0);
    if (D.19830 != 0) goto <D.19831>; else goto <D.19832>;
    <D.19831>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 1282, "ret == 0");
    <D.19832>:
  }
  i = 0;
  goto <D.19015>;
  <D.19014>:
  {
    struct MonoWSQ * wsq;

    wsqs.32 = wsqs;
    D.19833 = wsqs.32->pdata;
    D.19834 = (long unsigned int) i;
    D.19835 = D.19834 * 8;
    D.19836 = D.19833 + D.19835;
    wsq = *D.19836;
    if (wsq == local_wsq) goto <D.19837>; else goto <D.19839>;
    <D.19839>:
    D.19840 = mono_wsq_count (wsq);
    if (D.19840 == 0) goto <D.19837>; else goto <D.19838>;
    <D.19837>:
    // predicted unlikely by continue predictor.
    goto <D.19012>;
    <D.19838>:
    wsqs.32 = wsqs;
    D.19833 = wsqs.32->pdata;
    D.19834 = (long unsigned int) i;
    D.19835 = D.19834 * 8;
    D.19836 = D.19833 + D.19835;
    D.19841 = *D.19836;
    ms.33 = (unsigned int) ms;
    mono_wsq_try_steal (D.19841, data, ms.33);
    D.19822 = *data;
    if (D.19822 != 0B) goto <D.19843>; else goto <D.19844>;
    <D.19843>:
    {
      int ret;

      ret = pthread_mutex_unlock (&wsqs_lock.mutex);
      if (ret != 0) goto <D.19845>; else goto <D.19846>;
      <D.19845>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.19846>:
      D.19847 = ret != 0;
      D.19848 = (long int) D.19847;
      D.19849 = __builtin_expect (D.19848, 0);
      if (D.19849 != 0) goto <D.19850>; else goto <D.19851>;
      <D.19850>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 1291, "ret == 0");
      <D.19851>:
    }
    return;
    <D.19844>:
  }
  <D.19012>:
  i = i + 1;
  <D.19015>:
  wsqs.32 = wsqs;
  if (wsqs.32 != 0B) goto <D.19852>; else goto <D.19016>;
  <D.19852>:
  wsqs.32 = wsqs;
  D.19853 = wsqs.32->len;
  i.34 = (unsigned int) i;
  if (D.19853 > i.34) goto <D.19014>; else goto <D.19016>;
  <D.19016>:
  {
    int ret;

    ret = pthread_mutex_unlock (&wsqs_lock.mutex);
    if (ret != 0) goto <D.19855>; else goto <D.19856>;
    <D.19855>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.19856>:
    D.19857 = ret != 0;
    D.19858 = (long int) D.19857;
    D.19859 = __builtin_expect (D.19858, 0);
    if (D.19859 != 0) goto <D.19860>; else goto <D.19861>;
    <D.19860>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 1295, "ret == 0");
    <D.19861>:
  }
  ms = ms + 10;
  if (retry != 0) goto <D.19862>; else goto <D.19019>;
  <D.19862>:
  if (ms <= 10) goto <D.19018>; else goto <D.19019>;
  <D.19019>:
}


remove_wsq (struct MonoWSQ * wsq)
{
  _Bool D.19868;
  long int D.19869;
  long int D.19870;
  struct GPtrArray * wsqs.35;
  _Bool D.19878;
  long int D.19879;
  long int D.19880;
  int D.19883;
  void * data.36;
  int D.19887;
  _Bool D.19890;
  long int D.19891;
  long int D.19892;
  void * data;

  try
    {
      if (wsq == 0B) goto <D.19864>; else goto <D.19865>;
      <D.19864>:
      return;
      <D.19865>:
      {
        int ret;

        ret = pthread_mutex_lock (&wsqs_lock.mutex);
        if (ret != 0) goto <D.19866>; else goto <D.19867>;
        <D.19866>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.19867>:
        D.19868 = ret != 0;
        D.19869 = (long int) D.19868;
        D.19870 = __builtin_expect (D.19869, 0);
        if (D.19870 != 0) goto <D.19871>; else goto <D.19872>;
        <D.19871>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 1247, "ret == 0");
        <D.19872>:
      }
      wsqs.35 = wsqs;
      if (wsqs.35 == 0B) goto <D.19874>; else goto <D.19875>;
      <D.19874>:
      {
        int ret;

        ret = pthread_mutex_unlock (&wsqs_lock.mutex);
        if (ret != 0) goto <D.19876>; else goto <D.19877>;
        <D.19876>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.19877>:
        D.19878 = ret != 0;
        D.19879 = (long int) D.19878;
        D.19880 = __builtin_expect (D.19879, 0);
        if (D.19880 != 0) goto <D.19881>; else goto <D.19882>;
        <D.19881>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 1249, "ret == 0");
        <D.19882>:
      }
      return;
      <D.19875>:
      wsqs.35 = wsqs;
      monoeg_g_ptr_array_remove_fast (wsqs.35, wsq);
      data = 0B;
      D.19883 = mono_runtime_is_shutting_down ();
      if (D.19883 != 0) goto <D.19884>; else goto <D.19885>;
      <D.19884>:
      goto <D.19000>;
      <D.18999>:
      data.36 = data;
      threadpool_jobs_dec (data.36);
      data = 0B;
      <D.19000>:
      D.19887 = mono_wsq_local_pop (&data);
      if (D.19887 != 0) goto <D.18999>; else goto <D.19001>;
      <D.19001>:
      <D.19885>:
      mono_wsq_destroy (wsq);
      {
        int ret;

        ret = pthread_mutex_unlock (&wsqs_lock.mutex);
        if (ret != 0) goto <D.19888>; else goto <D.19889>;
        <D.19888>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.19889>:
        D.19890 = ret != 0;
        D.19891 = (long int) D.19890;
        D.19892 = __builtin_expect (D.19891, 0);
        if (D.19892 != 0) goto <D.19893>; else goto <D.19894>;
        <D.19893>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 1265, "ret == 0");
        <D.19894>:
      }
    }
  finally
    {
      data = {CLOBBER};
    }
}


fire_profiler_thread_end ()
{
  long unsigned int D.19898;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  D.19898 = thread->tid;
  mono_profiler_thread_end (D.19898);
}


__attribute__((__gnu_inline__, __pure__, __leaf__, __nothrow__))
atoi (const char * __nptr)
{
  int D.19899;
  long int D.19900;

  D.19900 = strtol (__nptr, 0B, 10);
  D.19899 = (int) D.19900;
  return D.19899;
}


threadpool_init (struct ThreadPool * tp, int min_threads, int max_threads, void (*<Tce2>) (void *) async_invoke)
{
  struct MonoCQ * D.19902;
  union MonoSemType * D.19903;

  memset (tp, 0, 184);
  tp->min_threads = min_threads;
  tp->max_threads = max_threads;
  tp->async_invoke = async_invoke;
  D.19902 = mono_cq_create ();
  tp->queue = D.19902;
  D.19903 = &tp->new_job;
  sem_init (D.19903, 0, 0);
}


__attribute__((__artificial__, __gnu_inline__, __always_inline__, __nothrow__, __leaf__))
memset (void * __dest, int __ch, size_t __len)
{
  void * D.19904;
  long unsigned int D.19905;

  D.19905 = __builtin_object_size (__dest, 0);
  D.19904 = __builtin___memset_chk (__dest, __ch, __len, D.19905);
  return D.19904;
}


init_perf_counter (const char * category, const char * counter)
{
  void * D.19910;
  struct MonoString * category_str;
  struct MonoString * counter_str;
  struct MonoString * machine;
  struct MonoDomain * root;
  MonoBoolean custom;
  int type;

  try
    {
      if (category == 0B) goto <D.19907>; else goto <D.19909>;
      <D.19909>:
      if (counter == 0B) goto <D.19907>; else goto <D.19908>;
      <D.19907>:
      D.19910 = 0B;
      return D.19910;
      <D.19908>:
      root = mono_get_root_domain ();
      category_str = mono_string_new (root, category);
      counter_str = mono_string_new (root, counter);
      machine = mono_string_new (root, ".");
      D.19910 = mono_perfcounter_get_impl (category_str, counter_str, 0B, machine, &type, &custom);
      return D.19910;
    }
  finally
    {
      custom = {CLOBBER};
      type = {CLOBBER};
    }
}


__attribute__((visibility ("hidden")))
icall_append_io_job (struct MonoObject * target, struct MonoSocketAsyncResult * state)
{
  struct MonoAsyncResult * ares;

  ares = create_simple_asyncresult (target, state);
  socket_io_add (ares, state);
}


socket_io_add (struct MonoAsyncResult * ares, struct MonoSocketAsyncResult * state)
{
  int D.19915;
  int D.19917;
  struct MonoGHashTable * D.19919;
  int D.19920;
  struct MonoAsyncResult * * D.19923;
  void * D.19924;
  long int D.19925;
  union mono_mutex_t * D.19926;
  _Bool D.19929;
  long int D.19930;
  long int D.19931;
  _Bool D.19938;
  long int D.19939;
  long int D.19940;
  long int D.19943;
  const void * D.19944;
  void (*<T30c4>) (void *, int, int, int, gboolean) D.19948;
  int D.19949;
  struct MonoMList * list;
  struct SocketIOData * data;
  int fd;
  gboolean is_new;
  int ievt;

  data = &socket_io_data;
  socket_io_init (&socket_io_data);
  D.19915 = mono_runtime_is_shutting_down ();
  if (D.19915 != 0) goto <D.19913>; else goto <D.19916>;
  <D.19916>:
  D.19917 = data->inited;
  if (D.19917 == 3) goto <D.19913>; else goto <D.19918>;
  <D.19918>:
  D.19919 = data->sock_to_state;
  if (D.19919 == 0B) goto <D.19913>; else goto <D.19914>;
  <D.19913>:
  return;
  <D.19914>:
  D.19920 = async_tp.pool_status;
  if (D.19920 == 2) goto <D.19921>; else goto <D.19922>;
  <D.19921>:
  return;
  <D.19922>:
  D.19923 = &state->ares;
  mono_gc_wbarrier_set_field (state, D.19923, ares);
  D.19924 = state->handle;
  D.19925 = (long int) D.19924;
  fd = (int) D.19925;
  {
    int ret;

    D.19926 = &data->io_lock.mutex;
    ret = pthread_mutex_lock (D.19926);
    if (ret != 0) goto <D.19927>; else goto <D.19928>;
    <D.19927>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.19928>:
    D.19929 = ret != 0;
    D.19930 = (long int) D.19929;
    D.19931 = __builtin_expect (D.19930, 0);
    if (D.19931 != 0) goto <D.19932>; else goto <D.19933>;
    <D.19932>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 546, "ret == 0");
    <D.19933>:
  }
  D.19919 = data->sock_to_state;
  if (D.19919 == 0B) goto <D.19934>; else goto <D.19935>;
  <D.19934>:
  {
    int ret;

    D.19926 = &data->io_lock.mutex;
    ret = pthread_mutex_unlock (D.19926);
    if (ret != 0) goto <D.19936>; else goto <D.19937>;
    <D.19936>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.19937>:
    D.19938 = ret != 0;
    D.19939 = (long int) D.19938;
    D.19940 = __builtin_expect (D.19939, 0);
    if (D.19940 != 0) goto <D.19941>; else goto <D.19942>;
    <D.19941>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 548, "ret == 0");
    <D.19942>:
  }
  return;
  <D.19935>:
  D.19919 = data->sock_to_state;
  D.19943 = (long int) fd;
  D.19944 = (const void *) D.19943;
  list = mono_g_hash_table_lookup (D.19919, D.19944);
  if (list == 0B) goto <D.19945>; else goto <D.19946>;
  <D.19945>:
  list = mono_mlist_alloc (state);
  is_new = 1;
  goto <D.19947>;
  <D.19946>:
  list = mono_mlist_append (list, state);
  is_new = 0;
  <D.19947>:
  D.19919 = data->sock_to_state;
  D.19924 = state->handle;
  mono_g_hash_table_replace (D.19919, D.19924, list);
  ievt = get_events_from_list (list);
  D.19948 = data->modify;
  D.19949 = state->operation;
  D.19948 (data, fd, D.19949, ievt, is_new);
}


socket_io_init (struct SocketIOData * data)
{
  int D.19951;
  int * D.19954;
  union mono_mutex_t * D.19959;
  _Bool D.19962;
  long int D.19963;
  long int D.19964;
  struct MonoGHashTable * D.19967;
  const gchar * D.19968;
  struct MonoDomain * D.19971;
  void (*<Tce2>) (void *) D.19972;
  _Bool D.19975;
  long int D.19976;
  long int D.19977;
  int inited;

  D.19951 = data->inited;
  if (D.19951 > 1) goto <D.19952>; else goto <D.19953>;
  <D.19952>:
  return;
  <D.19953>:
  D.19954 = &data->inited;
  inited = InterlockedCompareExchange (D.19954, 1, 0);
  if (inited > 0) goto <D.19955>; else goto <D.19956>;
  <D.19955>:
  <D.18770>:
  D.19951 = data->inited;
  if (D.19951 > 1) goto <D.19957>; else goto <D.19958>;
  <D.19957>:
  return;
  <D.19958>:
  SleepEx (1, 0);
  goto <D.18770>;
  <D.19956>:
  {
    int ret;

    D.19959 = &data->io_lock.mutex;
    ret = pthread_mutex_lock (D.19959);
    if (ret != 0) goto <D.19960>; else goto <D.19961>;
    <D.19960>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.19961>:
    D.19962 = ret != 0;
    D.19963 = (long int) D.19962;
    D.19964 = __builtin_expect (D.19963, 0);
    if (D.19964 != 0) goto <D.19965>; else goto <D.19966>;
    <D.19965>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 509, "ret == 0");
    <D.19966>:
  }
  D.19967 = mono_g_hash_table_new_type (monoeg_g_direct_hash, monoeg_g_direct_equal, 2);
  data->sock_to_state = D.19967;
  data->event_system = 1;
  D.19968 = monoeg_g_getenv ("MONO_DISABLE_AIO");
  if (D.19968 != 0B) goto <D.19969>; else goto <D.19970>;
  <D.19969>:
  data->event_system = 0;
  <D.19970>:
  init_event_system (data);
  D.19971 = mono_get_root_domain ();
  D.19972 = data->wait;
  mono_thread_create_internal (D.19971, D.19972, data, 1, 0, 262144);
  {
    int ret;

    D.19959 = &data->io_lock.mutex;
    ret = pthread_mutex_unlock (D.19959);
    if (ret != 0) goto <D.19973>; else goto <D.19974>;
    <D.19973>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.19974>:
    D.19975 = ret != 0;
    D.19976 = (long int) D.19975;
    D.19977 = __builtin_expect (D.19976, 0);
    if (D.19977 != 0) goto <D.19978>; else goto <D.19979>;
    <D.19978>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 523, "ret == 0");
    <D.19979>:
  }
  data->inited = 2;
  threadpool_start_thread (&async_io_tp);
}


init_event_system (struct SocketIOData * data)
{
  int D.19981;
  void * D.19984;
  void * D.19985;
  const gchar * D.19988;
  void * D.19993;

  D.19981 = data->event_system;
  if (D.19981 == 1) goto <D.19982>; else goto <D.19983>;
  <D.19982>:
  D.19984 = tp_epoll_init (data);
  data->event_data = D.19984;
  D.19985 = data->event_data;
  if (D.19985 == 0B) goto <D.19986>; else goto <D.19987>;
  <D.19986>:
  D.19988 = monoeg_g_getenv ("MONO_DEBUG");
  if (D.19988 != 0B) goto <D.19989>; else goto <D.19990>;
  <D.19989>:
  monoeg_g_log (0B, 32, "Falling back to poll()");
  <D.19990>:
  data->event_system = 0;
  <D.19987>:
  <D.19983>:
  D.19981 = data->event_system;
  if (D.19981 == 0) goto <D.19991>; else goto <D.19992>;
  <D.19991>:
  D.19993 = tp_poll_init (data);
  data->event_data = D.19993;
  <D.19992>:
}


tp_epoll_init (struct SocketIOData * data)
{
  int D.19994;
  int D.19995;
  int * D.19998;
  const gchar * D.19999;
  const gchar * D.20002;
  void * D.20003;
  struct tp_epoll_data * result;

  result = monoeg_malloc0 (4);
  D.19994 = epoll_create1 (524288);
  result->epollfd = D.19994;
  D.19995 = result->epollfd;
  if (D.19995 == -1) goto <D.19996>; else goto <D.19997>;
  <D.19996>:
  {
    int err;

    D.19998 = __errno_location ();
    err = *D.19998;
    D.19999 = monoeg_g_getenv ("MONO_DEBUG");
    if (D.19999 != 0B) goto <D.20000>; else goto <D.20001>;
    <D.20000>:
    D.20002 = monoeg_g_strerror (err);
    monoeg_g_log (0B, 32, "epoll_create1(EPOLL_CLOEXEC) failed: %d %s", err, D.20002);
    <D.20001>:
    D.20003 = 0B;
    return D.20003;
  }
  <D.19997>:
  data->shutdown = tp_epoll_shutdown;
  data->modify = tp_epoll_modify;
  data->wait = tp_epoll_wait;
  D.20003 = result;
  return D.20003;
}


tp_epoll_wait (void * p)
{
  int * D.20008;
  int D.20009;
  const gchar * D.20014;
  union mono_mutex_t * D.20015;
  _Bool D.20018;
  long int D.20019;
  long int D.20020;
  int D.20023;
  _Bool D.20028;
  long int D.20029;
  long int D.20030;
  long unsigned int D.20033;
  long unsigned int D.20034;
  struct MonoGHashTable * D.20035;
  long int D.20036;
  const void * D.20037;
  void * list.37;
  struct MonoMList * list.38;
  unsigned int D.20042;
  unsigned int D.20043;
  int nresults.39;
  unsigned int D.20051;
  int nresults.40;
  void * D.20059;
  unsigned int p.41;
  unsigned int D.20061;
  unsigned int D.20062;
  unsigned int D.20063;
  int D.20064;
  int D.20067;
  const gchar * D.20070;
  _Bool D.20074;
  long int D.20075;
  long int D.20076;
  long unsigned int D.20079;
  long unsigned int D.20080;
  struct SocketIOData * socket_io_data;
  int epollfd;
  struct epoll_event * events;
  struct epoll_event * evt;
  int ready;
  int i;
  void * async_results[256];
  gint nresults;
  struct tp_epoll_data * data;

  try
    {
      ready = 0;
      socket_io_data = p;
      data = socket_io_data->event_data;
      epollfd = data->epollfd;
      events = monoeg_malloc0 (2048);
      <D.18661>:
      mono_gc_set_skip_thread (1);
      <D.18647>:
      if (ready == -1) goto <D.20005>; else goto <D.20006>;
      <D.20005>:
      check_for_interruption_critical ();
      <D.20006>:
      ready = epoll_wait (epollfd, events, 128, -1);
      if (ready == -1) goto <D.20007>; else goto <D.18648>;
      <D.20007>:
      D.20008 = __errno_location ();
      D.20009 = *D.20008;
      if (D.20009 == 4) goto <D.18647>; else goto <D.18648>;
      <D.18648>:
      mono_gc_set_skip_thread (0);
      if (ready == -1) goto <D.20010>; else goto <D.20011>;
      <D.20010>:
      {
        int err;

        D.20008 = __errno_location ();
        err = *D.20008;
        monoeg_g_free (events);
        if (err != 9) goto <D.20012>; else goto <D.20013>;
        <D.20012>:
        D.20014 = monoeg_g_strerror (err);
        monoeg_g_log (0B, 16, "epoll_wait: %d %s", err, D.20014);
        <D.20013>:
        return;
      }
      <D.20011>:
      {
        int ret;

        D.20015 = &socket_io_data->io_lock.mutex;
        ret = pthread_mutex_lock (D.20015);
        if (ret != 0) goto <D.20016>; else goto <D.20017>;
        <D.20016>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
        <D.20017>:
        D.20018 = ret != 0;
        D.20019 = (long int) D.20018;
        D.20020 = __builtin_expect (D.20019, 0);
        if (D.20020 != 0) goto <D.20021>; else goto <D.20022>;
        <D.20021>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "../../mono/metadata/tpool-epoll.c", 132, "ret == 0");
        <D.20022>:
      }
      D.20023 = socket_io_data->inited;
      if (D.20023 == 3) goto <D.20024>; else goto <D.20025>;
      <D.20024>:
      monoeg_g_free (events);
      {
        int ret;

        D.20015 = &socket_io_data->io_lock.mutex;
        ret = pthread_mutex_unlock (D.20015);
        if (ret != 0) goto <D.20026>; else goto <D.20027>;
        <D.20026>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.20027>:
        D.20028 = ret != 0;
        D.20029 = (long int) D.20028;
        D.20030 = __builtin_expect (D.20029, 0);
        if (D.20030 != 0) goto <D.20031>; else goto <D.20032>;
        <D.20031>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "../../mono/metadata/tpool-epoll.c", 135, "ret == 0");
        <D.20032>:
      }
      return;
      <D.20025>:
      nresults = 0;
      i = 0;
      goto <D.18658>;
      <D.18657>:
      {
        int fd;
        struct MonoMList * list;
        struct MonoObject * ares;

        try
          {
            D.20033 = (long unsigned int) i;
            D.20034 = D.20033 * 16;
            evt = events + D.20034;
            fd = evt->data.fd;
            D.20035 = socket_io_data->sock_to_state;
            D.20036 = (long int) fd;
            D.20037 = (const void *) D.20036;
            list.37 = mono_g_hash_table_lookup (D.20035, D.20037);
            list = list.37;
            list.38 = list;
            if (list.38 != 0B) goto <D.20040>; else goto <D.20041>;
            <D.20040>:
            D.20042 = evt->events;
            D.20043 = D.20042 & 25;
            if (D.20043 != 0) goto <D.20044>; else goto <D.20045>;
            <D.20044>:
            ares = get_io_event (&list, 1);
            if (ares != 0B) goto <D.20046>; else goto <D.20047>;
            <D.20046>:
            nresults.39 = nresults;
            nresults = nresults.39 + 1;
            async_results[nresults.39] = ares;
            <D.20047>:
            <D.20045>:
            <D.20041>:
            list.38 = list;
            if (list.38 != 0B) goto <D.20049>; else goto <D.20050>;
            <D.20049>:
            D.20042 = evt->events;
            D.20051 = D.20042 & 28;
            if (D.20051 != 0) goto <D.20052>; else goto <D.20053>;
            <D.20052>:
            ares = get_io_event (&list, 4);
            if (ares != 0B) goto <D.20054>; else goto <D.20055>;
            <D.20054>:
            nresults.40 = nresults;
            nresults = nresults.40 + 1;
            async_results[nresults.40] = ares;
            <D.20055>:
            <D.20053>:
            <D.20050>:
            list.38 = list;
            if (list.38 != 0B) goto <D.20057>; else goto <D.20058>;
            <D.20057>:
            {
              int p;

              D.20035 = socket_io_data->sock_to_state;
              D.20036 = (long int) fd;
              D.20059 = (void *) D.20036;
              list.38 = list;
              mono_g_hash_table_replace (D.20035, D.20059, list.38);
              list.38 = list;
              p = get_events_from_list (list.38);
              p.41 = (unsigned int) p;
              D.20061 = p.41 & 4;
              evt->events = D.20061;
              D.20042 = evt->events;
              p.41 = (unsigned int) p;
              D.20062 = p.41 & 1;
              D.20063 = D.20042 | D.20062;
              evt->events = D.20063;
              D.20064 = epoll_ctl (epollfd, 3, fd, evt);
              if (D.20064 == -1) goto <D.20065>; else goto <D.20066>;
              <D.20065>:
              D.20067 = epoll_ctl (epollfd, 1, fd, evt);
              if (D.20067 == -1) goto <D.20068>; else goto <D.20069>;
              <D.20068>:
              {
                int err;

                D.20008 = __errno_location ();
                err = *D.20008;
                D.20070 = monoeg_g_strerror (err);
                monoeg_g_log (0B, 32, "epoll(ADD): %d %s", err, D.20070);
              }
              <D.20069>:
              <D.20066>:
            }
            goto <D.20071>;
            <D.20058>:
            D.20035 = socket_io_data->sock_to_state;
            D.20036 = (long int) fd;
            D.20037 = (const void *) D.20036;
            mono_g_hash_table_remove (D.20035, D.20037);
            epoll_ctl (epollfd, 2, fd, evt);
            <D.20071>:
          }
        finally
          {
            list = {CLOBBER};
          }
      }
      i = i + 1;
      <D.18658>:
      if (i < ready) goto <D.18657>; else goto <D.18659>;
      <D.18659>:
      {
        int ret;

        D.20015 = &socket_io_data->io_lock.mutex;
        ret = pthread_mutex_unlock (D.20015);
        if (ret != 0) goto <D.20072>; else goto <D.20073>;
        <D.20072>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.20073>:
        D.20074 = ret != 0;
        D.20075 = (long int) D.20074;
        D.20076 = __builtin_expect (D.20075, 0);
        if (D.20076 != 0) goto <D.20077>; else goto <D.20078>;
        <D.20077>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "../../mono/metadata/tpool-epoll.c", 178, "ret == 0");
        <D.20078>:
      }
      threadpool_append_jobs (&async_io_tp, &async_results, nresults);
      D.20079 = (long unsigned int) nresults;
      D.20080 = D.20079 * 8;
      mono_gc_bzero_aligned (&async_results, D.20080);
      goto <D.18661>;
    }
  finally
    {
      async_results = {CLOBBER};
    }
}


tp_epoll_modify (void * p, int fd, int operation, int events, gboolean is_new)
{
  int D.20083;
  unsigned int D.20086;
  unsigned int D.20087;
  int D.20088;
  unsigned int D.20091;
  int iftmp.42;
  int D.20096;
  int D.20097;
  int * D.20100;
  int D.20105;
  const gchar * D.20108;
  union mono_mutex_t * D.20109;
  _Bool D.20112;
  long int D.20113;
  long int D.20114;
  struct SocketIOData * socket_io_data;
  struct tp_epoll_data * data;
  struct epoll_event evt;
  int epoll_op;

  try
    {
      socket_io_data = p;
      data = socket_io_data->event_data;
      memset (&evt, 0, 16);
      evt.data.fd = fd;
      D.20083 = events & 1;
      if (D.20083 != 0) goto <D.20084>; else goto <D.20085>;
      <D.20084>:
      D.20086 = evt.events;
      D.20087 = D.20086 | 1;
      evt.events = D.20087;
      <D.20085>:
      D.20088 = events & 4;
      if (D.20088 != 0) goto <D.20089>; else goto <D.20090>;
      <D.20089>:
      D.20086 = evt.events;
      D.20091 = D.20086 | 4;
      evt.events = D.20091;
      <D.20090>:
      if (is_new != 0) goto <D.20093>; else goto <D.20094>;
      <D.20093>:
      iftmp.42 = 1;
      goto <D.20095>;
      <D.20094>:
      iftmp.42 = 3;
      <D.20095>:
      epoll_op = iftmp.42;
      D.20096 = data->epollfd;
      D.20097 = epoll_ctl (D.20096, epoll_op, fd, &evt);
      if (D.20097 == -1) goto <D.20098>; else goto <D.20099>;
      <D.20098>:
      {
        int err;

        D.20100 = __errno_location ();
        err = *D.20100;
        if (epoll_op == 1) goto <D.20101>; else goto <D.20102>;
        <D.20101>:
        if (err == 17) goto <D.20103>; else goto <D.20104>;
        <D.20103>:
        epoll_op = 3;
        D.20096 = data->epollfd;
        D.20105 = epoll_ctl (D.20096, epoll_op, fd, &evt);
        if (D.20105 == -1) goto <D.20106>; else goto <D.20107>;
        <D.20106>:
        D.20108 = monoeg_g_strerror (err);
        monoeg_g_log (0B, 32, "epoll_ctl(MOD): %d %s", err, D.20108);
        <D.20107>:
        <D.20104>:
        <D.20102>:
      }
      <D.20099>:
      {
        int ret;

        D.20109 = &socket_io_data->io_lock.mutex;
        ret = pthread_mutex_unlock (D.20109);
        if (ret != 0) goto <D.20110>; else goto <D.20111>;
        <D.20110>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.20111>:
        D.20112 = ret != 0;
        D.20113 = (long int) D.20112;
        D.20114 = __builtin_expect (D.20113, 0);
        if (D.20114 != 0) goto <D.20115>; else goto <D.20116>;
        <D.20115>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "../../mono/metadata/tpool-epoll.c", 81, "ret == 0");
        <D.20116>:
      }
    }
  finally
    {
      evt = {CLOBBER};
    }
}


tp_epoll_shutdown (void * event_data)
{
  int D.20117;
  struct tp_epoll_data * data;

  data = event_data;
  D.20117 = data->epollfd;
  close (D.20117);
  monoeg_g_free (data);
}


tp_poll_init (struct SocketIOData * data)
{
  int[2] * D.20118;
  int D.20119;
  int * D.20122;
  _Bool D.20123;
  long int D.20124;
  long int D.20125;
  union MonoSemType * D.20128;
  void * D.20129;
  struct tp_poll_data * result;

  result = monoeg_malloc0 (48);
  D.20118 = &result->pipe;
  D.20119 = pipe (D.20118);
  if (D.20119 != 0) goto <D.20120>; else goto <D.20121>;
  <D.20120>:
  {
    int err;

    D.20122 = __errno_location ();
    err = *D.20122;
    perror ("mono");
    D.20123 = err == 0;
    D.20124 = (long int) D.20123;
    D.20125 = __builtin_expect (D.20124, 0);
    if (D.20125 != 0) goto <D.20126>; else goto <D.20127>;
    <D.20126>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "../../mono/metadata/tpool-poll.c", 41, "err");
    <D.20127>:
  }
  <D.20121>:
  D.20128 = &result->new_sem;
  sem_init (D.20128, 0, 1);
  data->shutdown = tp_poll_shutdown;
  data->modify = tp_poll_modify;
  data->wait = tp_poll_wait;
  D.20129 = result;
  return D.20129;
}


tp_poll_wait (void * p)
{
  long unsigned int D.20131;
  long unsigned int D.20132;
  int D.20133;
  int D.20134;
  void * iftmp.43;
  long unsigned int D.20138;
  void * D.20139;
  int D.20141;
  long unsigned int D.20142;
  long unsigned int D.20143;
  struct mono_pollfd * D.20144;
  unsigned int maxfd.44;
  int * D.20149;
  int D.20150;
  short int D.20155;
  int D.20156;
  int D.20157;
  int D.20160;
  void * * D.20163;
  int D.20164;
  int D.20167;
  int D.20168;
  long int D.20176;
  short int D.20181;
  struct mono_pollfd * D.20182;
  union MonoSemType * D.20183;
  union mono_mutex_t * D.20188;
  _Bool D.20191;
  long int D.20192;
  long int D.20193;
  int D.20196;
  _Bool D.20203;
  long int D.20204;
  long int D.20205;
  long unsigned int D.20208;
  long unsigned int D.20209;
  short int D.20213;
  struct MonoGHashTable * D.20214;
  long int D.20215;
  const void * D.20216;
  void * list.45;
  struct MonoMList * list.46;
  int D.20221;
  int D.20222;
  int D.20227;
  long unsigned int D.20230;
  int D.20231;
  void * D.20232;
  int D.20235;
  int D.20236;
  long unsigned int D.20237;
  long unsigned int D.20238;
  void * * D.20239;
  int D.20242;
  void * D.20249;
  int D.20252;
  int D.20253;
  long unsigned int D.20254;
  long unsigned int D.20255;
  void * * D.20256;
  void * D.20259;
  int D.20260;
  short int D.20261;
  int D.20263;
  _Bool D.20269;
  long int D.20270;
  long int D.20271;
  struct mono_pollfd * pfds;
  gint maxfd;
  gint allocated;
  gint i;
  struct tp_poll_data * data;
  struct SocketIOData * socket_io_data;
  struct MonoPtrArray async_results;
  gint nresults;

  try
    {
      maxfd = 1;
      socket_io_data = p;
      data = socket_io_data->event_data;
      allocated = 1024;
      D.20131 = (long unsigned int) allocated;
      D.20132 = D.20131 * 8;
      pfds = monoeg_malloc0 (D.20132);
      async_results.size = 0;
      D.20133 = allocated * 2;
      D.20134 = MAX_EXPR <D.20133, 16>;
      async_results.capacity = D.20134;
      D.20133 = allocated * 2;
      if (D.20133 > 16) goto <D.20136>; else goto <D.20137>;
      <D.20136>:
      D.20131 = (long unsigned int) allocated;
      D.20138 = D.20131 * 16;
      D.20133 = allocated * 2;
      D.20139 = mono_gc_make_root_descr_all_refs (D.20133);
      iftmp.43 = mono_gc_alloc_fixed (D.20138, D.20139);
      goto <D.20140>;
      <D.20137>:
      iftmp.43 = __builtin_alloca (128);
      <D.20140>:
      async_results.data = iftmp.43;
      D.20141 = data->pipe[0];
      pfds->fd = D.20141;
      pfds->events = 1;
      pfds->revents = 0;
      i = 1;
      goto <D.18568>;
      <D.18567>:
      D.20142 = (long unsigned int) i;
      D.20143 = D.20142 * 8;
      D.20144 = pfds + D.20143;
      D.20144->fd = -1;
      D.20142 = (long unsigned int) i;
      D.20143 = D.20142 * 8;
      D.20144 = pfds + D.20143;
      D.20144->events = 0;
      D.20142 = (long unsigned int) i;
      D.20143 = D.20142 * 8;
      D.20144 = pfds + D.20143;
      D.20144->revents = 0;
      i = i + 1;
      <D.18568>:
      if (i < allocated) goto <D.18567>; else goto <D.18569>;
      <D.18569>:
      <D.18599>:
      {
        int nsock;
        struct mono_pollfd * pfd;
        char one[1];
        struct MonoMList * list;
        struct MonoObject * ares;

        try
          {
            nsock = 0;
            mono_gc_set_skip_thread (1);
            <D.18575>:
            if (nsock == -1) goto <D.20145>; else goto <D.20146>;
            <D.20145>:
            check_for_interruption_critical ();
            <D.20146>:
            maxfd.44 = (unsigned int) maxfd;
            nsock = mono_poll (pfds, maxfd.44, -1);
            if (nsock == -1) goto <D.20148>; else goto <D.18576>;
            <D.20148>:
            D.20149 = __errno_location ();
            D.20150 = *D.20149;
            if (D.20150 == 4) goto <D.18575>; else goto <D.18576>;
            <D.18576>:
            mono_gc_set_skip_thread (0);
            if (nsock == -1) goto <D.20151>; else goto <D.20152>;
            <D.20151>:
            D.20149 = __errno_location ();
            D.20150 = *D.20149;
            if (D.20150 == 9) goto <D.20153>; else goto <D.20154>;
            <D.20153>:
            pfds->revents = 0;
            nsock = mark_bad_fds (pfds, maxfd);
            <D.20154>:
            <D.20152>:
            D.20155 = pfds->revents;
            D.20156 = (int) D.20155;
            D.20157 = D.20156 & 56;
            if (D.20157 != 0) goto <D.20158>; else goto <D.20159>;
            <D.20158>:
            monoeg_g_free (pfds);
            D.20160 = async_results.capacity;
            if (D.20160 > 16) goto <D.20161>; else goto <D.20162>;
            <D.20161>:
            D.20163 = async_results.data;
            mono_gc_free_fixed (D.20163);
            <D.20162>:
            socket_io_cleanup (socket_io_data);
            return;
            <D.20159>:
            D.20155 = pfds->revents;
            D.20156 = (int) D.20155;
            D.20164 = D.20156 & 1;
            if (D.20164 != 0) goto <D.20165>; else goto <D.20166>;
            <D.20165>:
            {
              int nread;
              gboolean found;

              found = 0;
              i = 1;
              goto <D.18581>;
              <D.18580>:
              D.20142 = (long unsigned int) i;
              D.20143 = D.20142 * 8;
              pfd = pfds + D.20143;
              D.20167 = pfd->fd;
              D.20168 = data->newpfd.fd;
              if (D.20167 == D.20168) goto <D.20169>; else goto <D.20170>;
              <D.20169>:
              found = 1;
              goto <D.18579>;
              <D.20170>:
              i = i + 1;
              <D.18581>:
              if (i < allocated) goto <D.18580>; else goto <D.18579>;
              <D.18579>:
              if (found == 0) goto <D.20171>; else goto <D.20172>;
              <D.20171>:
              i = 1;
              goto <D.18584>;
              <D.18583>:
              D.20142 = (long unsigned int) i;
              D.20143 = D.20142 * 8;
              pfd = pfds + D.20143;
              D.20167 = pfd->fd;
              if (D.20167 == -1) goto <D.18582>; else goto <D.20173>;
              <D.20173>:
              i = i + 1;
              <D.18584>:
              if (i < allocated) goto <D.18583>; else goto <D.18582>;
              <D.18582>:
              <D.20172>:
              if (i == allocated) goto <D.20174>; else goto <D.20175>;
              <D.20174>:
              {
                struct mono_pollfd * oldfd;

                oldfd = pfds;
                i = allocated;
                allocated = allocated * 2;
                D.20131 = (long unsigned int) allocated;
                D.20132 = D.20131 * 8;
                pfds = monoeg_realloc (oldfd, D.20132);
                monoeg_g_free (oldfd);
                goto <D.18587>;
                <D.18586>:
                D.20142 = (long unsigned int) i;
                D.20143 = D.20142 * 8;
                D.20144 = pfds + D.20143;
                D.20144->fd = -1;
                D.20142 = (long unsigned int) i;
                D.20143 = D.20142 * 8;
                D.20144 = pfds + D.20143;
                D.20144->events = 0;
                D.20142 = (long unsigned int) i;
                D.20143 = D.20142 * 8;
                D.20144 = pfds + D.20143;
                D.20144->revents = 0;
                i = i + 1;
                <D.18587>:
                if (i < allocated) goto <D.18586>; else goto <D.18588>;
                <D.18588>:
              }
              <D.20175>:
              D.20141 = data->pipe[0];
              D.20176 = read (D.20141, &one, 1);
              nread = (int) D.20176;
              if (nread <= 0) goto <D.20177>; else goto <D.20178>;
              <D.20177>:
              monoeg_g_free (pfds);
              D.20160 = async_results.capacity;
              if (D.20160 > 16) goto <D.20179>; else goto <D.20180>;
              <D.20179>:
              D.20163 = async_results.data;
              mono_gc_free_fixed (D.20163);
              <D.20180>:
              return;
              <D.20178>:
              D.20142 = (long unsigned int) i;
              D.20143 = D.20142 * 8;
              D.20144 = pfds + D.20143;
              D.20168 = data->newpfd.fd;
              D.20144->fd = D.20168;
              D.20142 = (long unsigned int) i;
              D.20143 = D.20142 * 8;
              D.20144 = pfds + D.20143;
              D.20181 = data->newpfd.events;
              D.20144->events = D.20181;
              D.20142 = (long unsigned int) i;
              D.20143 = D.20142 * 8;
              D.20144 = pfds + D.20143;
              D.20144->revents = 0;
              D.20182 = &data->newpfd;
              memset (D.20182, 0, 8);
              D.20183 = &data->new_sem;
              mono_sem_post (D.20183);
              if (i >= maxfd) goto <D.20184>; else goto <D.20185>;
              <D.20184>:
              maxfd = i + 1;
              <D.20185>:
              nsock = nsock + -1;
            }
            <D.20166>:
            if (nsock == 0) goto <D.20186>; else goto <D.20187>;
            <D.20186>:
            // predicted unlikely by continue predictor.
            goto <D.18589>;
            <D.20187>:
            {
              int ret;

              D.20188 = &socket_io_data->io_lock.mutex;
              ret = pthread_mutex_lock (D.20188);
              if (ret != 0) goto <D.20189>; else goto <D.20190>;
              <D.20189>:
              monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
              <D.20190>:
              D.20191 = ret != 0;
              D.20192 = (long int) D.20191;
              D.20193 = __builtin_expect (D.20192, 0);
              if (D.20193 != 0) goto <D.20194>; else goto <D.20195>;
              <D.20194>:
              monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "../../mono/metadata/tpool-poll.c", 273, "ret == 0");
              <D.20195>:
            }
            D.20196 = socket_io_data->inited;
            if (D.20196 == 3) goto <D.20197>; else goto <D.20198>;
            <D.20197>:
            monoeg_g_free (pfds);
            D.20160 = async_results.capacity;
            if (D.20160 > 16) goto <D.20199>; else goto <D.20200>;
            <D.20199>:
            D.20163 = async_results.data;
            mono_gc_free_fixed (D.20163);
            <D.20200>:
            {
              int ret;

              D.20188 = &socket_io_data->io_lock.mutex;
              ret = pthread_mutex_unlock (D.20188);
              if (ret != 0) goto <D.20201>; else goto <D.20202>;
              <D.20201>:
              monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
              <D.20202>:
              D.20203 = ret != 0;
              D.20204 = (long int) D.20203;
              D.20205 = __builtin_expect (D.20204, 0);
              if (D.20205 != 0) goto <D.20206>; else goto <D.20207>;
              <D.20206>:
              monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "../../mono/metadata/tpool-poll.c", 277, "ret == 0");
              <D.20207>:
            }
            return;
            <D.20198>:
            nresults = 0;
            async_results.size = 0;
            D.20163 = async_results.data;
            D.20160 = async_results.capacity;
            D.20208 = (long unsigned int) D.20160;
            D.20209 = D.20208 * 8;
            mono_gc_bzero_aligned (D.20163, D.20209);
            i = 1;
            goto <D.18596>;
            <D.18595>:
            D.20142 = (long unsigned int) i;
            D.20143 = D.20142 * 8;
            pfd = pfds + D.20143;
            D.20167 = pfd->fd;
            if (D.20167 == -1) goto <D.20210>; else goto <D.20212>;
            <D.20212>:
            D.20213 = pfd->revents;
            if (D.20213 == 0) goto <D.20210>; else goto <D.20211>;
            <D.20210>:
            // predicted unlikely by continue predictor.
            goto <D.18592>;
            <D.20211>:
            nsock = nsock + -1;
            D.20214 = socket_io_data->sock_to_state;
            D.20167 = pfd->fd;
            D.20215 = (long int) D.20167;
            D.20216 = (const void *) D.20215;
            list.45 = mono_g_hash_table_lookup (D.20214, D.20216);
            list = list.45;
            list.46 = list;
            if (list.46 != 0B) goto <D.20219>; else goto <D.20220>;
            <D.20219>:
            D.20213 = pfd->revents;
            D.20221 = (int) D.20213;
            D.20222 = D.20221 & 57;
            if (D.20222 != 0) goto <D.20223>; else goto <D.20224>;
            <D.20223>:
            ares = get_io_event (&list, 1);
            if (ares != 0B) goto <D.20225>; else goto <D.20226>;
            <D.20225>:
            D.20227 = async_results.size;
            D.20160 = async_results.capacity;
            if (D.20227 >= D.20160) goto <D.20228>; else goto <D.20229>;
            <D.20228>:
            {
              void * __tmp;

              D.20160 = async_results.capacity;
              D.20208 = (long unsigned int) D.20160;
              D.20230 = D.20208 * 16;
              D.20160 = async_results.capacity;
              D.20231 = D.20160 * 2;
              D.20232 = mono_gc_make_root_descr_all_refs (D.20231);
              __tmp = mono_gc_alloc_fixed (D.20230, D.20232);
              D.20163 = async_results.data;
              D.20160 = async_results.capacity;
              D.20208 = (long unsigned int) D.20160;
              D.20209 = D.20208 * 8;
              mono_gc_memmove_aligned (__tmp, D.20163, D.20209);
              D.20160 = async_results.capacity;
              if (D.20160 > 16) goto <D.20233>; else goto <D.20234>;
              <D.20233>:
              D.20163 = async_results.data;
              mono_gc_free_fixed (D.20163);
              <D.20234>:
              async_results.data = __tmp;
              D.20160 = async_results.capacity;
              D.20231 = D.20160 * 2;
              async_results.capacity = D.20231;
            }
            <D.20229>:
            D.20163 = async_results.data;
            D.20227 = async_results.size;
            D.20235 = D.20227;
            D.20236 = D.20235 + 1;
            async_results.size = D.20236;
            D.20237 = (long unsigned int) D.20235;
            D.20238 = D.20237 * 8;
            D.20239 = D.20163 + D.20238;
            *D.20239 = ares;
            nresults = nresults + 1;
            <D.20226>:
            <D.20224>:
            <D.20220>:
            list.46 = list;
            if (list.46 != 0B) goto <D.20240>; else goto <D.20241>;
            <D.20240>:
            D.20213 = pfd->revents;
            D.20221 = (int) D.20213;
            D.20242 = D.20221 & 60;
            if (D.20242 != 0) goto <D.20243>; else goto <D.20244>;
            <D.20243>:
            ares = get_io_event (&list, 4);
            if (ares != 0B) goto <D.20245>; else goto <D.20246>;
            <D.20245>:
            D.20227 = async_results.size;
            D.20160 = async_results.capacity;
            if (D.20227 >= D.20160) goto <D.20247>; else goto <D.20248>;
            <D.20247>:
            {
              void * __tmp;

              D.20160 = async_results.capacity;
              D.20208 = (long unsigned int) D.20160;
              D.20230 = D.20208 * 16;
              D.20160 = async_results.capacity;
              D.20231 = D.20160 * 2;
              D.20249 = mono_gc_make_root_descr_all_refs (D.20231);
              __tmp = mono_gc_alloc_fixed (D.20230, D.20249);
              D.20163 = async_results.data;
              D.20160 = async_results.capacity;
              D.20208 = (long unsigned int) D.20160;
              D.20209 = D.20208 * 8;
              mono_gc_memmove_aligned (__tmp, D.20163, D.20209);
              D.20160 = async_results.capacity;
              if (D.20160 > 16) goto <D.20250>; else goto <D.20251>;
              <D.20250>:
              D.20163 = async_results.data;
              mono_gc_free_fixed (D.20163);
              <D.20251>:
              async_results.data = __tmp;
              D.20160 = async_results.capacity;
              D.20231 = D.20160 * 2;
              async_results.capacity = D.20231;
            }
            <D.20248>:
            D.20163 = async_results.data;
            D.20227 = async_results.size;
            D.20252 = D.20227;
            D.20253 = D.20252 + 1;
            async_results.size = D.20253;
            D.20254 = (long unsigned int) D.20252;
            D.20255 = D.20254 * 8;
            D.20256 = D.20163 + D.20255;
            *D.20256 = ares;
            nresults = nresults + 1;
            <D.20246>:
            <D.20244>:
            <D.20241>:
            list.46 = list;
            if (list.46 != 0B) goto <D.20257>; else goto <D.20258>;
            <D.20257>:
            D.20214 = socket_io_data->sock_to_state;
            D.20167 = pfd->fd;
            D.20215 = (long int) D.20167;
            D.20259 = (void *) D.20215;
            list.46 = list;
            mono_g_hash_table_replace (D.20214, D.20259, list.46);
            list.46 = list;
            D.20260 = get_events_from_list (list.46);
            D.20261 = (short int) D.20260;
            pfd->events = D.20261;
            goto <D.20262>;
            <D.20258>:
            D.20214 = socket_io_data->sock_to_state;
            D.20167 = pfd->fd;
            D.20215 = (long int) D.20167;
            D.20216 = (const void *) D.20215;
            mono_g_hash_table_remove (D.20214, D.20216);
            pfd->fd = -1;
            D.20263 = maxfd + -1;
            if (D.20263 == i) goto <D.20264>; else goto <D.20265>;
            <D.20264>:
            maxfd = maxfd + -1;
            <D.20265>:
            <D.20262>:
            <D.18592>:
            i = i + 1;
            <D.18596>:
            if (i < maxfd) goto <D.20266>; else goto <D.18597>;
            <D.20266>:
            if (nsock > 0) goto <D.18595>; else goto <D.18597>;
            <D.18597>:
            {
              int ret;

              D.20188 = &socket_io_data->io_lock.mutex;
              ret = pthread_mutex_unlock (D.20188);
              if (ret != 0) goto <D.20267>; else goto <D.20268>;
              <D.20267>:
              monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
              <D.20268>:
              D.20269 = ret != 0;
              D.20270 = (long int) D.20269;
              D.20271 = __builtin_expect (D.20270, 0);
              if (D.20271 != 0) goto <D.20272>; else goto <D.20273>;
              <D.20272>:
              monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "../../mono/metadata/tpool-poll.c", 317, "ret == 0");
              <D.20273>:
            }
            D.20163 = async_results.data;
            threadpool_append_jobs (&async_io_tp, D.20163, nresults);
            async_results.size = 0;
            D.20163 = async_results.data;
            D.20160 = async_results.capacity;
            D.20208 = (long unsigned int) D.20160;
            D.20209 = D.20208 * 8;
            mono_gc_bzero_aligned (D.20163, D.20209);
          }
        finally
          {
            one = {CLOBBER};
            list = {CLOBBER};
          }
      }
      <D.18589>:
      goto <D.18599>;
    }
  finally
    {
      async_results = {CLOBBER};
    }
}


mark_bad_fds (struct mono_pollfd * pfds, int nfds)
{
  long unsigned int D.20279;
  long unsigned int D.20280;
  int D.20281;
  int * D.20287;
  int D.20288;
  short int D.20290;
  short int D.20291;
  int D.20294;
  int i;
  int ret;
  struct mono_pollfd * pfd;
  int count;

  count = 0;
  i = 0;
  goto <D.18554>;
  <D.18553>:
  D.20279 = (long unsigned int) i;
  D.20280 = D.20279 * 8;
  pfd = pfds + D.20280;
  D.20281 = pfd->fd;
  if (D.20281 == -1) goto <D.20282>; else goto <D.20283>;
  <D.20282>:
  // predicted unlikely by continue predictor.
  goto <D.18552>;
  <D.20283>:
  ret = mono_poll (pfd, 1, 0);
  if (ret == -1) goto <D.20286>; else goto <D.20284>;
  <D.20286>:
  D.20287 = __errno_location ();
  D.20288 = *D.20287;
  if (D.20288 == 9) goto <D.20289>; else goto <D.20284>;
  <D.20289>:
  D.20290 = pfd->revents;
  D.20291 = D.20290 | 32;
  pfd->revents = D.20291;
  count = count + 1;
  goto <D.20285>;
  <D.20284>:
  if (ret == 1) goto <D.20292>; else goto <D.20293>;
  <D.20292>:
  count = count + 1;
  <D.20293>:
  <D.20285>:
  <D.18552>:
  i = i + 1;
  <D.18554>:
  if (i < nfds) goto <D.18553>; else goto <D.18555>;
  <D.18555>:
  D.20294 = count;
  return D.20294;
}


socket_io_cleanup (struct SocketIOData * data)
{
  union mono_mutex_t * D.20296;
  _Bool D.20299;
  long int D.20300;
  long int D.20301;
  int D.20304;
  _Bool D.20309;
  long int D.20310;
  long int D.20311;
  void (*<Tce2>) (void *) D.20314;
  void * D.20315;
  _Bool D.20318;
  long int D.20319;
  long int D.20320;

  {
    int ret;

    D.20296 = &data->io_lock.mutex;
    ret = pthread_mutex_lock (D.20296);
    if (ret != 0) goto <D.20297>; else goto <D.20298>;
    <D.20297>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.20298>:
    D.20299 = ret != 0;
    D.20300 = (long int) D.20299;
    D.20301 = __builtin_expect (D.20300, 0);
    if (D.20301 != 0) goto <D.20302>; else goto <D.20303>;
    <D.20302>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 317, "ret == 0");
    <D.20303>:
  }
  D.20304 = data->inited;
  if (D.20304 != 2) goto <D.20305>; else goto <D.20306>;
  <D.20305>:
  {
    int ret;

    D.20296 = &data->io_lock.mutex;
    ret = pthread_mutex_unlock (D.20296);
    if (ret != 0) goto <D.20307>; else goto <D.20308>;
    <D.20307>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.20308>:
    D.20309 = ret != 0;
    D.20310 = (long int) D.20309;
    D.20311 = __builtin_expect (D.20310, 0);
    if (D.20311 != 0) goto <D.20312>; else goto <D.20313>;
    <D.20312>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 319, "ret == 0");
    <D.20313>:
  }
  return;
  <D.20306>:
  data->inited = 3;
  D.20314 = data->shutdown;
  D.20315 = data->event_data;
  D.20314 (D.20315);
  {
    int ret;

    D.20296 = &data->io_lock.mutex;
    ret = pthread_mutex_unlock (D.20296);
    if (ret != 0) goto <D.20316>; else goto <D.20317>;
    <D.20316>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.20317>:
    D.20318 = ret != 0;
    D.20319 = (long int) D.20318;
    D.20320 = __builtin_expect (D.20319, 0);
    if (D.20320 != 0) goto <D.20321>; else goto <D.20322>;
    <D.20321>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 324, "ret == 0");
    <D.20322>:
  }
}


__attribute__((__artificial__, __gnu_inline__, __always_inline__))
read (int __fd, void * __buf, size_t __nbytes)
{
  long unsigned int D.20324;
  int D.20327;
  ssize_t D.20330;
  long unsigned int D.20331;
  long unsigned int D.20332;
  long unsigned int D.20335;

  D.20324 = __builtin_object_size (__buf, 0);
  if (D.20324 != 18446744073709551615) goto <D.20325>; else goto <D.20326>;
  <D.20325>:
  D.20327 = __builtin_constant_p (__nbytes);
  if (D.20327 == 0) goto <D.20328>; else goto <D.20329>;
  <D.20328>:
  D.20331 = __builtin_object_size (__buf, 0);
  D.20330 = __read_chk (__fd, __buf, __nbytes, D.20331);
  return D.20330;
  <D.20329>:
  D.20332 = __builtin_object_size (__buf, 0);
  if (D.20332 < __nbytes) goto <D.20333>; else goto <D.20334>;
  <D.20333>:
  D.20335 = __builtin_object_size (__buf, 0);
  D.20330 = __read_chk_warn (__fd, __buf, __nbytes, D.20335);
  return D.20330;
  <D.20334>:
  <D.20326>:
  D.20330 = __read_alias (__fd, __buf, __nbytes);
  return D.20330;
}


tp_poll_modify (void * p, int fd, int operation, int events, gboolean is_new)
{
  union mono_mutex_t * D.20337;
  _Bool D.20340;
  long int D.20341;
  long int D.20342;
  union MonoSemType * D.20345;
  short int D.20346;
  char D.20347;
  int D.20348;
  long int D.20349;
  struct SocketIOData * socket_io_data;
  struct tp_poll_data * data;
  char msg[1];
  int unused;

  try
    {
      socket_io_data = p;
      data = socket_io_data->event_data;
      {
        int ret;

        D.20337 = &socket_io_data->io_lock.mutex;
        ret = pthread_mutex_unlock (D.20337);
        if (ret != 0) goto <D.20338>; else goto <D.20339>;
        <D.20338>:
        monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
        <D.20339>:
        D.20340 = ret != 0;
        D.20341 = (long int) D.20340;
        D.20342 = __builtin_expect (D.20341, 0);
        if (D.20342 != 0) goto <D.20343>; else goto <D.20344>;
        <D.20343>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "../../mono/metadata/tpool-poll.c", 87, "ret == 0");
        <D.20344>:
      }
      D.20345 = &data->new_sem;
      mono_sem_wait (D.20345, 0);
      data->newpfd.fd = fd;
      D.20346 = (short int) events;
      data->newpfd.events = D.20346;
      data->newpfd.revents = 0;
      D.20347 = (char) operation;
      msg[0] = D.20347;
      D.20348 = data->pipe[1];
      D.20349 = write (D.20348, &msg, 1);
      unused = (int) D.20349;
    }
  finally
    {
      msg = {CLOBBER};
    }
}


tp_poll_shutdown (void * event_data)
{
  int D.20350;
  int D.20353;
  union MonoSemType * D.20356;
  struct tp_poll_data * data;

  data = event_data;
  D.20350 = data->pipe[0];
  if (D.20350 >= 0) goto <D.20351>; else goto <D.20352>;
  <D.20351>:
  D.20350 = data->pipe[0];
  close (D.20350);
  <D.20352>:
  D.20353 = data->pipe[1];
  if (D.20353 >= 0) goto <D.20354>; else goto <D.20355>;
  <D.20354>:
  D.20353 = data->pipe[1];
  close (D.20353);
  <D.20355>:
  data->pipe[0] = -1;
  data->pipe[1] = -1;
  D.20356 = &data->new_sem;
  sem_destroy (D.20356);
}


get_events_from_list (struct MonoMList * list)
{
  int D.20357;
  int D.20359;
  struct MonoSocketAsyncResult * state;
  int events;

  events = 0;
  goto <D.18731>;
  <D.18730>:
  D.20357 = get_event_from_state (state);
  events = D.20357 | events;
  list = mono_mlist_next (list);
  <D.18731>:
  if (list != 0B) goto <D.20358>; else goto <D.18732>;
  <D.20358>:
  state = mono_mlist_get_data (list);
  if (state != 0B) goto <D.18730>; else goto <D.18732>;
  <D.18732>:
  D.20359 = events;
  return D.20359;
}


__attribute__((visibility ("hidden")))
mono_thread_pool_add (struct MonoObject * target, struct MonoMethodMessage * msg, struct MonoDelegate * async_callback, struct MonoObject * state)
{
  struct MonoClass * async_call_klass.47;
  struct MonoMethodMessage * * D.20362;
  struct MonoObject * * D.20363;
  struct MonoVTable * D.20366;
  struct MonoClass * D.20367;
  struct MonoMethod * D.20368;
  struct MonoDelegate * * D.20369;
  struct MonoObject * D.20370;
  struct MonoObject * * D.20371;
  int D.20372;
  struct MonoAsyncResult * D.20375;
  struct MonoDomain * domain;
  struct MonoAsyncResult * ares;
  struct ASyncCall * ac;

  domain = mono_domain_get ();
  async_call_klass.47 = async_call_klass;
  ac = mono_object_new (domain, async_call_klass.47);
  D.20362 = &ac->msg;
  mono_gc_wbarrier_set_field (ac, D.20362, msg);
  D.20363 = &ac->state;
  mono_gc_wbarrier_set_field (ac, D.20363, state);
  if (async_callback != 0B) goto <D.20364>; else goto <D.20365>;
  <D.20364>:
  D.20366 = MEM[(struct MonoObject *)async_callback].vtable;
  D.20367 = D.20366->klass;
  D.20368 = mono_get_delegate_invoke (D.20367);
  ac->cb_method = D.20368;
  D.20369 = &ac->cb_target;
  mono_gc_wbarrier_set_field (ac, D.20369, async_callback);
  <D.20365>:
  D.20370 = ac->state;
  ares = mono_async_result_new (domain, 0B, D.20370, 0B, ac);
  D.20371 = &ares->async_delegate;
  mono_gc_wbarrier_set_field (ares, D.20371, target);
  D.20372 = socket_io_filter (target, state);
  if (D.20372 != 0) goto <D.20373>; else goto <D.20374>;
  <D.20373>:
  socket_io_add (ares, state);
  D.20375 = ares;
  return D.20375;
  <D.20374>:
  threadpool_append_job (&async_tp, ares);
  D.20375 = ares;
  return D.20375;
}


socket_io_filter (struct MonoObject * target, struct MonoObject * state)
{
  gboolean D.20380;
  struct MonoVTable * D.20381;
  struct MonoClass * socket_async_call_klass.48;
  int D.20385;
  struct MonoClass * process_async_call_klass.49;
  int D.20391;
  unsigned int op.50;
  gint op;
  struct MonoSocketAsyncResult * sock_res;
  struct MonoClass * klass;
  struct MonoDomain * domain;

  if (target == 0B) goto <D.20377>; else goto <D.20379>;
  <D.20379>:
  if (state == 0B) goto <D.20377>; else goto <D.20378>;
  <D.20377>:
  D.20380 = 0;
  return D.20380;
  <D.20378>:
  D.20381 = target->vtable;
  domain = D.20381->domain;
  D.20381 = target->vtable;
  klass = D.20381->klass;
  socket_async_call_klass.48 = socket_async_call_klass;
  if (socket_async_call_klass.48 == 0B) goto <D.20383>; else goto <D.20384>;
  <D.20383>:
  D.20385 = is_socketasynccall (domain, klass);
  if (D.20385 != 0) goto <D.20386>; else goto <D.20387>;
  <D.20386>:
  socket_async_call_klass = klass;
  <D.20387>:
  <D.20384>:
  process_async_call_klass.49 = process_async_call_klass;
  if (process_async_call_klass.49 == 0B) goto <D.20389>; else goto <D.20390>;
  <D.20389>:
  D.20391 = is_sdp_asyncreadhandler (domain, klass);
  if (D.20391 != 0) goto <D.20392>; else goto <D.20393>;
  <D.20392>:
  process_async_call_klass = klass;
  <D.20393>:
  <D.20390>:
  socket_async_call_klass.48 = socket_async_call_klass;
  if (klass != socket_async_call_klass.48) goto <D.20394>; else goto <D.20395>;
  <D.20394>:
  process_async_call_klass.49 = process_async_call_klass;
  if (klass != process_async_call_klass.49) goto <D.20396>; else goto <D.20397>;
  <D.20396>:
  D.20380 = 0;
  return D.20380;
  <D.20397>:
  <D.20395>:
  sock_res = state;
  op = sock_res->operation;
  op.50 = (unsigned int) op;
  if (op.50 > 13) goto <D.20399>; else goto <D.20400>;
  <D.20399>:
  D.20380 = 0;
  return D.20380;
  <D.20400>:
  D.20380 = 1;
  return D.20380;
}


is_socketasynccall (struct MonoDomain * domain, struct MonoClass * klass)
{
  gboolean D.20402;
  int iftmp.51;
  struct MonoClass * D.20406;
  int D.20408;
  const char * D.20410;
  int D.20411;

  D.20406 = klass->nested_in;
  if (D.20406 != 0B) goto <D.20407>; else goto <D.20404>;
  <D.20407>:
  D.20406 = klass->nested_in;
  D.20408 = is_socket (domain, D.20406);
  if (D.20408 != 0) goto <D.20409>; else goto <D.20404>;
  <D.20409>:
  D.20410 = klass->name;
  D.20411 = strcmp (D.20410, "SocketAsyncCall");
  if (D.20411 == 0) goto <D.20412>; else goto <D.20404>;
  <D.20412>:
  iftmp.51 = 1;
  goto <D.20405>;
  <D.20404>:
  iftmp.51 = 0;
  <D.20405>:
  D.20402 = iftmp.51;
  return D.20402;
}


is_sdp_asyncreadhandler (struct MonoDomain * domain, struct MonoClass * klass)
{
  gboolean D.20414;
  int iftmp.52;
  struct MonoClass * D.20418;
  int D.20420;
  const char * D.20422;
  int D.20423;

  D.20418 = klass->nested_in;
  if (D.20418 != 0B) goto <D.20419>; else goto <D.20416>;
  <D.20419>:
  D.20418 = klass->nested_in;
  D.20420 = is_sd_process (domain, D.20418);
  if (D.20420 != 0) goto <D.20421>; else goto <D.20416>;
  <D.20421>:
  D.20422 = klass->name;
  D.20423 = strcmp (D.20422, "AsyncReadHandler");
  if (D.20423 == 0) goto <D.20424>; else goto <D.20416>;
  <D.20424>:
  iftmp.52 = 1;
  goto <D.20417>;
  <D.20416>:
  iftmp.52 = 0;
  <D.20417>:
  D.20414 = iftmp.52;
  return D.20414;
}


is_sd_process (struct MonoDomain * domain, struct MonoClass * klass)
{
  struct MonoClass * D.20426;
  gboolean D.20429;
  _Bool D.20430;
  int D.20431;
  const char * D.20434;
  int D.20435;
  const char * D.20438;
  int D.20439;

  D.20426 = domain->process_class;
  if (D.20426 != 0B) goto <D.20427>; else goto <D.20428>;
  <D.20427>:
  D.20426 = domain->process_class;
  D.20430 = D.20426 == klass;
  D.20429 = (gboolean) D.20430;
  return D.20429;
  <D.20428>:
  D.20431 = is_system_type (domain, klass);
  if (D.20431 != 0) goto <D.20432>; else goto <D.20433>;
  <D.20432>:
  D.20434 = klass->name;
  D.20435 = strcmp ("Process", D.20434);
  if (D.20435 == 0) goto <D.20436>; else goto <D.20437>;
  <D.20436>:
  D.20438 = klass->name_space;
  D.20439 = strcmp ("System.Diagnostics", D.20438);
  if (D.20439 == 0) goto <D.20440>; else goto <D.20441>;
  <D.20440>:
  domain->process_class = klass;
  D.20429 = 1;
  return D.20429;
  <D.20441>:
  <D.20437>:
  <D.20433>:
  D.20429 = 0;
  return D.20429;
}


__attribute__((visibility ("hidden")))
mono_thread_pool_finish (struct MonoAsyncResult * ares, struct MonoArray * * out_args, struct MonoObject * * exc)
{
  unsigned char D.20443;
  struct MonoException * D.20446;
  struct MonoObject * D.20447;
  unsigned char D.20448;
  struct MonoObject * D.20451;
  _Bool D.20454;
  long int D.20455;
  long int D.20456;
  struct MonoObject * * D.20459;
  struct MonoVTable * D.20460;
  struct MonoDomain * D.20461;
  struct MonoWaitHandle * D.20462;
  _Bool D.20465;
  long int D.20466;
  long int D.20467;
  struct MonoMethodMessage * D.20470;
  struct MonoObject * D.20471;
  struct MonoArray * D.20472;
  struct ASyncCall * ac;
  void * wait_event;

  *exc = 0B;
  *out_args = 0B;
  mono_monitor_enter (ares);
  D.20443 = ares->endinvoke_called;
  if (D.20443 != 0) goto <D.20444>; else goto <D.20445>;
  <D.20444>:
  D.20446 = mono_get_exception_invalid_operation (0B);
  *exc = D.20446;
  mono_monitor_exit (ares);
  D.20447 = 0B;
  return D.20447;
  <D.20445>:
  ares->endinvoke_called = 1;
  D.20448 = ares->completed;
  if (D.20448 == 0) goto <D.20449>; else goto <D.20450>;
  <D.20449>:
  D.20451 = ares->handle;
  if (D.20451 == 0B) goto <D.20452>; else goto <D.20453>;
  <D.20452>:
  wait_event = CreateEvent (0B, 1, 0, 0B);
  D.20454 = wait_event == 0B;
  D.20455 = (long int) D.20454;
  D.20456 = __builtin_expect (D.20455, 0);
  if (D.20456 != 0) goto <D.20457>; else goto <D.20458>;
  <D.20457>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 958, "wait_event != 0");
  <D.20458>:
  D.20459 = &ares->handle;
  D.20460 = MEM[(struct MonoObject *)ares].vtable;
  D.20461 = D.20460->domain;
  D.20462 = mono_wait_handle_new (D.20461, wait_event);
  mono_gc_wbarrier_set_field (ares, D.20459, D.20462);
  goto <D.20463>;
  <D.20453>:
  D.20451 = ares->handle;
  wait_event = mono_wait_handle_get_handle (D.20451);
  <D.20463>:
  mono_monitor_exit (ares);
  WaitForSingleObjectEx (wait_event, 4294967295, 1);
  goto <D.20464>;
  <D.20450>:
  mono_monitor_exit (ares);
  <D.20464>:
  ac = ares->object_data;
  D.20465 = ac == 0B;
  D.20466 = (long int) D.20465;
  D.20467 = __builtin_expect (D.20466, 0);
  if (D.20467 != 0) goto <D.20468>; else goto <D.20469>;
  <D.20468>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 970, "ac != NULL");
  <D.20469>:
  D.20470 = ac->msg;
  D.20471 = D.20470->exc;
  *exc = D.20471;
  D.20472 = ac->out_args;
  *out_args = D.20472;
  D.20447 = ac->res;
  return D.20447;
}


__attribute__((visibility ("hidden")))
mono_thread_pool_cleanup ()
{
  int D.20474;
  struct MonoCQ * D.20477;
  int D.20480;
  struct GPtrArray * wsqs.53;
  _Bool D.20488;
  long int D.20489;
  long int D.20490;
  _Bool D.20497;
  long int D.20498;
  long int D.20499;

  D.20474 = InterlockedExchange (&async_io_tp.pool_status, 2);
  if (D.20474 == 1) goto <D.20475>; else goto <D.20476>;
  <D.20475>:
  socket_io_cleanup (&socket_io_data);
  threadpool_kill_idle_threads (&async_io_tp);
  <D.20476>:
  D.20477 = async_io_tp.queue;
  if (D.20477 != 0B) goto <D.20478>; else goto <D.20479>;
  <D.20478>:
  sem_destroy (&async_io_tp.new_job);
  threadpool_free_queue (&async_io_tp);
  <D.20479>:
  D.20480 = InterlockedExchange (&async_tp.pool_status, 2);
  if (D.20480 == 1) goto <D.20481>; else goto <D.20482>;
  <D.20481>:
  threadpool_kill_idle_threads (&async_tp);
  threadpool_free_queue (&async_tp);
  <D.20482>:
  wsqs.53 = wsqs;
  if (wsqs.53 != 0B) goto <D.20484>; else goto <D.20485>;
  <D.20484>:
  {
    int ret;

    ret = pthread_mutex_lock (&wsqs_lock.mutex);
    if (ret != 0) goto <D.20486>; else goto <D.20487>;
    <D.20486>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.20487>:
    D.20488 = ret != 0;
    D.20489 = (long int) D.20488;
    D.20490 = __builtin_expect (D.20489, 0);
    if (D.20490 != 0) goto <D.20491>; else goto <D.20492>;
    <D.20491>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 1009, "ret == 0");
    <D.20492>:
  }
  mono_wsq_cleanup ();
  wsqs.53 = wsqs;
  if (wsqs.53 != 0B) goto <D.20493>; else goto <D.20494>;
  <D.20493>:
  wsqs.53 = wsqs;
  monoeg_g_ptr_array_free (wsqs.53, 1);
  <D.20494>:
  wsqs = 0B;
  {
    int ret;

    ret = pthread_mutex_unlock (&wsqs_lock.mutex);
    if (ret != 0) goto <D.20495>; else goto <D.20496>;
    <D.20495>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.20496>:
    D.20497 = ret != 0;
    D.20498 = (long int) D.20497;
    D.20499 = __builtin_expect (D.20498, 0);
    if (D.20499 != 0) goto <D.20500>; else goto <D.20501>;
    <D.20500>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 1014, "ret == 0");
    <D.20501>:
  }
  sem_destroy (&async_tp.new_job);
  <D.20485>:
}


InterlockedExchange (volatile gint32 * val, gint32 new_val)
{
  unsigned int old_val.54;
  unsigned int new_val.55;
  unsigned int D.20504;
  int D.20505;
  gint32 D.20506;
  gint32 old_val;

  <D.17451>:
  old_val = *val;
  old_val.54 = (unsigned int) old_val;
  new_val.55 = (unsigned int) new_val;
  D.20504 = __sync_val_compare_and_swap_4 (val, old_val.54, new_val.55);
  D.20505 = (int) D.20504;
  if (D.20505 != old_val) goto <D.17451>; else goto <D.17452>;
  <D.17452>:
  D.20506 = old_val;
  return D.20506;
}


threadpool_kill_idle_threads (struct ThreadPool * tp)
{
  volatile gint * D.20508;
  union MonoSemType * D.20509;
  gint n;

  D.20508 = &tp->max_threads;
  n = InterlockedCompareExchange (D.20508, 0, -1);
  goto <D.18898>;
  <D.18897>:
  n = n + -1;
  D.20509 = &tp->new_job;
  mono_sem_post (D.20509);
  <D.18898>:
  if (n != 0) goto <D.18897>; else goto <D.18899>;
  <D.18899>:
}


threadpool_free_queue (struct ThreadPool * tp)
{
  struct MonoCQ * D.20510;

  D.20510 = tp->queue;
  mono_cq_destroy (D.20510);
  tp->queue = 0B;
}


__attribute__((visibility ("hidden")))
icall_append_job (struct MonoObject * ar)
{
  threadpool_append_jobs (&async_tp, &ar, 1);
}


__attribute__((visibility ("hidden")))
mono_thread_pool_remove_domain_jobs (struct MonoDomain * domain, int timeout)
{
  unsigned int D.20511;
  _Bool D.20512;
  long int D.20513;
  long int D.20514;
  _Bool D.20519;
  long int D.20520;
  long int D.20521;
  struct MonoGHashTable * D.20524;
  _Bool D.20529;
  long int D.20530;
  long int D.20531;
  int D.20534;
  unsigned int timeout.56;
  unsigned int D.20542;
  unsigned int D.20543;
  int D.20546;
  gboolean D.20547;
  void * sem_handle;
  int result;
  guint32 start_time;

  result = 1;
  start_time = 0;
  D.20511 = domain->state;
  D.20512 = D.20511 != 2;
  D.20513 = (long int) D.20512;
  D.20514 = __builtin_expect (D.20513, 0);
  if (D.20514 != 0) goto <D.20515>; else goto <D.20516>;
  <D.20515>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 1159, "domain->state == MONO_APPDOMAIN_UNLOADING");
  <D.20516>:
  threadpool_clear_queue (&async_tp, domain);
  threadpool_clear_queue (&async_io_tp, domain);
  {
    int ret;

    ret = pthread_mutex_lock (&socket_io_data.io_lock.mutex);
    if (ret != 0) goto <D.20517>; else goto <D.20518>;
    <D.20517>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.20518>:
    D.20519 = ret != 0;
    D.20520 = (long int) D.20519;
    D.20521 = __builtin_expect (D.20520, 0);
    if (D.20521 != 0) goto <D.20522>; else goto <D.20523>;
    <D.20522>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 1164, "ret == 0");
    <D.20523>:
  }
  D.20524 = socket_io_data.sock_to_state;
  if (D.20524 != 0B) goto <D.20525>; else goto <D.20526>;
  <D.20525>:
  D.20524 = socket_io_data.sock_to_state;
  mono_g_hash_table_foreach_remove (D.20524, remove_sockstate_for_domain, domain);
  <D.20526>:
  {
    int ret;

    ret = pthread_mutex_unlock (&socket_io_data.io_lock.mutex);
    if (ret != 0) goto <D.20527>; else goto <D.20528>;
    <D.20527>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.20528>:
    D.20529 = ret != 0;
    D.20530 = (long int) D.20529;
    D.20531 = __builtin_expect (D.20530, 0);
    if (D.20531 != 0) goto <D.20532>; else goto <D.20533>;
    <D.20532>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "threadpool.c", 1168, "ret == 0");
    <D.20533>:
  }
  sem_handle = CreateSemaphore (0B, 0, 1, 0B);
  domain->cleanup_semaphore = sem_handle;
  mono_memory_write_barrier ();
  D.20534 = domain->threadpool_jobs;
  if (D.20534 != 0) goto <D.20535>; else goto <D.20536>;
  <D.20535>:
  if (timeout != -1) goto <D.20537>; else goto <D.20538>;
  <D.20537>:
  start_time = mono_msec_ticks ();
  <D.20538>:
  <D.20536>:
  goto <D.18974>;
  <D.18973>:
  timeout.56 = (unsigned int) timeout;
  WaitForSingleObject (sem_handle, timeout.56);
  if (timeout != -1) goto <D.20540>; else goto <D.20541>;
  <D.20540>:
  D.20542 = mono_msec_ticks ();
  D.20543 = D.20542 - start_time;
  timeout.56 = (unsigned int) timeout;
  if (D.20543 > timeout.56) goto <D.20544>; else goto <D.20545>;
  <D.20544>:
  result = 0;
  goto <D.18972>;
  <D.20545>:
  <D.20541>:
  <D.18974>:
  D.20546 = domain->threadpool_jobs;
  if (D.20546 != 0) goto <D.18973>; else goto <D.18972>;
  <D.18972>:
  domain->cleanup_semaphore = 0B;
  CloseHandle (sem_handle);
  D.20547 = result;
  return D.20547;
}


remove_sockstate_for_domain (void * key, void * value, void * user_data)
{
  struct MonoVTable * D.20549;
  struct MonoDomain * D.20550;
  gboolean D.20553;
  struct MonoMList * list;
  gboolean remove;

  list = value;
  remove = 0;
  goto <D.18961>;
  <D.18960>:
  {
    struct MonoObject * data;

    data = mono_mlist_get_data (list);
    D.20549 = data->vtable;
    D.20550 = D.20549->domain;
    if (D.20550 == user_data) goto <D.20551>; else goto <D.20552>;
    <D.20551>:
    remove = 1;
    mono_mlist_set_data (list, 0B);
    <D.20552>:
    list = mono_mlist_next (list);
  }
  <D.18961>:
  if (list != 0B) goto <D.18960>; else goto <D.18962>;
  <D.18962>:
  D.20553 = remove;
  return D.20553;
}


threadpool_clear_queue (struct ThreadPool * tp, struct MonoDomain * domain)
{
  struct MonoObject * obj.57;
  struct MonoVTable * D.20560;
  struct MonoDomain * D.20561;
  int D.20564;
  int D.20565;
  struct MonoObject * D.20568;
  struct MonoObject * obj;
  struct MonoMList * other;
  struct MonoCQ * queue;

  try
    {
      other = 0B;
      queue = tp->queue;
      if (queue == 0B) goto <D.20555>; else goto <D.20556>;
      <D.20555>:
      return;
      <D.20556>:
      goto <D.18946>;
      <D.18947>:
      obj.57 = obj;
      if (obj.57 == 0B) goto <D.20558>; else goto <D.20559>;
      <D.20558>:
      // predicted unlikely by continue predictor.
      goto <D.18946>;
      <D.20559>:
      obj.57 = obj;
      D.20560 = obj.57->vtable;
      D.20561 = D.20560->domain;
      if (D.20561 != domain) goto <D.20562>; else goto <D.20563>;
      <D.20562>:
      obj.57 = obj;
      other = mono_mlist_prepend (other, obj.57);
      <D.20563>:
      obj.57 = obj;
      threadpool_jobs_dec (obj.57);
      <D.18946>:
      D.20564 = mono_cq_dequeue (queue, &obj);
      if (D.20564 != 0) goto <D.18947>; else goto <D.18948>;
      <D.18948>:
      D.20565 = mono_runtime_is_shutting_down ();
      if (D.20565 != 0) goto <D.20566>; else goto <D.20567>;
      <D.20566>:
      return;
      <D.20567>:
      goto <D.18950>;
      <D.18949>:
      D.20568 = mono_mlist_get_data (other);
      threadpool_append_job (tp, D.20568);
      other = mono_mlist_next (other);
      <D.18950>:
      if (other != 0B) goto <D.18949>; else goto <D.18951>;
      <D.18951>:
    }
  finally
    {
      obj = {CLOBBER};
    }
}


mono_memory_write_barrier ()
{
  mono_memory_barrier ();
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


__attribute__((visibility ("hidden")))
mono_thread_pool_is_queue_array (struct MonoArray * o)
{
  gboolean D.20572;

  D.20572 = 0;
  return D.20572;
}


__attribute__((visibility ("hidden")))
ves_icall_System_Threading_ThreadPool_GetAvailableThreads (gint * workerThreads, gint * completionPortThreads)
{
  int D.20574;
  int D.20575;
  int D.20576;
  int D.20577;
  int D.20578;
  int D.20579;

  D.20574 = async_tp.max_threads;
  D.20575 = async_tp.busy_threads;
  D.20576 = D.20574 - D.20575;
  *workerThreads = D.20576;
  D.20577 = async_io_tp.max_threads;
  D.20578 = async_io_tp.busy_threads;
  D.20579 = D.20577 - D.20578;
  *completionPortThreads = D.20579;
}


__attribute__((visibility ("hidden")))
ves_icall_System_Threading_ThreadPool_GetMaxThreads (gint * workerThreads, gint * completionPortThreads)
{
  int D.20580;
  int D.20581;

  D.20580 = async_tp.max_threads;
  *workerThreads = D.20580;
  D.20581 = async_io_tp.max_threads;
  *completionPortThreads = D.20581;
}


__attribute__((visibility ("hidden")))
ves_icall_System_Threading_ThreadPool_GetMinThreads (gint * workerThreads, gint * completionPortThreads)
{
  int D.20582;
  int D.20583;

  D.20582 = async_tp.min_threads;
  *workerThreads = D.20582;
  D.20583 = async_io_tp.min_threads;
  *completionPortThreads = D.20583;
}


__attribute__((visibility ("hidden")))
ves_icall_System_Threading_ThreadPool_SetMinThreads (gint workerThreads, gint completionPortThreads)
{
  MonoBoolean D.20587;
  int D.20591;
  struct MonoDomain * D.20594;
  int D.20595;
  struct MonoDomain * D.20598;
  gint max_threads;
  gint max_io_threads;

  max_threads = async_tp.max_threads;
  if (workerThreads <= 0) goto <D.20584>; else goto <D.20586>;
  <D.20586>:
  if (workerThreads > max_threads) goto <D.20584>; else goto <D.20585>;
  <D.20584>:
  D.20587 = 0;
  return D.20587;
  <D.20585>:
  max_io_threads = async_io_tp.max_threads;
  if (completionPortThreads <= 0) goto <D.20588>; else goto <D.20590>;
  <D.20590>:
  if (completionPortThreads > max_io_threads) goto <D.20588>; else goto <D.20589>;
  <D.20588>:
  D.20587 = 0;
  return D.20587;
  <D.20589>:
  InterlockedExchange (&async_tp.min_threads, workerThreads);
  InterlockedExchange (&async_io_tp.min_threads, completionPortThreads);
  D.20591 = async_tp.nthreads;
  if (D.20591 < workerThreads) goto <D.20592>; else goto <D.20593>;
  <D.20592>:
  D.20594 = mono_get_root_domain ();
  mono_thread_create_internal (D.20594, threadpool_start_idle_threads, &async_tp, 1, 0, 262144);
  <D.20593>:
  D.20595 = async_io_tp.nthreads;
  if (D.20595 < completionPortThreads) goto <D.20596>; else goto <D.20597>;
  <D.20596>:
  D.20598 = mono_get_root_domain ();
  mono_thread_create_internal (D.20598, threadpool_start_idle_threads, &async_io_tp, 1, 0, 262144);
  <D.20597>:
  D.20587 = 1;
  return D.20587;
}


__attribute__((visibility ("hidden")))
ves_icall_System_Threading_ThreadPool_SetMaxThreads (gint workerThreads, gint completionPortThreads)
{
  MonoBoolean D.20603;
  gint min_threads;
  gint min_io_threads;
  gint cpu_count;

  cpu_count = mono_cpu_count ();
  min_threads = async_tp.min_threads;
  if (workerThreads < min_threads) goto <D.20600>; else goto <D.20602>;
  <D.20602>:
  if (workerThreads < cpu_count) goto <D.20600>; else goto <D.20601>;
  <D.20600>:
  D.20603 = 0;
  return D.20603;
  <D.20601>:
  min_io_threads = async_io_tp.min_threads;
  if (completionPortThreads < min_io_threads) goto <D.20604>; else goto <D.20606>;
  <D.20606>:
  if (completionPortThreads < cpu_count) goto <D.20604>; else goto <D.20605>;
  <D.20604>:
  D.20603 = 0;
  return D.20603;
  <D.20605>:
  InterlockedExchange (&async_tp.max_threads, workerThreads);
  InterlockedExchange (&async_io_tp.max_threads, completionPortThreads);
  D.20603 = 1;
  return D.20603;
}


mono_install_threadpool_thread_hooks (void (*MonoThreadPoolFunc) (void *) start_func, void (*MonoThreadPoolFunc) (void *) finish_func, void * user_data)
{
  tp_start_func = start_func;
  tp_finish_func = finish_func;
  tp_hooks_user_data = user_data;
}


mono_install_threadpool_item_hooks (void (*MonoThreadPoolItemFunc) (void *) begin_func, void (*MonoThreadPoolItemFunc) (void *) end_func, void * user_data)
{
  tp_item_begin_func = begin_func;
  tp_item_end_func = end_func;
  tp_item_user_data = user_data;
}


__attribute__((visibility ("hidden")))
mono_internal_thread_unhandled_exception (struct MonoObject * exc)
{
  <unnamed type> D.20608;
  struct MonoVTable * D.20611;
  struct MonoDomain * D.20612;
  struct MonoClass * D.20615;
  int D.20618;
  struct MonoInternalThread * D.20623;

  D.20608 = mono_runtime_unhandled_exception_policy_get ();
  if (D.20608 == 1) goto <D.20609>; else goto <D.20610>;
  <D.20609>:
  {
    gboolean unloaded;
    struct MonoClass * klass;

    D.20611 = exc->vtable;
    klass = D.20611->klass;
    D.20611 = exc->vtable;
    D.20612 = D.20611->domain;
    unloaded = is_appdomainunloaded_exception (D.20612, klass);
    if (unloaded == 0) goto <D.20613>; else goto <D.20614>;
    <D.20613>:
    D.20615 = mono_defaults.threadabortexception_class;
    if (D.20615 != klass) goto <D.20616>; else goto <D.20617>;
    <D.20616>:
    mono_unhandled_exception (exc);
    D.20618 = mono_environment_exitcode_get ();
    if (D.20618 == 1) goto <D.20619>; else goto <D.20620>;
    <D.20619>:
    exit (255);
    <D.20620>:
    <D.20617>:
    <D.20614>:
    D.20615 = mono_defaults.threadabortexception_class;
    if (D.20615 == klass) goto <D.20621>; else goto <D.20622>;
    <D.20621>:
    D.20623 = mono_thread_internal_current ();
    mono_thread_internal_reset_abort (D.20623);
    <D.20622>:
  }
  <D.20610>:
}


is_appdomainunloaded_exception (struct MonoDomain * domain, struct MonoClass * klass)
{
  struct MonoClass * D.20624;
  gboolean D.20627;
  _Bool D.20628;
  int D.20629;
  const char * D.20632;
  int D.20633;
  const char * D.20636;
  int D.20637;

  D.20624 = domain->ad_unloaded_ex_class;
  if (D.20624 != 0B) goto <D.20625>; else goto <D.20626>;
  <D.20625>:
  D.20624 = domain->ad_unloaded_ex_class;
  D.20628 = D.20624 == klass;
  D.20627 = (gboolean) D.20628;
  return D.20627;
  <D.20626>:
  D.20629 = is_corlib_type (domain, klass);
  if (D.20629 != 0) goto <D.20630>; else goto <D.20631>;
  <D.20630>:
  D.20632 = klass->name;
  D.20633 = strcmp ("AppDomainUnloadedException", D.20632);
  if (D.20633 == 0) goto <D.20634>; else goto <D.20635>;
  <D.20634>:
  D.20636 = klass->name_space;
  D.20637 = strcmp ("System", D.20636);
  if (D.20637 == 0) goto <D.20638>; else goto <D.20639>;
  <D.20638>:
  domain->ad_unloaded_ex_class = klass;
  D.20627 = 1;
  return D.20627;
  <D.20639>:
  <D.20635>:
  <D.20631>:
  D.20627 = 0;
  return D.20627;
}


__attribute__((visibility ("hidden")))
mono_thread_pool_suspend ()
{
  suspended = 1;
}


__attribute__((visibility ("hidden")))
mono_thread_pool_resume ()
{
  suspended = 0;
}


