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
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
_______________________________________________ freebsd-net@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/freebsd-net To unsubscribe, send any mail to "freebsd-net-unsubscr...@freebsd.org"