Hello,

I removed the pthread_testcancel() calls and cut the interposing
stuff from my patch as suggested. I extended the send/recv(2) manpages
regarding
the mm calls. Comments and suggestions?

Best regards,
Boris Astardzhiev


On Mon, Jan 18, 2016 at 4:08 PM, Konstantin Belousov <kostik...@gmail.com>
wrote:

> On Mon, Jan 18, 2016 at 12:37:01PM +0200, Boris Astardzhiev wrote:
> > Hello,
> >
> > Sorry for the delay of my reply. As far as I understand
> pthread_testcancel()
> > is not necessary in the recvmmsg syscall since cancellation is not quite
> > common
> > among apps. But if there is cancellation attempts as long as I use
> > __sys_recvmsg() instead
> > of the interposing approach on a cancel attempt recvmmsg() will return
> > EINTR which will get
> > me out?
> Yes.
>
> The corner case is the cancellation attempt (SIGCANCEL == SIGTHR) coming
> while the thread is executing code around the syscall.
>
> >
> > Secondly, I guess it's better to use __sys_sendmmsg() similarly instead
> of
> > the
> > insterposing table regarding sendmmsg().
> Sure, sendmmsg and recvmmsg are same.
>
> >
> > Lastly, regarding the manpage - should I extend send/recv(2) for the new
> > calls or
> > create new manpage files?
> IMO it is more logical to extend the existing page than write a new one.
>
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/recv.2 b/lib/libc/sys/recv.2
index 326e7ff..81a0201 100644
--- a/lib/libc/sys/recv.2
+++ b/lib/libc/sys/recv.2
@@ -34,8 +34,9 @@
 .Sh NAME
 .Nm recv ,
 .Nm recvfrom ,
-.Nm recvmsg
-.Nd receive a message from a socket
+.Nm recvmsg ,
+.Nm recvmmsg
+.Nd receive message(s) from a socket
 .Sh LIBRARY
 .Lb libc
 .Sh SYNOPSIS
@@ -47,11 +48,15 @@
 .Fn recvfrom "int s" "void *buf" "size_t len" "int flags" "struct sockaddr * 
restrict from" "socklen_t * restrict fromlen"
 .Ft ssize_t
 .Fn recvmsg "int s" "struct msghdr *msg" "int flags"
+.Ft int
+.Fn recvmmsg "int s" "struct mmsghdr *msgvec" "int vlen" "int flags"
 .Sh DESCRIPTION
 The
 .Fn recvfrom
 and
 .Fn recvmsg
+and
+.Fn recvmmsg
 system calls
 are used to receive messages from a socket,
 and may be used to receive data on a socket whether or not
@@ -84,8 +89,25 @@ null pointer passed as its
 .Fa from
 argument.
 .Pp
-All three routines return the length of the message on successful
-completion.
+The
+.Fn recvmmsg
+function is used to receive multiple
+messages at a call.
+Their number
+is supplied by
+.Fa vlen
+(limited to 1024).
+The messages are placed in the
+.Fa msgvec
+vector after reception.
+The size of each received message is placed in the
+.Fa msg_len
+field of each element of the vector.
+.Pp
+The first three routines return the length of the message on successful
+completion whereas
+.Fn recvmmsg
+returns the number of received messages.
 If a message is too long to fit in the supplied buffer,
 excess bytes may be discarded depending on the type of socket
 the message is received from (see
@@ -100,7 +122,9 @@ in which case the value
 .Va errno
 is set to
 .Er EAGAIN .
-The receive calls normally return any data available,
+The receive calls except
+.Fn recvmmsg
+normally return any data available,
 up to the requested amount,
 rather than waiting for receipt of the full amount requested;
 this behavior is affected by the socket-level options
@@ -290,9 +314,34 @@ control data were discarded due to lack of space in the 
buffer
 for ancillary data.
 .Dv MSG_OOB
 is returned to indicate that expedited or out-of-band data were received.
+.Pp
+The
+.Fn recvmmsg
+system call uses the
+.Fa mmsghdr
+structure. Its form is as follows, as defined in
+.In sys/socket.h :
+.Bd -literal
+struct mmsghdr {
+       struct msghdr    msg_hdr;       /* message header */
+       unsigned int     msg_len;       /* message length */
+};
+.Ed
+.Pp
+For
+.Fa msg_hdr
+see above. On data reception the
+.Fa msg_len
+field is updated to the length of the received message. On
+data transmission it is updated to the number of
+characters sent.
 .Sh RETURN VALUES
-These calls return the number of bytes received, or -1
-if an error occurred.
+These calls except
+.Fn recvmmsg
+return the number of bytes received.
+.Fn recvmmsg
+returns the number of messages received.
+A value of -1 is returned if an error occurred.
 .Sh ERRORS
 The calls fail if:
 .Bl -tag -width Er
diff --git a/lib/libc/sys/recvmmsg.c b/lib/libc/sys/recvmmsg.c
new file mode 100644
index 0000000..6b5158a
--- /dev/null
+++ b/lib/libc/sys/recvmmsg.c
@@ -0,0 +1,72 @@
+/*
+ * 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;
+
+       rcvd = 0;
+       for (i = 0; i < vlen; i++) {
+               errno = 0;
+               ret = __sys_recvmsg(s, &msgvec[i].msg_hdr, flags);
+               if (ret < 0 || errno != 0) {
+                       if (rcvd != 0) {
+                               /* We've received messages. Let caller know. */
+                               errno = 0;
+                               return (rcvd);
+                       }
+                       return (-1);
+               }
+
+               /* Save received bytes */
+               msgvec[i].msg_len = ret;
+
+               rcvd++;
+       }
+
+       return (rcvd);
+}
+
+#undef VLEN_MAX
diff --git a/lib/libc/sys/send.2 b/lib/libc/sys/send.2
index 8fa2c64..6c14a60 100644
--- a/lib/libc/sys/send.2
+++ b/lib/libc/sys/send.2
@@ -34,8 +34,9 @@
 .Sh NAME
 .Nm send ,
 .Nm sendto ,
-.Nm sendmsg
-.Nd send a message from a socket
+.Nm sendmsg ,
+.Nm sendmmsg
+.Nd send message(s) from a socket
 .Sh LIBRARY
 .Lb libc
 .Sh SYNOPSIS
@@ -47,6 +48,8 @@
 .Fn sendto "int s" "const void *msg" "size_t len" "int flags" "const struct 
sockaddr *to" "socklen_t tolen"
 .Ft ssize_t
 .Fn sendmsg "int s" "const struct msghdr *msg" "int flags"
+.Ft int
+.Fn sendmmsg "int s" "struct mmsghdr *msgvec" "int vlen" "int flags"
 .Sh DESCRIPTION
 The
 .Fn send
@@ -55,8 +58,10 @@ and
 .Fn sendto
 and
 .Fn sendmsg
+and
+.Fn sendmmsg
 system calls
-are used to transmit a message to another socket.
+are used to transmit one or multiple messages (with the latter call) to 
another socket.
 The
 .Fn send
 function
@@ -66,6 +71,8 @@ state, while
 .Fn sendto
 and
 .Fn sendmsg
+and
+.Fn sendmmsg
 may be used at any time.
 .Pp
 The address of the target is given by
@@ -81,6 +88,18 @@ underlying protocol, the error
 is returned, and
 the message is not transmitted.
 .Pp
+The
+.Fn sendmmsg
+function sends multiple messages at a call.
+They are given by the
+.Fa msgvec
+vector along with
+.Fa vlen
+specifying its size (limited to 1024). The number of
+characters sent per each message is placed in the
+.Fa msg_len
+field of each element of the vector after transmission.
+.Pp
 No indication of failure to deliver is implicit in a
 .Fn send .
 Locally detected errors are indicated by a return value of -1.
@@ -138,10 +157,16 @@ See
 .Xr recv 2
 for a description of the
 .Fa msghdr
+structure and the
+.Fa mmsghdr
 structure.
 .Sh RETURN VALUES
-The call returns the number of characters sent, or -1
-if an error occurred.
+All calls except
+.Fn sendmmsg
+return the number of characters sent. The
+.Fn sendmmsg
+call returns the number of messages sent.
+If an error occurred a value of -1 is returned.
 .Sh ERRORS
 The
 .Fn send
@@ -149,6 +174,8 @@ function and
 .Fn sendto
 and
 .Fn sendmsg
+and
+.Fn sendmmsg
 system calls
 fail if:
 .Bl -tag -width Er
diff --git a/lib/libc/sys/sendmmsg.c b/lib/libc/sys/sendmmsg.c
new file mode 100644
index 0000000..3b90b90
--- /dev/null
+++ b/lib/libc/sys/sendmmsg.c
@@ -0,0 +1,72 @@
+/*
+ * 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;
+
+       sent = 0;
+       for (i = 0; i < vlen; i++) {
+               errno = 0;
+               ret = __sys_sendmsg(s, &msgvec[i].msg_hdr, flags);
+               if (ret < 0 || errno != 0) {
+                       if (sent != 0) {
+                               /* We have sent messages. Let caller know. */
+                               errno = 0;
+                               return (sent);
+                       }
+                       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..f70dced 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"

Reply via email to