-
-
Save luhenry/9604883 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/mono/metadata/appdomain.c b/mono/metadata/appdomain.c | |
index 5b3294a..0ed1ed3 100644 | |
--- a/mono/metadata/appdomain.c | |
+++ b/mono/metadata/appdomain.c | |
@@ -63,6 +63,7 @@ | |
#include <mono/utils/atomic.h> | |
#include <mono/utils/mono-memory-model.h> | |
#include <mono/utils/mono-threads.h> | |
+#include <mono/utils/mono-counters-agent.h> | |
#ifdef HOST_WIN32 | |
#include <direct.h> | |
#endif | |
@@ -278,6 +279,8 @@ mono_runtime_init (MonoDomain *domain, MonoThreadStartCB start_cb, | |
/* mscorlib is loaded before we install the load hook */ | |
mono_domain_fire_assembly_load (mono_defaults.corlib->assembly, NULL); | |
+ mono_counters_agent_start(); | |
+ | |
return; | |
} | |
diff --git a/mono/mini/driver.c b/mono/mini/driver.c | |
index d71c077..99f48e2 100644 | |
--- a/mono/mini/driver.c | |
+++ b/mono/mini/driver.c | |
@@ -47,6 +47,8 @@ | |
#include <mono/metadata/coree.h> | |
#include <mono/metadata/attach.h> | |
#include "mono/utils/mono-counters.h" | |
+#include <mono/utils/mono-counters-internals.h> | |
+#include "mono/utils/mono-counters-agent.h" | |
#include "mono/utils/mono-hwcap.h" | |
#include "mini.h" | |
@@ -1382,9 +1384,7 @@ mono_jit_parse_options (int argc, char * argv[]) | |
opt->break_on_exc = TRUE; | |
} else if (strcmp (argv [i], "--stats") == 0) { | |
- mono_counters_enable (-1); | |
- mono_stats.enabled = TRUE; | |
- mono_jit_stats.enabled = TRUE; | |
+ mono_counters_dump_on_cleanup(); | |
} else if (strcmp (argv [i], "--break") == 0) { | |
if (i+1 >= argc){ | |
fprintf (stderr, "Missing method name in --break command line option\n"); | |
@@ -1406,6 +1406,11 @@ mono_jit_parse_options (int argc, char * argv[]) | |
exit (1); | |
} | |
} | |
+ | |
+ // Always enable mono counters | |
+ mono_counters_enable (-1); | |
+ mono_stats.enabled = TRUE; | |
+ mono_jit_stats.enabled = TRUE; | |
if (trace_options != NULL) { | |
/* | |
@@ -1653,9 +1658,7 @@ mono_main (int argc, char* argv[]) | |
} else if (strcmp (argv [i], "--print-vtable") == 0) { | |
mono_print_vtable = TRUE; | |
} else if (strcmp (argv [i], "--stats") == 0) { | |
- mono_counters_enable (-1); | |
- mono_stats.enabled = TRUE; | |
- mono_jit_stats.enabled = TRUE; | |
+ mono_counters_dump_on_cleanup(); | |
#ifndef DISABLE_AOT | |
} else if (strcmp (argv [i], "--aot") == 0) { | |
error_if_aot_unsupported (); | |
@@ -1824,6 +1827,11 @@ mono_main (int argc, char* argv[]) | |
} | |
} | |
+ // Always enable mono counters | |
+ mono_counters_enable (-1); | |
+ mono_stats.enabled = TRUE; | |
+ mono_jit_stats.enabled = TRUE; | |
+ | |
#ifdef __native_client_codegen__ | |
if (g_getenv ("MONO_NACL_ALIGN_MASK_OFF")) | |
{ | |
diff --git a/mono/mini/mini.c b/mono/mini/mini.c | |
index 616d696..2a0e06c 100644 | |
--- a/mono/mini/mini.c | |
+++ b/mono/mini/mini.c | |
@@ -53,6 +53,7 @@ | |
#include <mono/utils/mono-math.h> | |
#include <mono/utils/mono-compiler.h> | |
#include <mono/utils/mono-counters.h> | |
+#include <mono/utils/mono-counters-internals.h> | |
#include <mono/utils/mono-logger-internal.h> | |
#include <mono/utils/mono-mmap.h> | |
#include <mono/utils/mono-path.h> | |
@@ -7643,7 +7644,7 @@ MonoJitStats mono_jit_stats = {0}; | |
static void | |
print_jit_stats (void) | |
{ | |
- if (mono_jit_stats.enabled) { | |
+ if (mono_jit_stats.enabled && mono_counters_dump_on_cleanup_enable()) { | |
g_print ("Mono Jit statistics\n"); | |
g_print ("Max code size ratio: %.2f (%s)\n", mono_jit_stats.max_code_size_ratio/100.0, | |
mono_jit_stats.max_ratio_method); | |
diff --git a/mono/utils/Makefile.am b/mono/utils/Makefile.am | |
index 1a4f6ac..2e7961c 100644 | |
--- a/mono/utils/Makefile.am | |
+++ b/mono/utils/Makefile.am | |
@@ -21,7 +21,7 @@ monoutils_sources = \ | |
dlmalloc.c \ | |
mono-counters.c \ | |
mono-compiler.h \ | |
- mono-counters-internals.h \ | |
+ mono-compiler-internals.h \ | |
mono-dl.c \ | |
mono-dl.h \ | |
mono-internal-hash.c \ | |
@@ -69,6 +69,7 @@ monoutils_sources = \ | |
monobitset.h \ | |
mono-codeman.h \ | |
mono-counters.h \ | |
+ mono-counters-internals.h \ | |
mono-digest.h \ | |
mono-error.h \ | |
mono-machine.h \ | |
@@ -111,7 +112,9 @@ monoutils_sources = \ | |
mono-hwcap.c \ | |
bsearch.h \ | |
bsearch.c \ | |
- mono-signal-handler.h | |
+ mono-signal-handler.h \ | |
+ mono-counters-agent.c \ | |
+ mono-counters-agent.h | |
arch_sources = | |
diff --git a/mono/utils/mono-counters-agent.c b/mono/utils/mono-counters-agent.c | |
new file mode 100644 | |
index 0000000..37d7e9a | |
--- /dev/null | |
+++ b/mono/utils/mono-counters-agent.c | |
@@ -0,0 +1,362 @@ | |
+/* | |
+ * Copyright 2014 Xamarin Inc | |
+ */ | |
+ | |
+#include <stdlib.h> | |
+#include <stdio.h> | |
+#include <errno.h> | |
+#include <pthread.h> | |
+#include <glib.h> | |
+#include <unistd.h> | |
+#include <arpa/inet.h> | |
+#include <netinet/in.h> | |
+#include <netinet/tcp.h> | |
+#include <sys/socket.h> | |
+#include <sys/time.h> | |
+#include <sys/types.h> | |
+#include "mono-counters.h" | |
+#include "mono-counters-internals.h" | |
+#include "mono-counters-agent.h" | |
+#include "mono-time.h" | |
+ | |
+/** | |
+ * Protocol : | |
+ * | Headers | Values | Values | ... [Infinity] | |
+ * | |
+ * Headers : | |
+ * | Count (2) | Counter | Counter | ... [Count] | |
+ * | |
+ * Counter : | |
+ * | Category (4) | Name Length (8) | Name (Name Length) | Type (4) | Unit (4) | Variance (4) | Index (2) | | |
+ * | |
+ * Values : | |
+ * | Timestamp (8) | Value | Value | ... | -1 (2) | | |
+ * | |
+ * Value : | |
+ * | Index (2) | Size (2) | Value (Size) | | |
+ */ | |
+ | |
+typedef struct MonoCounterAgent { | |
+ MonoCounterCategory category; | |
+ const char* name; | |
+ void* addr; | |
+ MonoCounterType type; | |
+ MonoCounterUnit unit; | |
+ MonoCounterVariance variance; | |
+ gboolean is_callback; | |
+ // MonoCounterAgent specific data : | |
+ void* value; | |
+ short index; | |
+} MonoCounterAgent; | |
+ | |
+static pthread_t agent_thread; | |
+ | |
+static GSList* counters; | |
+ | |
+static const gchar* inspector_ip; | |
+static int inspector_port; | |
+static int frequency; | |
+ | |
+static int enable; | |
+ | |
+static const short size4 = 4; | |
+static const short size8 = 8; | |
+ | |
+int | |
+parse_counters_all (MonoCounterCategory category, const char* name, void* addr, MonoCounterType type, MonoCounterUnit unit, MonoCounterVariance variance, gboolean is_callback, void** args) | |
+{ | |
+ static short index = 0; | |
+ | |
+ MonoCounterAgent* counter = g_malloc(sizeof(MonoCounterAgent)); | |
+ counter->category = category; | |
+ counter->name = g_strdup(name); | |
+ counter->addr = addr; | |
+ counter->type = type; | |
+ counter->unit = unit; | |
+ counter->variance = variance; | |
+ counter->is_callback = is_callback; | |
+ counter->value = NULL; | |
+ counter->index = index; | |
+ | |
+ counters = g_slist_append (counters, counter); | |
+ index += 1; | |
+ | |
+ return 1; | |
+} | |
+ | |
+void | |
+parse_counters_names (const char *counters_names) | |
+{ | |
+ if (!counters_names) { | |
+ mono_counters_foreach(parse_counters_all, NULL); | |
+ } else { | |
+ short index = 0; | |
+ gchar **names = g_strsplit (counters_names, ";", -1), **ptr; | |
+ | |
+ for (ptr = names; *ptr; ++ptr) { | |
+ gchar **split = g_strsplit(*ptr, "/", 2); | |
+ if (!split[0] || !split[1]) | |
+ continue; //FIXME warning | |
+ | |
+ MonoCounterCategory category = mono_counters_category_name_to_id(split[0]); | |
+ | |
+ void* addr; | |
+ MonoCounterType type; | |
+ MonoCounterUnit unit; | |
+ MonoCounterVariance variance; | |
+ gboolean is_callback; | |
+ | |
+ if (!mono_counters_get(category, split[1], &addr, &type, &unit, &variance, &is_callback)) { | |
+ continue; // FIXME warning | |
+ } | |
+ | |
+ MonoCounterAgent* counter = g_malloc(sizeof(MonoCounterAgent)); | |
+ counter->category = category; | |
+ counter->name = g_strdup(split[1]); | |
+ counter->addr = addr; | |
+ counter->type = type; | |
+ counter->unit = unit; | |
+ counter->variance = variance; | |
+ counter->is_callback = is_callback; | |
+ counter->index = index; | |
+ counter->value = NULL; | |
+ | |
+ counters = g_slist_append (counters, counter); | |
+ index += 1; | |
+ | |
+ g_strfreev(split); | |
+ } | |
+ g_strfreev (names); | |
+ } | |
+} | |
+ | |
+void | |
+parse_address (const char *address) | |
+{ | |
+ gchar **split = g_strsplit(address, ":", 2); | |
+ | |
+ inspector_ip = (split[0]) ? g_strdup(split[0]) : "127.0.0.1"; | |
+ inspector_port = (split[1]) ? strtol(split[1], NULL, 10) : 8888; | |
+ | |
+ g_strfreev(split); | |
+} | |
+ | |
+int | |
+write_buffer_to_socket(int socketfd, char* buffer, ssize_t size) | |
+{ | |
+ ssize_t left = size, sent; | |
+ | |
+ while (left > 0) { | |
+ sent = send(socketfd, buffer + (size - left), left, 0); | |
+ if (sent <= 0) | |
+ return 0; | |
+ left -= sent; | |
+ } | |
+ | |
+ return 1; | |
+} | |
+ | |
+int | |
+mono_counters_agent_write_int (MonoCounterAgent* counter, int socketfd) | |
+{ | |
+ int value = mono_counters_get_int (counter->addr, counter->is_callback); | |
+ | |
+ if (!counter->value) | |
+ counter->value = g_malloc(4); | |
+ else if (*(int*)counter->value == value) | |
+ return 1; | |
+ | |
+ *(int*)counter->value = value; | |
+ | |
+ if (!write_buffer_to_socket(socketfd, (char*)&counter->index, 2) | |
+ || !write_buffer_to_socket(socketfd, (char*)&size4, 2) | |
+ || !write_buffer_to_socket(socketfd, (char*)&value, 4)) | |
+ return 0; | |
+ | |
+ return 1; | |
+} | |
+ | |
+int | |
+mono_counters_agent_write_long (MonoCounterAgent* counter, int socketfd) | |
+{ | |
+ gint64 value = mono_counters_get_long (counter->addr, counter->is_callback); | |
+ | |
+ if (!counter->value) | |
+ counter->value = g_malloc(8); | |
+ else if (*(gint64*)counter->value == value) | |
+ return 1; | |
+ | |
+ *(gint64*)counter->value = value; | |
+ | |
+ if (!write_buffer_to_socket(socketfd, (char*)&counter->index, 2) | |
+ || !write_buffer_to_socket(socketfd, (char*)&size8, 2) | |
+ || !write_buffer_to_socket(socketfd, (char*)&value, 8)) | |
+ return 0; | |
+ | |
+ return 1; | |
+} | |
+ | |
+int | |
+mono_counters_agent_write_double (MonoCounterAgent* counter, int socketfd) | |
+{ | |
+ double value = mono_counters_get_double (counter->addr, counter->is_callback); | |
+ | |
+ if (!counter->value) | |
+ counter->value = g_malloc(8); | |
+ else if (*(double*)counter->value == value) | |
+ return 1; | |
+ | |
+ *(double*)counter->value = value; | |
+ | |
+ if (!write_buffer_to_socket(socketfd, (char*)&counter->index, 2) | |
+ || !write_buffer_to_socket(socketfd, (char*)&size8, 2) | |
+ || !write_buffer_to_socket(socketfd, (char*)&value, 8)) | |
+ return 0; | |
+ | |
+ return 1; | |
+} | |
+ | |
+static void* | |
+mono_counters_agent_sampling_thread (void* ptr) | |
+{ | |
+ int socketfd = 0; | |
+ struct sockaddr_in inspector_addr; | |
+ | |
+ if ((socketfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { | |
+ g_printf("mono-counters-agent | error with socket : %s", strerror(errno)); | |
+ return NULL; | |
+ } | |
+ | |
+ memset(&inspector_addr, 0, sizeof(inspector_addr)); | |
+ | |
+ inspector_addr.sin_family = AF_INET; | |
+ inspector_addr.sin_port = htons(inspector_port); | |
+ | |
+ if (!inet_pton(AF_INET, inspector_ip, &inspector_addr.sin_addr)) { | |
+ g_printf("mono-counters-agent | error with inet_pton : %s", strerror(errno)); | |
+ return NULL; | |
+ } | |
+ | |
+ if (connect(socketfd, (struct sockaddr*)&inspector_addr, sizeof(inspector_addr)) < 0) { | |
+ g_printf("mono-counters-agent | error with connect : %s", strerror(errno)); | |
+ return NULL; | |
+ } | |
+ | |
+ GSList* item; | |
+ | |
+ short count = 0; | |
+ for (item = counters; item; item = item->next) | |
+ count += 1; | |
+ | |
+ if (!write_buffer_to_socket(socketfd, (char*)&count, 2)) | |
+ goto cleanup; | |
+ | |
+ for (item = counters; item; item = item->next) { | |
+ MonoCounterAgent* counter = item->data; | |
+ | |
+ int len = strlen(counter->name); | |
+ | |
+ if (!write_buffer_to_socket(socketfd, (char*)&counter->category, 4) | |
+ || !write_buffer_to_socket(socketfd, (char*)&len, 4) | |
+ || !write_buffer_to_socket(socketfd, (char*) counter->name, len) | |
+ || !write_buffer_to_socket(socketfd, (char*)&counter->type, 4) | |
+ || !write_buffer_to_socket(socketfd, (char*)&counter->unit, 4) | |
+ || !write_buffer_to_socket(socketfd, (char*)&counter->variance, 4) | |
+ || !write_buffer_to_socket(socketfd, (char*)&counter->index, 2)) | |
+ goto cleanup; // FIXME error | |
+ } | |
+ | |
+ while (enable) { | |
+ gint64 timestamp = mono_100ns_ticks(); | |
+ if (!write_buffer_to_socket(socketfd, (char*)×tamp, 8)) | |
+ goto cleanup; // FIXME error | |
+ | |
+ for (item = counters; item; item = item->next) { | |
+ MonoCounterAgent* counter = item->data; | |
+ | |
+ if (!counter) | |
+ continue; // FIXME warning | |
+ | |
+ switch (counter->type) { | |
+ case MONO_COUNTER_TYPE_INT: | |
+#if SIZEOF_VOID_P == 4 | |
+ case MONO_COUNTER_TYPE_WORD: | |
+#endif | |
+ if (!mono_counters_agent_write_int(counter, socketfd)) | |
+ goto cleanup; | |
+ break; | |
+ case MONO_COUNTER_TYPE_LONG: | |
+#if SIZEOF_VOID_P == 8 | |
+ case MONO_COUNTER_TYPE_WORD: | |
+#endif | |
+ if (!mono_counters_agent_write_long(counter, socketfd)) | |
+ goto cleanup; | |
+ break; | |
+ case MONO_COUNTER_DOUBLE: | |
+ if (!mono_counters_agent_write_double(counter, socketfd)) | |
+ goto cleanup; | |
+ break; | |
+ } | |
+ } | |
+ | |
+ short end = -1; | |
+ if (!write_buffer_to_socket(socketfd, (char*)&end, 2)) | |
+ goto cleanup; // FIXME error | |
+ | |
+ usleep (1000000 / frequency); | |
+ } | |
+ | |
+cleanup: | |
+ close(socketfd); | |
+ | |
+ return NULL; | |
+} | |
+ | |
+void | |
+parse_configuration (const gchar* configuration) | |
+{ | |
+ const char *counters_names = NULL; | |
+ const char *address = "127.0.0.1:8888"; | |
+ | |
+ if (configuration == NULL) | |
+ return; | |
+ | |
+ gchar **opts = g_strsplit (configuration, ",", -1), **ptr; | |
+ for (ptr = opts; *ptr; ++ptr) { | |
+ const char *opt = *ptr; | |
+ if (g_str_has_prefix (opt, "address=")) { | |
+ opt = strchr (opt, '=') + 1; | |
+ address = g_strdup(opt); | |
+ } else if (g_str_has_prefix (opt, "counters=")) { | |
+ opt = strchr (opt, '=') + 1; | |
+ counters_names = g_strdup(opt); | |
+ } else if (g_str_has_prefix (opt, "frequency=")) { | |
+ opt = strchr (opt, '=') + 1; | |
+ frequency = strtol (opt, NULL, 10); | |
+ } | |
+ } | |
+ | |
+ parse_counters_names(counters_names); | |
+ parse_address(address); | |
+ | |
+ g_free((void*)counters_names); | |
+ g_free((void*)address); | |
+ g_strfreev(opts); | |
+} | |
+ | |
+void | |
+mono_counters_agent_start (void) | |
+{ | |
+ enable = 1; | |
+ | |
+ parse_configuration(g_getenv ("MONO_PERF_AGENT")); | |
+ pthread_create(&agent_thread, NULL, mono_counters_agent_sampling_thread, NULL); | |
+} | |
+ | |
+void | |
+mono_counters_agent_stop(void) | |
+{ | |
+ enable = 0; | |
+ | |
+ pthread_join(agent_thread, NULL); | |
+} | |
\ No newline at end of file | |
diff --git a/mono/utils/mono-counters-agent.h b/mono/utils/mono-counters-agent.h | |
new file mode 100644 | |
index 0000000..c7e275a | |
--- /dev/null | |
+++ b/mono/utils/mono-counters-agent.h | |
@@ -0,0 +1,7 @@ | |
+#ifndef __MONO_COUNTERS_AGENTS_H__ | |
+#define __MONO_COUNTERS_AGENTS_H__ | |
+ | |
+MONO_API void mono_counters_agent_start (void); | |
+MONO_API void mono_counters_agent_stop (void); | |
+ | |
+#endif /* __MONO_COUNTERS_AGENTS_H__ */ | |
\ No newline at end of file | |
diff --git a/mono/utils/mono-counters-internals.h b/mono/utils/mono-counters-internals.h | |
index a8cbfef..635d4c8 100644 | |
--- a/mono/utils/mono-counters-internals.h | |
+++ b/mono/utils/mono-counters-internals.h | |
@@ -1,6 +1,7 @@ | |
#ifndef __MONO_COUNTERS_INTERNALS_H__ | |
#define __MONO_COUNTERS_INTERNALS_H__ | |
+#include <glib.h> | |
#include "mono-counters.h" | |
#include "mono-compiler.h" | |
@@ -68,5 +69,26 @@ mono_counters_register_full (MonoCounterCategory category, const char *name, Mon | |
#define mono_counters_new_long_const(cat,name,unit,value) do { gint64 *__ptr = mono_counters_new(cat,name,MONO_COUNTER_TYPE_INT,unit,variance); *__ptr = value; } while (0) | |
#define mono_counters_new_double_const(cat,name,unit,value) do { double *__ptr = mono_counters_new(cat,name,MONO_COUNTER_TYPE_INT,unit,variance); *__ptr = value; } while (0) | |
+MONO_API void mono_counters_dump_on_cleanup (void); | |
+MONO_API int mono_counters_dump_on_cleanup_enable (void); | |
+MONO_API int mono_counters_get (MonoCounterCategory category, const char* name, void** addr, MonoCounterType* type, MonoCounterUnit *unit, MonoCounterVariance *variance, gboolean* is_callback); | |
+ | |
+MONO_API MonoCounterCategory mono_counters_category_name_to_id (const char* name); | |
+MONO_API const char* mono_counters_category_id_to_name (MonoCounterCategory id); | |
+ | |
+typedef int (*MonoCountersForeachFunc) (MonoCounterCategory category, const char* name, void* addr, MonoCounterType type, MonoCounterUnit unit, MonoCounterVariance variance, gboolean is_callback, void** args); | |
+MONO_API void mono_counters_foreach(MonoCountersForeachFunc func, void** args); | |
+ | |
+MONO_API int mono_counters_get_int (void* addr, gboolean is_callback); | |
+#if SIZEOF_VOID_P == 4 | |
+MONO_API int mono_counters_get_word (void* addr, gboolean is_callback); | |
+#elif SIZEOF_VOID_P == 8 | |
+MONO_API gint64 mono_counters_get_word (void* addr, gboolean is_callback); | |
#endif | |
+MONO_API gint64 mono_counters_get_long (void* addr, gboolean is_callback); | |
+MONO_API double mono_counters_get_double (void* addr, gboolean is_callback); | |
+ | |
+ | |
+#endif /* __MONO_COUNTERS_INTERNALS_H__ */ | |
+ | |
diff --git a/mono/utils/mono-counters.c b/mono/utils/mono-counters.c | |
index 9f22e01..7a28202 100644 | |
--- a/mono/utils/mono-counters.c | |
+++ b/mono/utils/mono-counters.c | |
@@ -5,8 +5,11 @@ | |
#include <stdlib.h> | |
#include <glib.h> | |
+#include "mono-counters.h" | |
#include "mono-counters-internals.h" | |
+typedef struct _MonoCounter MonoCounter; | |
+ | |
struct _MonoCounter { | |
MonoCounter *next; | |
const char *name; | |
@@ -21,6 +24,8 @@ struct _MonoCounter { | |
static MonoCounter *counters = NULL; | |
static int valid_mask = 0; | |
+static int dump_on_cleanup = 0; | |
+ | |
/** | |
* mono_counters_enable: | |
* @section_mask: a mask listing the sections that will be displayed | |
@@ -104,6 +109,18 @@ section_to_category (int type) | |
} | |
} | |
+void | |
+mono_counters_dump_on_cleanup (void) | |
+{ | |
+ dump_on_cleanup = 1; | |
+} | |
+ | |
+int | |
+mono_counters_dump_on_cleanup_enable (void) | |
+{ | |
+ return dump_on_cleanup; | |
+} | |
+ | |
/** | |
* mono_counters_register: | |
* @name: The name for this counters. | |
@@ -153,6 +170,8 @@ mono_counters_register (const char* name, int type, void *addr) | |
counter = mono_counters_register_full (cat, name, counter_type, unit, MONO_COUNTER_UNIT_VARIABLE, addr); | |
if (counter && type & MONO_COUNTER_CALLBACK) | |
counter->is_callback = TRUE; | |
+ else | |
+ counter->is_callback = FALSE; | |
} | |
@@ -238,6 +257,9 @@ mono_counters_dump_category (MonoCounterCategory category, FILE *outfile) | |
void | |
mono_counters_dump (int section_mask, FILE *outfile) | |
{ | |
+ if (!dump_on_cleanup) | |
+ return; | |
+ | |
int i, j; | |
section_mask &= valid_mask; | |
if (!counters) | |
@@ -334,4 +356,127 @@ mono_runtime_resource_set_callback (MonoResourceCallback callback) | |
limit_reached = callback; | |
} | |
+int | |
+mono_counters_get (MonoCounterCategory category, const char* name, void** addr, MonoCounterType* type, MonoCounterUnit *unit, MonoCounterVariance *variance, gboolean* is_callback) | |
+{ | |
+ if (!counters) | |
+ return 0; | |
+ | |
+ MonoCounter* counter = counters; | |
+ | |
+ do { | |
+ if (counter->category == category && strcmp(counter->name, name) == 0) { | |
+ *addr = counter->addr; | |
+ *type = counter->type; | |
+ *unit = counter->unit; | |
+ *variance = counter->variance; | |
+ *is_callback = counter->is_callback; | |
+ return 1; | |
+ } | |
+ } while ((counter = counter->next)); | |
+ | |
+ return 0; | |
+} | |
+ | |
+MonoCounterCategory | |
+mono_counters_category_name_to_id (const char* name) | |
+{ | |
+ if (strcmp("Mono JIT", name) == 0) { | |
+ return MONO_COUNTER_CAT_JIT; | |
+ } else if (strcmp("Mono GC", name) == 0) { | |
+ return MONO_COUNTER_CAT_GC; | |
+ } else if (strcmp("Mono Metadata", name) == 0) { | |
+ return MONO_COUNTER_CAT_METADATA; | |
+ } else if (strcmp("Mono Generics", name) == 0) { | |
+ return MONO_COUNTER_CAT_GENERICS; | |
+ } else if (strcmp("Mono Security", name) == 0) { | |
+ return MONO_COUNTER_CAT_SECURITY; | |
+ } else if (strcmp("Mono Remoting", name) == 0) { | |
+ return MONO_COUNTER_CAT_REMOTING; | |
+ } else if (strcmp("Mono EXC", name) == 0) { | |
+ return MONO_COUNTER_CAT_EXC; | |
+ } else if (strcmp("Mono Thread", name) == 0) { | |
+ return MONO_COUNTER_CAT_THREAD; | |
+ } else if (strcmp("Mono Threadpool", name) == 0) { | |
+ return MONO_COUNTER_CAT_THREADPOOL; | |
+ } else if (strcmp("Mono IO", name) == 0) { | |
+ return MONO_COUNTER_CAT_IO; | |
+ } else { | |
+ return -1; | |
+ } | |
+} | |
+ | |
+const char* | |
+mono_counters_category_id_to_name (MonoCounterCategory id) | |
+{ | |
+ switch (id) { | |
+ case MONO_COUNTER_CAT_JIT: | |
+ return "Mono JIT"; | |
+ case MONO_COUNTER_CAT_GC: | |
+ return "Mono GC"; | |
+ case MONO_COUNTER_CAT_METADATA: | |
+ return "Mono Metadata"; | |
+ case MONO_COUNTER_CAT_GENERICS: | |
+ return "Mono Generics"; | |
+ case MONO_COUNTER_CAT_SECURITY: | |
+ return "Mono Security"; | |
+ case MONO_COUNTER_CAT_REMOTING: | |
+ return "Mono Remoting"; | |
+ case MONO_COUNTER_CAT_EXC: | |
+ return "Mono EXC"; | |
+ case MONO_COUNTER_CAT_THREAD: | |
+ return "Mono Thread"; | |
+ case MONO_COUNTER_CAT_THREADPOOL: | |
+ return "Mono Threadpool"; | |
+ case MONO_COUNTER_CAT_IO: | |
+ return "Mono IO"; | |
+ default: | |
+ return NULL; | |
+ } | |
+} | |
+ | |
+int | |
+mono_counters_get_int (void* addr, gboolean is_callback) | |
+{ | |
+ return is_callback ? ((IntFunc)addr) () : *(int*)addr; | |
+} | |
+ | |
+gint64 | |
+mono_counters_get_long (void* addr, gboolean is_callback) | |
+{ | |
+ return is_callback ? ((LongFunc)addr) () : *(gint64*)addr; | |
+} | |
+#if SIZEOF_VOID_P == 4 | |
+int | |
+mono_counters_get_word (void* addr, gboolean is_callback) | |
+{ | |
+ return mono_counters_get_int(addr, is_callback); | |
+} | |
+#elif SIZEOF_VOID_P == 8 | |
+gint64 | |
+mono_counters_get_word (void* addr, gboolean is_callback) | |
+{ | |
+ return mono_counters_get_long(addr, is_callback); | |
+} | |
+#endif | |
+ | |
+double | |
+mono_counters_get_double (void* addr, gboolean is_callback) | |
+{ | |
+ return is_callback ? ((DoubleFunc)addr) () : *(double*)addr; | |
+} | |
+ | |
+void | |
+mono_counters_foreach(MonoCountersForeachFunc func, void** args) | |
+{ | |
+ if (!counters) | |
+ return; | |
+ | |
+ MonoCounter* counter = counters; | |
+ | |
+ do { | |
+ if (!func(counter->category, counter->name, counter->addr, counter->type, counter->unit, counter->variance, counter->is_callback, args)) | |
+ return; | |
+ } while ((counter = counter->next)); | |
+} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment