#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>
#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
} else if (dead->flags == CODE_FLAG_MALLOC) {
dlfree (dead->data);
}
+ code_memory_used -= dead->size;
free (dead);
}
}
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;
}
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;
+}
+
+
#define __MONO_COUNTERS_H__
#include <stdio.h>
+#include <mono/utils/mono-publib.h>
enum {
MONO_COUNTER_INT, /* 32 bit int */
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__ */