[sgen] Add debug option for valloc limit
authorVlad Brezae <brezaevlad@gmail.com>
Thu, 30 Mar 2017 21:01:16 +0000 (00:01 +0300)
committerVlad Brezae <brezaevlad@gmail.com>
Fri, 31 Mar 2017 12:17:53 +0000 (15:17 +0300)
This allows us to stress test OOM inside sgen (and potentially other areas).

mono/sgen/sgen-gc.c
mono/utils/mono-mmap-internals.h
mono/utils/mono-mmap-windows.c
mono/utils/mono-mmap.c
mono/utils/mono-mmap.h

index fb6082ab6ab097da6911bab9a45fa1e0280ecead..f6aad7eeb37f624f7c2acdda4bd8630b3a8a72b5 100644 (file)
 #include "mono/utils/hazard-pointer.h"
 
 #include <mono/utils/memcheck.h>
+#include <mono/utils/mono-mmap-internals.h>
 
 #undef pthread_create
 #undef pthread_join
@@ -3215,6 +3216,15 @@ sgen_gc_init (void)
                        } else if (!strcmp (opt, "verify-before-allocs")) {
                                verify_before_allocs = 1;
                                has_per_allocation_action = TRUE;
+                       } else if (g_str_has_prefix (opt, "max-valloc-size=")) {
+                               size_t max_valloc_size;
+                               char *arg = strchr (opt, '=') + 1;
+                               if (*opt && mono_gc_parse_environment_string_extract_number (arg, &max_valloc_size)) {
+                                       mono_valloc_set_limit (max_valloc_size);
+                               } else {
+                                       sgen_env_var_error (MONO_GC_DEBUG_NAME, NULL, "`max-valloc-size` must be an integer.");
+                               }
+                               continue;
                        } else if (g_str_has_prefix (opt, "verify-before-allocs=")) {
                                char *arg = strchr (opt, '=') + 1;
                                verify_before_allocs = atoi (arg);
@@ -3295,6 +3305,7 @@ sgen_gc_init (void)
                                fprintf (stderr, "Valid <option>s are:\n");
                                fprintf (stderr, "  collect-before-allocs[=<n>]\n");
                                fprintf (stderr, "  verify-before-allocs[=<n>]\n");
+                               fprintf (stderr, "  max-valloc-size=N (where N is an integer, possibly with a k, m or a g suffix)\n");
                                fprintf (stderr, "  check-remset-consistency\n");
                                fprintf (stderr, "  check-mark-bits\n");
                                fprintf (stderr, "  check-nursery-pinned\n");
index 8fa286337f5544deb33bff98616953fae9e34772..8831c8bdadff8250532f33df5577fd713dd99a76 100644 (file)
@@ -21,6 +21,12 @@ aligned_address (char *mem, size_t size, size_t alignment);
 void
 account_mem (MonoMemAccountType type, ssize_t size);
 
+gboolean
+mono_valloc_can_alloc (size_t size);
+
+void
+mono_valloc_set_limit (size_t size);
+
 int
 mono_pages_not_faulted (void *addr, size_t length);
 
index 0f482d1a0901c788884b85b77f29bbbc935dc16d..0ae90eee3b9039d2c4541e17db7c7227ec991543 100644 (file)
@@ -71,6 +71,9 @@ mono_valloc (void *addr, size_t length, int flags, MonoMemAccountType type)
        int prot = mono_mmap_win_prot_from_flags (flags);
        /* translate the flags */
 
+       if (!mono_valloc_can_alloc (length))
+               return NULL;
+
        ptr = VirtualAlloc (addr, length, mflags, prot);
 
        account_mem (type, (ssize_t)length);
@@ -88,6 +91,9 @@ mono_valloc_aligned (size_t length, size_t alignment, int flags, MonoMemAccountT
        if (!mem)
                return NULL;
 
+       if (!mono_valloc_can_alloc (length))
+               return NULL;
+
        aligned = aligned_address (mem, length, alignment);
 
        aligned = VirtualAlloc (aligned, length, MEM_COMMIT, prot);
index ccfcb0b8ac029d3e64c318cc5d98f447d9aea6cf..d579d5a46a5cadbed0d515f4ed79d6803cea00d9 100644 (file)
@@ -81,18 +81,36 @@ aligned_address (char *mem, size_t size, size_t alignment)
        return aligned;
 }
 
-static volatile size_t allocation_count [MONO_MEM_ACCOUNT_MAX];
+static size_t allocation_count [MONO_MEM_ACCOUNT_MAX];
+static size_t total_allocation_count;
+static size_t alloc_limit;
 
 void
 account_mem (MonoMemAccountType type, ssize_t size)
 {
 #if SIZEOF_VOID_P == 4
        InterlockedAdd ((volatile gint32*)&allocation_count [type], (gint32)size);
+       InterlockedAdd ((volatile gint32*)&total_allocation_count, (gint32)size);
 #else
        InterlockedAdd64 ((volatile gint64*)&allocation_count [type], (gint64)size);
+       InterlockedAdd64 ((volatile gint64*)&total_allocation_count, (gint64)size);
 #endif
 }
 
+void
+mono_valloc_set_limit (size_t size)
+{
+       alloc_limit = size;
+}
+
+gboolean
+mono_valloc_can_alloc (size_t size)
+{
+       if (alloc_limit)
+               return (total_allocation_count + size) < alloc_limit;
+       return TRUE;
+}
+
 const char*
 mono_mem_account_type_name (MonoMemAccountType type)
 {
@@ -194,6 +212,10 @@ mono_valloc (void *addr, size_t length, int flags, MonoMemAccountType type)
        void *ptr;
        int mflags = 0;
        int prot = prot_from_flags (flags);
+
+       if (!mono_valloc_can_alloc (length))
+               return NULL;
+
        /* translate the flags */
        if (flags & MONO_MMAP_FIXED)
                mflags |= MAP_FIXED;
index 72cf853389ac73e74cffc12ac35f8487ec354420..2e2c7cdf0367db5051c5aa8b5e800e63fc1f3256 100644 (file)
@@ -83,6 +83,6 @@ typedef void *(*mono_file_map_alloc_fn)   (size_t length);
 typedef void  (*mono_file_map_release_fn) (void *addr);
 
 MONO_API void mono_file_map_set_allocator (mono_file_map_alloc_fn alloc, mono_file_map_release_fn release);
-                                 
+
 #endif /* __MONO_UTILS_MMAP_H__ */