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.c2
-rw-r--r--erts/emulator/sys/win32/erl_win32_sys_ddll.c32
-rw-r--r--erts/emulator/sys/win32/erl_win_dyn_driver.h8
-rw-r--r--erts/emulator/sys/win32/erl_win_sys.h31
-rw-r--r--[-rwxr-xr-x]erts/emulator/sys/win32/sys.c470
-rw-r--r--erts/emulator/sys/win32/sys_env.c18
-rw-r--r--erts/emulator/sys/win32/sys_float.c8
-rw-r--r--erts/emulator/sys/win32/sys_time.c50
8 files changed, 288 insertions, 331 deletions
diff --git a/erts/emulator/sys/win32/erl_poll.c b/erts/emulator/sys/win32/erl_poll.c
index 7a1d129cd5..972170d465 100644
--- a/erts/emulator/sys/win32/erl_poll.c
+++ b/erts/emulator/sys/win32/erl_poll.c
@@ -1085,7 +1085,7 @@ void erts_poll_controlv(ErtsPollSet ps,
pcev[i].events,
pcev[i].on);
}
- ERTS_POLLSET_LOCK(ps);
+ ERTS_POLLSET_UNLOCK(ps);
HARDTRACEF(("Out erts_poll_controlv"));
}
diff --git a/erts/emulator/sys/win32/erl_win32_sys_ddll.c b/erts/emulator/sys/win32/erl_win32_sys_ddll.c
index 4c8d83ab16..338f0d7386 100644
--- a/erts/emulator/sys/win32/erl_win32_sys_ddll.c
+++ b/erts/emulator/sys/win32/erl_win32_sys_ddll.c
@@ -38,7 +38,7 @@
#include "erl_nif.h"
#define EXT_LEN 4
-#define FILE_EXT ".dll"
+#define FILE_EXT_WCHAR L".dll"
static DWORD tls_index = 0;
static TWinDynDriverCallbacks wddc;
@@ -57,11 +57,15 @@ void erl_sys_ddll_init(void) {
/*
* Open a shared object
+ * Expecting 'full_name' as an UTF-8 string.
*/
-int erts_sys_ddll_open2(const char *full_name, void **handle, ErtsSysDdllError* err)
+int erts_sys_ddll_open(const char *full_name, void **handle, ErtsSysDdllError* err)
{
+ HINSTANCE hinstance;
int len;
- char dlname[MAXPATHLEN + 1];
+ wchar_t* wcp;
+ Sint used;
+ int code;
if ((len = sys_strlen(full_name)) >= MAXPATHLEN - EXT_LEN) {
if (err != NULL) {
@@ -69,10 +73,26 @@ int erts_sys_ddll_open2(const char *full_name, void **handle, ErtsSysDdllError*
}
return ERL_DE_LOAD_ERROR_NAME_TO_LONG;
}
- sys_strcpy(dlname, full_name);
- sys_strcpy(dlname+len, FILE_EXT);
- return erts_sys_ddll_open_noext(dlname, handle, err);
+
+ wcp = (wchar_t*)erts_convert_filename_to_wchar((byte*)full_name, len,
+ NULL, 0,
+ ERTS_ALC_T_TMP, &used, EXT_LEN);
+ wcscpy(&wcp[used/2 - 1], FILE_EXT_WCHAR);
+
+ if ((hinstance = LoadLibraryW(wcp)) == NULL) {
+ code = ERL_DE_DYNAMIC_ERROR_OFFSET - GetLastError();
+ if (err != NULL) {
+ err->str = erts_sys_ddll_error(code);
+ }
+ }
+ else {
+ code = ERL_DE_NO_ERROR;
+ *handle = (void *) hinstance;
+ }
+ erts_free(ERTS_ALC_T_TMP, wcp);
+ return code;
}
+
int erts_sys_ddll_open_noext(char *dlname, void **handle, ErtsSysDdllError* err)
{
HINSTANCE hinstance;
diff --git a/erts/emulator/sys/win32/erl_win_dyn_driver.h b/erts/emulator/sys/win32/erl_win_dyn_driver.h
index a7c53c904d..4010d939e5 100644
--- a/erts/emulator/sys/win32/erl_win_dyn_driver.h
+++ b/erts/emulator/sys/win32/erl_win_dyn_driver.h
@@ -80,8 +80,8 @@ WDD_TYPEDEF(int, erl_drv_output_term, (ErlDrvTermData, ErlDrvTermData*, int));
WDD_TYPEDEF(int, driver_output_term, (ErlDrvPort, ErlDrvTermData*, int));
WDD_TYPEDEF(int, erl_drv_send_term, (ErlDrvTermData, ErlDrvTermData, ErlDrvTermData*, int));
WDD_TYPEDEF(int, driver_send_term, (ErlDrvPort, ErlDrvTermData, ErlDrvTermData*, int));
+WDD_TYPEDEF(unsigned int, driver_async_port_key, (ErlDrvPort));
WDD_TYPEDEF(long, driver_async, (ErlDrvPort,unsigned int*,void (*)(void*),void*,void (*)(void*)));
-WDD_TYPEDEF(int, driver_async_cancel, (unsigned int));
WDD_TYPEDEF(int, driver_lock_driver, (ErlDrvPort));
WDD_TYPEDEF(void *, driver_dl_open, (char *));
WDD_TYPEDEF(void *, driver_dl_sym, (void *, char *));
@@ -197,8 +197,8 @@ typedef struct {
WDD_FTYPE(driver_output_term) *driver_output_term;
WDD_FTYPE(erl_drv_send_term) *erl_drv_send_term;
WDD_FTYPE(driver_send_term) *driver_send_term;
+ WDD_FTYPE(driver_async_port_key) *driver_async_port_key;
WDD_FTYPE(driver_async) *driver_async;
- WDD_FTYPE(driver_async_cancel) *driver_async_cancel;
WDD_FTYPE(driver_lock_driver) *driver_lock_driver;
WDD_FTYPE(driver_dl_open) *driver_dl_open;
WDD_FTYPE(driver_dl_sym) *driver_dl_sym;
@@ -308,8 +308,8 @@ extern TWinDynDriverCallbacks WinDynDriverCallbacks;
#define driver_output_term (WinDynDriverCallbacks.driver_output_term)
#define erl_drv_send_term (WinDynDriverCallbacks.erl_drv_send_term)
#define driver_send_term (WinDynDriverCallbacks.driver_send_term)
+#define driver_async_port_key (WinDynDriverCallbacks.driver_async_port_key)
#define driver_async (WinDynDriverCallbacks.driver_async)
-#define driver_async_cancel (WinDynDriverCallbacks.driver_async_cancel)
#define driver_lock_driver (WinDynDriverCallbacks.driver_lock_driver)
#define driver_dl_open (WinDynDriverCallbacks.driver_dl_open)
#define driver_dl_sym (WinDynDriverCallbacks.driver_dl_sym)
@@ -443,8 +443,8 @@ do { \
((W).driver_output_term) = driver_output_term; \
((W).erl_drv_send_term) = erl_drv_send_term; \
((W).driver_send_term) = driver_send_term; \
+((W).driver_async_port_key) = driver_async_port_key; \
((W).driver_async) = driver_async; \
-((W).driver_async_cancel) = driver_async_cancel; \
((W).driver_lock_driver) = driver_lock_driver; \
((W).driver_dl_open) = driver_dl_open; \
((W).driver_dl_sym) = driver_dl_sym; \
diff --git a/erts/emulator/sys/win32/erl_win_sys.h b/erts/emulator/sys/win32/erl_win_sys.h
index 5ce1a61303..838f0c61eb 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-2012. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2014. 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
@@ -60,16 +60,18 @@
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
-/*
- * Define MAXPATHLEN in terms of MAXPATH if available.
- */
-
-#ifndef MAXPATH
-#define MAXPATH MAX_PATH
-#endif /* MAXPATH */
#ifndef MAXPATHLEN
-#define MAXPATHLEN MAXPATH
+#define MAXPATHLEN 4096
+/*
+ erts-6.0 (OTP 17.0):
+ We now accept windows paths longer than 260 (MAX_PATH) by conversion to
+ UNC path format. In order to also return long paths from the driver we
+ increased MAXPATHLEN from 260 to larger (but arbitrary) value 4096.
+ It would of course be nicer to instead dynamically allocate large enough
+ tmp buffers when efile_drv needs to return really long paths, and do that
+ for unix as well.
+ */
#endif /* MAXPATHLEN */
/*
@@ -82,7 +84,6 @@
#define NO_ERF
#define NO_ERFC
-#define NO_SYSLOG
#define NO_SYSCONF
#define NO_DAEMON
#define NO_PWD
@@ -95,6 +96,8 @@
# define ERTS_I64_LITERAL(X) X##i64
#endif
+#define ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC 1
+
/*
* Practial Windows specific macros.
*/
@@ -102,16 +105,18 @@
#define CreateAutoEvent(state) CreateEvent(NULL, FALSE, state, NULL)
#define CreateManualEvent(state) CreateEvent(NULL, TRUE, state, NULL)
+/*
+ * Min number of async threads
+ */
+#define ERTS_MIN_NO_OF_ASYNC_THREADS 0
/*
* Our own type of "FD's"
*/
+#define ERTS_SYS_FD_INVALID INVALID_HANDLE_VALUE
#define ERTS_SYS_FD_TYPE HANDLE
#define NO_FSTAT_ON_SYS_FD_TYPE 1 /* They are events, not files */
-#define HAVE_ERTS_CHECK_IO_DEBUG
-int erts_check_io_debug(void);
-
/*
* For erl_time_sup
*/
diff --git a/erts/emulator/sys/win32/sys.c b/erts/emulator/sys/win32/sys.c
index e0422de026..0ded6b274e 100755..100644
--- a/erts/emulator/sys/win32/sys.c
+++ b/erts/emulator/sys/win32/sys.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2013. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2014. 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
@@ -32,7 +32,7 @@
#include "erl_threads.h"
#include "../../drivers/win32/win_con.h"
#include "erl_cpu_topology.h"
-
+#include <malloc.h>
void erts_sys_init_float(void);
@@ -69,17 +69,14 @@ static void async_read_file(struct async_io* aio, LPVOID buf, DWORD numToRead);
static int async_write_file(struct async_io* aio, LPVOID buf, DWORD numToWrite);
static int get_overlapped_result(struct async_io* aio,
LPDWORD pBytesRead, BOOL wait);
-static BOOL create_child_process(char *, HANDLE, HANDLE,
+static BOOL create_child_process(wchar_t *, HANDLE, HANDLE,
HANDLE, LPHANDLE, LPDWORD, BOOL,
- LPVOID, LPTSTR, unsigned,
- char **, int *);
+ LPVOID, wchar_t*, unsigned,
+ wchar_t **, int *);
static int create_pipe(LPHANDLE, LPHANDLE, BOOL, BOOL);
-static int application_type(const char* originalName, char fullPath[MAX_PATH],
+static int application_type(const wchar_t* originalName, wchar_t fullPath[MAX_PATH],
BOOL search_in_path, BOOL handle_quotes,
int *error_return);
-static int application_type_w(const WCHAR *originalName, WCHAR fullPath[MAX_PATH],
- BOOL search_in_path, BOOL handle_quotes,
- int *error_return);
HANDLE erts_service_event;
@@ -399,11 +396,12 @@ int* pBuild; /* Pointer to build number. */
* Definitions for driver flags.
*/
-#define DF_OVR_READY 1 /* Overlapped result is ready. */
-#define DF_EXIT_THREAD 2 /* The thread should exit. */
-#define DF_XLAT_CR 4 /* The thread should translate CRs. */
-#define DF_DROP_IF_INVH 8 /* Drop packages instead of crash if
+#define DF_OVR_READY 1 /* Overlapped result is ready. */
+#define DF_EXIT_THREAD 2 /* The thread should exit. */
+#define DF_XLAT_CR 4 /* The thread should translate CRs. */
+#define DF_DROP_IF_INVH 8 /* Drop packages instead of crash if
invalid handle (stderr) */
+#define DF_THREAD_FLUSHED 16 /* The thread should exit. */
#define OV_BUFFER_PTR(dp) ((LPVOID) ((dp)->ov.Internal))
#define OV_NUM_TO_READ(dp) ((dp)->ov.InternalHigh)
@@ -1172,7 +1170,7 @@ spawn_init(void)
}
static ErlDrvData
-spawn_start(ErlDrvPort port_num, char* name, SysDriverOpts* opts)
+spawn_start(ErlDrvPort port_num, char* utf8_name, SysDriverOpts* opts)
{
HANDLE hToChild = INVALID_HANDLE_VALUE; /* Write handle to child. */
HANDLE hFromChild = INVALID_HANDLE_VALUE; /* Read handle from child. */
@@ -1188,7 +1186,9 @@ spawn_start(ErlDrvPort port_num, char* name, SysDriverOpts* opts)
SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
char* envir = opts->envir;
int errno_return = -1;
-
+ wchar_t *name;
+ int len;
+
if (opts->read_write & DO_READ)
neededSelects++;
if (opts->read_write & DO_WRITE)
@@ -1246,26 +1246,40 @@ spawn_start(ErlDrvPort port_num, char* name, SysDriverOpts* opts)
* Spawn the port program.
*/
- DEBUGF(("Spawning \"%s\"\n", name));
+ if ((len = MultiByteToWideChar(CP_UTF8, 0, utf8_name, -1, NULL, 0)) > 0) {
+ name = erts_alloc(ERTS_ALC_T_TMP, len*sizeof(wchar_t));
+ MultiByteToWideChar(CP_UTF8, 0, utf8_name, -1, name, len);
+ } else { /* Not valid utf-8, just convert byte to wchar */
+ int i;
+ len = strlen(utf8_name);
+ name = erts_alloc(ERTS_ALC_T_TMP, (1+len)*sizeof(wchar_t));
+ for(i=0; i<len; i++) {
+ name[i] = (wchar_t) utf8_name[i];
+ }
+ name[i] = L'\0';
+ }
+ DEBUGF(("Spawning \"%S\"\n", name));
envir = win_build_environment(envir); /* Always a unicode environment */
- ok = create_child_process(name,
- hChildStdin,
- hChildStdout,
- hChildStderr,
- &dp->port_pid,
- &pid,
- opts->hide_window,
- (LPVOID) envir,
- (LPTSTR) opts->wd,
- opts->spawn_type,
- opts->argv,
- &errno_return);
+ ok = create_child_process(name,
+ hChildStdin,
+ hChildStdout,
+ hChildStderr,
+ &dp->port_pid,
+ &pid,
+ opts->hide_window,
+ (LPVOID) envir,
+ (wchar_t *) opts->wd,
+ opts->spawn_type,
+ (wchar_t **) opts->argv,
+ &errno_return);
CloseHandle(hChildStdin);
CloseHandle(hChildStdout);
if (close_child_stderr && hChildStderr != INVALID_HANDLE_VALUE &&
hChildStderr != 0) {
CloseHandle(hChildStderr);
}
+ erts_free(ERTS_ALC_T_TMP, name);
+
if (envir != NULL) {
erts_free(ERTS_ALC_T_ENVIRONMENT, envir);
}
@@ -1343,9 +1357,9 @@ create_file_thread(AsyncIo* aio, int mode)
* Example: input = "\"Program Files\"\\erl arg1 arg2"
* gives 19 as result.
* The length returned is equivalent with length(argv[0]) if the
- * comman line should have been prepared by _setargv for the main function
+ * command line should have been prepared by _setargv for the main function
*/
-int parse_command(char* cmd){
+int parse_command(wchar_t* cmd){
#define NORMAL 2
#define STRING 1
#define STOP 0
@@ -1353,17 +1367,17 @@ int parse_command(char* cmd){
int state = NORMAL;
while (cmd[i]) {
switch (cmd[i]) {
- case '"':
+ case L'"':
if (state == NORMAL)
state = STRING;
else
state = NORMAL;
break;
- case '\\':
- if ((state == STRING) && (cmd[i+1]=='"'))
+ case L'\\':
+ if ((state == STRING) && (cmd[i+1]==L'"'))
i++;
break;
- case ' ':
+ case L' ':
if (state == NORMAL)
state = STOP;
break;
@@ -1378,7 +1392,7 @@ int parse_command(char* cmd){
return i;
}
-static BOOL need_quotes(WCHAR *str)
+static BOOL need_quotes(wchar_t *str)
{
int in_quote = 0;
int backslashed = 0;
@@ -1442,7 +1456,7 @@ static BOOL need_quotes(WCHAR *str)
static BOOL
create_child_process
(
- char *origcmd, /* Command line for child process (including
+ wchar_t *origcmd, /* Command line for child process (including
* name of executable). Or whole executable if st is
* ERTS_SPAWN_EXECUTABLE
*/
@@ -1453,57 +1467,53 @@ create_child_process
LPDWORD pdwID, /* Pointer to variable to received Process ID */
BOOL hide, /* Hide the window unconditionally. */
LPVOID env, /* Environment for the child */
- LPTSTR wd, /* Working dir for the child */
+ wchar_t *wd, /* Working dir for the child */
unsigned st, /* Flags for spawn, tells us how to interpret origcmd */
- char **argv, /* Argument vector if given. */
+ wchar_t **argv, /* Argument vector if given. */
int *errno_return /* Place to put an errno in in case of failure */
)
-{
+{
PROCESS_INFORMATION piProcInfo = {0};
BOOL ok = FALSE;
int applType;
/* Not to be changed for different types of executables */
int staticCreateFlags = GetPriorityClass(GetCurrentProcess());
int createFlags = DETACHED_PROCESS;
- char *newcmdline = NULL;
+ wchar_t *newcmdline = NULL;
int cmdlength;
- char* thecommand;
- LPTSTR appname = NULL;
+ wchar_t* thecommand;
+ wchar_t* appname = NULL;
HANDLE hProcess = GetCurrentProcess();
-
- *errno_return = -1;
+ STARTUPINFOW siStartInfo = {0};
+ wchar_t execPath[MAX_PATH];
+ *errno_return = -1;
+ siStartInfo.cb = sizeof(STARTUPINFOW);
+ siStartInfo.dwFlags = STARTF_USESTDHANDLES;
+ siStartInfo.hStdInput = hStdin;
+ siStartInfo.hStdOutput = hStdout;
+ siStartInfo.hStdError = hStderr;
if (st != ERTS_SPAWN_EXECUTABLE) {
- STARTUPINFO siStartInfo = {0};
- char execPath[MAX_PATH];
-
- siStartInfo.cb = sizeof(STARTUPINFO);
- siStartInfo.dwFlags = STARTF_USESTDHANDLES;
- siStartInfo.hStdInput = hStdin;
- siStartInfo.hStdOutput = hStdout;
- siStartInfo.hStdError = hStderr;
-
/*
* Parse out the program name from the command line (it can be quoted and
* contain spaces).
*/
- newcmdline = erts_alloc(ERTS_ALC_T_TMP, 2048);
+ newcmdline = (wchar_t *) erts_alloc(ERTS_ALC_T_TMP, 2048*sizeof(wchar_t));
cmdlength = parse_command(origcmd);
- thecommand = (char *) erts_alloc(ERTS_ALC_T_TMP, cmdlength+1);
- strncpy(thecommand, origcmd, cmdlength);
- thecommand[cmdlength] = '\0';
- DEBUGF(("spawn command: %s\n", thecommand));
-
- applType = application_type(thecommand, execPath, TRUE,
- TRUE, errno_return);
- DEBUGF(("application_type returned for (%s) is %d\n", thecommand, applType));
+ thecommand = (wchar_t *) erts_alloc(ERTS_ALC_T_TMP, (cmdlength+1)*sizeof(wchar_t));
+ wcsncpy(thecommand, origcmd, cmdlength);
+ thecommand[cmdlength] = L'\0';
+ DEBUGF(("spawn command: %S\n", thecommand));
+
+ applType = application_type(thecommand, execPath, TRUE, TRUE, errno_return);
+ DEBUGF(("application_type returned for (%S) is %d\n", thecommand, applType));
erts_free(ERTS_ALC_T_TMP, (void *) thecommand);
if (applType == APPL_NONE) {
erts_free(ERTS_ALC_T_TMP,newcmdline);
return FALSE;
}
- newcmdline[0] = '\0';
+ newcmdline[0] = L'\0';
if (applType == APPL_DOS) {
/*
@@ -1512,11 +1522,11 @@ create_child_process
* a normal process inside of a hidden console application,
* and then run that hidden console as a detached process.
*/
-
+
siStartInfo.wShowWindow = SW_HIDE;
siStartInfo.dwFlags |= STARTF_USESHOWWINDOW;
createFlags = CREATE_NEW_CONSOLE;
- strcat(newcmdline, "cmd.exe /c ");
+ wcscat(newcmdline, L"cmd.exe /c ");
} else if (hide) {
DEBUGF(("hiding window\n"));
siStartInfo.wShowWindow = SW_HIDE;
@@ -1524,35 +1534,25 @@ create_child_process
createFlags = 0;
}
- strcat(newcmdline, execPath);
- strcat(newcmdline, origcmd+cmdlength);
- DEBUGF(("Creating child process: %s, createFlags = %d\n", newcmdline, createFlags));
- ok = CreateProcessA(appname,
- newcmdline,
- NULL,
- NULL,
- TRUE,
- createFlags | staticCreateFlags |
- CREATE_UNICODE_ENVIRONMENT,
- env,
- wd,
- &siStartInfo,
+ wcscat(newcmdline, execPath);
+ wcscat(newcmdline, origcmd+cmdlength);
+ DEBUGF(("Creating child process: %S, createFlags = %d\n", newcmdline, createFlags));
+ ok = CreateProcessW(appname,
+ newcmdline,
+ NULL,
+ NULL,
+ TRUE,
+ createFlags | staticCreateFlags |
+ CREATE_UNICODE_ENVIRONMENT,
+ env,
+ wd,
+ &siStartInfo,
&piProcInfo);
} else { /* ERTS_SPAWN_EXECUTABLE, filename and args are in unicode ({utf16,little}) */
int run_cmd = 0;
- STARTUPINFOW siStartInfo = {0};
- WCHAR execPath[MAX_PATH];
-
- siStartInfo.cb = sizeof(STARTUPINFOW);
- siStartInfo.dwFlags = STARTF_USESTDHANDLES;
- siStartInfo.hStdInput = hStdin;
- siStartInfo.hStdOutput = hStdout;
- siStartInfo.hStdError = hStderr;
-
- applType = application_type_w((WCHAR *) origcmd, execPath, FALSE, FALSE,
- errno_return);
+ applType = application_type(origcmd, execPath, FALSE, FALSE, errno_return);
if (applType == APPL_NONE) {
return FALSE;
}
@@ -1572,37 +1572,37 @@ create_child_process
createFlags = 0;
}
if (run_cmd) {
- WCHAR cmdPath[MAX_PATH];
+ wchar_t cmdPath[MAX_PATH];
int cmdType;
- cmdType = application_type_w(L"cmd.exe", cmdPath, TRUE, FALSE, errno_return);
+ cmdType = application_type(L"cmd.exe", cmdPath, TRUE, FALSE, errno_return);
if (cmdType == APPL_NONE || cmdType == APPL_DOS) {
return FALSE;
}
- appname = (char *) erts_alloc(ERTS_ALC_T_TMP, (wcslen(cmdPath)+1)*sizeof(WCHAR));
- wcscpy((WCHAR *) appname,cmdPath);
+ appname = (wchar_t *) erts_alloc(ERTS_ALC_T_TMP, (wcslen(cmdPath)+1)*sizeof(wchar_t));
+ wcscpy(appname,cmdPath);
} else {
- appname = (char *) erts_alloc(ERTS_ALC_T_TMP, (wcslen(execPath)+1)*sizeof(WCHAR));
- wcscpy((WCHAR *) appname, execPath);
+ appname = (wchar_t *) erts_alloc(ERTS_ALC_T_TMP, (wcslen(execPath)+1)*sizeof(wchar_t));
+ wcscpy(appname, execPath);
}
if (argv == NULL) {
BOOL orig_need_q = need_quotes(execPath);
- WCHAR *ptr;
+ wchar_t *ptr;
int ocl = wcslen(execPath);
if (run_cmd) {
- newcmdline = (char *) erts_alloc(ERTS_ALC_T_TMP,
- (ocl + ((orig_need_q) ? 3 : 1)
- + 11)*sizeof(WCHAR));
- memcpy(newcmdline,L"cmd.exe /c ",11*sizeof(WCHAR));
- ptr = (WCHAR *) (newcmdline + (11*sizeof(WCHAR)));
+ newcmdline = (wchar_t *) erts_alloc(ERTS_ALC_T_TMP,
+ (ocl + ((orig_need_q) ? 3 : 1)
+ + 11)*sizeof(wchar_t));
+ memcpy(newcmdline,L"cmd.exe /c ",11*sizeof(wchar_t));
+ ptr = newcmdline + 11;
} else {
- newcmdline = (char *) erts_alloc(ERTS_ALC_T_TMP,
- (ocl + ((orig_need_q) ? 3 : 1))*sizeof(WCHAR));
- ptr = (WCHAR *) newcmdline;
+ newcmdline = (wchar_t *) erts_alloc(ERTS_ALC_T_TMP,
+ (ocl + ((orig_need_q) ? 3 : 1))*sizeof(wchar_t));
+ ptr = (wchar_t *) newcmdline;
}
if (orig_need_q) {
*ptr++ = L'"';
}
- memcpy(ptr,execPath,ocl*sizeof(WCHAR));
+ memcpy(ptr,execPath,ocl*sizeof(wchar_t));
ptr += ocl;
if (orig_need_q) {
*ptr++ = L'"';
@@ -1610,12 +1610,12 @@ create_child_process
*ptr = L'\0';
} else {
int sum = 1; /* '\0' */
- WCHAR **ar = (WCHAR **) argv;
- WCHAR *n;
- char *save_arg0 = NULL;
- if (argv[0] == erts_default_arg0 || run_cmd) {
+ wchar_t **ar = argv;
+ wchar_t *n;
+ wchar_t *save_arg0 = NULL;
+ if (argv[0] == (wchar_t *) erts_default_arg0 || run_cmd) {
save_arg0 = argv[0];
- argv[0] = (char *) execPath;
+ argv[0] = execPath;
}
if (run_cmd) {
sum += 11; /* cmd.exe /c */
@@ -1628,11 +1628,11 @@ create_child_process
sum++; /* space */
++ar;
}
- ar = (WCHAR **) argv;
- newcmdline = erts_alloc(ERTS_ALC_T_TMP, sum*sizeof(WCHAR));
- n = (WCHAR *) newcmdline;
+ ar = argv;
+ newcmdline = (wchar_t *) erts_alloc(ERTS_ALC_T_TMP, sum*sizeof(wchar_t));
+ n = newcmdline;
if (run_cmd) {
- memcpy(n,L"cmd.exe /c ",11*sizeof(WCHAR));
+ memcpy(n,L"cmd.exe /c ",11*sizeof(wchar_t));
n += 11;
}
while (*ar != NULL) {
@@ -1641,7 +1641,7 @@ create_child_process
if (q) {
*n++ = L'"';
}
- memcpy(n,*ar,sum*sizeof(WCHAR));
+ memcpy(n,*ar,sum*sizeof(wchar_t));
n += sum;
if (q) {
*n++ = L'"';
@@ -1656,16 +1656,16 @@ create_child_process
}
DEBUGF(("Creating child process: %s, createFlags = %d\n", newcmdline, createFlags));
- ok = CreateProcessW((WCHAR *) appname,
- (WCHAR *) newcmdline,
- NULL,
- NULL,
- TRUE,
- createFlags | staticCreateFlags |
- CREATE_UNICODE_ENVIRONMENT,
- env,
- (WCHAR *) wd,
- &siStartInfo,
+ ok = CreateProcessW((wchar_t *) appname,
+ (wchar_t *) newcmdline,
+ NULL,
+ NULL,
+ TRUE,
+ createFlags | staticCreateFlags |
+ CREATE_UNICODE_ENVIRONMENT,
+ env,
+ wd,
+ &siStartInfo,
&piProcInfo);
} /* end SPAWN_EXECUTABLE */
@@ -1774,180 +1774,23 @@ static int create_pipe(HANDLE *phRead, HANDLE *phWrite, BOOL inheritRead, BOOL o
return TRUE;
}
-
-
-
-static int application_type
-(
- const char *originalName, /* Name of the application to find. */
- char fullPath[MAX_PATH], /* Filled with complete path to
- * application. */
- BOOL search_in_path, /* If we should search the system wide path */
- BOOL handle_quotes, /* If we should handle quotes around executable */
- int *error_return /* A place to put an error code */
- )
-{
- int applType, i;
- HANDLE hFile;
- char *ext, *rest;
- char buf[2];
- DWORD read;
- IMAGE_DOS_HEADER header;
- static char extensions[][5] = {"", ".com", ".exe", ".bat"};
- int is_quoted;
- int len;
-
- /* Look for the program as an external program. First try the name
- * as it is, then try adding .com, .exe, and .bat, in that order, to
- * the name, looking for an executable.
- * NOTE! that we does not support execution of .com programs on Windows NT
- *
- *
- * Using the raw SearchPath() procedure doesn't do quite what is
- * necessary. If the name of the executable already contains a '.'
- * character, it will not try appending the specified extension when
- * searching (in other words, SearchPath will not find the program
- * "a.b.exe" if the arguments specified "a.b" and ".exe").
- * So, first look for the file as it is named. Then manually append
- * the extensions, looking for a match. (')
- */
-
- len = strlen(originalName);
- is_quoted = handle_quotes && len > 0 && originalName[0] == '"' &&
- originalName[len-1] == '"';
-
- applType = APPL_NONE;
- *error_return = ENOENT;
- for (i = 0; i < (int) (sizeof(extensions) / sizeof(extensions[0])); i++) {
- if(is_quoted) {
- lstrcpyn(fullPath, originalName+1, MAX_PATH - 7);
- len = strlen(fullPath);
- if(len > 0) {
- fullPath[len-1] = '\0';
- }
- } else {
- lstrcpyn(fullPath, originalName, MAX_PATH - 5);
- }
- lstrcat(fullPath, extensions[i]);
- SearchPath((search_in_path) ? NULL : ".", fullPath, NULL, MAX_PATH, fullPath, &rest);
-
- /*
- * Ignore matches on directories or data files, return if identified
- * a known type.
- */
-
- if (GetFileAttributes(fullPath) & FILE_ATTRIBUTE_DIRECTORY) {
- continue;
- }
-
- ext = strrchr(fullPath, '.');
- if ((ext != NULL) && (strcmpi(ext, ".bat") == 0)) {
- *error_return = EACCES;
- applType = APPL_DOS;
- break;
- }
-
- hFile = CreateFile(fullPath, GENERIC_READ, FILE_SHARE_READ, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (hFile == INVALID_HANDLE_VALUE) {
- continue;
- }
-
- *error_return = EACCES; /* If considered an error,
- it's an access error */
- header.e_magic = 0;
- ReadFile(hFile, (void *) &header, sizeof(header), &read, NULL);
- if (header.e_magic != IMAGE_DOS_SIGNATURE) {
- /*
- * Doesn't have the magic number for relocatable executables. If
- * filename ends with .com, assume it's a DOS application anyhow.
- * Note that we didn't make this assumption at first, because some
- * supposed .com files are really 32-bit executables with all the
- * magic numbers and everything.
- */
-
- CloseHandle(hFile);
- if ((ext != NULL) && (strcmpi(ext, ".com") == 0)) {
- applType = APPL_DOS;
- break;
- }
- continue;
- }
- if (header.e_lfarlc != sizeof(header)) {
- /*
- * All Windows 3.X and Win32 and some DOS programs have this value
- * set here. If it doesn't, assume that since it already had the
- * other magic number it was a DOS application.
- */
-
- CloseHandle(hFile);
- applType = APPL_DOS;
- break;
- }
-
- /*
- * The DWORD at header.e_lfanew points to yet another magic number.
- */
-
- buf[0] = '\0';
- SetFilePointer(hFile, header.e_lfanew, NULL, FILE_BEGIN);
- ReadFile(hFile, (void *) buf, 2, &read, NULL);
- CloseHandle(hFile);
-
- if ((buf[0] == 'L') && (buf[1] == 'E')) {
- applType = APPL_DOS;
- } else if ((buf[0] == 'N') && (buf[1] == 'E')) {
- applType = APPL_WIN3X;
- } else if ((buf[0] == 'P') && (buf[1] == 'E')) {
- applType = APPL_WIN32;
- } else {
- continue;
- }
- break;
- }
-
- if (applType == APPL_NONE) {
- return APPL_NONE;
- }
-
- if ((applType == APPL_DOS) || (applType == APPL_WIN3X)) {
- /*
- * Replace long path name of executable with short path name for
- * 16-bit applications. Otherwise the application may not be able
- * to correctly parse its own command line to separate off the
- * application name from the arguments.
- */
-
- GetShortPathName(fullPath, fullPath, MAX_PATH);
- }
- if (is_quoted) {
- /* restore quotes on quoted program name */
- len = strlen(fullPath);
- memmove(fullPath+1,fullPath,len);
- fullPath[0]='"';
- fullPath[len+1]='"';
- fullPath[len+2]='\0';
- }
- return applType;
-}
-
-static int application_type_w (const WCHAR *originalName, /* Name of the application to find. */
- WCHAR wfullpath[MAX_PATH],/* Filled with complete path to
+static int application_type (const wchar_t *originalName, /* Name of the application to find. */
+ wchar_t wfullpath[MAX_PATH],/* Filled with complete path to
* application. */
- BOOL search_in_path, /* If we should search the system wide path */
- BOOL handle_quotes, /* If we should handle quotes around executable */
- int *error_return) /* A place to put an error code */
+ BOOL search_in_path, /* If we should search the system wide path */
+ BOOL handle_quotes, /* If we should handle quotes around executable */
+ int *error_return) /* A place to put an error code */
{
int applType, i;
HANDLE hFile;
- WCHAR *ext, *rest;
+ wchar_t *ext, *rest;
char buf[2];
DWORD read;
IMAGE_DOS_HEADER header;
- static WCHAR extensions[][5] = {L"", L".com", L".exe", L".bat"};
+ static wchar_t extensions[][5] = {L"", L".com", L".exe", L".bat"};
int is_quoted;
int len;
- WCHAR xfullpath[MAX_PATH];
+ wchar_t xfullpath[MAX_PATH];
len = wcslen(originalName);
is_quoted = handle_quotes && len > 0 && originalName[0] == L'"' &&
@@ -2062,7 +1905,7 @@ static int application_type_w (const WCHAR *originalName, /* Name of the applica
if (is_quoted) {
/* restore quotes on quoted program name */
len = wcslen(wfullpath);
- memmove(wfullpath+1,wfullpath,len*sizeof(WCHAR));
+ memmove(wfullpath+1,wfullpath,len*sizeof(wchar_t));
wfullpath[0]=L'"';
wfullpath[len+1]=L'"';
wfullpath[len+2]=L'\0';
@@ -2141,8 +1984,9 @@ threaded_writer(LPVOID param)
for (;;) {
handle = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
- if (aio->flags & DF_EXIT_THREAD)
+ if (aio->flags & DF_EXIT_THREAD) {
break;
+ }
buf = OV_BUFFER_PTR(aio);
numToWrite = OV_NUM_TO_READ(aio);
@@ -2150,6 +1994,7 @@ threaded_writer(LPVOID param)
if (handle == (WAIT_OBJECT_0 + 1) && numToWrite == 0) {
SetEvent(aio->flushReplyEvent);
+ aio->flags |= DF_THREAD_FLUSHED;
continue;
}
@@ -2197,6 +2042,7 @@ threaded_writer(LPVOID param)
if (aio->flags & DF_EXIT_THREAD)
break;
}
+ aio->flags |= DF_THREAD_FLUSHED;
CloseHandle(aio->fd);
aio->fd = INVALID_HANDLE_VALUE;
unrefer_driver_data(aio->dp);
@@ -2340,9 +2186,11 @@ static void fd_stop(ErlDrvData data)
(void) driver_select(dp->port_num,
(ErlDrvEvent)dp->out.ov.hEvent,
ERL_DRV_WRITE, 0);
- ASSERT(dp->out.flushEvent);
- SetEvent(dp->out.flushEvent);
- WaitForSingleObject(dp->out.flushReplyEvent, INFINITE);
+ do {
+ ASSERT(dp->out.flushEvent);
+ SetEvent(dp->out.flushEvent);
+ } while (WaitForSingleObject(dp->out.flushReplyEvent, 10) == WAIT_TIMEOUT
+ || !(dp->out.flags & DF_THREAD_FLUSHED));
}
}
@@ -2433,12 +2281,12 @@ threaded_exiter(LPVOID param)
*/
i = 0;
if (dp->out.thread != (HANDLE) -1) {
- dp->out.flags = DF_EXIT_THREAD;
+ dp->out.flags |= DF_EXIT_THREAD;
SetEvent(dp->out.ioAllowed);
handles[i++] = dp->out.thread;
}
if (dp->in.thread != (HANDLE) -1) {
- dp->in.flags = DF_EXIT_THREAD;
+ dp->in.flags |= DF_EXIT_THREAD;
SetEvent(dp->in.ioAllowed);
handles[i++] = dp->in.thread;
}
@@ -2906,6 +2754,30 @@ void erts_sys_free(ErtsAlcType_t t, void *x, void *p)
free(p);
}
+void *erts_sys_aligned_alloc(UWord alignment, UWord size)
+{
+ void *ptr;
+ ASSERT(alignment && (alignment & (alignment-1)) == 0); /* power of 2 */
+ ptr = _aligned_malloc((size_t) size, (size_t) alignment);
+ ASSERT(!ptr || (((UWord) ptr) & (alignment - 1)) == 0);
+ return ptr;
+}
+
+void erts_sys_aligned_free(UWord alignment, void *ptr)
+{
+ ASSERT(alignment && (alignment & (alignment-1)) == 0); /* power of 2 */
+ _aligned_free(ptr);
+}
+
+void *erts_sys_aligned_realloc(UWord alignment, void *ptr, UWord size, UWord old_size)
+{
+ void *new_ptr;
+ ASSERT(alignment && (alignment & (alignment-1)) == 0); /* power of 2 */
+ new_ptr = _aligned_realloc(ptr, (size_t) size, (size_t) alignment);
+ ASSERT(!new_ptr || (((UWord) new_ptr) & (alignment - 1)) == 0);
+ return new_ptr;
+}
+
static Preload* preloaded = NULL;
static unsigned* res_name = NULL;
static int num_preloaded = 0;
@@ -3194,7 +3066,7 @@ erl_bin_write(buf, sz, max)
}
void
-erl_assert_error(char* expr, char* file, int line)
+erl_assert_error(const char* expr, const char* func, const char* file, int line)
{
char message[1024];
@@ -3325,7 +3197,7 @@ void erl_sys_init(void)
noinherit_std_handle(STD_ERROR_HANDLE);
#ifdef ERTS_SMP
- erts_smp_tsd_key_create(&win32_errstr_key);
+ erts_smp_tsd_key_create(&win32_errstr_key,"win32_errstr_key");
InitializeCriticalSection(&htbc_lock);
#endif
erts_smp_atomic_init_nob(&pipe_creation_counter,0);
diff --git a/erts/emulator/sys/win32/sys_env.c b/erts/emulator/sys/win32/sys_env.c
index 754f4c6e4c..9f977ad6c8 100644
--- a/erts/emulator/sys/win32/sys_env.c
+++ b/erts/emulator/sys/win32/sys_env.c
@@ -141,6 +141,24 @@ void fini_getenv_state(GETENV_STATE *state)
erts_smp_rwmtx_runlock(&environ_rwmtx);
}
+int erts_sys_unsetenv(char *key)
+{
+ int res = 0;
+ WCHAR *wkey = (WCHAR *) key;
+
+ SetLastError(0);
+ erts_smp_rwmtx_rlock(&environ_rwmtx);
+ GetEnvironmentVariableW(wkey,
+ NULL,
+ 0);
+ if (GetLastError() != ERROR_ENVVAR_NOT_FOUND) {
+ res = (SetEnvironmentVariableW(wkey,
+ NULL) ? 0 : 1);
+ }
+ erts_smp_rwmtx_runlock(&environ_rwmtx);
+ return res;
+}
+
char*
win_build_environment(char* new_env)
{
diff --git a/erts/emulator/sys/win32/sys_float.c b/erts/emulator/sys/win32/sys_float.c
index fb1ffc3089..0e19746cf5 100644
--- a/erts/emulator/sys/win32/sys_float.c
+++ b/erts/emulator/sys/win32/sys_float.c
@@ -52,7 +52,7 @@ void erts_thread_disable_fpe(void)
int
sys_chars_to_double(char *buf, double *fp)
{
- char *s = buf, *t, *dp;
+ unsigned char *s = buf, *t, *dp;
/* Robert says that something like this is what he really wanted:
* (The [.,] radix test is NOT what Robert wanted - it was added later)
@@ -120,7 +120,7 @@ sys_chars_to_double(char *buf, double *fp)
int
sys_double_to_chars_ext(double fp, char *buffer, size_t buffer_size, size_t decimals)
{
- char *s = buffer;
+ unsigned char *s = buffer;
if (erts_snprintf(buffer, buffer_size, "%.*e", decimals, fp) >= buffer_size)
return -1;
@@ -133,6 +133,8 @@ sys_double_to_chars_ext(double fp, char *buffer, size_t buffer_size, size_t deci
return s-buffer; /* i.e strlen(buffer) */
}
+#ifdef USE_MATHERR
+
int
matherr(struct _exception *exc)
{
@@ -141,6 +143,8 @@ matherr(struct _exception *exc)
return 1;
}
+#endif
+
static void
fpe_exception(int sig)
{
diff --git a/erts/emulator/sys/win32/sys_time.c b/erts/emulator/sys/win32/sys_time.c
index 2f2dfc8197..b84c8f85ce 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-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2013. 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
@@ -63,6 +63,8 @@
static SysHrTime wrap = 0;
static DWORD last_tick_count = 0;
+static erts_smp_mtx_t wrap_lock;
+static ULONGLONG (WINAPI *pGetTickCount64)(void) = NULL;
/* Getting timezone information is a heavy operation, so we want to do this
only once */
@@ -77,11 +79,23 @@ static int days_in_month[2][13] = {
int
sys_init_time(void)
{
+ char kernel_dll_name[] = "kernel32";
+ HMODULE module;
+
+ module = GetModuleHandle(kernel_dll_name);
+ pGetTickCount64 = (module != NULL) ?
+ (ULONGLONG (WINAPI *)(void))
+ GetProcAddress(module,"GetTickCount64") :
+ NULL;
+
if(GetTimeZoneInformation(&static_tzi) &&
static_tzi.StandardDate.wMonth != 0 &&
static_tzi.DaylightDate.wMonth != 0) {
have_static_tzi = 1;
}
+
+ erts_smp_mtx_init(&wrap_lock, "sys_gethrtime");
+
return 1;
}
@@ -363,15 +377,39 @@ sys_gettimeofday(SysTimeval *tv)
EPOCH_JULIAN_DIFF);
}
+extern int erts_initialized;
SysHrTime
sys_gethrtime(void)
{
- DWORD ticks = (SysHrTime) (GetTickCount() & 0x7FFFFFFF);
- if (ticks < (SysHrTime) last_tick_count) {
- wrap += LL_LITERAL(1) << 31;
+ if (pGetTickCount64 != NULL) {
+ return ((SysHrTime) pGetTickCount64()) * LL_LITERAL(1000000);
+ } else {
+ DWORD ticks;
+ SysHrTime res;
+ erts_smp_mtx_lock(&wrap_lock);
+ ticks = (SysHrTime) (GetTickCount() & 0x7FFFFFFF);
+ if (ticks < (SysHrTime) last_tick_count) {
+ /* Detect a race that should no longer be here... */
+ if ((((SysHrTime) last_tick_count) - ((SysHrTime) ticks)) > 1000) {
+ wrap += LL_LITERAL(1) << 31;
+ } else {
+ /*
+ * XXX Debug: Violates locking order, remove all this,
+ * after testing!
+ */
+ erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf();
+ erts_dsprintf(dsbufp, "Did not wrap when last_tick %d "
+ "and tick %d",
+ last_tick_count, ticks);
+ erts_send_error_to_logger_nogl(dsbufp);
+ ticks = last_tick_count;
+ }
+ }
+ last_tick_count = ticks;
+ res = ((((LONGLONG) ticks) + wrap) * LL_LITERAL(1000000));
+ erts_smp_mtx_unlock(&wrap_lock);
+ return res;
}
- last_tick_count = ticks;
- return ((((LONGLONG) ticks) + wrap) * LL_LITERAL(1000000));
}
clock_t