Introduce a callback API to have notifications when runtime resources exceed preset...
authorPaolo Molaro <lupus@oddwiz.org>
Tue, 4 Oct 2011 15:50:57 +0000 (17:50 +0200)
committerPaolo Molaro <lupus@oddwiz.org>
Tue, 4 Oct 2011 15:52:23 +0000 (17:52 +0200)
mono/metadata/sgen-gc.c
mono/utils/mono-codeman.c
mono/utils/mono-counters.c
mono/utils/mono-counters.h

index 57af651704313fcda6f2b7515850e2d94ca9b016..a6dc091558ec4746508ed6edd92210d437e58e4b 100644 (file)
@@ -733,6 +733,7 @@ mono_sgen_try_alloc_space (mword size, int space)
                return FALSE;
 
        allocated_heap += size;
+       mono_runtime_resource_check_limit (MONO_RESOURCE_GC_HEAP, allocated_heap);
        return TRUE;
 }
 
index 33dc025df3ea6d33a37223627df72bbc48aac4fa..4efcea0ae25500addaca763aaa9bb3721d495734 100644 (file)
@@ -13,6 +13,7 @@
 
 #include "mono-codeman.h"
 #include "mono-mmap.h"
+#include "mono-counters.h"
 #include "dlmalloc.h"
 #include <mono/metadata/class-internals.h>
 #include <mono/metadata/profiler-private.h>
@@ -25,6 +26,8 @@
 #include <nacl/nacl_dyncode.h>
 #endif
 
+static uintptr_t code_memory_used = 0;
+
 /*
  * AMD64 processors maintain icache coherency only for pages which are 
  * marked executable. Also, windows DEP requires us to obtain executable memory from
@@ -284,6 +287,7 @@ free_chunklist (CodeChunk *chunk)
                } else if (dead->flags == CODE_FLAG_MALLOC) {
                        dlfree (dead->data);
                }
+               code_memory_used -= dead->size;
                free (dead);
        }
 }
@@ -451,6 +455,8 @@ new_codechunk (int dynamic, int size)
        chunk->bsize = bsize;
        mono_profiler_code_chunk_new((gpointer) chunk->data, chunk->size);
 
+       code_memory_used += chunk_size;
+       mono_runtime_resource_check_limit (MONO_RESOURCE_JIT_CODE, code_memory_used);
        /*printf ("code chunk at: %p\n", ptr);*/
        return chunk;
 }
index b769d82b0905171afe251e5c5d7b97c57dae38a3..dc7c2f9963b598084d579a544785fdfad08a3030 100644 (file)
@@ -201,3 +201,69 @@ mono_counters_cleanup (void)
        counters = NULL;
 }
 
+static MonoResourceCallback limit_reached = NULL;
+static uintptr_t resource_limits [MONO_RESOURCE_COUNT * 2];
+
+/**
+ * mono_runtime_resource_check_limit:
+ * @resource_type: one of the #MonoResourceType enum values
+ * @value: the current value of the resource usage
+ *
+ * Check if a runtime resource limit has been reached. This function
+ * is intended to be used by the runtime only.
+ */
+void
+mono_runtime_resource_check_limit (int resource_type, uintptr_t value)
+{
+       if (!limit_reached)
+               return;
+       /* check the hard limit first */
+       if (value > resource_limits [resource_type * 2 + 1]) {
+               limit_reached (resource_type, value, 0);
+               return;
+       }
+       if (value > resource_limits [resource_type * 2])
+               limit_reached (resource_type, value, 1);
+}
+
+/**
+ * mono_runtime_resource_limit:
+ * @resource_type: one of the #MonoResourceType enum values
+ * @soft_limit: the soft limit value
+ * @hard_limit: the hard limit value
+ *
+ * This function sets the soft and hard limit for runtime resources. When the limit
+ * is reached, a user-specified callback is called. The callback runs in a restricted
+ * environment, in which the world coult be stopped, so it can't take locks, perform
+ * allocations etc. The callback may be called multiple times once a limit has been reached
+ * if action is not taken to decrease the resource use.
+ *
+ * Returns: 0 on error or a positive integer otherwise.
+ */
+int
+mono_runtime_resource_limit (int resource_type, uintptr_t soft_limit, uintptr_t hard_limit)
+{
+       if (resource_type >= MONO_RESOURCE_COUNT || resource_type < 0)
+               return 0;
+       if (soft_limit > hard_limit)
+               return 0;
+       resource_limits [resource_type * 2] = soft_limit;
+       resource_limits [resource_type * 2 + 1] = hard_limit;
+       return 1;
+}
+
+/**
+ * mono_runtime_resource_set_callback:
+ * @callback: a function pointer
+ * 
+ * Set the callback to be invoked when a resource limit is reached.
+ * The callback will receive the resource type, the resource amount in resource-specific
+ * units and a flag indicating whether the soft or hard limit was reached.
+ */
+void
+mono_runtime_resource_set_callback (MonoResourceCallback callback)
+{
+       limit_reached = callback;
+}
+
+
index e7396d79a0907bc21b6c5a3d479701a26642fbc7..f7d8ea1d4bfbff28fd47b7dc4969a61eb8325fa3 100644 (file)
@@ -2,6 +2,7 @@
 #define __MONO_COUNTERS_H__
 
 #include <stdio.h>
+#include <mono/utils/mono-publib.h>
 
 enum {
        MONO_COUNTER_INT,    /* 32 bit int */
@@ -39,5 +40,18 @@ void mono_counters_dump (int section_mask, FILE *outfile);
 
 void mono_counters_cleanup (void);
 
+typedef enum {
+       MONO_RESOURCE_JIT_CODE, /* bytes */
+       MONO_RESOURCE_METADATA, /* bytes */
+       MONO_RESOURCE_GC_HEAP,  /* bytes */
+       MONO_RESOURCE_COUNT /* non-ABI value */
+} MonoResourceType;
+
+typedef void (*MonoResourceCallback) (int resource_type, uintptr_t value, int is_soft);
+
+int  mono_runtime_resource_limit        (int resource_type, uintptr_t soft_limit, uintptr_t hard_limit);
+void mono_runtime_resource_set_callback (MonoResourceCallback callback);
+void mono_runtime_resource_check_limit  (int resource_type, uintptr_t value);
+
 #endif /* __MONO_COUNTERS_H__ */