Merge pull request #1718 from madewokherd/sgenthreadcleanup
authormonojenkins <jo.shields+jenkins@xamarin.com>
Tue, 29 Mar 2016 20:01:05 +0000 (21:01 +0100)
committermonojenkins <jo.shields+jenkins@xamarin.com>
Tue, 29 Mar 2016 20:01:05 +0000 (21:01 +0100)
[sgen] Clean up thread pool on shutdown.

Keeping threads around can cause processes to keep running when they shouldn't, particularly on Windows when the entry point returns.

(The reason this is important for me is that Wine provides _CorExeMain, which is an entry point that does return, unlike normal compiled C programs which appear to call exit() after main() returns. A Windows process doesn't exit until ALL threads have exited, so a thread that never exits means a hung process.)

It doesn't seem like we have other GC-specific cleanup code, so I don't know if this is a good approach. Feedback on that question would be appreciated.

1  2 
mono/metadata/sgen-mono.c

index 42f860df05d7bc979130e9672a251d0f4535c5b9,262589f2a995cc5fa7cc70f58f4a216b4adb7614..efa0e892eccf3bd312a72915c482e115c8fad163
  #include "metadata/runtime.h"
  #include "metadata/sgen-bridge-internals.h"
  #include "metadata/gc-internals.h"
 +#include "metadata/handle.h"
  #include "utils/mono-memory-model.h"
  #include "utils/mono-logger-internals.h"
+ #include "sgen/sgen-thread-pool.h"
  
  #ifdef HEAVY_STATISTICS
  static guint64 stat_wbarrier_set_arrayref = 0;
@@@ -936,10 -936,8 +937,10 @@@ mono_gc_alloc_obj (MonoVTable *vtable, 
  {
        MonoObject *obj = sgen_alloc_obj (vtable, size);
  
 -      if (G_UNLIKELY (alloc_events))
 -              mono_profiler_allocation (obj);
 +      if (G_UNLIKELY (alloc_events)) {
 +              if (obj)
 +                      mono_profiler_allocation (obj);
 +      }
  
        return obj;
  }
@@@ -949,23 -947,22 +950,23 @@@ mono_gc_alloc_pinned_obj (MonoVTable *v
  {
        MonoObject *obj = sgen_alloc_obj_pinned (vtable, size);
  
 -      if (G_UNLIKELY (alloc_events))
 -              mono_profiler_allocation (obj);
 +      if (G_UNLIKELY (alloc_events)) {
 +              if (obj)
 +                      mono_profiler_allocation (obj);
 +      }
  
        return obj;
  }
  
  void*
 -mono_gc_alloc_mature (MonoVTable *vtable)
 +mono_gc_alloc_mature (MonoVTable *vtable, size_t size)
  {
 -      MonoObject *obj = sgen_alloc_obj_mature (vtable, vtable->klass->instance_size);
 -
 -      if (obj && G_UNLIKELY (obj->vtable->klass->has_finalize))
 -              mono_object_register_finalizer (obj);
 +      MonoObject *obj = sgen_alloc_obj_mature (vtable, size);
  
 -      if (G_UNLIKELY (alloc_events))
 -              mono_profiler_allocation (obj);
 +      if (G_UNLIKELY (alloc_events)) {
 +              if (obj)
 +                      mono_profiler_allocation (obj);
 +      }
  
        return obj;
  }
@@@ -1108,16 -1105,16 +1109,16 @@@ create_allocator (int atype, gboolean s
                case ATYPE_NORMAL:
                case ATYPE_SMALL:
                        mono_mb_emit_ldarg (mb, 0);
 -                      mono_mb_emit_icall (mb, mono_object_new_specific);
 +                      mono_mb_emit_icall (mb, ves_icall_object_new_specific);
                        break;
                case ATYPE_VECTOR:
                        mono_mb_emit_ldarg (mb, 0);
                        mono_mb_emit_ldarg (mb, 1);
 -                      mono_mb_emit_icall (mb, mono_array_new_specific);
 +                      mono_mb_emit_icall (mb, ves_icall_array_new_specific);
                        break;
                case ATYPE_STRING:
                        mono_mb_emit_ldarg (mb, 1);
 -                      mono_mb_emit_icall (mb, mono_string_alloc);
 +                      mono_mb_emit_icall (mb, ves_icall_string_alloc);
                        break;
                default:
                        g_assert_not_reached ();
                /* catch */
                clause->flags = MONO_EXCEPTION_CLAUSE_NONE;
                clause->try_len = mono_mb_get_pos (mb) - clause->try_offset;
 -              clause->data.catch_class = mono_class_from_name (mono_defaults.corlib,
 +              clause->data.catch_class = mono_class_load_from_name (mono_defaults.corlib,
                                "System", "OverflowException");
 -              g_assert (clause->data.catch_class);
                clause->handler_offset = mono_mb_get_label (mb);
  
 -              oom_exc_class = mono_class_from_name (mono_defaults.corlib,
 +              oom_exc_class = mono_class_load_from_name (mono_defaults.corlib,
                                "System", "OutOfMemoryException");
 -              g_assert (oom_exc_class);
                ctor = mono_class_get_method_from_name (oom_exc_class, ".ctor", 0);
                g_assert (ctor);
  
        info->d.alloc.gc_name = "sgen";
        info->d.alloc.alloc_type = atype;
  
 -      res = mono_mb_create (mb, csig, 8, info);
 -      mono_mb_free (mb);
  #ifndef DISABLE_JIT
 -      mono_method_get_header (res)->init_locals = FALSE;
 +      mb->init_locals = FALSE;
  #endif
  
 +      res = mono_mb_create (mb, csig, 8, info);
 +      mono_mb_free (mb);
 +
  
        return res;
  }
  int
  mono_gc_get_aligned_size_for_allocator (int size)
  {
 -      int aligned_size = size;
 -      aligned_size += SGEN_ALLOC_ALIGN - 1;
 -      aligned_size &= ~(SGEN_ALLOC_ALIGN - 1);
 -      return aligned_size;
 +      return SGEN_ALIGN_UP (size);
  }
  
  /*
@@@ -1591,7 -1592,7 +1592,7 @@@ find_next_card (guint8 *card_data, guin
  #define ARRAY_OBJ_INDEX(ptr,array,elem_size) (((char*)(ptr) - ((char*)(array) + G_STRUCT_OFFSET (MonoArray, vector))) / (elem_size))
  
  gboolean
 -sgen_client_cardtable_scan_object (GCObject *obj, mword block_obj_size, guint8 *cards, gboolean mod_union, ScanCopyContext ctx)
 +sgen_client_cardtable_scan_object (GCObject *obj, mword block_obj_size, guint8 *cards, ScanCopyContext ctx)
  {
        MonoVTable *vt = SGEN_LOAD_VTABLE (obj);
        MonoClass *klass = vt->klass;
@@@ -1671,11 -1672,20 +1672,11 @@@ LOOP_HEAD
                                for (; elem < card_end; elem += elem_size)
                                        scan_vtype_func (obj, elem, desc, ctx.queue BINARY_PROTOCOL_ARG (elem_size));
                        } else {
 -                              CopyOrMarkObjectFunc copy_func = ctx.ops->copy_or_mark_object;
 +                              ScanPtrFieldFunc scan_ptr_field_func = ctx.ops->scan_ptr_field;
  
                                HEAVY_STAT (++los_array_cards);
 -                              for (; elem < card_end; elem += SIZEOF_VOID_P) {
 -                                      GCObject *new_;
 -                                      gpointer old = *(gpointer*)elem;
 -                                      if ((mod_union && old) || G_UNLIKELY (sgen_ptr_in_nursery (old))) {
 -                                              HEAVY_STAT (++los_array_remsets);
 -                                              copy_func ((GCObject**)elem, ctx.queue);
 -                                              new_ = *(GCObject **)elem;
 -                                              if (G_UNLIKELY (sgen_ptr_in_nursery (new_)))
 -                                                      sgen_add_to_global_remset (elem, new_);
 -                                      }
 -                              }
 +                              for (; elem < card_end; elem += SIZEOF_VOID_P)
 +                                      scan_ptr_field_func (obj, (GCObject**)elem, ctx.queue);
                        }
  
                        binary_protocol_card_scan (first_elem, elem - first_elem);
@@@ -1726,7 -1736,7 +1727,7 @@@ mono_gc_alloc_vector (MonoVTable *vtabl
        arr = (MonoArray*)sgen_alloc_obj_nolock (vtable, size);
        if (G_UNLIKELY (!arr)) {
                UNLOCK_GC;
 -              return mono_gc_out_of_memory (size);
 +              return NULL;
        }
  
        arr->max_length = (mono_array_size_t)max_length;
@@@ -1771,7 -1781,7 +1772,7 @@@ mono_gc_alloc_array (MonoVTable *vtable
        arr = (MonoArray*)sgen_alloc_obj_nolock (vtable, size);
        if (G_UNLIKELY (!arr)) {
                UNLOCK_GC;
 -              return mono_gc_out_of_memory (size);
 +              return NULL;
        }
  
        arr->max_length = (mono_array_size_t)max_length;
@@@ -1815,7 -1825,7 +1816,7 @@@ mono_gc_alloc_string (MonoVTable *vtabl
        str = (MonoString*)sgen_alloc_obj_nolock (vtable, size);
        if (G_UNLIKELY (!str)) {
                UNLOCK_GC;
 -              return mono_gc_out_of_memory (size);
 +              return NULL;
        }
  
        str->length = len;
@@@ -2267,8 -2277,6 +2268,8 @@@ thread_in_critical_region (SgenThreadIn
  static void
  sgen_thread_attach (SgenThreadInfo *info)
  {
 +      mono_handle_arena_init ((MonoHandleArena**) &info->client_info.info.handle_arena);
 +
        if (mono_gc_get_gc_callbacks ()->thread_attach_func && !info->client_info.runtime_data)
                info->client_info.runtime_data = mono_gc_get_gc_callbacks ()->thread_attach_func ();
  }
@@@ -2284,8 -2292,6 +2285,8 @@@ sgen_thread_detach (SgenThreadInfo *p
         */
        if (mono_domain_get ())
                mono_thread_detach_internal (mono_thread_internal_current ());
 +
 +      mono_handle_arena_cleanup ((MonoHandleArena**) &p->client_info.info.handle_arena);
  }
  
  gboolean
@@@ -2333,6 -2339,8 +2334,6 @@@ mono_gc_scan_object (void *obj, void *g
  void
  sgen_client_scan_thread_data (void *start_nursery, void *end_nursery, gboolean precise, ScanCopyContext ctx)
  {
 -      SgenThreadInfo *info;
 -
        scan_area_arg_start = start_nursery;
        scan_area_arg_end = end_nursery;
  
  
                if (!precise) {
  #ifdef USE_MONO_CTX
 -                      sgen_conservatively_pin_objects_from ((void**)&info->client_info.ctx, (void**)&info->client_info.ctx + ARCH_NUM_REGS,
 +                      sgen_conservatively_pin_objects_from ((void**)&info->client_info.ctx, (void**)(&info->client_info.ctx + 1),
                                start_nursery, end_nursery, PIN_TYPE_STACK);
  #else
                        sgen_conservatively_pin_objects_from ((void**)&info->client_info.regs, (void**)&info->client_info.regs + ARCH_NUM_REGS,
                                }
                        }
                }
 -      } END_FOREACH_THREAD
 +      } FOREACH_THREAD_END
  }
  
  /*
@@@ -2593,7 -2601,7 +2594,7 @@@ sgen_client_metadata_for_object (GCObje
   * @gchandle: a GCHandle's handle.
   * @domain: An application domain.
   *
 - * Returns: true if the object wrapped by the @gchandle belongs to the specific @domain.
 + * Returns: TRUE if the object wrapped by the @gchandle belongs to the specific @domain.
   */
  gboolean
  mono_gchandle_is_in_domain (guint32 gchandle, MonoDomain *domain)
@@@ -2697,6 -2705,12 +2698,6 @@@ mono_gc_register_altstack (gpointer sta
        // FIXME:
  }
  
 -void
 -sgen_client_out_of_memory (size_t size)
 -{
 -      mono_gc_out_of_memory (size);
 -}
 -
  guint8*
  mono_gc_get_card_table (int *shift_bits, gpointer *mask)
  {
@@@ -2726,7 -2740,7 +2727,7 @@@ sgen_client_degraded_allocation (size_
        static int last_major_gc_warned = -1;
        static int num_degraded = 0;
  
 -      if (last_major_gc_warned < gc_stats.major_gc_count) {
 +      if (last_major_gc_warned < (int)gc_stats.major_gc_count) {
                ++num_degraded;
                if (num_degraded == 1 || num_degraded == 3)
                        mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_GC, "Warning: Degraded allocation.  Consider increasing nursery-size if the warning persists.");
@@@ -2978,6 -2992,7 +2979,7 @@@ mono_gc_base_init (void
  void
  mono_gc_base_cleanup (void)
  {
+       sgen_thread_pool_shutdown ();
  }
  
  gboolean