aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/drivers')
-rw-r--r--erts/emulator/drivers/common/efile_drv.c4
-rw-r--r--erts/emulator/drivers/common/inet_drv.c131
-rw-r--r--erts/emulator/drivers/unix/ttsl_drv.c43
-rw-r--r--erts/emulator/drivers/win32/ttsl_drv.c4
4 files changed, 116 insertions, 66 deletions
diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c
index 6cc1295973..595b0488a8 100644
--- a/erts/emulator/drivers/common/efile_drv.c
+++ b/erts/emulator/drivers/common/efile_drv.c
@@ -1679,10 +1679,10 @@ static void invoke_pwritev(void *data) {
d->again = 0;
}
} else
- ASSERT(written == FILE_SEGMENT_WRITE);
+ ASSERT(written >= FILE_SEGMENT_WRITE);
MUTEX_LOCK(d->c.writev.q_mtx);
- driver_deq(d->c.pwritev.port, size);
+ driver_deq(d->c.pwritev.port, written);
MUTEX_UNLOCK(d->c.writev.q_mtx);
done:
EF_FREE(iov); /* Free our copy of the vector, nothing to restore */
diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c
index 2451f41a82..301ce2d0e2 100644
--- a/erts/emulator/drivers/common/inet_drv.c
+++ b/erts/emulator/drivers/common/inet_drv.c
@@ -678,8 +678,8 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n)
#define INET_LOPT_UDP_READ_PACKETS 33 /* Number of packets to read */
#define INET_OPT_RAW 34 /* Raw socket options */
#define INET_LOPT_TCP_SEND_TIMEOUT_CLOSE 35 /* auto-close on send timeout or not */
-#define INET_LOPT_TCP_MSGQ_HIWTRMRK 36 /* set local high watermark */
-#define INET_LOPT_TCP_MSGQ_LOWTRMRK 37 /* set local low watermark */
+#define INET_LOPT_MSGQ_HIWTRMRK 36 /* set local msgq high watermark */
+#define INET_LOPT_MSGQ_LOWTRMRK 37 /* set local msgq low watermark */
/* SCTP options: a separate range, from 100: */
#define SCTP_OPT_RTOINFO 100
#define SCTP_OPT_ASSOCINFO 101
@@ -5476,27 +5476,25 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
}
continue;
- case INET_LOPT_TCP_MSGQ_HIWTRMRK:
- if (desc->stype == SOCK_STREAM) {
- ErlDrvSizeT high;
- if (ival < ERL_DRV_BUSY_MSGQ_LIM_MIN
- || ERL_DRV_BUSY_MSGQ_LIM_MAX < ival)
- return -1;
- high = (ErlDrvSizeT) ival;
- erl_drv_busy_msgq_limits(desc->port, NULL, &high);
- }
+ case INET_LOPT_MSGQ_HIWTRMRK: {
+ ErlDrvSizeT high;
+ if (ival < ERL_DRV_BUSY_MSGQ_LIM_MIN
+ || ERL_DRV_BUSY_MSGQ_LIM_MAX < ival)
+ return -1;
+ high = (ErlDrvSizeT) ival;
+ erl_drv_busy_msgq_limits(desc->port, NULL, &high);
continue;
+ }
- case INET_LOPT_TCP_MSGQ_LOWTRMRK:
- if (desc->stype == SOCK_STREAM) {
- ErlDrvSizeT low;
- if (ival < ERL_DRV_BUSY_MSGQ_LIM_MIN
- || ERL_DRV_BUSY_MSGQ_LIM_MAX < ival)
- return -1;
- low = (ErlDrvSizeT) ival;
- erl_drv_busy_msgq_limits(desc->port, &low, NULL);
- }
+ case INET_LOPT_MSGQ_LOWTRMRK: {
+ ErlDrvSizeT low;
+ if (ival < ERL_DRV_BUSY_MSGQ_LIM_MIN
+ || ERL_DRV_BUSY_MSGQ_LIM_MAX < ival)
+ return -1;
+ low = (ErlDrvSizeT) ival;
+ erl_drv_busy_msgq_limits(desc->port, &low, NULL);
continue;
+ }
case INET_LOPT_TCP_SEND_TIMEOUT:
if (desc->stype == SOCK_STREAM) {
@@ -6398,31 +6396,23 @@ static ErlDrvSSizeT inet_fill_opts(inet_descriptor* desc,
}
continue;
- case INET_LOPT_TCP_MSGQ_HIWTRMRK:
- if (desc->stype == SOCK_STREAM) {
- ErlDrvSizeT high = ERL_DRV_BUSY_MSGQ_READ_ONLY;
- *ptr++ = opt;
- erl_drv_busy_msgq_limits(desc->port, NULL, &high);
- ival = high > INT_MAX ? INT_MAX : (int) high;
- put_int32(ival, ptr);
- }
- else {
- TRUNCATE_TO(0,ptr);
- }
+ case INET_LOPT_MSGQ_HIWTRMRK: {
+ ErlDrvSizeT high = ERL_DRV_BUSY_MSGQ_READ_ONLY;
+ *ptr++ = opt;
+ erl_drv_busy_msgq_limits(desc->port, NULL, &high);
+ ival = high > INT_MAX ? INT_MAX : (int) high;
+ put_int32(ival, ptr);
continue;
+ }
- case INET_LOPT_TCP_MSGQ_LOWTRMRK:
- if (desc->stype == SOCK_STREAM) {
- ErlDrvSizeT low = ERL_DRV_BUSY_MSGQ_READ_ONLY;
- *ptr++ = opt;
- erl_drv_busy_msgq_limits(desc->port, &low, NULL);
- ival = low > INT_MAX ? INT_MAX : (int) low;
- put_int32(ival, ptr);
- }
- else {
- TRUNCATE_TO(0,ptr);
- }
+ case INET_LOPT_MSGQ_LOWTRMRK: {
+ ErlDrvSizeT low = ERL_DRV_BUSY_MSGQ_READ_ONLY;
+ *ptr++ = opt;
+ erl_drv_busy_msgq_limits(desc->port, &low, NULL);
+ ival = low > INT_MAX ? INT_MAX : (int) low;
+ put_int32(ival, ptr);
continue;
+ }
case INET_LOPT_TCP_SEND_TIMEOUT:
if (desc->stype == SOCK_STREAM) {
@@ -7471,6 +7461,20 @@ static void inet_stop(inet_descriptor* desc)
FREE(desc);
}
+static void set_default_msgq_limits(ErlDrvPort port)
+{
+ ErlDrvSizeT q_high = INET_HIGH_MSGQ_WATERMARK;
+ ErlDrvSizeT q_low = INET_LOW_MSGQ_WATERMARK;
+ if (q_low < ERL_DRV_BUSY_MSGQ_LIM_MIN)
+ q_low = ERL_DRV_BUSY_MSGQ_LIM_MIN;
+ else if (q_low > ERL_DRV_BUSY_MSGQ_LIM_MAX)
+ q_low = ERL_DRV_BUSY_MSGQ_LIM_MAX;
+ if (q_high < ERL_DRV_BUSY_MSGQ_LIM_MIN)
+ q_high = ERL_DRV_BUSY_MSGQ_LIM_MIN;
+ else if (q_high > ERL_DRV_BUSY_MSGQ_LIM_MAX)
+ q_high = ERL_DRV_BUSY_MSGQ_LIM_MAX;
+ erl_drv_busy_msgq_limits(port, &q_low, &q_high);
+}
/* Allocate descriptor */
static ErlDrvData inet_start(ErlDrvPort port, int size, int protocol)
@@ -8091,9 +8095,8 @@ static int tcp_inet_init(void)
/* initialize the TCP descriptor */
-static ErlDrvData tcp_inet_start(ErlDrvPort port, char* args)
+static ErlDrvData prep_tcp_inet_start(ErlDrvPort port, char* args)
{
- ErlDrvSizeT q_low, q_high;
tcp_descriptor* desc;
DEBUGF(("tcp_inet_start(%ld) {\r\n", (long)port));
@@ -8103,17 +8106,6 @@ static ErlDrvData tcp_inet_start(ErlDrvPort port, char* args)
return ERL_DRV_ERROR_ERRNO;
desc->high = INET_HIGH_WATERMARK;
desc->low = INET_LOW_WATERMARK;
- q_high = INET_HIGH_MSGQ_WATERMARK;
- q_low = INET_LOW_MSGQ_WATERMARK;
- if (q_low < ERL_DRV_BUSY_MSGQ_LIM_MIN)
- q_low = ERL_DRV_BUSY_MSGQ_LIM_MIN;
- else if (q_low > ERL_DRV_BUSY_MSGQ_LIM_MAX)
- q_low = ERL_DRV_BUSY_MSGQ_LIM_MAX;
- if (q_high < ERL_DRV_BUSY_MSGQ_LIM_MIN)
- q_high = ERL_DRV_BUSY_MSGQ_LIM_MIN;
- else if (q_high > ERL_DRV_BUSY_MSGQ_LIM_MAX)
- q_high = ERL_DRV_BUSY_MSGQ_LIM_MAX;
- erl_drv_busy_msgq_limits(port, &q_low, &q_high);
desc->send_timeout = INET_INFINITY;
desc->send_timeout_close = 0;
desc->busy_on_send = 0;
@@ -8130,6 +8122,12 @@ static ErlDrvData tcp_inet_start(ErlDrvPort port, char* args)
return (ErlDrvData) desc;
}
+static ErlDrvData tcp_inet_start(ErlDrvPort port, char* args)
+{
+ ErlDrvData data = prep_tcp_inet_start(port, args);
+ set_default_msgq_limits(port);
+ return data;
+}
/* Copy a descriptor, by creating a new port with same settings
* as the descriptor desc.
* return NULL on error (SYSTEM_LIMIT no ports avail)
@@ -8141,7 +8139,7 @@ static tcp_descriptor* tcp_inet_copy(tcp_descriptor* desc,SOCKET s,
ErlDrvPort port = desc->inet.port;
tcp_descriptor* copy_desc;
- copy_desc = (tcp_descriptor*) tcp_inet_start(port, NULL);
+ copy_desc = (tcp_descriptor*) prep_tcp_inet_start(port, NULL);
/* Setup event if needed */
if ((copy_desc->inet.s = s) != INVALID_SOCKET) {
@@ -9864,12 +9862,15 @@ static int should_use_so_bsdcompat(void)
* as the descriptor desc.
* return NULL on error (ENFILE no ports avail)
*/
+static ErlDrvData packet_inet_start(ErlDrvPort port, char* args, int protocol);
+
static udp_descriptor* sctp_inet_copy(udp_descriptor* desc, SOCKET s, int* err)
{
+ ErlDrvSizeT q_low, q_high;
ErlDrvPort port = desc->inet.port;
udp_descriptor* copy_desc;
- copy_desc = (udp_descriptor*) sctp_inet_start(port, NULL);
+ copy_desc = (udp_descriptor*) packet_inet_start(port, NULL, IPPROTO_SCTP);
/* Setup event if needed */
if ((copy_desc->inet.s = s) != INVALID_SOCKET) {
@@ -9900,9 +9901,17 @@ static udp_descriptor* sctp_inet_copy(udp_descriptor* desc, SOCKET s, int* err)
FREE(copy_desc);
return NULL;
}
+
+ /* Read busy msgq limits of parent */
+ q_low = q_high = ERL_DRV_BUSY_MSGQ_READ_ONLY;
+ erl_drv_busy_msgq_limits(desc->inet.port, &q_low, &q_high);
+ /* Write same busy msgq limits to child */
+ erl_drv_busy_msgq_limits(port, &q_low, &q_high);
+
copy_desc->inet.port = port;
copy_desc->inet.dport = driver_mk_port(port);
*err = 0;
+
return copy_desc;
}
#endif
@@ -9935,13 +9944,17 @@ static ErlDrvData packet_inet_start(ErlDrvPort port, char* args, int protocol)
static ErlDrvData udp_inet_start(ErlDrvPort port, char *args)
{
- return packet_inet_start(port, args, IPPROTO_UDP);
+ ErlDrvData data = packet_inet_start(port, args, IPPROTO_UDP);
+ set_default_msgq_limits(port);
+ return data;
}
#ifdef HAVE_SCTP
static ErlDrvData sctp_inet_start(ErlDrvPort port, char *args)
{
- return packet_inet_start(port, args, IPPROTO_SCTP);
+ ErlDrvData data = packet_inet_start(port, args, IPPROTO_SCTP);
+ set_default_msgq_limits(port);
+ return data;
}
#endif
diff --git a/erts/emulator/drivers/unix/ttsl_drv.c b/erts/emulator/drivers/unix/ttsl_drv.c
index bedb5ef784..1e436830e7 100644
--- a/erts/emulator/drivers/unix/ttsl_drv.c
+++ b/erts/emulator/drivers/unix/ttsl_drv.c
@@ -42,6 +42,9 @@ static ErlDrvData ttysl_start(ErlDrvPort, char*);
#include <locale.h>
#include <unistd.h>
#include <termios.h>
+#ifdef HAVE_WCWIDTH
+#include <wchar.h>
+#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
@@ -95,6 +98,9 @@ static int lpos; /* The current "cursor position" in the line buf
*/
#define CONTROL_TAG 0x10000000U /* Control character, value in first position */
#define ESCAPED_TAG 0x01000000U /* Escaped character, value in first position */
+#ifdef HAVE_WCWIDTH
+#define WIDE_TAG 0x02000000U /* Wide character, value in first position */
+#endif
#define TAG_MASK 0xFF000000U
#define MAXSIZE (1 << 16)
@@ -597,12 +603,20 @@ static int check_buf_size(byte *s, int n)
}
if (utf8_mode) { /* That is, terminal is UTF8 compliant */
if (ch >= 128 || isprint(ch)) {
- DEBUGLOG(("Printable(UTF-8:%d):%d",(pos - opos),ch));
- size++; /* Buffer contains wide characters... */
+#ifdef HAVE_WCWIDTH
+ int width;
+#endif
+ DEBUGLOG(("Printable(UTF-8:%d):%d",pos,ch));
+ size++;
+#ifdef HAVE_WCWIDTH
+ if ((width = wcwidth(ch)) > 1) {
+ size += width - 1;
+ }
+#endif
} else if (ch == '\t') {
size += 8;
} else {
- DEBUGLOG(("Magic(UTF-8:%d):%d",(pos - opos),ch));
+ DEBUGLOG(("Magic(UTF-8:%d):%d",pos,ch));
size += 2;
}
} else {
@@ -868,12 +882,22 @@ static int step_over_chars(int n)
end = lbuf + llen;
c = lbuf + lpos;
for ( ; n > 0 && c < end; --n) {
+#ifdef HAVE_WCWIDTH
+ while (*c & WIDE_TAG) {
+ c++;
+ }
+#endif
c++;
while (c < end && (*c & TAG_MASK) && ((*c & ~TAG_MASK) == 0))
c++;
}
for ( ; n < 0 && c > beg; n++) {
--c;
+#ifdef HAVE_WCWIDTH
+ while (c > beg + 1 && (c[-1] & WIDE_TAG)) {
+ --c;
+ }
+#endif
while (c > beg && (*c & TAG_MASK) && ((*c & ~TAG_MASK) == 0))
--c;
}
@@ -899,6 +923,15 @@ static int insert_buf(byte *s, int n)
++pos;
}
if ((utf8_mode && (ch >= 128 || isprint(ch))) || (ch <= 255 && isprint(ch))) {
+#ifdef HAVE_WCWIDTH
+ int width;
+ if ((width = wcwidth(ch)) > 1) {
+ while (--width) {
+ DEBUGLOG(("insert_buf: Wide(UTF-8):%d,%d",width,ch));
+ lbuf[lpos++] = (WIDE_TAG | ((Uint32) ch));
+ }
+ }
+#endif
DEBUGLOG(("insert_buf: Printable(UTF-8):%d",ch));
lbuf[lpos++] = (Uint32) ch;
} else if (ch >= 128) { /* not utf8 mode */
@@ -1006,6 +1039,10 @@ static int write_buf(Uint32 *s, int n)
if (octbuff != octtmp) {
driver_free(octbuff);
}
+#ifdef HAVE_WCWIDTH
+ } else if (*s & WIDE_TAG) {
+ --n; s++;
+#endif
} else {
DEBUGLOG(("Very unexpected character %d",(int) *s));
++n;
diff --git a/erts/emulator/drivers/win32/ttsl_drv.c b/erts/emulator/drivers/win32/ttsl_drv.c
index 1a74d21e99..8b5e3eeefd 100644
--- a/erts/emulator/drivers/win32/ttsl_drv.c
+++ b/erts/emulator/drivers/win32/ttsl_drv.c
@@ -414,12 +414,12 @@ static int check_buf_size(byte *s, int n)
}
if (utf8_mode) { /* That is, terminal is UTF8 compliant */
if (ch >= 128 || isprint(ch)) {
- DEBUGLOG(("Printable(UTF-8:%d):%d",(pos - opos),ch));
+ DEBUGLOG(("Printable(UTF-8:%d):%d",pos,ch));
size++; /* Buffer contains wide characters... */
} else if (ch == '\t') {
size += 8;
} else {
- DEBUGLOG(("Magic(UTF-8:%d):%d",(pos - opos),ch));
+ DEBUGLOG(("Magic(UTF-8:%d):%d",pos,ch));
size += 2;
}
} else {