udp: add uv_udp_using_recvmmsg query
Allows for determining if a buffer large enough for multiple dgrams should be allocated in alloc_cb of uv_udp_recvstart, for example. Contributes towards #2822. PR-URL: https://github.com/libuv/libuv/pull/2830 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Jameson Nash <vtjnash@gmail.com>
This commit is contained in:
parent
540d723fa4
commit
6b5aa669db
@ -391,6 +391,16 @@ API
|
|||||||
.. versionchanged:: 1.37.0 :man:`recvmmsg(2)` support is no longer enabled implicitly,
|
.. versionchanged:: 1.37.0 :man:`recvmmsg(2)` support is no longer enabled implicitly,
|
||||||
it must be explicitly requested by passing the `UV_UDP_RECVMMSG` flag to
|
it must be explicitly requested by passing the `UV_UDP_RECVMMSG` flag to
|
||||||
:c:func:`uv_udp_init_ex`.
|
:c:func:`uv_udp_init_ex`.
|
||||||
|
.. versionchanged:: 1.39.0 :c:func:`uv_udp_using_recvmmsg` can be used in `alloc_cb` to
|
||||||
|
determine if a buffer sized for use with :man:`recvmmsg(2)` should be
|
||||||
|
allocated for the current handle/platform.
|
||||||
|
|
||||||
|
.. c:function:: int uv_udp_using_recvmmsg(uv_udp_t* handle)
|
||||||
|
|
||||||
|
Returns 1 if the UDP handle was created with the `UV_UDP_RECVMMSG` flag
|
||||||
|
and the platform supports :man:`recvmmsg(2)`, 0 otherwise.
|
||||||
|
|
||||||
|
.. versionadded:: 1.39.0
|
||||||
|
|
||||||
.. c:function:: int uv_udp_recv_stop(uv_udp_t* handle)
|
.. c:function:: int uv_udp_recv_stop(uv_udp_t* handle)
|
||||||
|
|
||||||
|
|||||||
@ -693,6 +693,7 @@ UV_EXTERN int uv_udp_try_send(uv_udp_t* handle,
|
|||||||
UV_EXTERN int uv_udp_recv_start(uv_udp_t* handle,
|
UV_EXTERN int uv_udp_recv_start(uv_udp_t* handle,
|
||||||
uv_alloc_cb alloc_cb,
|
uv_alloc_cb alloc_cb,
|
||||||
uv_udp_recv_cb recv_cb);
|
uv_udp_recv_cb recv_cb);
|
||||||
|
UV_EXTERN int uv_udp_using_recvmmsg(const uv_udp_t* handle);
|
||||||
UV_EXTERN int uv_udp_recv_stop(uv_udp_t* handle);
|
UV_EXTERN int uv_udp_recv_stop(uv_udp_t* handle);
|
||||||
UV_EXTERN size_t uv_udp_get_send_queue_size(const uv_udp_t* handle);
|
UV_EXTERN size_t uv_udp_get_send_queue_size(const uv_udp_t* handle);
|
||||||
UV_EXTERN size_t uv_udp_get_send_queue_count(const uv_udp_t* handle);
|
UV_EXTERN size_t uv_udp_get_send_queue_count(const uv_udp_t* handle);
|
||||||
|
|||||||
@ -270,14 +270,11 @@ static void uv__udp_recvmsg(uv_udp_t* handle) {
|
|||||||
assert(buf.base != NULL);
|
assert(buf.base != NULL);
|
||||||
|
|
||||||
#if HAVE_MMSG
|
#if HAVE_MMSG
|
||||||
if (handle->flags & UV_HANDLE_UDP_RECVMMSG) {
|
if (uv_udp_using_recvmmsg(handle)) {
|
||||||
uv_once(&once, uv__udp_mmsg_init);
|
nread = uv__udp_recvmmsg(handle, &buf);
|
||||||
if (uv__recvmmsg_avail) {
|
if (nread > 0)
|
||||||
nread = uv__udp_recvmmsg(handle, &buf);
|
count -= nread;
|
||||||
if (nread > 0)
|
continue;
|
||||||
count -= nread;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -976,6 +973,17 @@ int uv__udp_init_ex(uv_loop_t* loop,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uv_udp_using_recvmmsg(const uv_udp_t* handle) {
|
||||||
|
#if HAVE_MMSG
|
||||||
|
if (handle->flags & UV_HANDLE_UDP_RECVMMSG) {
|
||||||
|
uv_once(&once, uv__udp_mmsg_init);
|
||||||
|
return uv__recvmmsg_avail;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
|
int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
|||||||
@ -189,6 +189,11 @@ void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uv_udp_using_recvmmsg(const uv_udp_t* handle) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int uv_udp_maybe_bind(uv_udp_t* handle,
|
static int uv_udp_maybe_bind(uv_udp_t* handle,
|
||||||
const struct sockaddr* addr,
|
const struct sockaddr* addr,
|
||||||
unsigned int addrlen,
|
unsigned int addrlen,
|
||||||
|
|||||||
@ -30,7 +30,7 @@
|
|||||||
ASSERT((uv_udp_t*)(handle) == &recver || (uv_udp_t*)(handle) == &sender)
|
ASSERT((uv_udp_t*)(handle) == &recver || (uv_udp_t*)(handle) == &sender)
|
||||||
|
|
||||||
#define BUFFER_MULTIPLIER 4
|
#define BUFFER_MULTIPLIER 4
|
||||||
#define BUFFER_SIZE (BUFFER_MULTIPLIER * 64 * 1024)
|
#define MAX_DGRAM_SIZE (64 * 1024)
|
||||||
#define NUM_SENDS 8
|
#define NUM_SENDS 8
|
||||||
#define EXPECTED_MMSG_ALLOCS (NUM_SENDS / BUFFER_MULTIPLIER)
|
#define EXPECTED_MMSG_ALLOCS (NUM_SENDS / BUFFER_MULTIPLIER)
|
||||||
|
|
||||||
@ -44,11 +44,18 @@ static int alloc_cb_called;
|
|||||||
static void alloc_cb(uv_handle_t* handle,
|
static void alloc_cb(uv_handle_t* handle,
|
||||||
size_t suggested_size,
|
size_t suggested_size,
|
||||||
uv_buf_t* buf) {
|
uv_buf_t* buf) {
|
||||||
|
size_t buffer_size;
|
||||||
CHECK_HANDLE(handle);
|
CHECK_HANDLE(handle);
|
||||||
|
|
||||||
|
/* Only allocate enough room for multiple dgrams if we can actually recv them */
|
||||||
|
buffer_size = MAX_DGRAM_SIZE;
|
||||||
|
if (uv_udp_using_recvmmsg((uv_udp_t*)handle))
|
||||||
|
buffer_size *= BUFFER_MULTIPLIER;
|
||||||
|
|
||||||
/* Actually malloc to exercise free'ing the buffer later */
|
/* Actually malloc to exercise free'ing the buffer later */
|
||||||
buf->base = malloc(BUFFER_SIZE);
|
buf->base = malloc(buffer_size);
|
||||||
ASSERT(buf->base != NULL);
|
ASSERT(buf->base != NULL);
|
||||||
buf->len = BUFFER_SIZE;
|
buf->len = buffer_size;
|
||||||
alloc_cb_called++;
|
alloc_cb_called++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +126,10 @@ TEST_IMPL(udp_mmsg) {
|
|||||||
printf("%d allocs for %d recvs\n", alloc_cb_called, recv_cb_called);
|
printf("%d allocs for %d recvs\n", alloc_cb_called, recv_cb_called);
|
||||||
|
|
||||||
/* On platforms that don't support mmsg, each recv gets its own alloc */
|
/* On platforms that don't support mmsg, each recv gets its own alloc */
|
||||||
ASSERT(alloc_cb_called == EXPECTED_MMSG_ALLOCS || alloc_cb_called == recv_cb_called);
|
if (uv_udp_using_recvmmsg(&recver))
|
||||||
|
ASSERT_EQ(alloc_cb_called, EXPECTED_MMSG_ALLOCS);
|
||||||
|
else
|
||||||
|
ASSERT_EQ(alloc_cb_called, recv_cb_called);
|
||||||
|
|
||||||
MAKE_VALGRIND_HAPPY();
|
MAKE_VALGRIND_HAPPY();
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user