summaryrefslogtreecommitdiff
path: root/erts/emulator/nifs
diff options
context:
space:
mode:
authorRaimo Niskanen <raimo@erlang.org>2020-11-20 17:17:06 +0100
committerRaimo Niskanen <raimo@erlang.org>2020-12-03 12:32:13 +0100
commit6f3ebb6c8a6c120f2349777cdb04106081759cb5 (patch)
treee633e8fba9576080830336bd6e002667555f1498 /erts/emulator/nifs
parent5e9f5de8a68be0df57f682554d85e3c78b2d7d6d (diff)
downloaderlang-6f3ebb6c8a6c120f2349777cdb04106081759cb5.tar.gz
Implement efficient send continuation
Diffstat (limited to 'erts/emulator/nifs')
-rw-r--r--erts/emulator/nifs/common/prim_socket_nif.c116
-rw-r--r--erts/emulator/nifs/common/socket_util.c20
-rw-r--r--erts/emulator/nifs/common/socket_util.h4
3 files changed, 71 insertions, 69 deletions
diff --git a/erts/emulator/nifs/common/prim_socket_nif.c b/erts/emulator/nifs/common/prim_socket_nif.c
index 053bf1cbe6..905dff630a 100644
--- a/erts/emulator/nifs/common/prim_socket_nif.c
+++ b/erts/emulator/nifs/common/prim_socket_nif.c
@@ -1234,7 +1234,8 @@ static ERL_NIF_TERM esock_sendmsg(ErlNifEnv* env,
ERL_NIF_TERM sockRef,
ERL_NIF_TERM sendRef,
ERL_NIF_TERM eMsg,
- int flags);
+ int flags,
+ ERL_NIF_TERM eIOV);
static ERL_NIF_TERM esock_recv(ErlNifEnv* env,
ESockDescriptor* descP,
ERL_NIF_TERM sendRef,
@@ -4664,7 +4665,7 @@ ERL_NIF_TERM nif_open(ErlNifEnv* env,
if (! GET_INT(env, argv[0], &fd)) {
if (IS_INTEGER(env, argv[0]))
- return esock_make_invalid_integer(env, argv[0]);
+ return esock_make_error_invalid_integer(env, argv[0]);
else
return enif_make_badarg(env);
}
@@ -4692,7 +4693,7 @@ ERL_NIF_TERM nif_open(ErlNifEnv* env,
if (! GET_INT(env, argv[2], &proto)) {
if (IS_INTEGER(env, argv[2]))
- return esock_make_invalid_integer(env, argv[2]);
+ return esock_make_error_invalid_integer(env, argv[2]);
else
return enif_make_badarg(env);
}
@@ -5639,7 +5640,7 @@ ERL_NIF_TERM nif_listen(ErlNifEnv* env,
}
if (! GET_INT(env, argv[1], &backlog)) {
if (IS_INTEGER(env, argv[1]))
- return esock_make_invalid_integer(env, argv[1]);
+ return esock_make_error_invalid_integer(env, argv[1]);
else
return enif_make_badarg(env);
}
@@ -6230,9 +6231,9 @@ BOOLEAN_T esock_accept_accepted(ErlNifEnv* env,
*
* Arguments:
* Socket (ref) - Points to the socket descriptor.
- * SendRef - A unique id for this (send) request.
- * Data - The data to send in the form of a IOVec.
- * Flags - Send flags.
+ * Bin - The data to send as a binary()
+ * Flags - Send flags as an integer()
+ * SendRef - A unique id reference() for this (send) request.
*/
static
@@ -6254,7 +6255,7 @@ ERL_NIF_TERM nif_send(ErlNifEnv* env,
SGDBG( ("SOCKET", "nif_send -> entry with argc: %d\r\n", argc) );
sockRef = argv[0]; // We need this in case we send in case we send abort
- sendRef = argv[1];
+ sendRef = argv[3];
if (! ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) {
SSDBG( descP, ("SOCKET", "nif_send -> get resource failed\r\n") );
@@ -6264,14 +6265,14 @@ ERL_NIF_TERM nif_send(ErlNifEnv* env,
/* Extract arguments and perform preliminary validation */
if ((! enif_is_ref(env, sendRef)) ||
- (! GET_BIN(env, argv[2], &sndData))) {
+ (! GET_BIN(env, argv[1], &sndData))) {
SGDBG( ("SOCKET", "nif_send -> argv decode failed\r\n") );
return enif_make_badarg(env);
}
- if (! GET_INT(env, argv[3], &flags)) {
+ if (! GET_INT(env, argv[2], &flags)) {
SGDBG( ("SOCKET", "nif_send -> argv decode failed\r\n") );
- if (IS_INTEGER(env, argv[3]))
- return esock_make_invalid_integer(env, argv[3]);
+ if (IS_INTEGER(env, argv[2]))
+ return esock_make_error_invalid_integer(env, argv[2]);
else
return enif_make_badarg(env);
}
@@ -6342,7 +6343,7 @@ ERL_NIF_TERM esock_send(ErlNifEnv* env,
send_result = (ssize_t) sndDataP->size;
if ((size_t) send_result != sndDataP->size)
- return esock_make_invalid(env, atom_data_size);
+ return esock_make_error_invalid(env, atom_data_size);
/* Ensure that we either have no current writer or we are it,
* or enqueue this process if there is a current writer */
@@ -6377,10 +6378,10 @@ ERL_NIF_TERM esock_send(ErlNifEnv* env,
*
* Arguments:
* Socket (ref) - Points to the socket descriptor.
- * SendRef - A unique id for this (send) request.
- * Data - The data to send in the form of a IOVec.
+ * Bin - The data to send as a binary()
* Dest - Destination (socket) address.
- * Flags - Send flags.
+ * Flags - Send flags as an integer().
+ * SendRef - A unique id reference() for this (send) request.
*/
static
@@ -6405,7 +6406,7 @@ ERL_NIF_TERM nif_sendto(ErlNifEnv* env,
SGDBG( ("SOCKET", "nif_sendto -> entry with argc: %d\r\n", argc) );
sockRef = argv[0]; // We need this in case we send abort (to the caller)
- sendRef = argv[1];
+ sendRef = argv[4];
if (! ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) {
SSDBG( descP, ("SOCKET", "nif_sendto -> get resource failed\r\n") );
@@ -6415,18 +6416,18 @@ ERL_NIF_TERM nif_sendto(ErlNifEnv* env,
/* Extract arguments and perform preliminary validation */
if ((! enif_is_ref(env, sendRef)) ||
- (! GET_BIN(env, argv[2], &sndData))) {
+ (! GET_BIN(env, argv[1], &sndData))) {
SGDBG( ("SOCKET", "nif_sendto -> argv decode failed\r\n") );
return enif_make_badarg(env);
}
- if (! GET_INT(env, argv[4], &flags)) {
+ if (! GET_INT(env, argv[3], &flags)) {
SGDBG( ("SOCKET", "nif_sendto -> argv decode failed\r\n") );
- if (IS_INTEGER(env, argv[4]))
- return esock_make_invalid_integer(env, argv[4]);
+ if (IS_INTEGER(env, argv[3]))
+ return esock_make_error_invalid_integer(env, argv[3]);
else
return enif_make_badarg(env);
}
- eSockAddr = argv[3];
+ eSockAddr = argv[2];
if (! esock_decode_sockaddr(env, eSockAddr,
&remoteAddr,
&remoteAddrLen)) {
@@ -6490,7 +6491,7 @@ ERL_NIF_TERM esock_sendto(ErlNifEnv* env,
sendto_result = (ssize_t) dataP->size;
if ((size_t) sendto_result != dataP->size)
- return esock_make_invalid(env, atom_data_size);
+ return esock_make_error_invalid(env, atom_data_size);
/* Ensure that we either have no current writer or we are it,
* or enqueue this process if there is a current writer */
@@ -6532,9 +6533,9 @@ ERL_NIF_TERM esock_sendto(ErlNifEnv* env,
*
* Arguments:
* Socket (ref) - Points to the socket descriptor.
- * SendRef - A unique id for this (send) request.
- * Msg - Message Header - data and (maybe) control and dest
- * Flags - Send flags.
+ * Msg - Message - map() with data and (maybe) control and dest
+ * Flags - Send flags as an integer().
+ * SendRef - A unique id reference() for this (send) request.
*/
static
@@ -6545,17 +6546,18 @@ ERL_NIF_TERM nif_sendmsg(ErlNifEnv* env,
#ifdef __WIN32__
return enif_raise_exception(env, MKA(env, "notsup"));
#else
- ERL_NIF_TERM res, sockRef, sendRef, eMsg;
+ ERL_NIF_TERM res, sockRef, sendRef, eMsg, eIOV;
ESockDescriptor* descP;
int flags;
- ESOCK_ASSERT( argc == 4 );
+ ESOCK_ASSERT( argc == 5 );
SGDBG( ("SOCKET", "nif_sendmsg -> entry with argc: %d\r\n", argc) );
sockRef = argv[0]; // We need this in case we send abort (to the caller)
- sendRef = argv[1];
- eMsg = argv[2];
+ eMsg = argv[1];
+ sendRef = argv[3];
+ eIOV = argv[4];
if (! ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) {
SSDBG( descP, ("SOCKET", "nif_sendmsg -> get resource failed\r\n") );
@@ -6569,9 +6571,9 @@ ERL_NIF_TERM nif_sendmsg(ErlNifEnv* env,
SGDBG( ("SOCKET", "nif_sendmsg -> argv decode failed\r\n") );
return enif_make_badarg(env);
}
- if (! GET_INT(env, argv[3], &flags)) {
- if (IS_INTEGER(env, argv[3]))
- return esock_make_invalid_integer(env, argv[3]);
+ if (! GET_INT(env, argv[2], &flags)) {
+ if (IS_INTEGER(env, argv[2]))
+ return esock_make_error_invalid_integer(env, argv[2]);
else
return enif_make_badarg(env);
}
@@ -6586,7 +6588,7 @@ ERL_NIF_TERM nif_sendmsg(ErlNifEnv* env,
sockRef, descP->sock, descP->writeState,
sendRef, flags) );
- res = esock_sendmsg(env, descP, sockRef, sendRef, eMsg, flags);
+ res = esock_sendmsg(env, descP, sockRef, sendRef, eMsg, flags, eIOV);
MUNLOCK(descP->writeMtx);
@@ -6607,9 +6609,10 @@ ERL_NIF_TERM esock_sendmsg(ErlNifEnv* env,
ERL_NIF_TERM sockRef,
ERL_NIF_TERM sendRef,
ERL_NIF_TERM eMsg,
- int flags)
+ int flags,
+ ERL_NIF_TERM eIOV)
{
- ERL_NIF_TERM res, eAddr, eIOV, eCtrl;
+ ERL_NIF_TERM res, eAddr, eCtrl;
ESockAddress addr;
struct msghdr msgHdr;
ErlNifIOVec *iovec = NULL;
@@ -6666,12 +6669,11 @@ ERL_NIF_TERM esock_sendmsg(ErlNifEnv* env,
}
/* Extract the *mandatory* 'iov', which must be an erlang:iovec(),
- * and not larger than IOV_MAX
+ * from which we take at most IOV_MAX binaries
*/
- if ((! GET_MAP_VAL(env, eMsg, esock_atom_iov, &eIOV)) ||
- (! enif_inspect_iovec(NULL, data.iov_max, eIOV, &tail, &iovec))) {
+ if ((! enif_inspect_iovec(NULL, data.iov_max, eIOV, &tail, &iovec))) {
SSDBG( descP, ("SOCKET",
- "esock_sendmsg {%d} -> no iov or not an iov\r\n",
+ "esock_sendmsg {%d} -> not an iov\r\n",
descP->sock) );
return esock_make_invalid(env, esock_atom_iov);
@@ -6948,13 +6950,13 @@ ERL_NIF_TERM nif_recv(ErlNifEnv* env,
return enif_make_badarg(env);
if (argv2_is_integer)
- return esock_make_invalid_integer(env, argv[2]);
+ return esock_make_error_invalid_integer(env, argv[2]);
return
- esock_make_invalid_integer(env, argv[3]);
+ esock_make_error_invalid_integer(env, argv[3]);
}
len = (ssize_t) elen;
if (elen != (ErlNifUInt64) len)
- return esock_make_invalid_integer(env, elen);
+ return esock_make_error_invalid_integer(env, elen);
MLOCK(descP->readMtx);
@@ -7129,13 +7131,13 @@ ERL_NIF_TERM nif_recvfrom(ErlNifEnv* env,
return enif_make_badarg(env);
if (argv2_is_integer)
- return esock_make_invalid_integer(env, argv[2]);
+ return esock_make_error_invalid_integer(env, argv[2]);
return
- esock_make_invalid_integer(env, argv[3]);
+ esock_make_error_invalid_integer(env, argv[3]);
}
len = (ssize_t) elen;
if (elen != (ErlNifUInt64) len)
- return esock_make_invalid_integer(env, elen);
+ return esock_make_error_invalid_integer(env, elen);
MLOCK(descP->readMtx);
@@ -7321,20 +7323,20 @@ ERL_NIF_TERM nif_recvmsg(ErlNifEnv* env,
return enif_make_badarg(env);
if (argv2_is_integer)
- return esock_make_invalid_integer(env, argv[2]);
+ return esock_make_error_invalid_integer(env, argv[2]);
if (argv3_is_integer)
- return esock_make_invalid_integer(env, argv[3]);
+ return esock_make_error_invalid_integer(env, argv[3]);
return
- esock_make_invalid_integer(env, argv[4]);
+ esock_make_error_invalid_integer(env, argv[4]);
}
bufSz = (ssize_t) eBufSz;
if (eBufSz != (ErlNifUInt64) bufSz)
- return esock_make_invalid_integer(env, eBufSz);
+ return esock_make_error_invalid_integer(env, eBufSz);
ctrlSz = (ssize_t) eCtrlSz;
if (eCtrlSz != (ErlNifUInt64) ctrlSz)
- return esock_make_invalid_integer(env, eCtrlSz);
+ return esock_make_error_invalid_integer(env, eCtrlSz);
MLOCK(descP->readMtx);
@@ -8045,7 +8047,7 @@ ERL_NIF_TERM nif_setopt(ErlNifEnv* env,
if (! IS_INTEGER(env, argv[2]))
return enif_make_badarg(env);
else
- return esock_make_invalid_integer(env, argv[2]);
+ return esock_make_error_invalid_integer(env, argv[2]);
}
eVal = argv[3];
@@ -8067,7 +8069,7 @@ ERL_NIF_TERM nif_setopt(ErlNifEnv* env,
SGDBG( ("SOCKET", "nif_setopt -> failed arg check\r\n") );
if (IS_INTEGER(env, argv[1]))
- return esock_make_invalid_integer(env, argv[1]);
+ return esock_make_error_invalid_integer(env, argv[1]);
else
return enif_make_badarg(env);
#endif // #ifdef __WIN32__ #else
@@ -9729,7 +9731,7 @@ ERL_NIF_TERM nif_getopt(ErlNifEnv* env,
if (! IS_INTEGER(env, argv[2]))
return enif_make_badarg(env);
else
- return esock_make_invalid_integer(env, argv[2]);
+ return esock_make_error_invalid_integer(env, argv[2]);
}
if (esock_decode_level(env, argv[1], &level)) {
@@ -9748,7 +9750,7 @@ ERL_NIF_TERM nif_getopt(ErlNifEnv* env,
SGDBG( ("SOCKET", "nif_getopt -> failed args check\r\n") );
if (IS_INTEGER(env, argv[1]))
- return esock_make_invalid_integer(env, argv[1]);
+ return esock_make_error_invalid_integer(env, argv[1]);
else
return enif_make_badarg(env);
@@ -10967,7 +10969,7 @@ ERL_NIF_TERM esock_getopt_bin_opt(ErlNifEnv* env,
vsz = (SOCKOPTLEN_T) binP->size;
if (SZT(vsz) != binP->size) {
- result = esock_make_error(env, esock_atom_invalid);
+ result = esock_make_error_invalid(env, atom_data_size);
} else {
ESOCK_ASSERT( ALLOC_BIN(vsz, &val) );
sys_memcpy(val.data, binP->data, vsz);
@@ -16899,7 +16901,7 @@ ErlNifFunc esock_funcs[] =
{"nif_accept", 2, nif_accept, 0},
{"nif_send", 4, nif_send, 0},
{"nif_sendto", 5, nif_sendto, 0},
- {"nif_sendmsg", 4, nif_sendmsg, 0},
+ {"nif_sendmsg", 5, nif_sendmsg, 0},
{"nif_recv", 4, nif_recv, 0},
{"nif_recvfrom", 4, nif_recvfrom, 0},
{"nif_recvmsg", 5, nif_recvmsg, 0},
diff --git a/erts/emulator/nifs/common/socket_util.c b/erts/emulator/nifs/common/socket_util.c
index 1f06256ebd..6c196ef6f7 100644
--- a/erts/emulator/nifs/common/socket_util.c
+++ b/erts/emulator/nifs/common/socket_util.c
@@ -1766,33 +1766,33 @@ ERL_NIF_TERM esock_make_error_invalid(ErlNifEnv* env, ERL_NIF_TERM what)
-/* Create an 'invalid' two (2) tuple in the form:
+/* Create an 'error' two (2) tuple in the form:
*
- * {invalid, Reason}
+ * {error, {invalid, {integer_range, I}}}
*
- * The second element (Reason) is already in the form of an
+ * The second element (i) is already in the form of an
* ERL_NIF_TERM so all we have to do is create the tuple.
*/
extern
-ERL_NIF_TERM esock_make_invalid(ErlNifEnv* env, ERL_NIF_TERM reason)
+ERL_NIF_TERM esock_make_error_invalid_integer(ErlNifEnv* env, ERL_NIF_TERM i)
{
- return MKT2(env, esock_atom_invalid, reason);
+ return
+ esock_make_invalid(env, MKT2(env, esock_atom_integer_range, i));
}
/* Create an 'invalid' two (2) tuple in the form:
*
- * {invalid, {integer_range, I}}
+ * {invalid, Reason}
*
- * The second element (i) is already in the form of an
+ * The second element (Reason) is already in the form of an
* ERL_NIF_TERM so all we have to do is create the tuple.
*/
extern
-ERL_NIF_TERM esock_make_invalid_integer(ErlNifEnv* env, ERL_NIF_TERM i)
+ERL_NIF_TERM esock_make_invalid(ErlNifEnv* env, ERL_NIF_TERM reason)
{
- return
- esock_make_invalid(env, MKT2(env, esock_atom_integer_range, i));
+ return MKT2(env, esock_atom_invalid, reason);
}
diff --git a/erts/emulator/nifs/common/socket_util.h b/erts/emulator/nifs/common/socket_util.h
index e0ebf1143b..f20b33fe7b 100644
--- a/erts/emulator/nifs/common/socket_util.h
+++ b/erts/emulator/nifs/common/socket_util.h
@@ -241,9 +241,9 @@ ERL_NIF_TERM esock_make_error_errno(ErlNifEnv* env, int err);
extern
ERL_NIF_TERM esock_make_error_invalid(ErlNifEnv* env, ERL_NIF_TERM what);
extern
-ERL_NIF_TERM esock_make_invalid(ErlNifEnv* env, ERL_NIF_TERM reason);
+ERL_NIF_TERM esock_make_error_invalid_integer(ErlNifEnv* env, ERL_NIF_TERM i);
extern
-ERL_NIF_TERM esock_make_invalid_integer(ErlNifEnv* env, ERL_NIF_TERM i);
+ERL_NIF_TERM esock_make_invalid(ErlNifEnv* env, ERL_NIF_TERM reason);
extern
ERL_NIF_TERM esock_raise_invalid(ErlNifEnv* env, ERL_NIF_TERM what);