#include "metadata/class-internals.h"
#include "utils/mono-time.h"
#include "utils/mono-mmap.h"
+#include "utils/mono-proclib.h"
#include <mono/io-layer/io-layer.h>
/* map of CounterSample.cs */
};
#define PERFCTR_CAT(id,name,help,type,inst,first_counter) CATEGORY_ ## id,
-#define PERFCTR_COUNTER(id,name,help,type)
+#define PERFCTR_COUNTER(id,name,help,type,field)
enum {
#include "mono-perfcounters-def.h"
NUM_CATEGORIES
#undef PERFCTR_CAT
#undef PERFCTR_COUNTER
#define PERFCTR_CAT(id,name,help,type,inst,first_counter) CATEGORY_START_ ## id = -1,
-#define PERFCTR_COUNTER(id,name,help,type) COUNTER_ ## id,
+#define PERFCTR_COUNTER(id,name,help,type,field) COUNTER_ ## id,
/* each counter is assigned an id starting from 0 inside the category */
enum {
#include "mono-perfcounters-def.h"
#undef PERFCTR_CAT
#undef PERFCTR_COUNTER
#define PERFCTR_CAT(id,name,help,type,inst,first_counter)
-#define PERFCTR_COUNTER(id,name,help,type) CCOUNTER_ ## id,
+#define PERFCTR_COUNTER(id,name,help,type,field) CCOUNTER_ ## id,
/* this is used just to count the number of counters */
enum {
#include "mono-perfcounters-def.h"
typedef struct {
const char *name;
const char *help;
- int id;
+ short id;
+ unsigned short offset; // offset inside MonoPerfCounters
int type;
} CounterDesc;
#undef PERFCTR_CAT
#undef PERFCTR_COUNTER
#define PERFCTR_CAT(id,name,help,type,inst,first_counter) {name, help, CATEGORY_ ## id, type, inst ## Instance, CCOUNTER_ ## first_counter},
-#define PERFCTR_COUNTER(id,name,help,type)
+#define PERFCTR_COUNTER(id,name,help,type,field)
static const CategoryDesc
predef_categories [] = {
#include "mono-perfcounters-def.h"
#undef PERFCTR_CAT
#undef PERFCTR_COUNTER
#define PERFCTR_CAT(id,name,help,type,inst,first_counter)
-#define PERFCTR_COUNTER(id,name,help,type) {name, help, COUNTER_ ## id, type},
+#define PERFCTR_COUNTER(id,name,help,type,field) {name, help, COUNTER_ ## id, G_STRUCT_OFFSET (MonoPerfCounters, field), type},
static const CounterDesc
predef_counters [] = {
#include "mono-perfcounters-def.h"
- {NULL, NULL, -1, 0}
+ {NULL, NULL, -1, 0, 0}
};
/*
return id;
}
-static void
-get_cpu_times (int cpu_id, gint64 *user, gint64 *systemt, gint64 *irq, gint64 *sirq, gint64 *idle)
-{
- SYSTEM_INFO info;
- char buf [256];
- char *s;
- int hz = 100;
- long long unsigned int user_ticks, nice_ticks, system_ticks, idle_ticks, iowait_ticks, irq_ticks, sirq_ticks;
- FILE *f = fopen ("/proc/stat", "r");
- if (!f)
- return;
- GetSystemInfo (&info);
- hz *= info.dwNumberOfProcessors;
- while ((s = fgets (buf, sizeof (buf), f))) {
- char *data = NULL;
- if (cpu_id < 0 && strncmp (s, "cpu", 3) == 0 && g_ascii_isspace (s [3])) {
- data = s + 4;
- } else if (cpu_id >= 0 && strncmp (s, "cpu", 3) == 0 && strtol (s + 3, &data, 10) == cpu_id) {
- if (data == s + 3)
- continue;
- data++;
- } else {
- continue;
- }
- sscanf (data, "%Lu %Lu %Lu %Lu %Lu %Lu %Lu", &user_ticks, &nice_ticks, &system_ticks, &idle_ticks, &iowait_ticks, &irq_ticks, &sirq_ticks);
- }
- fclose (f);
-
- if (user)
- *user = (user_ticks + nice_ticks) * 10000000 / hz;
- if (systemt)
- *systemt = (system_ticks) * 10000000 / hz;
- if (irq)
- *irq = (irq_ticks) * 10000000 / hz;
- if (sirq)
- *sirq = (sirq_ticks) * 10000000 / hz;
- if (idle)
- *idle = (idle_ticks) * 10000000 / hz;
-}
-
static MonoBoolean
get_cpu_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample *sample)
{
- gint64 value = 0;
+ MonoProcessError error;
int id = GPOINTER_TO_INT (vtable->arg);
int pid = id >> 5;
id &= 0x1f;
sample->counterType = predef_counters [predef_categories [CATEGORY_CPU].first_counter + id].type;
switch (id) {
case COUNTER_CPU_USER_TIME:
- get_cpu_times (pid, &value, NULL, NULL, NULL, NULL);
- sample->rawValue = value;
+ sample->rawValue = mono_cpu_get_data (pid, MONO_CPU_USER_TIME, &error);
return TRUE;
case COUNTER_CPU_PRIV_TIME:
- get_cpu_times (pid, NULL, &value, NULL, NULL, NULL);
- sample->rawValue = value;
+ sample->rawValue = mono_cpu_get_data (pid, MONO_CPU_PRIV_TIME, &error);
return TRUE;
case COUNTER_CPU_INTR_TIME:
- get_cpu_times (pid, NULL, NULL, &value, NULL, NULL);
- sample->rawValue = value;
+ sample->rawValue = mono_cpu_get_data (pid, MONO_CPU_INTR_TIME, &error);
return TRUE;
case COUNTER_CPU_DCP_TIME:
- get_cpu_times (pid, NULL, NULL, NULL, &value, NULL);
- sample->rawValue = value;
+ sample->rawValue = mono_cpu_get_data (pid, MONO_CPU_DCP_TIME, &error);
return TRUE;
case COUNTER_CPU_PROC_TIME:
- get_cpu_times (pid, NULL, NULL, NULL, NULL, &value);
- sample->rawValue = value;
+ sample->rawValue = mono_cpu_get_data (pid, MONO_CPU_IDLE_TIME, &error);
return TRUE;
}
return FALSE;
return NULL;
}
-/*
- * /proc/pid/stat format:
- * pid (cmdname) S
- * [0] ppid pgid sid tty_nr tty_pgrp flags min_flt cmin_flt maj_flt cmaj_flt
- * [10] utime stime cutime cstime prio nice threads start_time vsize rss
- * [20] rsslim start_code end_code start_stack esp eip pending blocked sigign sigcatch
- * [30] wchan 0 0 exit_signal cpu rt_prio policy
- */
-
-static gint64
-get_process_time (int pid, int pos, int sum)
-{
- char buf [512];
- char *s, *end;
- FILE *f;
- int len, i;
- gint64 value;
-
- g_snprintf (buf, sizeof (buf), "/proc/%d/stat", pid);
- f = fopen (buf, "r");
- if (!f)
- return 0;
- len = fread (buf, 1, sizeof (buf), f);
- fclose (f);
- if (len <= 0)
- return 0;
- s = strchr (buf, ')');
- if (!s)
- return 0;
- s++;
- while (g_ascii_isspace (*s)) s++;
- if (!*s)
- return 0;
- /* skip the status char */
- while (*s && !g_ascii_isspace (*s)) s++;
- if (!*s)
- return 0;
- for (i = 0; i < pos; ++i) {
- while (g_ascii_isspace (*s)) s++;
- if (!*s)
- return 0;
- while (*s && !g_ascii_isspace (*s)) s++;
- if (!*s)
- return 0;
- }
- /* we are finally at the needed item */
- value = strtoul (s, &end, 0);
- /* add also the following value */
- if (sum) {
- while (g_ascii_isspace (*s)) s++;
- if (!*s)
- return 0;
- value += strtoul (s, &end, 0);
- }
- return value;
-}
-
-static gint64
-get_pid_stat_item (int pid, const char *item)
-{
- char buf [256];
- char *s;
- FILE *f;
- int len = strlen (item);
-
- g_snprintf (buf, sizeof (buf), "/proc/%d/status", pid);
- f = fopen (buf, "r");
- if (!f)
- return 0;
- while ((s = fgets (buf, sizeof (buf), f))) {
- if (*item != *buf)
- continue;
- if (strncmp (buf, item, len))
- continue;
- if (buf [len] != ':')
- continue;
- fclose (f);
- return atoi (buf + len + 1);
- }
- fclose (f);
- return 0;
-}
-
static MonoBoolean
get_process_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample *sample)
{
sample->counterType = predef_counters [predef_categories [CATEGORY_PROC].first_counter + id].type;
switch (id) {
case COUNTER_PROC_USER_TIME:
- sample->rawValue = get_process_time (pid, 12, FALSE);
+ sample->rawValue = mono_process_get_data (GINT_TO_POINTER (pid), MONO_PROCESS_USER_TIME);
return TRUE;
case COUNTER_PROC_PRIV_TIME:
- sample->rawValue = get_process_time (pid, 13, FALSE);
+ sample->rawValue = mono_process_get_data (GINT_TO_POINTER (pid), MONO_PROCESS_SYSTEM_TIME);
return TRUE;
case COUNTER_PROC_PROC_TIME:
- sample->rawValue = get_process_time (pid, 12, TRUE);
+ sample->rawValue = mono_process_get_data (GINT_TO_POINTER (pid), MONO_PROCESS_TOTAL_TIME);
return TRUE;
case COUNTER_PROC_THREADS:
- sample->rawValue = get_pid_stat_item (pid, "Threads");
+ sample->rawValue = mono_process_get_data (GINT_TO_POINTER (pid), MONO_PROCESS_NUM_THREADS);
return TRUE;
case COUNTER_PROC_VBYTES:
- sample->rawValue = get_pid_stat_item (pid, "VmSize") * 1024;
+ sample->rawValue = mono_process_get_data (GINT_TO_POINTER (pid), MONO_PROCESS_VIRTUAL_BYTES);
return TRUE;
case COUNTER_PROC_WSET:
- sample->rawValue = get_pid_stat_item (pid, "VmRSS") * 1024;
+ sample->rawValue = mono_process_get_data (GINT_TO_POINTER (pid), MONO_PROCESS_WORKING_SET);
return TRUE;
case COUNTER_PROC_PBYTES:
- sample->rawValue = get_pid_stat_item (pid, "VmData") * 1024;
+ sample->rawValue = mono_process_get_data (GINT_TO_POINTER (pid), MONO_PROCESS_PRIVATE_BYTES);
return TRUE;
}
return FALSE;
*custom = FALSE;
if ((cdesc = get_counter_in_category (&predef_categories [CATEGORY_MONO_MEM], counter))) {
*type = cdesc->type;
- return create_vtable (GINT_TO_POINTER (cdesc->id), mono_mem_counter, NULL);
+ return create_vtable (GINT_TO_POINTER ((gint) cdesc->id), mono_mem_counter, NULL);
}
return NULL;
}
predef_readonly_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample *sample)
{
PredefVtable *vt = (PredefVtable *)vtable;
+ const CounterDesc *desc;
int cat_id = GPOINTER_TO_INT (vtable->arg);
int id = cat_id >> 16;
cat_id &= 0xffff;
fill_sample (sample);
sample->baseValue = 1;
}
- sample->counterType = predef_counters [predef_categories [cat_id].first_counter + id].type;
- switch (cat_id) {
- case CATEGORY_JIT:
- switch (id) {
- case COUNTER_JIT_BYTES:
- case COUNTER_JIT_BYTES_PSEC:
- sample->rawValue = vt->counters->jit_bytes;
- return TRUE;
- case COUNTER_JIT_METHODS:
- sample->rawValue = vt->counters->jit_methods;
- return TRUE;
- }
- break;
- case CATEGORY_EXC:
- switch (id) {
- case COUNTER_EXC_THROWN:
- case COUNTER_EXC_THROWN_PSEC:
- sample->rawValue = vt->counters->exceptions_thrown;
- return TRUE;
- }
- break;
-
- case CATEGORY_ASPNET:
- switch (id) {
- case COUNTER_ASPNET_REQ_Q:
- sample->rawValue = vt->counters->aspnet_requests_queued;
- return TRUE;
- }
- }
- return FALSE;
+ desc = &predef_counters [predef_categories [cat_id].first_counter + id];
+ sample->counterType = desc->type;
+ /* FIXME: check that the offset fits inside imported counters */
+ /*g_print ("loading %s at %d\n", desc->name, desc->offset);*/
+ sample->rawValue = *(guint32*)((char*)vt->counters + desc->offset);
+ return TRUE;
}
static ImplVtable*
vtable->vtable.arg = arg;
vtable->vtable.sample = predef_readonly_counter;
vtable->vtable.cleanup = predef_cleanup;
- vtable->counters = &area->counters;
+ vtable->counters = (MonoPerfCounters*)((char*)area + area->counters_start);
vtable->pid = pid;
return (ImplVtable*)vtable;
return mono_mem_get_impl (counter, instance, type, custom);
case CATEGORY_JIT:
case CATEGORY_EXC:
+ case CATEGORY_GC:
+ case CATEGORY_REMOTING:
+ case CATEGORY_LOADING:
+ case CATEGORY_THREAD:
+ case CATEGORY_INTEROP:
+ case CATEGORY_SECURITY:
case CATEGORY_ASPNET:
return predef_writable_get_impl (cdesc->id, counter, instance, type, custom);
}
return mono_array_new (domain, mono_get_string_class (), 0);
}
-static char*
-read_proc_name (int pid, char *buf, int len)
-{
- char fname [128];
- FILE *file;
- char *p;
- int r;
- sprintf (fname, "/proc/%d/cmdline", pid);
- buf [0] = 0;
- file = fopen (fname, "r");
- if (!file)
- return buf;
- r = fread (buf, 1, len - 1, file);
- fclose (file);
- buf [r] = 0;
- p = strrchr (buf, '/');
- if (p)
- return p + 1;
- return buf;
-}
-
static MonoArray*
get_string_array (void **array, int count, gboolean is_process)
{
char buf [128];
char *p;
if (is_process) {
- char *pname = read_proc_name (GPOINTER_TO_INT (array [i]), buf, sizeof (buf));
+ char *pname = mono_process_get_name (array [i], buf, sizeof (buf));
p = g_strdup_printf ("%d/%s", GPOINTER_TO_INT (array [i]), pname);
} else {
sprintf (buf, "%d", GPOINTER_TO_INT (array [i]));
get_cpu_instances (void)
{
void **buf = NULL;
- int i;
+ int i, count;
MonoArray *array;
- SYSTEM_INFO info;
- GetSystemInfo (&info);
- buf = g_new (void*, info.dwNumberOfProcessors);
- for (i = 0; i < info.dwNumberOfProcessors; ++i)
+ count = mono_cpu_count ();
+ buf = g_new (void*, count);
+ for (i = 0; i < count; ++i)
buf [i] = GINT_TO_POINTER (i);
- array = get_string_array (buf, info.dwNumberOfProcessors, FALSE);
+ array = get_string_array (buf, count, FALSE);
g_free (buf);
return array;
}
static MonoArray*
get_processes_instances (void)
{
- const char *name;
- void **buf = NULL;
- int count = 0;
- int i = 0;
MonoArray *array;
- GDir *dir = g_dir_open ("/proc/", 0, NULL);
- if (!dir)
+ int count = 0;
+ void **buf = mono_process_list (&count);
+ if (!buf)
return get_string_array (NULL, 0, FALSE);
- while ((name = g_dir_read_name (dir))) {
- int pid;
- char *nend;
- pid = strtol (name, &nend, 10);
- if (pid <= 0 || nend == name || *nend)
- continue;
- if (i >= count) {
- if (!count)
- count = 16;
- else
- count *= 2;
- buf = g_realloc (buf, count * sizeof (void*));
- }
- buf [i++] = GINT_TO_POINTER (pid);
- }
- g_dir_close (dir);
- array = get_string_array (buf, i, TRUE);
+ array = get_string_array (buf, count, TRUE);
g_free (buf);
return array;
}