aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/sys/win32
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/sys/win32')
-rw-r--r--erts/emulator/sys/win32/erl_poll.c74
-rw-r--r--erts/emulator/sys/win32/erl_win32_sys_ddll.c5
-rw-r--r--erts/emulator/sys/win32/erl_win_dyn_driver.h44
-rw-r--r--erts/emulator/sys/win32/erl_win_sys.h41
-rwxr-xr-x[-rw-r--r--]erts/emulator/sys/win32/sys.c219
-rw-r--r--erts/emulator/sys/win32/sys_env.c16
-rw-r--r--erts/emulator/sys/win32/sys_float.c5
-rw-r--r--erts/emulator/sys/win32/sys_interrupt.c12
-rw-r--r--erts/emulator/sys/win32/sys_time.c327
9 files changed, 471 insertions, 272 deletions
diff --git a/erts/emulator/sys/win32/erl_poll.c b/erts/emulator/sys/win32/erl_poll.c
index 074e2e247f..7a1d129cd5 100644
--- a/erts/emulator/sys/win32/erl_poll.c
+++ b/erts/emulator/sys/win32/erl_poll.c
@@ -309,9 +309,9 @@ struct ErtsPollSet_ {
#ifdef ERTS_SMP
extern erts_smp_atomic32_t erts_break_requested;
#define ERTS_SET_BREAK_REQUESTED \
- erts_smp_atomic32_set(&erts_break_requested, (erts_aint32_t) 1)
+ erts_smp_atomic32_set_nob(&erts_break_requested, (erts_aint32_t) 1)
#define ERTS_UNSET_BREAK_REQUESTED \
- erts_smp_atomic32_set(&erts_break_requested, (erts_aint32_t) 0)
+ erts_smp_atomic32_set_nob(&erts_break_requested, (erts_aint32_t) 0)
#else
extern volatile int erts_break_requested;
#define ERTS_SET_BREAK_REQUESTED (erts_break_requested = 1)
@@ -371,19 +371,19 @@ do { \
static ERTS_INLINE int
is_io_ready(ErtsPollSet ps)
{
- return erts_atomic32_read(&ps->wakeup_state) == ERTS_POLL_WOKEN_IO_READY;
+ return erts_atomic32_read_nob(&ps->wakeup_state) == ERTS_POLL_WOKEN_IO_READY;
}
static ERTS_INLINE void
woke_up(ErtsPollSet ps)
{
- if (erts_atomic32_read(&ps->wakeup_state) == ERTS_POLL_NOT_WOKEN)
- erts_atomic32_cmpxchg(&ps->wakeup_state,
- ERTS_POLL_WOKEN_TIMEDOUT,
- ERTS_POLL_NOT_WOKEN);
+ if (erts_atomic32_read_nob(&ps->wakeup_state) == ERTS_POLL_NOT_WOKEN)
+ erts_atomic32_cmpxchg_nob(&ps->wakeup_state,
+ ERTS_POLL_WOKEN_TIMEDOUT,
+ ERTS_POLL_NOT_WOKEN);
#ifdef DEBUG
{
- erts_aint32_t wakeup_state = erts_atomic32_read(&ps->wakeup_state);
+ erts_aint32_t wakeup_state = erts_atomic32_read_nob(&ps->wakeup_state);
switch (wakeup_state) {
case ERTS_POLL_WOKEN_IO_READY:
case ERTS_POLL_WOKEN_INTR:
@@ -401,7 +401,7 @@ static ERTS_INLINE int
wakeup_cause(ErtsPollSet ps)
{
int res;
- erts_aint32_t wakeup_state = erts_atomic32_read(&ps->wakeup_state);
+ erts_aint32_t wakeup_state = erts_atomic32_read_nob(&ps->wakeup_state);
switch (wakeup_state) {
case ERTS_POLL_WOKEN_IO_READY:
res = 0;
@@ -439,11 +439,11 @@ poll_wait_timeout(ErtsPollSet ps, SysTimeval *tvp)
* by ResetEvent().
*/
ERTS_THR_MEMORY_BARRIER;
- if (erts_atomic32_read(&ps->wakeup_state) != ERTS_POLL_NOT_WOKEN)
+ if (erts_atomic32_read_nob(&ps->wakeup_state) != ERTS_POLL_NOT_WOKEN)
return (DWORD) 0;
- if (timeout > ERTS_AINT32_T_MAX) /* Also prevents DWORD overflow */
- timeout = ERTS_AINT32_T_MAX;
+ if (timeout > ((time_t) ERTS_AINT32_T_MAX))
+ timeout = ERTS_AINT32_T_MAX; /* Also prevents DWORD overflow */
erts_smp_atomic32_set_relb(&ps->timeout, (erts_aint32_t) timeout);
return (DWORD) timeout;
@@ -455,17 +455,17 @@ wake_poller(ErtsPollSet ps, int io_ready)
erts_aint32_t wakeup_state;
if (io_ready) {
/* We may set the event multiple times. This is, however, harmless. */
- wakeup_state = erts_atomic32_read(&ps->wakeup_state);
+ wakeup_state = erts_atomic32_read_nob(&ps->wakeup_state);
erts_atomic32_set_relb(&ps->wakeup_state, ERTS_POLL_WOKEN_IO_READY);
}
else {
ERTS_THR_MEMORY_BARRIER;
- wakeup_state = erts_atomic32_read(&ps->wakeup_state);
+ wakeup_state = erts_atomic32_read_nob(&ps->wakeup_state);
while (wakeup_state != ERTS_POLL_WOKEN_IO_READY
&& wakeup_state != ERTS_POLL_WOKEN_INTR) {
- erts_aint32_t act = erts_atomic32_cmpxchg(&ps->wakeup_state,
- ERTS_POLL_WOKEN_INTR,
- wakeup_state);
+ erts_aint32_t act = erts_atomic32_cmpxchg_nob(&ps->wakeup_state,
+ ERTS_POLL_WOKEN_INTR,
+ wakeup_state);
if (act == wakeup_state) {
wakeup_state = act;
break;
@@ -488,13 +488,13 @@ wake_poller(ErtsPollSet ps, int io_ready)
static ERTS_INLINE void
reset_io_ready(ErtsPollSet ps)
{
- erts_atomic32_set(&ps->wakeup_state, ERTS_POLL_NOT_WOKEN);
+ erts_atomic32_set_nob(&ps->wakeup_state, ERTS_POLL_NOT_WOKEN);
}
static ERTS_INLINE void
restore_io_ready(ErtsPollSet ps)
{
- erts_atomic32_set(&ps->wakeup_state, ERTS_POLL_WOKEN_IO_READY);
+ erts_atomic32_set_nob(&ps->wakeup_state, ERTS_POLL_WOKEN_IO_READY);
}
/*
@@ -511,12 +511,12 @@ static ERTS_INLINE void
reset_interrupt(ErtsPollSet ps)
{
/* We need to keep io-ready if set */
- erts_aint32_t wakeup_state = erts_atomic32_read(&ps->wakeup_state);
+ erts_aint32_t wakeup_state = erts_atomic32_read_nob(&ps->wakeup_state);
while (wakeup_state != ERTS_POLL_WOKEN_IO_READY
&& wakeup_state != ERTS_POLL_NOT_WOKEN) {
- erts_aint32_t act = erts_atomic32_cmpxchg(&ps->wakeup_state,
- ERTS_POLL_NOT_WOKEN,
- wakeup_state);
+ erts_aint32_t act = erts_atomic32_cmpxchg_nob(&ps->wakeup_state,
+ ERTS_POLL_NOT_WOKEN,
+ wakeup_state);
if (wakeup_state == act)
break;
wakeup_state = act;
@@ -692,7 +692,7 @@ static void *break_waiter(void *param)
case WAIT_OBJECT_0:
ResetEvent(harr[0]);
erts_mtx_lock(&break_waiter_lock);
- erts_atomic32_set(&break_waiter_state,BREAK_WAITER_GOT_BREAK);
+ erts_atomic32_set_nob(&break_waiter_state,BREAK_WAITER_GOT_BREAK);
ERTS_THR_MEMORY_BARRIER;
SetEvent(break_happened_event);
erts_mtx_unlock(&break_waiter_lock);
@@ -700,7 +700,7 @@ static void *break_waiter(void *param)
case (WAIT_OBJECT_0+1):
ResetEvent(harr[1]);
erts_mtx_lock(&break_waiter_lock);
- erts_atomic32_set(&break_waiter_state,BREAK_WAITER_GOT_HALT);
+ erts_atomic32_set_nob(&break_waiter_state,BREAK_WAITER_GOT_HALT);
ERTS_THR_MEMORY_BARRIER;
SetEvent(break_happened_event);
erts_mtx_unlock(&break_waiter_lock);
@@ -1012,7 +1012,7 @@ void erts_poll_interrupt(ErtsPollSet ps, int set /* bool */)
void erts_poll_interrupt_timed(ErtsPollSet ps,
int set /* bool */,
- long msec)
+ erts_short_time_t msec)
{
HARDTRACEF(("In erts_poll_interrupt_timed(%d,%ld)",set,msec));
if (!set)
@@ -1153,23 +1153,29 @@ int erts_poll_wait(ErtsPollSet ps,
/*HARDDEBUGF(("timeout = %ld",(long) timeout));*/
- if (timeout > 0 && !erts_atomic32_read(&break_waiter_state)) {
+ if (timeout > 0 && !erts_atomic32_read_nob(&break_waiter_state)) {
HANDLE harr[2] = {ps->event_io_ready, break_happened_event};
int num_h = 2;
HARDDEBUGF(("Start waiting %d [%d]",num_h, (int) timeout));
ERTS_POLLSET_UNLOCK(ps);
+#ifdef ERTS_SMP
+ erts_thr_progress_prepare_wait(NULL);
+#endif
WaitForMultipleObjects(num_h, harr, FALSE, timeout);
+#ifdef ERTS_SMP
+ erts_thr_progress_finalize_wait(NULL);
+#endif
ERTS_POLLSET_LOCK(ps);
HARDDEBUGF(("Stop waiting %d [%d]",num_h, (int) timeout));
woke_up(ps);
}
ERTS_UNSET_BREAK_REQUESTED;
- if(erts_atomic32_read(&break_waiter_state)) {
+ if(erts_atomic32_read_nob(&break_waiter_state)) {
erts_mtx_lock(&break_waiter_lock);
- break_state = erts_atomic32_read(&break_waiter_state);
- erts_atomic32_set(&break_waiter_state,0);
+ break_state = erts_atomic32_read_nob(&break_waiter_state);
+ erts_atomic32_set_nob(&break_waiter_state,0);
ResetEvent(break_happened_event);
erts_mtx_unlock(&break_waiter_lock);
switch (break_state) {
@@ -1236,7 +1242,7 @@ int erts_poll_wait(ErtsPollSet ps,
erts_mtx_unlock(&w->mtx);
}
done:
- erts_smp_atomic32_set(&ps->timeout, ERTS_AINT32_T_MAX);
+ erts_smp_atomic32_set_nob(&ps->timeout, ERTS_AINT32_T_MAX);
*len = num;
ERTS_POLLSET_UNLOCK(ps);
HARDTRACEF(("Out erts_poll_wait"));
@@ -1316,11 +1322,11 @@ ErtsPollSet erts_poll_create_pollset(void)
ps->standby_wait_event = CreateManualEvent(FALSE);
ps->restore_events = 0;
- erts_atomic32_init(&ps->wakeup_state, ERTS_POLL_NOT_WOKEN);
+ erts_atomic32_init_nob(&ps->wakeup_state, ERTS_POLL_NOT_WOKEN);
#ifdef ERTS_SMP
erts_smp_mtx_init(&ps->mtx, "pollset");
#endif
- erts_smp_atomic32_init(&ps->timeout, ERTS_AINT32_T_MAX);
+ erts_smp_atomic32_init_nob(&ps->timeout, ERTS_AINT32_T_MAX);
HARDTRACEF(("Out erts_poll_create_pollset"));
return ps;
@@ -1372,7 +1378,7 @@ void erts_poll_init(void)
erts_mtx_init(&break_waiter_lock,"break_waiter_lock");
break_happened_event = CreateManualEvent(FALSE);
- erts_atomic32_init(&break_waiter_state, 0);
+ erts_atomic32_init_nob(&break_waiter_state, 0);
erts_thr_create(&thread, &break_waiter, NULL, NULL);
ERTS_UNSET_BREAK_REQUESTED;
diff --git a/erts/emulator/sys/win32/erl_win32_sys_ddll.c b/erts/emulator/sys/win32/erl_win32_sys_ddll.c
index a19f49af10..d00eed932b 100644
--- a/erts/emulator/sys/win32/erl_win32_sys_ddll.c
+++ b/erts/emulator/sys/win32/erl_win32_sys_ddll.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2006-2009. All Rights Reserved.
+ * Copyright Ericsson AB 2006-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -25,6 +25,9 @@
#include <windows.h>
#define GET_ERTS_ALC_TEST
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
#include "sys.h"
#include "global.h"
#include "erl_alloc.h"
diff --git a/erts/emulator/sys/win32/erl_win_dyn_driver.h b/erts/emulator/sys/win32/erl_win_dyn_driver.h
index ecb06868d5..ec5141838a 100644
--- a/erts/emulator/sys/win32/erl_win_dyn_driver.h
+++ b/erts/emulator/sys/win32/erl_win_dyn_driver.h
@@ -39,11 +39,11 @@ WDD_TYPEDEF(int, driver_exit, (ErlDrvPort, int));
WDD_TYPEDEF(int, driver_failure_eof, (ErlDrvPort));
WDD_TYPEDEF(int, driver_select, (ErlDrvPort, ErlDrvEvent, int, int));
WDD_TYPEDEF(int, driver_event, (ErlDrvPort, ErlDrvEvent,ErlDrvEventData));
-WDD_TYPEDEF(int, driver_output, (ErlDrvPort, char *, int));
-WDD_TYPEDEF(int, driver_output2, (ErlDrvPort, char *, int,char *, int));
-WDD_TYPEDEF(int, driver_output_binary, (ErlDrvPort, char *, int,ErlDrvBinary*, int, int));
-WDD_TYPEDEF(int, driver_outputv, (ErlDrvPort, char*, int, ErlIOVec *,int));
-WDD_TYPEDEF(int, driver_vec_to_buf, (ErlIOVec *, char *, int));
+WDD_TYPEDEF(int, driver_output, (ErlDrvPort, char *, ErlDrvSizeT));
+WDD_TYPEDEF(int, driver_output2, (ErlDrvPort, char *, ErlDrvSizeT ,char *, ErlDrvSizeT));
+WDD_TYPEDEF(int, driver_output_binary, (ErlDrvPort, char *, ErlDrvSizeT, ErlDrvBinary*, ErlDrvSizeT, ErlDrvSizeT));
+WDD_TYPEDEF(int, driver_outputv, (ErlDrvPort, char*, ErlDrvSizeT, ErlIOVec *, ErlDrvSizeT));
+WDD_TYPEDEF(ErlDrvSizeT, driver_vec_to_buf, (ErlIOVec *, char *, ErlDrvSizeT));
WDD_TYPEDEF(int, driver_set_timer, (ErlDrvPort, unsigned long));
WDD_TYPEDEF(int, driver_cancel_timer, (ErlDrvPort));
WDD_TYPEDEF(int, driver_read_timer, (ErlDrvPort, unsigned long *));
@@ -51,22 +51,22 @@ WDD_TYPEDEF(char *, erl_errno_id, (int));
WDD_TYPEDEF(void, set_busy_port, (ErlDrvPort, int));
WDD_TYPEDEF(void, set_port_control_flags, (ErlDrvPort, int));
WDD_TYPEDEF(int, get_port_flags, (ErlDrvPort));
-WDD_TYPEDEF(ErlDrvBinary *, driver_alloc_binary, (int));
-WDD_TYPEDEF(ErlDrvBinary *, driver_realloc_binary, (ErlDrvBinary *, int));
+WDD_TYPEDEF(ErlDrvBinary *, driver_alloc_binary, (ErlDrvSizeT));
+WDD_TYPEDEF(ErlDrvBinary *, driver_realloc_binary, (ErlDrvBinary *, ErlDrvSizeT));
WDD_TYPEDEF(void, driver_free_binary, (ErlDrvBinary *));
-WDD_TYPEDEF(void *, driver_alloc, (size_t));
-WDD_TYPEDEF(void *, driver_realloc, (void *, size_t));
+WDD_TYPEDEF(void *, driver_alloc, (ErlDrvSizeT));
+WDD_TYPEDEF(void *, driver_realloc, (void *, ErlDrvSizeT));
WDD_TYPEDEF(void, driver_free, (void *));
-WDD_TYPEDEF(int, driver_enq, (ErlDrvPort, char*, int));
-WDD_TYPEDEF(int, driver_pushq, (ErlDrvPort, char*, int));
-WDD_TYPEDEF(int, driver_deq, (ErlDrvPort, int));
-WDD_TYPEDEF(int, driver_sizeq, (ErlDrvPort));
-WDD_TYPEDEF(int, driver_enq_bin, (ErlDrvPort, ErlDrvBinary *, int,int));
-WDD_TYPEDEF(int, driver_pushq_bin, (ErlDrvPort, ErlDrvBinary *, int,int));
-WDD_TYPEDEF(int, driver_peekqv, (ErlDrvPort, ErlIOVec *));
+WDD_TYPEDEF(int, driver_enq, (ErlDrvPort, char*, ErlDrvSizeT));
+WDD_TYPEDEF(int, driver_pushq, (ErlDrvPort, char*, ErlDrvSizeT));
+WDD_TYPEDEF(ErlDrvSizeT, driver_deq, (ErlDrvPort, ErlDrvSizeT));
+WDD_TYPEDEF(ErlDrvSizeT, driver_sizeq, (ErlDrvPort));
+WDD_TYPEDEF(int, driver_enq_bin, (ErlDrvPort, ErlDrvBinary *, ErlDrvSizeT, ErlDrvSizeT));
+WDD_TYPEDEF(int, driver_pushq_bin, (ErlDrvPort, ErlDrvBinary *, ErlDrvSizeT, ErlDrvSizeT));
+WDD_TYPEDEF(ErlDrvSizeT, driver_peekqv, (ErlDrvPort, ErlIOVec *));
WDD_TYPEDEF(SysIOVec *, driver_peekq, (ErlDrvPort, int *));
-WDD_TYPEDEF(int, driver_enqv, (ErlDrvPort, ErlIOVec *, int));
-WDD_TYPEDEF(int, driver_pushqv, (ErlDrvPort, ErlIOVec *, int));
+WDD_TYPEDEF(int, driver_enqv, (ErlDrvPort, ErlIOVec *, ErlDrvSizeT));
+WDD_TYPEDEF(int, driver_pushqv, (ErlDrvPort, ErlIOVec *, ErlDrvSizeT));
WDD_TYPEDEF(void, add_driver_entry, (ErlDrvEntry *));
WDD_TYPEDEF(int, remove_driver_entry, (ErlDrvEntry *));
WDD_TYPEDEF(ErlDrvTermData, driver_mk_atom, (char*));
@@ -83,10 +83,10 @@ WDD_TYPEDEF(void *, driver_dl_open, (char *));
WDD_TYPEDEF(void *, driver_dl_sym, (void *, char *));
WDD_TYPEDEF(int, driver_dl_close, (void *));
WDD_TYPEDEF(char *, driver_dl_error, (void));
-WDD_TYPEDEF(unsigned long, erts_alc_test, (unsigned long,
- unsigned long,
- unsigned long,
- unsigned long));
+WDD_TYPEDEF(ErlDrvUInt, erts_alc_test, (ErlDrvUInt,
+ ErlDrvUInt,
+ ErlDrvUInt,
+ ErlDrvUInt));
WDD_TYPEDEF(ErlDrvSInt, driver_binary_get_refc, (ErlDrvBinary *dbp));
WDD_TYPEDEF(ErlDrvSInt, driver_binary_inc_refc, (ErlDrvBinary *dbp));
WDD_TYPEDEF(ErlDrvSInt, driver_binary_dec_refc, (ErlDrvBinary *dbp));
diff --git a/erts/emulator/sys/win32/erl_win_sys.h b/erts/emulator/sys/win32/erl_win_sys.h
index 92d8577537..03298a6c54 100644
--- a/erts/emulator/sys/win32/erl_win_sys.h
+++ b/erts/emulator/sys/win32/erl_win_sys.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1997-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -117,9 +117,30 @@ int erts_check_io_debug(void);
#define SYS_CLK_TCK 1000
#define SYS_CLOCK_RESOLUTION 1
+#if SIZEOF_TIME_T != 8
+# error "Unexpected sizeof(time_t)"
+#endif
+
+/*
+ * gcc uses a 4 byte time_t and vc++ uses an 8 byte time_t.
+ * Types seen in beam_emu.c *need* to have the same size
+ * as in the rest of the system...
+ */
+typedef __int64 erts_time_t;
+
+struct tm *sys_localtime_r(time_t *epochs, struct tm *ptm);
+struct tm *sys_gmtime_r(time_t *epochs, struct tm *ptm);
+time_t sys_mktime( struct tm *ptm);
+
+#define localtime_r sys_localtime_r
+#define HAVE_LOCALTIME_R 1
+#define gmtime_r sys_gmtime_r
+#define HAVE_GMTIME_R
+#define mktime sys_mktime
+
typedef struct {
- long tv_sec;
- long tv_usec;
+ erts_time_t tv_sec;
+ erts_time_t tv_usec;
} SysTimeval;
typedef struct {
@@ -169,10 +190,12 @@ void erts_sys_env_init(void);
extern volatile int erl_fp_exception;
#include <float.h>
-#if defined (__GNUC__)
+/* I suspect this test isn't right, it might depend on the version of GCC
+ rather than if it's a MINGW gcc, but I havent been able to pinpoint the
+ exact point where _finite was added to the headers in cygwin... */
+#if defined (__GNUC__) && !defined(__MINGW32__)
int _finite(double x);
#endif
-#endif
/*#define NO_FPE_SIGNALS*/
#define erts_get_current_fp_exception() NULL
@@ -191,13 +214,6 @@ int _finite(double x);
#define erts_sys_block_fpe() 0
#define erts_sys_unblock_fpe(x) do{}while(0)
-#define SIZEOF_SHORT 2
-#define SIZEOF_INT 4
-#define SIZEOF_LONG 4
-#define SIZEOF_VOID_P 4
-#define SIZEOF_SIZE_T 4
-#define SIZEOF_OFF_T 4
-
/*
* Seems to be missing.
*/
@@ -210,3 +226,4 @@ typedef long ssize_t;
int init_async(int);
int exit_async(void);
#endif
+#endif
diff --git a/erts/emulator/sys/win32/sys.c b/erts/emulator/sys/win32/sys.c
index a2159d063c..b106f0932d 100644..100755
--- a/erts/emulator/sys/win32/sys.c
+++ b/erts/emulator/sys/win32/sys.c
@@ -198,7 +198,7 @@ Uint
erts_sys_misc_mem_sz(void)
{
Uint res = (Uint) erts_check_io_size();
- res += (Uint) erts_smp_atomic_read(&sys_misc_mem_sz);
+ res += (Uint) erts_smp_atomic_read_mb(&sys_misc_mem_sz);
return res;
}
@@ -216,6 +216,9 @@ void sys_tty_reset(int exit_code)
void erl_sys_args(int* argc, char** argv)
{
char *event_name;
+
+ erts_sys_env_init();
+
nohup = get_and_remove_option(argc, argv, "-nohup");
#ifdef DEBUG
@@ -471,7 +474,7 @@ static int spawn_init(void);
static int fd_init(void);
static void fd_stop(ErlDrvData);
static void stop(ErlDrvData);
-static void output(ErlDrvData, char*, int);
+static void output(ErlDrvData, char*, ErlDrvSizeT);
static void ready_input(ErlDrvData, ErlDrvEvent);
static void ready_output(ErlDrvData, ErlDrvEvent);
static void stop_select(ErlDrvEvent, void*);
@@ -566,51 +569,6 @@ struct erl_drv_entry vanilla_driver_entry = {
stop_select
};
-#if defined(USE_THREADS) && !defined(ERTS_SMP)
-
-static int async_drv_init(void);
-static ErlDrvData async_drv_start(ErlDrvPort, char*, SysDriverOpts*);
-static void async_drv_stop(ErlDrvData);
-static void async_drv_input(ErlDrvData, ErlDrvEvent);
-
-/* INTERNAL use only */
-
-void null_output(ErlDrvData drv_data, char* buf, int len)
-{
-}
-
-void null_ready_output(ErlDrvData drv_data, ErlDrvEvent event)
-{
-}
-
-struct erl_drv_entry async_driver_entry = {
- async_drv_init,
- async_drv_start,
- async_drv_stop,
- null_output,
- async_drv_input,
- null_ready_output,
- "async",
- NULL, /* finish */
- NULL, /* handle */
- NULL, /* control */
- NULL, /* timeout */
- NULL, /* outputv */
- NULL, /* ready_async */
- NULL, /* flush */
- NULL, /* call */
- NULL, /* event */
- ERL_DRV_EXTENDED_MARKER,
- ERL_DRV_EXTENDED_MAJOR_VERSION,
- ERL_DRV_EXTENDED_MINOR_VERSION,
- 0, /* ERL_DRV_FLAGs */
- NULL,
- NULL, /* process_exit */
- stop_select
-};
-
-#endif
-
/*
* Initialises a DriverData structure.
*
@@ -648,7 +606,7 @@ new_driver_data(int port_num, int packet_bytes, int wait_objs_required, int use_
erts_smp_mtx_unlock(&sys_driver_data_lock);
return NULL;
}
- erts_smp_atomic_add(&sys_misc_mem_sz, dp->inBufSize);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, dp->inBufSize);
dp->outBufSize = 0;
dp->outbuf = NULL;
dp->port_num = port_num;
@@ -733,8 +691,8 @@ release_driver_data(DriverData* dp)
#endif
if (dp->inbuf != NULL) {
- ASSERT(erts_smp_atomic_read(&sys_misc_mem_sz) >= dp->inBufSize);
- erts_smp_atomic_add(&sys_misc_mem_sz, -1*dp->inBufSize);
+ ASSERT(erts_smp_atomic_read_nob(&sys_misc_mem_sz) >= dp->inBufSize);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, -1*dp->inBufSize);
DRV_BUF_FREE(dp->inbuf);
dp->inBufSize = 0;
dp->inbuf = NULL;
@@ -742,8 +700,8 @@ release_driver_data(DriverData* dp)
ASSERT(dp->inBufSize == 0);
if (dp->outbuf != NULL) {
- ASSERT(erts_smp_atomic_read(&sys_misc_mem_sz) >= dp->outBufSize);
- erts_smp_atomic_add(&sys_misc_mem_sz, -1*dp->outBufSize);
+ ASSERT(erts_smp_atomic_read_nob(&sys_misc_mem_sz) >= dp->outBufSize);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, -1*dp->outBufSize);
DRV_BUF_FREE(dp->outbuf);
dp->outBufSize = 0;
dp->outbuf = NULL;
@@ -1162,7 +1120,8 @@ spawn_init(void)
#endif
driver_data = (struct driver_data *)
erts_alloc(ERTS_ALC_T_DRV_TAB, max_files * sizeof(struct driver_data));
- erts_smp_atomic_add(&sys_misc_mem_sz, max_files*sizeof(struct driver_data));
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz,
+ max_files*sizeof(struct driver_data));
for (i = 0; i < max_files; i++)
driver_data[i].port_num = PORT_FREE;
@@ -1675,17 +1634,6 @@ create_child_process
WaitForSingleObject(hProcess, 50);
}
- /*
- * When an application spawns a process repeatedly, a new thread
- * instance will be created for each process but the previous
- * instances may not be cleaned up. This results in a significant
- * virtual memory loss each time the process is spawned. If there
- * is a WaitForInputIdle() call between CreateProcess() and
- * CloseHandle(), the problem does not occur. PSS ID Number: Q124121
- */
-
- WaitForInputIdle(piProcInfo.hProcess, 5000);
-
return ok;
}
@@ -1698,7 +1646,7 @@ create_child_process
static int create_pipe(HANDLE *phRead, HANDLE *phWrite, BOOL inheritRead, BOOL overlapped_io)
{
SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
- char pipe_name[128]; /* Name of pipe. */
+ char pipe_name[256]; /* Name of pipe. */
Uint calls;
/*
@@ -1735,9 +1683,9 @@ static int create_pipe(HANDLE *phRead, HANDLE *phWrite, BOOL inheritRead, BOOL o
* Otherwise, create named pipes.
*/
- calls = (Uint) erts_smp_atomic_inctest(&pipe_creation_counter);
- sprintf(pipe_name, "\\\\.\\pipe\\erlang44_%d_%d",
- getpid(), calls);
+ calls = (UWord) erts_smp_atomic_inc_read_nob(&pipe_creation_counter);
+ erts_snprintf(pipe_name, sizeof(pipe_name),
+ "\\\\.\\pipe\\erlang44_%d_%bpu", getpid(), calls);
DEBUGF(("Creating pipe %s\n", pipe_name));
sa.bInheritHandle = inheritRead;
@@ -2483,13 +2431,13 @@ threaded_exiter(LPVOID param)
*/
static void
-output(ErlDrvData drv_data, char* buf, int len)
+output(ErlDrvData drv_data, char* buf, ErlDrvSizeT len)
/* long drv_data; /* The slot to use in the driver data table.
* For Windows NT, this is *NOT* a file handle.
* The handle is found in the driver data.
*/
-/* char *buf; /* Pointer to data to write to the port program. */
-/* int len; /* Number of bytes to write. */
+/* char *buf; /* Pointer to data to write to the port program. */
+/* ErlDrvSizeT len; /* Number of bytes to write. */
{
DriverData* dp;
int pb; /* The header size for this port. */
@@ -2529,7 +2477,7 @@ output(ErlDrvData drv_data, char* buf, int len)
}
dp->outBufSize = pb+len;
- erts_smp_atomic_add(&sys_misc_mem_sz, dp->outBufSize);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, dp->outBufSize);
/*
* Store header bytes (if any).
@@ -2558,8 +2506,8 @@ output(ErlDrvData drv_data, char* buf, int len)
} else {
dp->out.ov.Offset += pb+len; /* For vanilla driver. */
/* XXX OffsetHigh should be changed too. */
- ASSERT(erts_smp_atomic_read(&sys_misc_mem_sz) >= dp->outBufSize);
- erts_smp_atomic_add(&sys_misc_mem_sz, -1*dp->outBufSize);
+ ASSERT(erts_smp_atomic_read_nob(&sys_misc_mem_sz) >= dp->outBufSize);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, -1*dp->outBufSize);
DRV_BUF_FREE(dp->outbuf);
dp->outBufSize = 0;
dp->outbuf = NULL;
@@ -2673,9 +2621,9 @@ ready_input(ErlDrvData drv_data, ErlDrvEvent ready_event)
error = ERROR_NOT_ENOUGH_MEMORY;
break; /* Break out of loop into error handler. */
}
- ASSERT(erts_smp_atomic_read(&sys_misc_mem_sz) >= dp->inBufSize);
- erts_smp_atomic_add(&sys_misc_mem_sz,
- dp->totalNeeded - dp->inBufSize);
+ ASSERT(erts_smp_atomic_read_nob(&sys_misc_mem_sz) >= dp->inBufSize);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz,
+ dp->totalNeeded - dp->inBufSize);
dp->inBufSize = dp->totalNeeded;
dp->inbuf = new_buf;
}
@@ -2771,12 +2719,12 @@ ready_output(ErlDrvData drv_data, ErlDrvEvent ready_event)
DEBUGF(("ready_output(%d, 0x%x)\n", drv_data, ready_event));
set_busy_port(dp->port_num, 0);
if (!(dp->outbuf)) {
- /* Happens because event sometimes get signalled during a succesful
+ /* Happens because event sometimes get signalled during a successful
write... */
return;
}
- ASSERT(erts_smp_atomic_read(&sys_misc_mem_sz) >= dp->outBufSize);
- erts_smp_atomic_add(&sys_misc_mem_sz, -1*dp->outBufSize);
+ ASSERT(erts_smp_atomic_read_nob(&sys_misc_mem_sz) >= dp->outBufSize);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, -1*dp->outBufSize);
DRV_BUF_FREE(dp->outbuf);
dp->outBufSize = 0;
dp->outbuf = NULL;
@@ -2824,30 +2772,6 @@ sys_init_io(void)
We estimate the number to twice the amount of ports.
We really dont know on windows, do we? */
max_files = 2*erts_max_ports;
-
-#ifdef USE_THREADS
-#ifdef ERTS_SMP
- if (init_async(-1) < 0)
- erl_exit(1, "Failed to initialize async-threads\n");
-#else
- {
- /* This is special stuff, starting a driver from the
- * system routines, but is a nice way of handling stuff
- * the erlang way
- */
- SysDriverOpts dopts;
- int ret;
-
- sys_memset((void*)&dopts, 0, sizeof(SysDriverOpts));
- add_driver_entry(&async_driver_entry);
- ret = erts_open_driver(NULL, NIL, "async", &dopts, NULL);
- DEBUGF(("open_driver = %d\n", ret));
- if (ret < 0)
- erl_exit(1, "Failed to open async driver\n");
- erts_port[ret].status |= ERTS_PORT_SFLG_IMMORTAL;
- }
-#endif
-#endif
}
#ifdef ERTS_SMP
@@ -2926,8 +2850,8 @@ Preload* sys_preloaded(void)
(num_preloaded+1)*sizeof(Preload));
res_name = erts_alloc(ERTS_ALC_T_PRELOADED,
(num_preloaded+1)*sizeof(unsigned));
- erts_smp_atomic_add(&sys_misc_mem_sz,
- (num_preloaded+1)*sizeof(Preload)
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz,
+ (num_preloaded+1)*sizeof(Preload)
+ (num_preloaded+1)*sizeof(unsigned));
for (i = 0; i < num_preloaded; i++) {
int n;
@@ -2939,7 +2863,7 @@ Preload* sys_preloaded(void)
n = GETWORD(data);
data += 2;
preloaded[i].name = erts_alloc(ERTS_ALC_T_PRELOADED, n+1);
- erts_smp_atomic_add(&sys_misc_mem_sz, n+1);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, n+1);
sys_memcpy(preloaded[i].name, data, n);
preloaded[i].name[n] = '\0';
data += n;
@@ -3281,7 +3205,7 @@ erts_sys_pre_init(void)
#endif
}
#endif
- erts_smp_atomic_init(&sys_misc_mem_sz, 0);
+ erts_smp_atomic_init_nob(&sys_misc_mem_sz, 0);
}
void noinherit_std_handle(DWORD type)
@@ -3297,8 +3221,6 @@ void erl_sys_init(void)
{
HANDLE handle;
- erts_sys_env_init();
-
noinherit_std_handle(STD_OUTPUT_HANDLE);
noinherit_std_handle(STD_INPUT_HANDLE);
noinherit_std_handle(STD_ERROR_HANDLE);
@@ -3310,7 +3232,7 @@ void erl_sys_init(void)
erts_smp_tsd_key_create(&win32_errstr_key);
InitializeCriticalSection(&htbc_lock);
#endif
- erts_smp_atomic_init(&pipe_creation_counter,0);
+ erts_smp_atomic_init_nob(&pipe_creation_counter,0);
/*
* Test if we have named pipes or not.
*/
@@ -3360,15 +3282,15 @@ void erl_sys_init(void)
SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
}
-#ifdef ERTS_SMP
void
erts_sys_schedule_interrupt(int set)
{
erts_check_io_interrupt(set);
}
+#ifdef ERTS_SMP
void
-erts_sys_schedule_interrupt_timed(int set, long msec)
+erts_sys_schedule_interrupt_timed(int set, erts_short_time_t msec)
{
erts_check_io_interrupt_timed(set, msec);
}
@@ -3382,76 +3304,7 @@ erts_sys_schedule_interrupt_timed(int set, long msec)
void
erl_sys_schedule(int runnable)
{
-#ifdef ERTS_SMP
erts_check_io(!runnable);
- ERTS_SMP_LC_ASSERT(!ERTS_LC_IS_BLOCKING);
-#else
- erts_check_io_interrupt(0);
- if (runnable) {
- erts_check_io(0); /* Poll for I/O */
- check_async_ready(); /* Check async completions */
- } else {
- erts_check_io(check_async_ready() ? 0 : 1);
- }
-#endif
-}
-
-#if defined(USE_THREADS) && !defined(ERTS_SMP)
-/*
- * Async operation support.
- */
-
-static ErlDrvEvent async_drv_event;
-
-void
-sys_async_ready(int fd)
-{
- SetEvent((HANDLE)async_drv_event);
-}
-
-static int
-async_drv_init(void)
-{
- async_drv_event = (ErlDrvEvent) NULL;
- return 0;
-}
-
-static ErlDrvData
-async_drv_start(ErlDrvPort port_num, char* name, SysDriverOpts* opts)
-{
- if (async_drv_event != (ErlDrvEvent) NULL) {
- return ERL_DRV_ERROR_GENERAL;
- }
- if ((async_drv_event = (ErlDrvEvent)CreateAutoEvent(FALSE)) == (ErlDrvEvent) NULL) {
- return ERL_DRV_ERROR_GENERAL;
- }
-
- driver_select(port_num, async_drv_event, ERL_DRV_READ|ERL_DRV_USE, 1);
- if (init_async(async_drv_event) < 0) {
- return ERL_DRV_ERROR_GENERAL;
- }
- return (ErlDrvData)port_num;
+ ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking());
}
-static void
-async_drv_stop(ErlDrvData port_num)
-{
- exit_async();
- driver_select((ErlDrvPort)port_num, async_drv_event, ERL_DRV_READ|ERL_DRV_USE, 0);
- /*CloseHandle((HANDLE)async_drv_event);*/
- async_drv_event = (ErlDrvEvent) NULL;
-}
-
-
-static void
-async_drv_input(ErlDrvData port_num, ErlDrvEvent e)
-{
- check_async_ready();
-
- /*
- * Our event is auto-resetting.
- */
-}
-
-#endif
-
diff --git a/erts/emulator/sys/win32/sys_env.c b/erts/emulator/sys/win32/sys_env.c
index 02c8433a10..064745d418 100644
--- a/erts/emulator/sys/win32/sys_env.c
+++ b/erts/emulator/sys/win32/sys_env.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -55,19 +55,17 @@ erts_sys_putenv(char *key_value, int sep_ix)
}
int
-erts_sys_getenv(char *key, char *value, size_t *size)
+erts_sys_getenv__(char *key, char *value, size_t *size)
{
size_t req_size = 0;
int res = 0;
DWORD new_size;
- erts_smp_rwmtx_rlock(&environ_rwmtx);
SetLastError(0);
new_size = GetEnvironmentVariable((LPCTSTR) key,
(LPTSTR) value,
(DWORD) *size);
res = !new_size && GetLastError() == ERROR_ENVVAR_NOT_FOUND ? -1 : 0;
- erts_smp_rwmtx_runlock(&environ_rwmtx);
if (res < 0)
return res;
res = new_size > *size ? 1 : 0;
@@ -75,6 +73,16 @@ erts_sys_getenv(char *key, char *value, size_t *size)
return res;
}
+int
+erts_sys_getenv(char *key, char *value, size_t *size)
+{
+ int res;
+ erts_smp_rwmtx_rlock(&environ_rwmtx);
+ res = erts_sys_getenv__(key, value, size);
+ erts_smp_rwmtx_runlock(&environ_rwmtx);
+ return res;
+}
+
struct win32_getenv_state {
char *env;
char *next;
diff --git a/erts/emulator/sys/win32/sys_float.c b/erts/emulator/sys/win32/sys_float.c
index 9e67ca7f48..6558ad2d99 100644
--- a/erts/emulator/sys/win32/sys_float.c
+++ b/erts/emulator/sys/win32/sys_float.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1997-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -18,6 +18,9 @@
*/
/* Float conversions */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
#include "sys.h"
#include "signal.h"
diff --git a/erts/emulator/sys/win32/sys_interrupt.c b/erts/emulator/sys/win32/sys_interrupt.c
index 943c338794..347c31053b 100644
--- a/erts/emulator/sys/win32/sys_interrupt.c
+++ b/erts/emulator/sys/win32/sys_interrupt.c
@@ -19,8 +19,12 @@
/*
* Purpose: Interrupt handling in windows.
*/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
#include "sys.h"
#include "erl_alloc.h"
+#include "erl_thr_progress.h"
#include "erl_driver.h"
#include "../../drivers/win32/win_con.h"
@@ -33,9 +37,9 @@
#ifdef ERTS_SMP
erts_smp_atomic32_t erts_break_requested;
#define ERTS_SET_BREAK_REQUESTED \
- erts_smp_atomic32_set(&erts_break_requested, (erts_aint32_t) 1)
+ erts_smp_atomic32_set_nob(&erts_break_requested, (erts_aint32_t) 1)
#define ERTS_UNSET_BREAK_REQUESTED \
- erts_smp_atomic32_set(&erts_break_requested, (erts_aint32_t) 0)
+ erts_smp_atomic32_set_nob(&erts_break_requested, (erts_aint32_t) 0)
#else
volatile int erts_break_requested = 0;
#define ERTS_SET_BREAK_REQUESTED (erts_break_requested = 1)
@@ -52,14 +56,14 @@ void erts_do_break_handling(void)
* therefore, make sure that all threads but this one are blocked before
* proceeding!
*/
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
/* call the break handling function, reset the flag */
do_break();
ResetEvent(erts_sys_break_event);
ERTS_UNSET_BREAK_REQUESTED;
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
}
diff --git a/erts/emulator/sys/win32/sys_time.c b/erts/emulator/sys/win32/sys_time.c
index 50e43065b5..b5123dc45d 100644
--- a/erts/emulator/sys/win32/sys_time.c
+++ b/erts/emulator/sys/win32/sys_time.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1997-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -20,6 +20,9 @@
* Purpose: System-dependent time functions.
*/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
#include "sys.h"
#include "assert.h"
@@ -32,28 +35,336 @@
/******************* Routines for time measurement *********************/
#define EPOCH_JULIAN_DIFF LL_LITERAL(11644473600)
+#define TICKS_PER_SECOND LL_LITERAL(10000000)
+#define SECONDS_PER_DAY LL_LITERAL(86400)
+
+#define ULI_TO_FILETIME(ft,ull) \
+ do { \
+ (ft).dwLowDateTime = (ull).LowPart; \
+ (ft).dwHighDateTime = (ull).HighPart; \
+ } while (0)
+
+#define FILETIME_TO_ULI(ull,ft) \
+ do { \
+ (ull).LowPart = (ft).dwLowDateTime; \
+ (ull).HighPart = (ft).dwHighDateTime; \
+ } while (0)
+
+#define EPOCH_TO_FILETIME(ft, epoch) \
+ do { \
+ ULARGE_INTEGER ull; \
+ ull.QuadPart = (((epoch) + EPOCH_JULIAN_DIFF) * TICKS_PER_SECOND); \
+ ULI_TO_FILETIME(ft,ull); \
+ } while(0)
+
+#define FILETIME_TO_EPOCH(epoch, ft) \
+ do { \
+ ULARGE_INTEGER ull; \
+ FILETIME_TO_ULI(ull,ft); \
+ (epoch) = ((ull.QuadPart / TICKS_PER_SECOND) - EPOCH_JULIAN_DIFF); \
+ } while(0)
+
static SysHrTime wrap = 0;
static DWORD last_tick_count = 0;
+/* Getting timezone information is a heavy operation, so we want to do this
+ only once */
+
+static TIME_ZONE_INFORMATION static_tzi;
+static int have_static_tzi = 0;
+
+static int days_in_month[2][13] = {
+ {0,31,28,31,30,31,30,31,31,30,31,30,31},
+ {0,31,29,31,30,31,30,31,31,30,31,30,31}};
+
int
sys_init_time(void)
{
+ if(GetTimeZoneInformation(&static_tzi) &&
+ static_tzi.StandardDate.wMonth != 0 &&
+ static_tzi.DaylightDate.wMonth != 0) {
+ have_static_tzi = 1;
+ }
return 1;
}
+/* Returns a switchtimes for DST as UTC filetimes given data from a
+ TIME_ZONE_INFORMATION, see sys_localtime_r for usage. */
+static void
+get_dst_switchtime(DWORD year,
+ SYSTEMTIME dstinfo, LONG bias,
+ FILETIME *utc_switchtime)
+{
+ DWORD occu;
+ DWORD weekday,wday_1st;
+ DWORD day, days_in;
+ FILETIME tmp,tmp2;
+ ULARGE_INTEGER ull;
+ int leap_year = 0;
+ if (dstinfo.wYear != 0) {
+ /* A year specific transition, in which case the data in the structure
+ is already properly set for a specific year. Compare year
+ with parameter and see if they correspond, in that case generate a
+ filetime directly, otherwise set the filetime to 0 */
+ if (year != dstinfo.wYear) {
+ utc_switchtime->dwLowDateTime = utc_switchtime->dwHighDateTime = 0;
+ return;
+ }
+ } else {
+ occu = dstinfo.wDay;
+ weekday = dstinfo.wDayOfWeek;
+
+ dstinfo.wDayOfWeek = 0;
+ dstinfo.wDay = 1;
+ dstinfo.wYear = year;
+
+ SystemTimeToFileTime(&dstinfo,&tmp);
+ ull.LowPart = tmp.dwLowDateTime;
+ ull.HighPart = tmp.dwHighDateTime;
+
+ ull.QuadPart /= (TICKS_PER_SECOND*SECONDS_PER_DAY); /* Julian Day */
+ wday_1st = (DWORD) ((ull.QuadPart + LL_LITERAL(1)) % LL_LITERAL(7));
+ day = (weekday >= wday_1st) ?
+ weekday - wday_1st + 1 :
+ weekday - wday_1st + 8;
+ --occu;
+ if (((dstinfo.wYear % 4) == 0 && (dstinfo.wYear % 100) > 0) ||
+ ((dstinfo.wYear % 400) == 0)) {
+ leap_year = 1;
+ }
+ days_in = days_in_month[leap_year][dstinfo.wMonth];
+ while (occu > 0 && (day + 7 <= days_in)) {
+ --occu;
+ day += 7;
+ }
+ dstinfo.wDay = day;
+ }
+ SystemTimeToFileTime(&dstinfo,&tmp);
+ /* correct for bias */
+ ull.LowPart = tmp.dwLowDateTime;
+ ull.HighPart = tmp.dwHighDateTime;
+ ull.QuadPart += (((LONGLONG) bias) * LL_LITERAL(60) * TICKS_PER_SECOND);
+ utc_switchtime->dwLowDateTime = ull.LowPart;
+ utc_switchtime->dwHighDateTime = ull.HighPart;
+ return;
+}
+
+/* This function gives approximately the correct year from a FILETIME
+ Around the actual new year, it may return the wrong value, but that's OK
+ as DST never switches around new year. */
+static DWORD
+approx_year(FILETIME ft)
+{
+ ULARGE_INTEGER ull;
+ FILETIME_TO_ULI(ull,ft);
+ ull.QuadPart /= LL_LITERAL(1000);
+ ull.QuadPart /= SECONDS_PER_DAY;
+ ull.QuadPart /= LL_LITERAL(3652425);
+ ull.QuadPart += 1601;
+ return (DWORD) ull.QuadPart;
+}
+
+struct tm *
+sys_localtime_r(time_t *epochs, struct tm *ptm)
+{
+ FILETIME ft,lft;
+ SYSTEMTIME st;
+
+ if ((((*epochs) + EPOCH_JULIAN_DIFF) * TICKS_PER_SECOND) < 0LL) {
+ fprintf(stderr,"1\r\n"); fflush(stderr);
+ return NULL;
+ }
+
+ EPOCH_TO_FILETIME(ft,*epochs);
+ ptm->tm_isdst = 0;
+ if (have_static_tzi) {
+ FILETIME dst_start, dst_stop;
+ ULARGE_INTEGER ull;
+ DWORD year = approx_year(ft);
+ get_dst_switchtime(year,static_tzi.DaylightDate,
+ static_tzi.Bias+static_tzi.StandardBias,&dst_start);
+ get_dst_switchtime(year,static_tzi.StandardDate,
+ static_tzi.Bias+static_tzi.StandardBias+
+ static_tzi.DaylightBias,
+ &dst_stop);
+ FILETIME_TO_ULI(ull,ft);
+
+ if (CompareFileTime(&ft,&dst_start) >= 0 &&
+ CompareFileTime(&ft,&dst_stop) < 0) {
+ ull.QuadPart -=
+ ((LONGLONG) static_tzi.Bias+static_tzi.StandardBias+
+ static_tzi.DaylightBias) *
+ LL_LITERAL(60) * TICKS_PER_SECOND;
+ ptm->tm_isdst = 1;
+ } else {
+ ull.QuadPart -=
+ ((LONGLONG) static_tzi.Bias+static_tzi.StandardBias)
+ * LL_LITERAL(60) * TICKS_PER_SECOND;
+ }
+ ULI_TO_FILETIME(ft,ull);
+ } else {
+ if (!FileTimeToLocalFileTime(&ft,&lft)) {
+ return NULL;
+ }
+ ft = lft;
+ }
+
+ if (!FileTimeToSystemTime(&ft,&st)) {
+ return NULL;
+ }
+
+ ptm->tm_year = (int) st.wYear - 1900;
+ ptm->tm_mon = (int) st.wMonth - 1;
+ ptm->tm_mday = (int) st.wDay;
+ ptm->tm_hour = (int) st.wHour;
+ ptm->tm_min = (int) st.wMinute;
+ ptm->tm_sec = (int) st.wSecond;
+ ptm->tm_wday = (int) st.wDayOfWeek;
+ {
+ int yday = ptm->tm_mday - 1;
+ int m = ptm->tm_mon;
+ int leap_year = 0;
+ if (((st.wYear % 4) == 0 && (st.wYear % 100) > 0) ||
+ ((st.wYear % 400) == 0)) {
+ leap_year = 1;
+ }
+ while (m > 0) {
+ yday +=days_in_month[leap_year][m];
+ --m;
+ }
+ ptm->tm_yday = yday;
+ }
+ return ptm;
+}
+
+struct tm *
+sys_gmtime_r(time_t *epochs, struct tm *ptm)
+{
+ FILETIME ft;
+ SYSTEMTIME st;
+
+ if ((((*epochs) + EPOCH_JULIAN_DIFF) * TICKS_PER_SECOND) < 0LL) {
+ return NULL;
+ }
+
+ EPOCH_TO_FILETIME(ft,*epochs);
+
+ if (!FileTimeToSystemTime(&ft,&st)) {
+ return NULL;
+ }
+
+ ptm->tm_year = (int) st.wYear - 1900;
+ ptm->tm_mon = (int) st.wMonth - 1;
+ ptm->tm_mday = (int) st.wDay;
+ ptm->tm_hour = (int) st.wHour;
+ ptm->tm_min = (int) st.wMinute;
+ ptm->tm_sec = (int) st.wSecond;
+ ptm->tm_wday = (int) st.wDayOfWeek;
+ ptm->tm_isdst = 0;
+ {
+ int yday = ptm->tm_mday - 1;
+ int m = ptm->tm_mon;
+ int leap_year = 0;
+ if (((st.wYear % 4) == 0 && (st.wYear % 100) > 0) ||
+ ((st.wYear % 400) == 0)) {
+ leap_year = 1;
+ }
+ while (m > 0) {
+ yday +=days_in_month[leap_year][m];
+ --m;
+ }
+ ptm->tm_yday = yday;
+ }
+
+ return ptm;
+}
+
+time_t
+sys_mktime(struct tm *ptm)
+{
+ FILETIME ft;
+ SYSTEMTIME st;
+ int dst = 0;
+ time_t epochs;
+
+ memset(&st,0,sizeof(st));
+ /* Convert relevant parts of truct tm to SYSTEMTIME */
+ st.wYear = (USHORT) (ptm->tm_year + 1900);
+ st.wMonth = (USHORT) (ptm->tm_mon + 1);
+ st.wDay = (USHORT) ptm->tm_mday;
+ st.wHour = (USHORT) ptm->tm_hour;
+ st.wMinute = (USHORT) ptm->tm_min;
+ st.wSecond = (USHORT) ptm->tm_sec;
+
+ SystemTimeToFileTime(&st,&ft);
+
+ /* ft is now some kind of local file time, but it may be wrong depending
+ on what is in the tm_dst field. We need to manually convert it to
+ UTC before turning it into epochs */
+
+ if (have_static_tzi) {
+ FILETIME dst_start, dst_stop;
+ ULARGE_INTEGER ull_start,ull_stop,ull_ft;
+
+ FILETIME_TO_ULI(ull_ft,ft);
+
+ /* Correct everything except DST */
+ ull_ft.QuadPart += (static_tzi.Bias+static_tzi.StandardBias)
+ * LL_LITERAL(60) * TICKS_PER_SECOND;
+
+ /* Determine if DST is active */
+ if (ptm->tm_isdst >= 0) {
+ dst = ptm->tm_isdst;
+ } else if (static_tzi.DaylightDate.wMonth != 0){
+ /* This is how windows mktime does it, meaning it does not
+ take nonexisting local times into account */
+ get_dst_switchtime(st.wYear,static_tzi.DaylightDate,
+ static_tzi.Bias+static_tzi.StandardBias,
+ &dst_start);
+ get_dst_switchtime(st.wYear,static_tzi.StandardDate,
+ static_tzi.Bias+static_tzi.StandardBias+
+ static_tzi.DaylightBias,
+ &dst_stop);
+ FILETIME_TO_ULI(ull_start,dst_start);
+ FILETIME_TO_ULI(ull_stop,dst_stop);
+ if ((ull_ft.QuadPart >= ull_start.QuadPart) &&
+ (ull_ft.QuadPart < ull_stop.QuadPart)) {
+ /* We are in DST */
+ dst = 1;
+ }
+ }
+ /* Correct for DST */
+ if (dst) {
+ ull_ft.QuadPart += static_tzi.DaylightBias *
+ LL_LITERAL(60) * TICKS_PER_SECOND;
+ }
+ epochs = ((ull_ft.QuadPart / TICKS_PER_SECOND) - EPOCH_JULIAN_DIFF);
+ } else {
+ /* No DST, life is easy... */
+ FILETIME lft;
+ LocalFileTimeToFileTime(&ft,&lft);
+ FILETIME_TO_EPOCH(epochs,lft);
+ }
+ /* Normalize the struct tm */
+ sys_localtime_r(&epochs,ptm);
+ return epochs;
+}
+
void
sys_gettimeofday(SysTimeval *tv)
{
SYSTEMTIME t;
FILETIME ft;
- LONGLONG lft;
+ ULARGE_INTEGER ull;
GetSystemTime(&t);
SystemTimeToFileTime(&t, &ft);
- memcpy(&lft, &ft, sizeof(lft));
- tv->tv_usec = (long) ((lft / LL_LITERAL(10)) % LL_LITERAL(1000000));
- tv->tv_sec = (long) ((lft / LL_LITERAL(10000000)) - EPOCH_JULIAN_DIFF);
+ FILETIME_TO_ULI(ull,ft);
+ tv->tv_usec = (long) ((ull.QuadPart / LL_LITERAL(10)) %
+ LL_LITERAL(1000000));
+ tv->tv_sec = (long) ((ull.QuadPart / LL_LITERAL(10000000)) -
+ EPOCH_JULIAN_DIFF);
}
SysHrTime
@@ -88,9 +399,3 @@ sys_times(SysTimes *buffer) {
buffer->tms_stime = (clock_t) (system & LL_LITERAL(0x7FFFFFFF));
return kernel_ticks;
}
-
-
-
-
-
-