From: Ludovic Henry Date: Mon, 25 Apr 2016 15:22:15 +0000 (-0400) Subject: Merge pull request #2721 from ludovic-henry/fix-mono_ms_ticks X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=mono.git;a=commitdiff_plain;h=6b139f4c98eb90bfb7e1285933fc682dae541cad;hp=04162ffbbdfed88ba298341f0384a35949b3c0f9 Merge pull request #2721 from ludovic-henry/fix-mono_ms_ticks [runtime] Fix potential overflow when using mono_msec_ticks --- diff --git a/mono/io-layer/processes.c b/mono/io-layer/processes.c index 0157e92f5be..913f0b8af4b 100644 --- a/mono/io-layer/processes.c +++ b/mono/io-layer/processes.c @@ -2727,8 +2727,7 @@ process_wait (gpointer handle, guint32 timeout, gboolean alertable) WapiHandle_process *process_handle; pid_t pid G_GNUC_UNUSED, ret; int status; - guint32 start; - guint32 now; + gint64 start, now; struct MonoProcess *mp; /* FIXME: We can now easily wait on processes that aren't our own children, diff --git a/mono/io-layer/timefuncs-private.h b/mono/io-layer/timefuncs-private.h index a4029a91e20..ff008793d5b 100644 --- a/mono/io-layer/timefuncs-private.h +++ b/mono/io-layer/timefuncs-private.h @@ -15,8 +15,6 @@ #include extern void _wapi_time_t_to_filetime (time_t timeval, WapiFileTime *filetime); -extern void _wapi_timeval_to_filetime (struct timeval *tv, - WapiFileTime *filetime); extern void _wapi_guint64_to_filetime (guint64 ticks, WapiFileTime *filetime); #endif /* _WAPI_TIMEFUNCS_PRIVATE_H_ */ diff --git a/mono/io-layer/timefuncs.c b/mono/io-layer/timefuncs.c index 8a79f3b4d57..0528ae6946d 100644 --- a/mono/io-layer/timefuncs.c +++ b/mono/io-layer/timefuncs.c @@ -28,33 +28,8 @@ void _wapi_time_t_to_filetime (time_t timeval, WapiFileTime *filetime) filetime->dwHighDateTime = ticks >> 32; } -void _wapi_timeval_to_filetime (struct timeval *tv, WapiFileTime *filetime) -{ - guint64 ticks; - - ticks = ((guint64)tv->tv_sec * 10000000) + - ((guint64)tv->tv_usec * 10) + 116444736000000000ULL; - filetime->dwLowDateTime = ticks & 0xFFFFFFFF; - filetime->dwHighDateTime = ticks >> 32; -} - void _wapi_guint64_to_filetime (guint64 ticks, WapiFileTime *filetime) { filetime->dwLowDateTime = ticks & 0xFFFFFFFF; filetime->dwHighDateTime = ticks >> 32; } - -gboolean QueryPerformanceCounter(WapiLargeInteger *count G_GNUC_UNUSED) -{ - return(FALSE); -} - -gboolean QueryPerformanceFrequency(WapiLargeInteger *freq G_GNUC_UNUSED) -{ - return(FALSE); -} - -guint32 GetTickCount (void) -{ - return mono_msec_ticks (); -} diff --git a/mono/io-layer/timefuncs.h b/mono/io-layer/timefuncs.h index 2097b85788c..d24800229f2 100644 --- a/mono/io-layer/timefuncs.h +++ b/mono/io-layer/timefuncs.h @@ -30,9 +30,5 @@ typedef struct #endif } WapiFileTime; -extern gboolean QueryPerformanceCounter(WapiLargeInteger *count); -extern gboolean QueryPerformanceFrequency(WapiLargeInteger *freq); -extern guint32 GetTickCount (void); - G_END_DECLS #endif /* _WAPI_TIME_H_ */ diff --git a/mono/io-layer/wapi-remap.h b/mono/io-layer/wapi-remap.h index 10118183618..d8c4aaccb00 100644 --- a/mono/io-layer/wapi-remap.h +++ b/mono/io-layer/wapi-remap.h @@ -89,9 +89,6 @@ #define WSARecv wapi_WSARecv #define WSASend wapi_WSASend #define GetSystemInfo wapi_GetSystemInfo -#define QueryPerformanceCounter wapi_QueryPerformanceCounter -#define QueryPerformanceFrequency wapi_QueryPerformanceFrequency -#define GetTickCount wapi_GetTickCount #define GetFileVersionInfoSize wapi_GetFileVersionInfoSize #define GetFileVersionInfo wapi_GetFileVersionInfo #define VerQueryValue wapi_VerQueryValue diff --git a/mono/metadata/gc.c b/mono/metadata/gc.c index 9ab8f7dd6d6..2cff646db17 100644 --- a/mono/metadata/gc.c +++ b/mono/metadata/gc.c @@ -876,14 +876,14 @@ mono_gc_cleanup (void) finished = TRUE; if (mono_thread_internal_current () != gc_thread) { gboolean timed_out = FALSE; - guint32 start_ticks = mono_msec_ticks (); - guint32 end_ticks = start_ticks + 2000; + gint64 start_ticks = mono_msec_ticks (); + gint64 end_ticks = start_ticks + 2000; mono_gc_finalize_notify (); /* Finishing the finalizer thread, so wait a little bit... */ /* MS seems to wait for about 2 seconds */ while (!finalizer_thread_exited) { - guint32 current_ticks = mono_msec_ticks (); + gint64 current_ticks = mono_msec_ticks (); guint32 timeout; if (current_ticks >= end_ticks) diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h index 9c345a269cd..b74631fd942 100644 --- a/mono/metadata/icall-def.h +++ b/mono/metadata/icall-def.h @@ -239,7 +239,7 @@ ICALL(ENV_10, "get_HasShutdownStarted", ves_icall_System_Environment_get_HasShut ICALL(ENV_11, "get_MachineName", ves_icall_System_Environment_get_MachineName) ICALL(ENV_13, "get_Platform", ves_icall_System_Environment_get_Platform) ICALL(ENV_14, "get_ProcessorCount", mono_cpu_count) -ICALL(ENV_15, "get_TickCount", mono_msec_ticks) +ICALL(ENV_15, "get_TickCount", ves_icall_System_Environment_get_TickCount) ICALL(ENV_16, "get_UserName", ves_icall_System_Environment_get_UserName) ICALL(ENV_16m, "internalBroadcastSettingChange", ves_icall_System_Environment_BroadcastSettingChange) ICALL(ENV_17, "internalGetEnvironmentVariable", ves_icall_System_Environment_GetEnvironmentVariable) diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index 285905fb9b8..e22c730342d 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -7278,6 +7278,14 @@ ves_icall_System_Environment_BroadcastSettingChange (void) #endif } +ICALL_EXPORT +gint32 +ves_icall_System_Environment_get_TickCount (void) +{ + /* this will overflow after ~24 days */ + return (gint32) (mono_msec_boottime () & 0xffffffff); +} + ICALL_EXPORT gint32 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void) { diff --git a/mono/metadata/monitor.c b/mono/metadata/monitor.c index 45c13be4e0f..510d1c18bcd 100644 --- a/mono/metadata/monitor.c +++ b/mono/metadata/monitor.c @@ -743,7 +743,7 @@ mono_monitor_try_enter_inflated (MonoObject *obj, guint32 ms, gboolean allow_int LockWord lw; MonoThreadsSync *mon; HANDLE sem; - guint32 then = 0, now, delta; + gint64 then = 0, now, delta; guint32 waitms; guint32 ret; guint32 new_status, old_status, tmp_status; @@ -900,14 +900,9 @@ retry_contended: if (!mono_thread_test_state (mono_thread_internal_current (), (MonoThreadState)(ThreadState_StopRequested | ThreadState_SuspendRequested | ThreadState_AbortRequested))) { if (ms != INFINITE) { now = mono_msec_ticks (); - if (now < then) { - LOCK_DEBUG (g_message ("%s: wrapped around! now=0x%x then=0x%x", __func__, now, then)); - now += (0xffffffff - then); - then = 0; - - LOCK_DEBUG (g_message ("%s: wrap rejig: now=0x%x then=0x%x delta=0x%x", __func__, now, then, now-then)); - } + /* it should not overflow before ~30k years */ + g_assert (now >= then); delta = now - then; if (delta >= ms) { diff --git a/mono/metadata/threadpool-ms.c b/mono/metadata/threadpool-ms.c index 61513956880..69ade32e593 100644 --- a/mono/metadata/threadpool-ms.c +++ b/mono/metadata/threadpool-ms.c @@ -140,10 +140,10 @@ typedef struct { MonoCoopMutex worker_creation_lock; gint32 heuristic_completions; - guint32 heuristic_sample_start; - guint32 heuristic_last_dequeue; // ms - guint32 heuristic_last_adjustment; // ms - guint32 heuristic_adjustment_interval; // ms + gint64 heuristic_sample_start; + gint64 heuristic_last_dequeue; // ms + gint64 heuristic_last_adjustment; // ms + gint64 heuristic_adjustment_interval; // ms ThreadPoolHillClimbing heuristic_hill_climbing; MonoCoopMutex heuristic_lock; @@ -855,7 +855,7 @@ monitor_should_keep_running (void) static gboolean monitor_sufficient_delay_since_last_dequeue (void) { - guint32 threshold; + gint64 threshold; g_assert (threadpool); @@ -893,7 +893,7 @@ monitor_thread (void) mono_gc_set_skip_thread (TRUE); do { - guint32 ts; + gint64 ts; gboolean alerted = FALSE; if (mono_runtime_is_shutting_down ()) @@ -1052,7 +1052,7 @@ hill_climbing_get_wave_component (gdouble *samples, guint sample_count, gdouble } static gint16 -hill_climbing_update (gint16 current_thread_count, guint32 sample_duration, gint32 completions, guint32 *adjustment_interval) +hill_climbing_update (gint16 current_thread_count, guint32 sample_duration, gint32 completions, gint64 *adjustment_interval) { ThreadPoolHillClimbing *hc; ThreadPoolHeuristicStateTransition transition; @@ -1292,8 +1292,8 @@ heuristic_adjust (void) if (mono_coop_mutex_trylock (&threadpool->heuristic_lock) == 0) { gint32 completions = InterlockedExchange (&threadpool->heuristic_completions, 0); - guint32 sample_end = mono_msec_ticks (); - guint32 sample_duration = sample_end - threadpool->heuristic_sample_start; + gint64 sample_end = mono_msec_ticks (); + gint64 sample_duration = sample_end - threadpool->heuristic_sample_start; if (sample_duration >= threadpool->heuristic_adjustment_interval / 2) { ThreadPoolCounter counter; @@ -1418,7 +1418,7 @@ gboolean mono_threadpool_ms_remove_domain_jobs (MonoDomain *domain, int timeout) { gboolean res = TRUE; - guint32 start; + gint64 end; gpointer sem; g_assert (domain); @@ -1427,13 +1427,12 @@ mono_threadpool_ms_remove_domain_jobs (MonoDomain *domain, int timeout) g_assert (mono_domain_is_unloading (domain)); if (timeout != -1) - start = mono_msec_ticks (); + end = mono_msec_ticks () + timeout; #ifndef DISABLE_SOCKETS mono_threadpool_ms_io_remove_domain_jobs (domain); if (timeout != -1) { - timeout -= mono_msec_ticks () - start; - if (timeout < 0) + if (mono_msec_ticks () > end) return FALSE; } #endif @@ -1452,16 +1451,19 @@ mono_threadpool_ms_remove_domain_jobs (MonoDomain *domain, int timeout) mono_memory_write_barrier (); while (domain->threadpool_jobs) { - MONO_PREPARE_BLOCKING; - WaitForSingleObject (sem, timeout); - MONO_FINISH_BLOCKING; + gint64 now; + if (timeout != -1) { - timeout -= mono_msec_ticks () - start; - if (timeout <= 0) { + now = mono_msec_ticks (); + if (now > end) { res = FALSE; break; } } + + MONO_PREPARE_BLOCKING; + WaitForSingleObject (sem, timeout != -1 ? end - now : timeout); + MONO_FINISH_BLOCKING; } domain->cleanup_semaphore = NULL; diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c index b842edbc08f..34f3be0d488 100644 --- a/mono/metadata/threads.c +++ b/mono/metadata/threads.c @@ -3790,7 +3790,7 @@ mono_threads_abort_appdomain_threads (MonoDomain *domain, int timeout) #endif abort_appdomain_data user_data; - guint32 start_time; + gint64 start_time; int orig_timeout = timeout; int i; diff --git a/mono/mini/debugger-agent.c b/mono/mini/debugger-agent.c index 5b05e57c90e..8c4d16aa4f2 100644 --- a/mono/mini/debugger-agent.c +++ b/mono/mini/debugger-agent.c @@ -1120,8 +1120,8 @@ socket_transport_recv (void *buf, int len) int total = 0; int fd = conn_fd; int flags = 0; - static gint32 last_keepalive; - gint32 msecs; + static gint64 last_keepalive; + gint64 msecs; MONO_PREPARE_BLOCKING; diff --git a/mono/utils/mono-proclib.c b/mono/utils/mono-proclib.c index 7a4a02e39a3..efd732d6d56 100644 --- a/mono/utils/mono-proclib.c +++ b/mono/utils/mono-proclib.c @@ -325,7 +325,7 @@ mono_process_get_times (gpointer pid, gint64 *start_time, gint64 *user_time, gin if (*start_time == 0) { static guint64 boot_time = 0; if (!boot_time) - boot_time = mono_100ns_datetime () - ((guint64)mono_msec_ticks ()) * 10000; + boot_time = mono_100ns_datetime () - mono_msec_boottime () * 10000; *start_time = boot_time + mono_process_get_data (pid, MONO_PROCESS_ELAPSED); } diff --git a/mono/utils/mono-time.c b/mono/utils/mono-time.c index 5f0168ebb74..5a34f440353 100644 --- a/mono/utils/mono-time.c +++ b/mono/utils/mono-time.c @@ -16,16 +16,27 @@ #include -#define MTICKS_PER_SEC 10000000 +#define MTICKS_PER_SEC (10 * 1000 * 1000) + +gint64 +mono_msec_ticks (void) +{ + return mono_100ns_ticks () / 10 / 1000; +} #ifdef HOST_WIN32 #include -guint32 -mono_msec_ticks (void) +#ifndef _MSC_VER +/* we get "error: implicit declaration of function 'GetTickCount64'" */ +ULONGLONG GetTickCount64(void); +#endif + +gint64 +mono_msec_boottime (void) { /* GetTickCount () is reportedly monotonic */ - return GetTickCount (); + return GetTickCount64 (); } /* Returns the number of 100ns ticks from unspecified time: this should be monotonic */ @@ -114,8 +125,8 @@ get_boot_time (void) } /* Returns the number of milliseconds from boot time: this should be monotonic */ -guint32 -mono_msec_ticks (void) +gint64 +mono_msec_boottime (void) { static gint64 boot_time = 0; gint64 now; @@ -123,6 +134,7 @@ mono_msec_ticks (void) boot_time = get_boot_time (); now = mono_100ns_ticks (); /*printf ("now: %llu (boot: %llu) ticks: %llu\n", (gint64)now, (gint64)boot_time, (gint64)(now - boot_time));*/ + g_assert (now > boot_time); return (now - boot_time)/10000; } diff --git a/mono/utils/mono-time.h b/mono/utils/mono-time.h index 95bda8e5309..438b9ef1881 100644 --- a/mono/utils/mono-time.h +++ b/mono/utils/mono-time.h @@ -8,14 +8,19 @@ #include #endif -/* Returns the number of milliseconds from boot time: this should be monotonic */ -guint32 mono_msec_ticks (void); +/* Returns the number of milliseconds from boot time: this should be monotonic + * + * Prefer to use mono_msec_ticks for elapsed time calculation. */ +gint64 mono_msec_boottime (void); + +/* Returns the number of milliseconds ticks from unspecified time: this should be monotonic */ +gint64 mono_msec_ticks (void); /* Returns the number of 100ns ticks from unspecified time: this should be monotonic */ -gint64 mono_100ns_ticks (void); +gint64 mono_100ns_ticks (void); /* Returns the number of 100ns ticks since 1/1/1601, UTC timezone */ -gint64 mono_100ns_datetime (void); +gint64 mono_100ns_datetime (void); #ifndef HOST_WIN32 gint64 mono_100ns_datetime_from_timeval (struct timeval tv);