aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/sys
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/sys')
-rw-r--r--erts/emulator/sys/unix/sys.c29
-rw-r--r--erts/emulator/sys/vxworks/sys.c4
-rw-r--r--erts/emulator/sys/win32/erl_win_dyn_driver.h36
-rw-r--r--erts/emulator/sys/win32/erl_win_sys.h10
-rwxr-xr-xerts/emulator/sys/win32/sys.c8
-rw-r--r--erts/emulator/sys/win32/sys_time.c322
6 files changed, 362 insertions, 47 deletions
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index 52477467b3..f94e0f2296 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -1033,14 +1033,15 @@ static struct driver_data {
/* Driver interfaces */
static ErlDrvData spawn_start(ErlDrvPort, char*, SysDriverOpts*);
static ErlDrvData fd_start(ErlDrvPort, char*, SysDriverOpts*);
-static int fd_control(ErlDrvData, unsigned int, char *, int, char **, int);
+static ErlDrvSSizeT fd_control(ErlDrvData, unsigned int, char *, ErlDrvSizeT,
+ char **, ErlDrvSizeT);
static ErlDrvData vanilla_start(ErlDrvPort, char*, SysDriverOpts*);
static int spawn_init(void);
static void fd_stop(ErlDrvData);
static void stop(ErlDrvData);
static void ready_input(ErlDrvData, ErlDrvEvent);
static void ready_output(ErlDrvData, ErlDrvEvent);
-static void output(ErlDrvData, char*, int);
+static void output(ErlDrvData, char*, ErlDrvSizeT);
static void outputv(ErlDrvData, ErlIOVec*);
static void stop_select(ErlDrvEvent, void*);
@@ -1726,10 +1727,10 @@ static int fd_get_window_size(int fd, Uint32 *width, Uint32 *height)
return -1;
}
-static int fd_control(ErlDrvData drv_data,
- unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen)
+static ErlDrvSSizeT fd_control(ErlDrvData drv_data,
+ unsigned int command,
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen)
{
int fd = (int)(long)drv_data;
char resbuff[2*sizeof(Uint32)];
@@ -2001,18 +2002,20 @@ static void outputv(ErlDrvData e, ErlIOVec* ev)
int ix = driver_data[fd].port_num;
int pb = driver_data[fd].packet_bytes;
int ofd = driver_data[fd].ofd;
- int n;
- int sz;
+ ssize_t n;
+ ErlDrvSizeT sz;
char lb[4];
char* lbp;
- int len = ev->size;
+ ErlDrvSizeT len = ev->size;
/* (len > ((unsigned long)-1 >> (4-pb)*8)) */
+ /* if (pb >= 0 && (len & (((ErlDrvSizeT)1 << (pb*8))) - 1) != len) {*/
if (((pb == 2) && (len > 0xffff)) || (pb == 1 && len > 0xff)) {
driver_failure_posix(ix, EINVAL);
return; /* -1; */
}
- put_int32(len, lb);
+ /* Handles 0 <= pb <= 4 only */
+ put_int32((Uint32) len, lb);
lbp = lb + (4-pb);
ev->iov[0].iov_base = lbp;
@@ -2043,14 +2046,14 @@ static void outputv(ErlDrvData e, ErlIOVec* ev)
}
-static void output(ErlDrvData e, char* buf, int len)
+static void output(ErlDrvData e, char* buf, ErlDrvSizeT len)
{
int fd = (int)(long)e;
int ix = driver_data[fd].port_num;
int pb = driver_data[fd].packet_bytes;
int ofd = driver_data[fd].ofd;
- int n;
- int sz;
+ ssize_t n;
+ ErlDrvSizeT sz;
char lb[4];
char* lbp;
struct iovec iv[2];
diff --git a/erts/emulator/sys/vxworks/sys.c b/erts/emulator/sys/vxworks/sys.c
index d6d1fe64e0..739b026fb1 100644
--- a/erts/emulator/sys/vxworks/sys.c
+++ b/erts/emulator/sys/vxworks/sys.c
@@ -565,7 +565,7 @@ static void fd_stop(ErlDrvData);
static void stop(ErlDrvData);
static void ready_input(ErlDrvData fd, ErlDrvEvent ready_fd);
static void ready_output(ErlDrvData fd, ErlDrvEvent ready_fd);
-static void output(ErlDrvData fd, char *buf, int len);
+static void output(ErlDrvData fd, char *buf, ErlDrvSizeT len);
static void stop_select(ErlDrvEvent, void*);
struct erl_drv_entry spawn_driver_entry = {
@@ -1187,7 +1187,7 @@ static int sched_write(int port_num,int fd, char *buf, int len, int pb)
}
/* Fd is the value returned as drv_data by the start func */
-static void output(ErlDrvData drv_data, char *buf, int len)
+static void output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len)
{
int buf_done, port_num, wval, pb, ofd;
byte lb[4];
diff --git a/erts/emulator/sys/win32/erl_win_dyn_driver.h b/erts/emulator/sys/win32/erl_win_dyn_driver.h
index afc72bb898..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*));
diff --git a/erts/emulator/sys/win32/erl_win_sys.h b/erts/emulator/sys/win32/erl_win_sys.h
index cf3fb4446f..e8453205ea 100644
--- a/erts/emulator/sys/win32/erl_win_sys.h
+++ b/erts/emulator/sys/win32/erl_win_sys.h
@@ -128,6 +128,16 @@ int erts_check_io_debug(void);
*/
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 {
erts_time_t tv_sec;
erts_time_t tv_usec;
diff --git a/erts/emulator/sys/win32/sys.c b/erts/emulator/sys/win32/sys.c
index a701747b78..b106f0932d 100755
--- a/erts/emulator/sys/win32/sys.c
+++ b/erts/emulator/sys/win32/sys.c
@@ -474,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*);
@@ -2431,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. */
diff --git a/erts/emulator/sys/win32/sys_time.c b/erts/emulator/sys/win32/sys_time.c
index e5b9513edc..6362c1a06d 100644
--- a/erts/emulator/sys/win32/sys_time.c
+++ b/erts/emulator/sys/win32/sys_time.c
@@ -35,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 = (erts_time_t) ((lft / LL_LITERAL(10)) % LL_LITERAL(1000000));
- tv->tv_sec = (erts_time_t) ((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
@@ -91,9 +399,3 @@ sys_times(SysTimes *buffer) {
buffer->tms_stime = (clock_t) (system & LL_LITERAL(0x7FFFFFFF));
return kernel_ticks;
}
-
-
-
-
-
-