Date: Fri, 15 Jan 2016 13:53:14 +0200 From: Boris Astardzhiev <boris.astardzhiev@gmail.com> To: Konstantin Belousov <kostikbel@gmail.com> Cc: Adrian Chadd <adrian.chadd@gmail.com>, Mark Delany <c2h@romeo.emu.st>, FreeBSD Net <freebsd-net@freebsd.org> Subject: Re: Does FreeBSD have sendmmsg or recvmmsg system calls? Message-ID: <CAP=KkTxVaqZvigg78Dg%2Bv8kuTCaZyky8x15NHqD9uabuRKRkMw@mail.gmail.com> In-Reply-To: <20160113080349.GC72455@kib.kiev.ua> References: <CAP=KkTzFUDsZwDDLD3n97xJW0qLVZMPduZGSX%2BeXC3UuLpVjMg@mail.gmail.com> <20160107161213.GZ3625@kib.kiev.ua> <CA%2BhQ2%2Bg6OB3MmZrW5hzNSnkcqKaKf1XGDraHfWXtSrowxKuL5g@mail.gmail.com> <20160107192840.GF3625@kib.kiev.ua> <20160108172323.W1815@besplex.bde.org> <20160108075815.3243.qmail@f5-external.bushwire.net> <CAJ-VmonYPhcN-gikuYQU_k5GaTAqTijoxR_0ORV4BZqsHMRJSg@mail.gmail.com> <20160108204606.G2420@besplex.bde.org> <CAJ-Vmom26mukSv3JmsmNiAONvpc6f1bQ%2BujO25qefGHY=5przA@mail.gmail.com> <CAP=KkTwG0SVUmrBuWm33EC-tG4tMTdF5rLZQ_u6G1=-ujnfjkA@mail.gmail.com> <20160113080349.GC72455@kib.kiev.ua>
next in thread | previous in thread | raw e-mail | index | archive | help
[-- Attachment #1 --]
Hello,
Thanks for the insightful comments.
kb>Please find below.
kb>
kb> This implementation has some strangeness, like NOASM and PSEUDO in
makefile,
kb> which I cannot find a purpose for.
I removed it but initially I thought it was necessary.
kb>Big issue with the implementation is the interposing stuff, why do you
kb> need it at all ? Is it to correctly handle cancellation, to not fall
kb> into sleepable syscall when previous loop step was cancelled ?
Yes. I initially thought it was better to use the interposing table.
kb> If yes, you _can_ use pthread_testcancel(3) etc in libc. Libc provides
kb> stubs for them with trivial implementation, which is reset to the real
kb> one if libthr is loaded. Then you can simplify your patch
significantly,
kb> avoiding the need for interposing and writing the loops both in libc and
kb> libthr.
Got it. See patch. I think I removed the interposing stuff as suggested. I
didn't know
about the stubs. But how for instance pthread_testcancel() will cope with
sleeping
recvmmsg for example? I'm not sure about the cancellation stuff here.
Probably my
approach is not correct? I looked through lib/ for an example and only
stumbled on
lib/libc/gen/sem.c where pthread_testcancel() is used but again I'm not
sure if I'm tackling
it correctly in the calls.
kb> BTW, do you have tests for the cancellation of the new functions ?
Unfortunately no. Ideas and guidelines how to stress test the calls
regarding functionality
and especially cancellation?
kb> Again, the patch lacks man page updates.
I'll try to write some soon.
Best regards,
Boris Astardzhiev
[-- Attachment #2 --]
diff --git a/lib/libc/include/namespace.h b/lib/libc/include/namespace.h
index 739d7b1..c95829e 100644
--- a/lib/libc/include/namespace.h
+++ b/lib/libc/include/namespace.h
@@ -208,6 +208,7 @@
#define readv _readv
#define recvfrom _recvfrom
#define recvmsg _recvmsg
+#define recvmmsg _recvmmsg
#define select _select
#define sem_close _sem_close
#define sem_destroy _sem_destroy
@@ -220,6 +221,7 @@
#define sem_unlink _sem_unlink
#define sem_wait _sem_wait
#define sendmsg _sendmsg
+#define sendmmsg _sendmmsg
#define sendto _sendto
#define setsockopt _setsockopt
/*#define sigaction _sigaction*/
diff --git a/lib/libc/include/un-namespace.h b/lib/libc/include/un-namespace.h
index f31fa7a..0233348 100644
--- a/lib/libc/include/un-namespace.h
+++ b/lib/libc/include/un-namespace.h
@@ -189,6 +189,7 @@
#undef readv
#undef recvfrom
#undef recvmsg
+#undef recvmmsg
#undef select
#undef sem_close
#undef sem_destroy
@@ -201,6 +202,7 @@
#undef sem_unlink
#undef sem_wait
#undef sendmsg
+#undef sendmmsg
#undef sendto
#undef setsockopt
#undef sigaction
diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc
index e4fe1b2..5f8b699 100644
--- a/lib/libc/sys/Makefile.inc
+++ b/lib/libc/sys/Makefile.inc
@@ -28,6 +28,8 @@ SRCS+= futimens.c utimensat.c
NOASM+= futimens.o utimensat.o
PSEUDO+= _futimens.o _utimensat.o
+SRCS+= recvmmsg.c sendmmsg.c
+
INTERPOSED = \
accept \
accept4 \
diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map
index 7b3257c..724e1b4 100644
--- a/lib/libc/sys/Symbol.map
+++ b/lib/libc/sys/Symbol.map
@@ -399,6 +399,8 @@ FBSD_1.4 {
utimensat;
numa_setaffinity;
numa_getaffinity;
+ sendmmsg;
+ recvmmsg;
};
FBSDprivate_1.0 {
@@ -1051,4 +1053,6 @@ FBSDprivate_1.0 {
gssd_syscall;
__libc_interposing_slot;
__libc_sigwait;
+ _sendmmsg;
+ _recvmmsg;
};
diff --git a/lib/libc/sys/recvmmsg.c b/lib/libc/sys/recvmmsg.c
new file mode 100644
index 0000000..763930c
--- /dev/null
+++ b/lib/libc/sys/recvmmsg.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016 Boris Astardzhiev, Smartcom-Bulgaria AD
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice(s), this list of conditions and the following disclaimer as
+ * the first lines of this file unmodified other than the possible
+ * addition of one or more copyright notices.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice(s), this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <sys/socket.h>
+#include <pthread.h>
+#include "libc_private.h"
+
+#define VLEN_MAX 1024
+
+int
+recvmmsg(int s, struct mmsghdr *msgvec, unsigned int vlen, int flags)
+{
+ int i, ret, rcvd;
+
+ if (vlen > VLEN_MAX)
+ vlen = VLEN_MAX;
+
+ pthread_testcancel();
+ rcvd = 0;
+ for (i = 0; i < vlen; i++) {
+ errno = 0;
+ ret = (((int (*)(int, const struct msghdr *, int))
+ __libc_interposing[INTERPOS_recvmsg])(s,
+ &msgvec[i].msg_hdr, flags));
+ if (ret < 0 || errno != 0) {
+ if (rcvd != 0) {
+ /* We've received messages. Let caller know. */
+ errno = 0;
+ pthread_testcancel();
+ return (rcvd);
+ }
+ pthread_testcancel();
+ return (-1);
+ }
+
+ /* Save received bytes */
+ msgvec[i].msg_len = ret;
+
+ rcvd++;
+ }
+
+ return (rcvd);
+}
+
+#undef VLEN_MAX
diff --git a/lib/libc/sys/sendmmsg.c b/lib/libc/sys/sendmmsg.c
new file mode 100644
index 0000000..bafa9bc
--- /dev/null
+++ b/lib/libc/sys/sendmmsg.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2016 Boris Astardzhiev, Smartcom-Bulgaria AD
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice(s), this list of conditions and the following disclaimer as
+ * the first lines of this file unmodified other than the possible
+ * addition of one or more copyright notices.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice(s), this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <sys/socket.h>
+#include <pthread.h>
+#include "libc_private.h"
+
+#define VLEN_MAX 1024
+
+int
+sendmmsg(int s, struct mmsghdr *msgvec, unsigned int vlen, int flags)
+{
+ int i, ret, sent;
+
+ if (vlen > VLEN_MAX)
+ vlen = VLEN_MAX;
+
+ pthread_testcancel();
+ sent = 0;
+ for (i = 0; i < vlen; i++) {
+ errno = 0;
+ ret = (((int (*)(int, const struct msghdr *, int))
+ __libc_interposing[INTERPOS_sendmsg])(s,
+ &msgvec[i].msg_hdr, flags));
+
+ if (ret < 0 || errno != 0) {
+ if (sent != 0) {
+ /* We have sent messages. Let caller know. */
+ errno = 0;
+ pthread_testcancel();
+ return (sent);
+ }
+ pthread_testcancel();
+ return (-1);
+ }
+
+ /* Save sent bytes */
+ msgvec[i].msg_len = ret;
+
+ sent++;
+ }
+
+ return (sent);
+}
+
+#undef VLEN_MAX
diff --git a/sys/sys/socket.h b/sys/sys/socket.h
index 18e2de1..504313e 100644
--- a/sys/sys/socket.h
+++ b/sys/sys/socket.h
@@ -595,6 +595,18 @@ struct sf_hdtr {
#endif /* _KERNEL */
#endif /* __BSD_VISIBLE */
+#ifndef _KERNEL
+#ifdef __BSD_VISIBLE
+/*
+ * Send/recvmmsg specific structure(s)
+ */
+struct mmsghdr {
+ struct msghdr msg_hdr; /* message header */
+ unsigned int msg_len; /* message length */
+};
+#endif /* __BSD_VISIBLE */
+#endif /* !_KERNEL */
+
#ifndef _KERNEL
#include <sys/cdefs.h>
@@ -615,11 +627,17 @@ int listen(int, int);
ssize_t recv(int, void *, size_t, int);
ssize_t recvfrom(int, void *, size_t, int, struct sockaddr * __restrict, socklen_t * __restrict);
ssize_t recvmsg(int, struct msghdr *, int);
+#if __BSD_VISIBLE
+int recvmmsg(int, struct mmsghdr *, unsigned int, int);
+#endif
ssize_t send(int, const void *, size_t, int);
ssize_t sendto(int, const void *,
size_t, int, const struct sockaddr *, socklen_t);
ssize_t sendmsg(int, const struct msghdr *, int);
#if __BSD_VISIBLE
+int sendmmsg(int, struct mmsghdr *, unsigned int, int);
+#endif
+#if __BSD_VISIBLE
int sendfile(int, int, off_t, size_t, struct sf_hdtr *, off_t *, int);
int setfib(int);
#endif
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAP=KkTxVaqZvigg78Dg%2Bv8kuTCaZyky8x15NHqD9uabuRKRkMw>
