aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/sys/win32
diff options
context:
space:
mode:
authorRickard Green <[email protected]>2012-12-07 00:28:50 +0100
committerRickard Green <[email protected]>2012-12-07 00:28:50 +0100
commit6027f852217f0014f1892fbbfa45c69e104da652 (patch)
treebdb10abcf579b5607dc287b395fb15fa667b0512 /erts/emulator/sys/win32
parentd29c460c4ad1ca0cc2fb6a13a81b4ccc07516941 (diff)
parent3f85767e086e08b70baee34d719df9a8bc8814f4 (diff)
downloadotp-6027f852217f0014f1892fbbfa45c69e104da652.tar.gz
otp-6027f852217f0014f1892fbbfa45c69e104da652.tar.bz2
otp-6027f852217f0014f1892fbbfa45c69e104da652.zip
Merge branch 'rickard/port-optimizations/OTP-10336' into rickard/r16/port-optimizations/OTP-10336
* rickard/port-optimizations/OTP-10336: Change annotate level for emacs-22 in cerl Update etp-commands Add documentation on communication in Erlang Add support for busy port message queue Add driver callback epilogue Implement true asynchronous signaling between processes and ports Add erl_drv_[send|output]_term Move busy port flag Use rwlock for driver list Optimize management of port tasks Improve configuration of process and port tables Remove R9 compatibility features Use ptab functionality also for ports Prepare for use of ptab functionality also for ports Atomic port state Generalize process table implementation Implement functionality for delaying thread progress from unmanaged threads Conflicts: erts/doc/src/erl_driver.xml erts/doc/src/erlang.xml erts/emulator/beam/beam_bif_load.c erts/emulator/beam/beam_bp.c erts/emulator/beam/beam_emu.c erts/emulator/beam/bif.c erts/emulator/beam/copy.c erts/emulator/beam/erl_alloc.c erts/emulator/beam/erl_alloc.types erts/emulator/beam/erl_bif_info.c erts/emulator/beam/erl_bif_port.c erts/emulator/beam/erl_bif_trace.c erts/emulator/beam/erl_init.c erts/emulator/beam/erl_message.c erts/emulator/beam/erl_port_task.c erts/emulator/beam/erl_process.c erts/emulator/beam/erl_process.h erts/emulator/beam/erl_process_lock.c erts/emulator/beam/erl_trace.c erts/emulator/beam/export.h erts/emulator/beam/global.h erts/emulator/beam/io.c erts/emulator/sys/unix/sys.c erts/emulator/sys/vxworks/sys.c erts/emulator/test/port_SUITE.erl erts/etc/unix/cerl.src erts/preloaded/ebin/erlang.beam erts/preloaded/ebin/prim_inet.beam erts/preloaded/src/prim_inet.erl lib/hipe/cerl/erl_bif_types.erl lib/kernel/doc/src/inet.xml lib/kernel/src/inet.erl
Diffstat (limited to 'erts/emulator/sys/win32')
-rw-r--r--erts/emulator/sys/win32/erl_win_dyn_driver.h8
-rwxr-xr-xerts/emulator/sys/win32/sys.c155
2 files changed, 62 insertions, 101 deletions
diff --git a/erts/emulator/sys/win32/erl_win_dyn_driver.h b/erts/emulator/sys/win32/erl_win_dyn_driver.h
index ec5141838a..8b6be2b2f1 100644
--- a/erts/emulator/sys/win32/erl_win_dyn_driver.h
+++ b/erts/emulator/sys/win32/erl_win_dyn_driver.h
@@ -74,7 +74,9 @@ WDD_TYPEDEF(ErlDrvTermData, driver_mk_port,(ErlDrvPort));
WDD_TYPEDEF(ErlDrvTermData, driver_connected,(ErlDrvPort));
WDD_TYPEDEF(ErlDrvTermData, driver_caller,(ErlDrvPort));
WDD_TYPEDEF(ErlDrvTermData, driver_mk_term_nil,(void));
+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(long, driver_async, (ErlDrvPort,unsigned int*,void (*)(void*),void*,void (*)(void*)));
WDD_TYPEDEF(int, driver_async_cancel, (unsigned int));
@@ -187,7 +189,9 @@ typedef struct {
WDD_FTYPE(driver_connected) *driver_connected;
WDD_FTYPE(driver_caller) *driver_caller;
WDD_FTYPE(driver_mk_term_nil) *driver_mk_term_nil;
+ WDD_FTYPE(erl_drv_output_term) *erl_drv_output_term;
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) *driver_async;
WDD_FTYPE(driver_async_cancel) *driver_async_cancel;
@@ -294,7 +298,9 @@ extern TWinDynDriverCallbacks WinDynDriverCallbacks;
#define driver_connected (WinDynDriverCallbacks.driver_connected)
#define driver_caller (WinDynDriverCallbacks.driver_caller)
#define driver_mk_term_nil (WinDynDriverCallbacks.driver_mk_term_nil)
+#define erl_drv_output_term (WinDynDriverCallbacks.erl_drv_output_term)
#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 (WinDynDriverCallbacks.driver_async)
#define driver_async_cancel (WinDynDriverCallbacks.driver_async_cancel)
@@ -425,7 +431,9 @@ do { \
((W).driver_connected) = driver_connected; \
((W).driver_caller) = driver_caller; \
((W).driver_mk_term_nil) = driver_mk_term_nil; \
+((W).erl_drv_output_term) = erl_drv_output_term; \
((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) = driver_async; \
((W).driver_async_cancel) = driver_async_cancel; \
diff --git a/erts/emulator/sys/win32/sys.c b/erts/emulator/sys/win32/sys.c
index f19f4ebd8c..1cd9072cea 100755
--- a/erts/emulator/sys/win32/sys.c
+++ b/erts/emulator/sys/win32/sys.c
@@ -87,9 +87,6 @@ static erts_smp_tsd_key_t win32_errstr_key;
static erts_smp_atomic_t pipe_creation_counter;
-static erts_smp_mtx_t sys_driver_data_lock;
-
-
/* Results from application_type(_w) is one of */
#define APPL_NONE 0
#define APPL_DOS 1
@@ -97,7 +94,6 @@ static erts_smp_mtx_t sys_driver_data_lock;
#define APPL_WIN32 3
static int driver_write(long, HANDLE, byte*, int);
-static void common_stop(int);
static int create_file_thread(struct async_io* aio, int mode);
#ifdef ERTS_SMP
static void close_active_handle(ErlDrvPort, HANDLE handle);
@@ -115,9 +111,6 @@ BOOL WINAPI ctrl_handler(DWORD dwCtrlType);
#define PORT_BUFSIZ 4096
-#define PORT_FREE (-1)
-#define PORT_EXITING (-2)
-
#define DRV_BUF_ALLOC(SZ) \
erts_alloc_fnf(ERTS_ALC_T_DRV_DATA_BUF, (SZ))
#define DRV_BUF_REALLOC(P, SZ) \
@@ -269,7 +262,8 @@ int erts_sys_prepare_crash_dump(int secs)
list = CONS(hp, make_small(8), list); hp += 2;
/* send to heart port, CMD = 8, i.e. prepare crash dump =o */
- erts_write_to_port(NIL, heart_port, list);
+ erts_port_output(NULL, ERTS_PORT_SIG_FLG_FORCE_IMM_CALL, heart_port,
+ heart_port->common.id, list, NULL);
return 1;
}
@@ -474,7 +468,7 @@ typedef struct driver_data {
byte *inbuf; /* Buffer to use for overlapped read. */
int outBufSize; /* Size of output buffer. */
byte *outbuf; /* Buffer to use for overlapped write. */
- ErlDrvPort port_num; /* The port number. */
+ ErlDrvPort port_num; /* The port handle. */
int packet_bytes; /* 0: continous stream, 1, 2, or 4: the number
* of bytes in the packet header.
*/
@@ -484,8 +478,6 @@ typedef struct driver_data {
int report_exit; /* Do report exit status for the port */
} DriverData;
-static DriverData* driver_data; /* Pointer to array of driver data. */
-
/* Driver interfaces */
static ErlDrvData spawn_start(ErlDrvPort, char*, SysDriverOpts*);
static ErlDrvData fd_start(ErlDrvPort, char*, SysDriverOpts*);
@@ -597,67 +589,53 @@ struct erl_drv_entry vanilla_driver_entry = {
*/
static DriverData*
-new_driver_data(int port_num, int packet_bytes, int wait_objs_required, int use_threads)
+new_driver_data(ErlDrvPort port_num, int packet_bytes, int wait_objs_required, int use_threads)
{
DriverData* dp;
-
- erts_smp_mtx_lock(&sys_driver_data_lock);
- DEBUGF(("new_driver_data(port_num %d, pb %d)\n",
- port_num, packet_bytes));
+ DEBUGF(("new_driver_data(%p, pb %d)\n", port_num, packet_bytes));
+ dp = driver_alloc(sizeof(DriverData));
+ if (!dp)
+ return NULL;
/*
* We used to test first at all that there is enough room in the
* array used by WaitForMultipleObjects(), but that is not necessary
* any more, since driver_select() can't fail.
*/
- /*
- * Search for a free slot.
- */
+ dp->bytesInBuffer = 0;
+ dp->totalNeeded = packet_bytes;
+ dp->inBufSize = PORT_BUFSIZ;
+ dp->inbuf = DRV_BUF_ALLOC(dp->inBufSize);
+ if (dp->inbuf == NULL)
+ goto buf_alloc_error;
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, dp->inBufSize);
+ dp->outBufSize = 0;
+ dp->outbuf = NULL;
+ dp->port_num = port_num;
+ dp->packet_bytes = packet_bytes;
+ dp->port_pid = INVALID_HANDLE_VALUE;
+ if (init_async_io(&dp->in, use_threads) == -1)
+ goto async_io_error1;
+ if (init_async_io(&dp->out, use_threads) == -1)
+ goto async_io_error2;
- for (dp = driver_data; dp < driver_data+max_files; dp++) {
- if (dp->port_num == PORT_FREE) {
- dp->bytesInBuffer = 0;
- dp->totalNeeded = packet_bytes;
- dp->inBufSize = PORT_BUFSIZ;
- dp->inbuf = DRV_BUF_ALLOC(dp->inBufSize);
- if (dp->inbuf == NULL) {
- erts_smp_mtx_unlock(&sys_driver_data_lock);
- return NULL;
- }
- erts_smp_atomic_add_nob(&sys_misc_mem_sz, dp->inBufSize);
- dp->outBufSize = 0;
- dp->outbuf = NULL;
- dp->port_num = port_num;
- dp->packet_bytes = packet_bytes;
- dp->port_pid = INVALID_HANDLE_VALUE;
- if (init_async_io(&dp->in, use_threads) == -1)
- break;
- if (init_async_io(&dp->out, use_threads) == -1)
- break;
- erts_smp_mtx_unlock(&sys_driver_data_lock);
- return dp;
- }
- }
+ return dp;
- /*
- * Error or no free driver data.
- */
+async_io_error2:
+ release_async_io(&dp->in, dp->port_num);
+async_io_error1:
+ release_async_io(&dp->out, dp->port_num);
- if (dp < driver_data+max_files) {
- release_async_io(&dp->in, dp->port_num);
- release_async_io(&dp->out, dp->port_num);
- }
- erts_smp_mtx_unlock(&sys_driver_data_lock);
+buf_alloc_error:
+ driver_free(dp);
return NULL;
}
static void
release_driver_data(DriverData* dp)
{
- erts_smp_mtx_lock(&sys_driver_data_lock);
-
#ifdef ERTS_SMP
#ifdef USE_CANCELIOEX
if (fpCancelIoEx != NULL) {
@@ -741,8 +719,7 @@ release_driver_data(DriverData* dp)
* the exit thread.
*/
- dp->port_num = PORT_FREE;
- erts_smp_mtx_unlock(&sys_driver_data_lock);
+ driver_free(dp);
}
#ifdef ERTS_SMP
@@ -837,7 +814,6 @@ threaded_handle_closer(LPVOID param)
static ErlDrvData
set_driver_data(DriverData* dp, HANDLE ifd, HANDLE ofd, int read_write, int report_exit)
{
- int index = dp - driver_data;
int result;
dp->in.fd = ifd;
@@ -856,13 +832,12 @@ set_driver_data(DriverData* dp, HANDLE ifd, HANDLE ofd, int read_write, int repo
ERL_DRV_WRITE|ERL_DRV_USE, 1);
ASSERT(result != -1);
}
- return (ErlDrvData)index;
+ return (ErlDrvData) dp;
}
static ErlDrvData
reuse_driver_data(DriverData *dp, HANDLE ifd, HANDLE ofd, int read_write, ErlDrvPort port_num)
{
- int index = dp - driver_data;
int result;
dp->port_num = port_num;
@@ -881,7 +856,7 @@ reuse_driver_data(DriverData *dp, HANDLE ifd, HANDLE ofd, int read_write, ErlDrv
ERL_DRV_WRITE|ERL_DRV_USE, 1);
ASSERT(result != -1);
}
- return (ErlDrvData)index;
+ return (ErlDrvData) dp;
}
/*
@@ -1154,12 +1129,6 @@ spawn_init(void)
((module != NULL) ? GetProcAddress(module,"CancelIoEx") : NULL);
DEBUGF(("fpCancelIoEx = %p\r\n", fpCancelIoEx));
#endif
- driver_data = (struct driver_data *)
- erts_alloc(ERTS_ALC_T_DRV_TAB, 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;
return 0;
}
@@ -1290,9 +1259,12 @@ spawn_start(ErlDrvPort port_num, char* name, SysDriverOpts* opts)
#endif
retval = set_driver_data(dp, hFromChild, hToChild, opts->read_write,
opts->exit_status);
- if (retval != ERL_DRV_ERROR_GENERAL && retval != ERL_DRV_ERROR_ERRNO)
- /* We assume that this cannot generate a negative number */
- erts_port[port_num].os_pid = (SWord) pid;
+ if (retval != ERL_DRV_ERROR_GENERAL && retval != ERL_DRV_ERROR_ERRNO) {
+ Port *prt = erts_drvport2port_raw(port_num);
+ /* We assume that this cannot generate a negative number */
+ ASSERT(prt);
+ prt->os_pid = (SWord) pid;
+ }
}
if (retval != ERL_DRV_ERROR_GENERAL && retval != ERL_DRV_ERROR_ERRNO)
@@ -2281,12 +2253,10 @@ fd_start(ErlDrvPort port_num, char* name, SysDriverOpts* opts)
**/
if (!create_file_thread(&dp->in, DO_READ)) {
- dp->port_num = PORT_FREE;
return ERL_DRV_ERROR_GENERAL;
}
if (!create_file_thread(&dp->out, DO_WRITE)) {
- dp->port_num = PORT_FREE;
return ERL_DRV_ERROR_GENERAL;
}
@@ -2306,10 +2276,9 @@ fd_start(ErlDrvPort port_num, char* name, SysDriverOpts* opts)
}
}
-static void fd_stop(ErlDrvData d)
+static void fd_stop(ErlDrvData data)
{
- int fd = (int)d;
- DriverData* dp = driver_data+fd;
+ DriverData * dp = (DriverData *) data;
/*
* There's no way we can terminate an fd port in a consistent way.
* Instead we let it live until it's opened again (which it is,
@@ -2372,16 +2341,10 @@ vanilla_start(ErlDrvPort port_num, char* name, SysDriverOpts* opts)
}
static void
-stop(ErlDrvData index)
-{
- common_stop((int)index);
-}
-
-static void common_stop(int index)
+stop(ErlDrvData data)
{
- DriverData* dp = driver_data+index;
-
- DEBUGF(("common_stop(%d)\n", index));
+ DriverData *dp = (DriverData *) data;
+ DEBUGF(("stop(%p)\n", dp));
if (dp->in.ov.hEvent != NULL) {
(void) driver_select(dp->port_num,
@@ -2403,7 +2366,6 @@ static void common_stop(int index)
*/
HANDLE thread;
DWORD tid;
- dp->port_num = PORT_EXITING;
thread = (HANDLE *) _beginthreadex(NULL, 0, threaded_exiter, dp, 0, &tid);
CloseHandle(thread);
}
@@ -2528,22 +2490,17 @@ threaded_exiter(LPVOID param)
static void
output(ErlDrvData drv_data, char* buf, ErlDrvSizeT len)
-/* long drv_data; /* The slot to use in the driver data table.
+/* ErlDrvData 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. */
/* ErlDrvSizeT len; /* Number of bytes to write. */
{
- DriverData* dp;
+ DriverData* dp = (DriverData *) drv_data;
int pb; /* The header size for this port. */
- int port_num; /* The actual port number (for diagnostics). */
char* current;
- dp = driver_data + (int)drv_data;
- if ((port_num = dp->port_num) == -1)
- return ; /*-1;*/
-
pb = dp->packet_bytes;
if ((pb+len) == 0)
@@ -2554,7 +2511,7 @@ output(ErlDrvData drv_data, char* buf, ErlDrvSizeT len)
*/
if ((pb == 2 && len > 65535) || (pb == 1 && len > 255)) {
- driver_failure_posix(port_num, EINVAL);
+ driver_failure_posix(dp->port_num, EINVAL);
return ; /* -1; */
}
@@ -2568,7 +2525,7 @@ output(ErlDrvData drv_data, char* buf, ErlDrvSizeT len)
ASSERT(!dp->outbuf);
dp->outbuf = DRV_BUF_ALLOC(pb+len);
if (!dp->outbuf) {
- driver_failure_posix(port_num, ENOMEM);
+ driver_failure_posix(dp->port_num, ENOMEM);
return ; /* -1; */
}
@@ -2598,7 +2555,7 @@ output(ErlDrvData drv_data, char* buf, ErlDrvSizeT len)
memcpy(current, buf, len);
if (!async_write_file(&dp->out, dp->outbuf, pb+len)) {
- set_busy_port(port_num, 1);
+ set_busy_port(dp->port_num, 1);
} else {
dp->out.ov.Offset += pb+len; /* For vanilla driver. */
/* XXX OffsetHigh should be changed too. */
@@ -2633,10 +2590,9 @@ ready_input(ErlDrvData drv_data, ErlDrvEvent ready_event)
{
int error = 0; /* The error code (assume initially no errors). */
DWORD bytesRead; /* Number of bytes read. */
- DriverData* dp;
+ DriverData* dp = (DriverData *) drv_data;
int pb;
- dp = driver_data+(int)drv_data;
pb = dp->packet_bytes;
#ifdef ERTS_SMP
if(dp->in.thread == (HANDLE) -1) {
@@ -2804,7 +2760,7 @@ static void
ready_output(ErlDrvData drv_data, ErlDrvEvent ready_event)
{
DWORD bytesWritten;
- DriverData* dp = driver_data + (int)drv_data;
+ DriverData *dp = (DriverData *) drv_data;
int error;
#ifdef ERTS_SMP
@@ -2812,7 +2768,7 @@ ready_output(ErlDrvData drv_data, ErlDrvEvent ready_event)
dp->out.async_io_active = 0;
}
#endif
- DEBUGF(("ready_output(%d, 0x%x)\n", drv_data, ready_event));
+ DEBUGF(("ready_output(%p, 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 successful
@@ -2867,7 +2823,7 @@ sys_init_io(void)
can change our view of the number of open files possible.
We estimate the number to twice the amount of ports.
We really dont know on windows, do we? */
- max_files = 2*erts_max_ports;
+ max_files = 2*erts_ptab_max(&erts_port);
}
#ifdef ERTS_SMP
@@ -3322,9 +3278,6 @@ void erl_sys_init(void)
noinherit_std_handle(STD_INPUT_HANDLE);
noinherit_std_handle(STD_ERROR_HANDLE);
-
- erts_smp_mtx_init(&sys_driver_data_lock, "sys_driver_data_lock");
-
#ifdef ERTS_SMP
erts_smp_tsd_key_create(&win32_errstr_key);
InitializeCriticalSection(&htbc_lock);