#include "config.h"
#include "utils/mono-proclib.h"
+#include "utils/mono-time.h"
#include <stdlib.h>
#include <stdio.h>
#ifdef HOST_WIN32
#include <windows.h>
#include <process.h>
+#include <Winbase.h>
#endif
-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
+#if defined(_POSIX_VERSION)
+#include <sys/errno.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/sysctl.h>
+#include <sys/resource.h>
+#endif
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
#include <sys/proc.h>
#if defined(__APPLE__)
#include <mach/mach.h>
struct kinfo_proc2 *processes = malloc (data_len);
#else
int mib [4];
- size_t data_len = sizeof (struct kinfo_proc) * 400;
- struct kinfo_proc *processes = malloc (data_len);
+ size_t data_len = sizeof (struct kinfo_proc) * 16;
+ struct kinfo_proc *processes;
+ int limit = 8;
#endif /* KERN_PROC2 */
void **buf = NULL;
if (size)
*size = 0;
+
+#ifdef KERN_PROC2
if (!processes)
return NULL;
-#ifdef KERN_PROC2
mib [0] = CTL_KERN;
mib [1] = KERN_PROC2;
mib [2] = KERN_PROC_ALL;
mib [5] = 400; /* XXX */
res = sysctl (mib, 6, processes, &data_len, NULL, 0);
-#else
- mib [0] = CTL_KERN;
- mib [1] = KERN_PROC;
- mib [2] = KERN_PROC_ALL;
- mib [3] = 0;
-
- res = sysctl (mib, 4, processes, &data_len, NULL, 0);
-#endif /* KERN_PROC2 */
-
if (res < 0) {
free (processes);
return NULL;
}
+#else
+ processes = NULL;
+ while (limit) {
+ mib [0] = CTL_KERN;
+ mib [1] = KERN_PROC;
+ mib [2] = KERN_PROC_ALL;
+ mib [3] = 0;
+
+ res = sysctl (mib, 4, NULL, &data_len, NULL, 0);
+ if (res)
+ return NULL;
+ processes = malloc (data_len);
+ res = sysctl (mib, 4, processes, &data_len, NULL, 0);
+ if (res < 0) {
+ free (processes);
+ if (errno != ENOMEM)
+ return NULL;
+ limit --;
+ } else {
+ break;
+ }
+ }
+#endif /* KERN_PROC2 */
+
#ifdef KERN_PROC2
res = data_len/sizeof (struct kinfo_proc2);
#else
return get_process_stat_item (rpid, 18, FALSE, error) / get_user_hz ();
case MONO_PROCESS_PPID:
return get_process_stat_time (rpid, 0, FALSE, error);
+ case MONO_PROCESS_PAGED_BYTES:
+ return get_pid_status_item (rpid, "VmSwap", error, 1024);
/* Nothing yet */
case MONO_PROCESS_END:
return value;
}
+int
+mono_atexit (void (*func)(void))
+{
+#ifdef PLATFORM_ANDROID
+ /* Some versions of android libc doesn't define atexit () */
+ return 0;
+#else
+ return atexit (func);
+#endif
+}
+
+gint32
+mono_cpu_usage (MonoCpuUsageState *prev)
+{
+ gint32 cpu_usage = 0;
+ gint64 cpu_total_time;
+ gint64 cpu_busy_time;
+
+#ifndef HOST_WIN32
+ struct rusage resource_usage;
+ gint64 current_time;
+ gint64 kernel_time;
+ gint64 user_time;
+
+ if (getrusage (RUSAGE_SELF, &resource_usage) == -1) {
+ g_error ("getrusage() failed, errno is %d (%s)\n", errno, strerror (errno));
+ return -1;
+ }
+
+ current_time = mono_100ns_ticks ();
+ kernel_time = resource_usage.ru_stime.tv_sec * 1000 * 1000 * 10 + resource_usage.ru_stime.tv_usec * 10;
+ user_time = resource_usage.ru_utime.tv_sec * 1000 * 1000 * 10 + resource_usage.ru_utime.tv_usec * 10;
+
+ cpu_busy_time = (user_time - (prev ? prev->user_time : 0)) + (kernel_time - (prev ? prev->kernel_time : 0));
+ cpu_total_time = (current_time - (prev ? prev->current_time : 0)) * mono_cpu_count ();
+
+ if (prev) {
+ prev->kernel_time = kernel_time;
+ prev->user_time = user_time;
+ prev->current_time = current_time;
+ }
+#else
+ guint64 idle_time;
+ guint64 kernel_time;
+ guint64 user_time;
+
+ if (!GetSystemTimes ((FILETIME*) &idle_time, (FILETIME*) &kernel_time, (FILETIME*) &user_time)) {
+ g_error ("GetSystemTimes() failed, error code is %d\n", GetLastError ());
+ return -1;
+ }
+
+ cpu_total_time = (gint64)((user_time - (prev ? prev->user_time : 0)) + (kernel_time - (prev ? prev->kernel_time : 0)));
+ cpu_busy_time = (gint64)(cpu_total_time - (idle_time - (prev ? prev->idle_time : 0)));
+
+ if (prev) {
+ prev->idle_time = idle_time;
+ prev->kernel_time = kernel_time;
+ prev->user_time = user_time;
+ }
+#endif
+
+ if (cpu_total_time > 0 && cpu_busy_time > 0)
+ cpu_usage = (gint32)(cpu_busy_time * 100 / cpu_total_time);
+
+ g_assert (cpu_usage >= 0);
+ g_assert (cpu_usage <= 100);
+
+ return cpu_usage;
+}