From 5ed284a15e028e0435f3b6e0773e14225d8f165d Mon Sep 17 00:00:00 2001 From: stijn Date: Thu, 8 May 2014 10:56:33 +0200 Subject: [PATCH] windows: Add modtime implementation --- py/runtime.c | 5 ++++ unix/modtime.c | 22 ++++++++++++-- windows/Makefile | 2 ++ windows/init.c | 10 +++++++ windows/init.h | 1 + windows/mpconfigport.h | 7 +++++ windows/msvc/gettimeofday.c | 58 +++++++++++++++++++++++++++++++++++++ windows/msvc/sources.props | 2 +- windows/msvc/sys/time.h | 28 ++++++++++++++++++ windows/sleep.c | 34 ++++++++++++++++++++++ 10 files changed, 165 insertions(+), 4 deletions(-) create mode 100644 windows/msvc/gettimeofday.c create mode 100644 windows/msvc/sys/time.h create mode 100644 windows/sleep.c diff --git a/py/runtime.c b/py/runtime.c index 7a701fec5..f8eac4060 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -91,6 +91,11 @@ void mp_deinit(void) { //mp_obj_dict_free(&dict_main); mp_module_deinit(); mp_emit_glue_deinit(); + + // call port specific deinitialization if any +#ifdef MICROPY_PORT_INIT_FUNC + MICROPY_PORT_DEINIT_FUNC; +#endif } mp_obj_t mp_load_const_dec(qstr qstr) { diff --git a/unix/modtime.c b/unix/modtime.c index 283b9dfd6..c497763bf 100644 --- a/unix/modtime.c +++ b/unix/modtime.c @@ -36,6 +36,23 @@ #include "obj.h" #include "runtime.h" +#ifdef _WIN32 +void msec_sleep_tv(struct timeval *tv) { + msec_sleep(tv->tv_sec * 1000.0 + tv->tv_usec / 1000.0); +} +#define sleep_select(a,b,c,d,e) msec_sleep_tv((e)) +#else +#define sleep_select select +#endif + +#if CLOCKS_PER_SEC == 1000000 // POSIX +#define CLOCK_DIV 1000.0 +#elif CLOCKS_PER_SEC == 1000 // WIN32 +#define CLOCK_DIV 1.0 +#else +#error Unsupported clock() implementation +#endif + STATIC mp_obj_t mod_time_time() { #if MICROPY_ENABLE_FLOAT struct timeval tv; @@ -51,11 +68,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_time_time_obj, mod_time_time); // Note: this is deprecated since CPy3.3, but pystone still uses it. STATIC mp_obj_t mod_time_clock() { #if MICROPY_ENABLE_FLOAT - // POSIX requires CLOCKS_PER_SEC equals 1000000, so that's what we assume. // float cannot represent full range of int32 precisely, so we pre-divide // int to reduce resolution, and then actually do float division hoping // to preserve integer part resolution. - return mp_obj_new_float((float)(clock() / 1000) / 1000.0); + return mp_obj_new_float((float)(clock() / 1000) / CLOCK_DIV); #else return mp_obj_new_int((machine_int_t)clock()); #endif @@ -69,7 +85,7 @@ STATIC mp_obj_t mod_time_sleep(mp_obj_t arg) { double ipart; tv.tv_usec = round(modf(val, &ipart) * 1000000); tv.tv_sec = ipart; - select(0, NULL, NULL, NULL, &tv); + sleep_select(0, NULL, NULL, NULL, &tv); #else sleep(mp_obj_get_int(arg)); #endif diff --git a/windows/Makefile b/windows/Makefile index aeb105634..8fcc0b581 100644 --- a/windows/Makefile +++ b/windows/Makefile @@ -31,8 +31,10 @@ SRC_C = \ unix/main.c \ unix/file.c \ unix/input.c \ + unix/modtime.c \ realpath.c \ init.c \ + sleep.c \ OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) diff --git a/windows/init.c b/windows/init.c index 5bb29b8f3..69f1026bb 100644 --- a/windows/init.c +++ b/windows/init.c @@ -26,11 +26,21 @@ #include #include +#include + +HANDLE hSleepEvent = NULL; void init() { + hSleepEvent = CreateEvent(NULL, TRUE, FALSE, FALSE); #ifdef __MINGW32__ putenv("PRINTF_EXPONENT_DIGITS=2"); #else _set_output_format(_TWO_DIGIT_EXPONENT); #endif } + +void deinit() { + if (hSleepEvent != NULL) { + CloseHandle(hSleepEvent); + } +} diff --git a/windows/init.h b/windows/init.h index a5672840e..69e577689 100644 --- a/windows/init.h +++ b/windows/init.h @@ -25,3 +25,4 @@ */ void init(void); +void deinit(void); diff --git a/windows/mpconfigport.h b/windows/mpconfigport.h index 3651a6120..0a1e313cb 100644 --- a/windows/mpconfigport.h +++ b/windows/mpconfigport.h @@ -44,6 +44,7 @@ #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_PORT_INIT_FUNC init() +#define MICROPY_PORT_DEINIT_FUNC deinit() // type definitions for the specific machine @@ -69,9 +70,15 @@ extern const struct _mp_obj_fun_native_t mp_builtin_open_obj; #define MICROPY_EXTRA_BUILTINS \ { MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj }, +extern const struct _mp_obj_module_t mp_module_time; +#define MICROPY_EXTRA_BUILTIN_MODULES \ + { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&mp_module_time }, \ + #include "realpath.h" #include "init.h" +// sleep for given number of milliseconds +void msec_sleep(double msec); // MSVC specifics #ifdef _MSC_VER diff --git a/windows/msvc/gettimeofday.c b/windows/msvc/gettimeofday.c new file mode 100644 index 000000000..363d59d7b --- /dev/null +++ b/windows/msvc/gettimeofday.c @@ -0,0 +1,58 @@ +/* +* This file is part of the Micro Python project, http://micropython.org/ +* +* The MIT License (MIT) +* +* Copyright (c) 2013, 2014 Damien P. George +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +#include + +typedef union { + unsigned __int64 tm; // time in 100 nanoseconds interval + FILETIME ft; +} FT; + +int gettimeofday(struct timeval *tp, struct timezone *tz) { + if (tp == NULL) { + return 0; + } + + // UTC time + FT ft; + ZeroMemory(&ft, sizeof(ft)); + GetSystemTimeAsFileTime(&ft.ft); + + // to microseconds + ft.tm /= 10; + + // convert to unix format + // number of microseconds intervals between the 1st january 1601 and the 1st january 1970 (369 years + 89 leap days) + const unsigned __int64 deltaEpoch = 11644473600000000ull; + const unsigned __int64 microSecondsToSeconds = 1000000ull; + tp->tv_usec = ft.tm % microSecondsToSeconds; + tp->tv_sec = (ft.tm - deltaEpoch) / microSecondsToSeconds; + + // see man gettimeofday: timezone is deprecated and expected to be NULL + (void)tz; + + return 0; +} diff --git a/windows/msvc/sources.props b/windows/msvc/sources.props index 9af7d6e11..8af03e756 100644 --- a/windows/msvc/sources.props +++ b/windows/msvc/sources.props @@ -5,7 +5,7 @@ - + diff --git a/windows/msvc/sys/time.h b/windows/msvc/sys/time.h new file mode 100644 index 000000000..96bca1ccb --- /dev/null +++ b/windows/msvc/sys/time.h @@ -0,0 +1,28 @@ +/* +* This file is part of the Micro Python project, http://micropython.org/ +* +* The MIT License (MIT) +* +* Copyright (c) 2013, 2014 Damien P. George +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +// Get the definitions for timeval etc +#include diff --git a/windows/sleep.c b/windows/sleep.c new file mode 100644 index 000000000..98387350f --- /dev/null +++ b/windows/sleep.c @@ -0,0 +1,34 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +extern HANDLE hSleepEvent; + +void msec_sleep(double msec) { + ResetEvent(hSleepEvent); + WaitForSingleObjectEx(hSleepEvent, msec, FALSE); +}