Add {send,recv}mmsg from Linux
This commit is contained in:
parent
bda667f3a1
commit
7bee3146e4
@ -1,4 +1,4 @@
|
||||
$NetBSD: syscalls.master,v 1.259 2012/05/05 19:37:37 christos Exp $
|
||||
$NetBSD: syscalls.master,v 1.260 2012/06/22 18:26:35 christos Exp $
|
||||
|
||||
; @(#)syscalls.master 8.2 (Berkeley) 1/13/94
|
||||
|
||||
@ -930,7 +930,11 @@
|
||||
473 STD RUMP { int|sys||__quotactl(const char *path, \
|
||||
struct quotactl_args *args); }
|
||||
474 NOERR { int|sys||posix_spawn(pid_t *pid, const char *path, \
|
||||
const struct posix_spawn_file_actions *file_actions, \
|
||||
const struct posix_spawnattr *attrp, \
|
||||
char *const *argv, char *const *envp); }
|
||||
|
||||
const struct posix_spawn_file_actions *file_actions, \
|
||||
const struct posix_spawnattr *attrp, \
|
||||
char *const *argv, char *const *envp); }
|
||||
475 STD { int|sys||recvmmsg(int s, struct mmsghdr *mmsg, \
|
||||
unsigned int vlen, unsigned int flags, \
|
||||
struct timespec *timeout); }
|
||||
476 STD { int|sys||sendmmsg(int s, struct mmsghdr *mmsg, \
|
||||
unsigned int vlen, unsigned int flags); }
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: uipc_syscalls.c,v 1.154 2012/01/25 16:56:13 christos Exp $ */
|
||||
/* $NetBSD: uipc_syscalls.c,v 1.155 2012/06/22 18:26:35 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
|
||||
@ -61,7 +61,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.154 2012/01/25 16:56:13 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.155 2012/06/22 18:26:35 christos Exp $");
|
||||
|
||||
#include "opt_pipe.h"
|
||||
|
||||
@ -529,14 +529,13 @@ sys_sendmsg(struct lwp *l, const struct sys_sendmsg_args *uap, register_t *retva
|
||||
return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
|
||||
}
|
||||
|
||||
int
|
||||
do_sys_sendmsg(struct lwp *l, int s, struct msghdr *mp, int flags,
|
||||
register_t *retsize)
|
||||
static int
|
||||
do_sys_sendmsg_so(struct lwp *l, int s, struct socket *so, file_t *fp,
|
||||
struct msghdr *mp, int flags, register_t *retsize)
|
||||
{
|
||||
|
||||
struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov = NULL;
|
||||
struct mbuf *to, *control;
|
||||
struct socket *so;
|
||||
file_t *fp;
|
||||
struct uio auio;
|
||||
size_t len, iovsz;
|
||||
int i, error;
|
||||
@ -610,9 +609,6 @@ do_sys_sendmsg(struct lwp *l, int s, struct msghdr *mp, int flags,
|
||||
memcpy(ktriov, auio.uio_iov, iovsz);
|
||||
}
|
||||
|
||||
if ((error = fd_getsock1(s, &so, &fp)) != 0)
|
||||
goto bad;
|
||||
|
||||
if (mp->msg_name)
|
||||
MCLAIM(to, so->so_mowner);
|
||||
if (mp->msg_control)
|
||||
@ -623,8 +619,6 @@ do_sys_sendmsg(struct lwp *l, int s, struct msghdr *mp, int flags,
|
||||
/* Protocol is responsible for freeing 'control' */
|
||||
control = NULL;
|
||||
|
||||
fd_putfile(s);
|
||||
|
||||
if (error) {
|
||||
if (auio.uio_resid != len && (error == ERESTART ||
|
||||
error == EINTR || error == EWOULDBLOCK))
|
||||
@ -655,6 +649,21 @@ bad:
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
do_sys_sendmsg(struct lwp *l, int s, struct msghdr *mp, int flags,
|
||||
register_t *retsize)
|
||||
{
|
||||
int error;
|
||||
struct socket *so;
|
||||
file_t *fp;
|
||||
|
||||
if ((error = fd_getsock1(s, &so, &fp)) != 0)
|
||||
return error;
|
||||
error = do_sys_sendmsg_so(l, s, so, fp, mp, flags, retsize);
|
||||
fd_putfile(s);
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
sys_recvfrom(struct lwp *l, const struct sys_recvfrom_args *uap, register_t *retval)
|
||||
{
|
||||
@ -729,6 +738,68 @@ sys_recvmsg(struct lwp *l, const struct sys_recvmsg_args *uap, register_t *retva
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
sys_sendmmsg(struct lwp *l, const struct sys_sendmmsg_args *uap,
|
||||
register_t *retval)
|
||||
{
|
||||
/* {
|
||||
syscallarg(int) s;
|
||||
syscallarg(struct mmsghdr *) mmsg;
|
||||
syscallarg(unsigned int) vlen;
|
||||
syscallarg(unsigned int) flags;
|
||||
} */
|
||||
struct mmsghdr mmsg;
|
||||
struct socket *so;
|
||||
file_t *fp;
|
||||
struct msghdr *msg = &mmsg.msg_hdr;
|
||||
int error, s;
|
||||
unsigned int vlen, flags, dg;
|
||||
|
||||
s = SCARG(uap, s);
|
||||
if ((error = fd_getsock1(s, &so, &fp)) != 0)
|
||||
return error;
|
||||
|
||||
vlen = SCARG(uap, vlen);
|
||||
if (vlen > 1024)
|
||||
vlen = 1024;
|
||||
|
||||
flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE;
|
||||
|
||||
for (dg = 0; dg < vlen;) {
|
||||
error = copyin(SCARG(uap, mmsg) + dg, &mmsg, sizeof(mmsg));
|
||||
if (error)
|
||||
break;
|
||||
|
||||
msg->msg_flags = flags;
|
||||
|
||||
error = do_sys_sendmsg_so(l, s, so, fp, msg, flags, retval);
|
||||
if (error)
|
||||
break;
|
||||
|
||||
ktrkuser("msghdr", msg, sizeof *msg);
|
||||
mmsg.msg_len = *retval;
|
||||
error = copyout(&mmsg, SCARG(uap, mmsg) + dg, sizeof(mmsg));
|
||||
if (error)
|
||||
break;
|
||||
dg++;
|
||||
|
||||
}
|
||||
|
||||
*retval = dg;
|
||||
if (error)
|
||||
so->so_error = error;
|
||||
|
||||
fd_putfile(s);
|
||||
|
||||
/*
|
||||
* If we succeeded at least once, return 0, hopefully so->so_error
|
||||
* will catch it next time.
|
||||
*/
|
||||
if (dg)
|
||||
return 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust for a truncated SCM_RIGHTS control message.
|
||||
* This means closing any file descriptors that aren't present
|
||||
@ -822,12 +893,11 @@ copyout_msg_control(struct lwp *l, struct msghdr *mp, struct mbuf *control)
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
do_sys_recvmsg(struct lwp *l, int s, struct msghdr *mp, struct mbuf **from,
|
||||
struct mbuf **control, register_t *retsize)
|
||||
static int
|
||||
do_sys_recvmsg_so(struct lwp *l, int s, struct socket *so, struct msghdr *mp,
|
||||
struct mbuf **from, struct mbuf **control, register_t *retsize)
|
||||
{
|
||||
struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov;
|
||||
struct socket *so;
|
||||
struct uio auio;
|
||||
size_t len, iovsz;
|
||||
int i, error;
|
||||
@ -838,9 +908,6 @@ do_sys_recvmsg(struct lwp *l, int s, struct msghdr *mp, struct mbuf **from,
|
||||
if (control != NULL)
|
||||
*control = NULL;
|
||||
|
||||
if ((error = fd_getsock(s, &so)) != 0)
|
||||
return (error);
|
||||
|
||||
iovsz = mp->msg_iovlen * sizeof(struct iovec);
|
||||
|
||||
if (mp->msg_flags & MSG_IOVUSRSPACE) {
|
||||
@ -913,11 +980,130 @@ do_sys_recvmsg(struct lwp *l, int s, struct msghdr *mp, struct mbuf **from,
|
||||
out:
|
||||
if (iov != aiov)
|
||||
kmem_free(iov, iovsz);
|
||||
fd_putfile(s);
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
do_sys_recvmsg(struct lwp *l, int s, struct msghdr *mp, struct mbuf **from,
|
||||
struct mbuf **control, register_t *retsize)
|
||||
{
|
||||
int error;
|
||||
struct socket *so;
|
||||
|
||||
if ((error = fd_getsock(s, &so)) != 0)
|
||||
return error;
|
||||
error = do_sys_recvmsg_so(l, s, so, mp, from, control, retsize);
|
||||
fd_putfile(s);
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
sys_recvmmsg(struct lwp *l, const struct sys_recvmmsg_args *uap,
|
||||
register_t *retval)
|
||||
{
|
||||
/* {
|
||||
syscallarg(int) s;
|
||||
syscallarg(struct mmsghdr *) mmsg;
|
||||
syscallarg(unsigned int) vlen;
|
||||
syscallarg(unsigned int) flags;
|
||||
syscallarg(struct timespec *) timeout;
|
||||
} */
|
||||
struct mmsghdr mmsg;
|
||||
struct socket *so;
|
||||
struct msghdr *msg = &mmsg.msg_hdr;
|
||||
int error, s;
|
||||
struct mbuf *from, *control;
|
||||
struct timespec ts, now;
|
||||
unsigned int vlen, flags, dg;
|
||||
|
||||
if (SCARG(uap, timeout)) {
|
||||
if ((error = copyin(SCARG(uap, timeout), &ts, sizeof(ts))) != 0)
|
||||
return error;
|
||||
getnanotime(&now);
|
||||
timespecadd(&now, &ts, &ts);
|
||||
}
|
||||
|
||||
s = SCARG(uap, s);
|
||||
if ((error = fd_getsock(s, &so)) != 0)
|
||||
return error;
|
||||
|
||||
vlen = SCARG(uap, vlen);
|
||||
if (vlen > 1024)
|
||||
vlen = 1024;
|
||||
|
||||
from = NULL;
|
||||
flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE;
|
||||
|
||||
for (dg = 0; dg < vlen;) {
|
||||
error = copyin(SCARG(uap, mmsg) + dg, &mmsg, sizeof(mmsg));
|
||||
if (error)
|
||||
break;
|
||||
|
||||
msg->msg_flags = flags & ~MSG_WAITFORONE;
|
||||
|
||||
if (from != NULL) {
|
||||
m_free(from);
|
||||
from = NULL;
|
||||
}
|
||||
|
||||
error = do_sys_recvmsg_so(l, s, so, msg, &from,
|
||||
msg->msg_control != NULL ? &control : NULL, retval);
|
||||
if (error)
|
||||
break;
|
||||
|
||||
if (msg->msg_control != NULL)
|
||||
error = copyout_msg_control(l, msg, control);
|
||||
if (error)
|
||||
break;
|
||||
|
||||
error = copyout_sockname(msg->msg_name, &msg->msg_namelen, 0,
|
||||
from);
|
||||
if (error)
|
||||
break;
|
||||
|
||||
ktrkuser("msghdr", msg, sizeof *msg);
|
||||
mmsg.msg_len = *retval;
|
||||
|
||||
error = copyout(&mmsg, SCARG(uap, mmsg) + dg, sizeof(mmsg));
|
||||
if (error)
|
||||
break;
|
||||
|
||||
dg++;
|
||||
if (msg->msg_flags & MSG_OOB)
|
||||
break;
|
||||
|
||||
if (SCARG(uap, timeout)) {
|
||||
getnanotime(&now);
|
||||
timespecsub(&now, &ts, &now);
|
||||
if (now.tv_sec > 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (flags & MSG_WAITFORONE)
|
||||
flags |= MSG_DONTWAIT;
|
||||
|
||||
}
|
||||
|
||||
if (from != NULL)
|
||||
m_free(from);
|
||||
|
||||
*retval = dg;
|
||||
if (error)
|
||||
so->so_error = error;
|
||||
|
||||
fd_putfile(s);
|
||||
|
||||
/*
|
||||
* If we succeeded at least once, return 0, hopefully so->so_error
|
||||
* will catch it next time.
|
||||
*/
|
||||
if (dg)
|
||||
return 0;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
sys_shutdown(struct lwp *l, const struct sys_shutdown_args *uap, register_t *retval)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: param.h,v 1.415 2012/05/10 07:48:07 riastradh Exp $ */
|
||||
/* $NetBSD: param.h,v 1.416 2012/06/22 18:26:35 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
@ -63,7 +63,7 @@
|
||||
* 2.99.9 (299000900)
|
||||
*/
|
||||
|
||||
#define __NetBSD_Version__ 699000700 /* NetBSD 6.99.7 */
|
||||
#define __NetBSD_Version__ 699000800 /* NetBSD 6.99.8 */
|
||||
|
||||
#define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \
|
||||
(m) * 1000000) + (p) * 100) <= __NetBSD_Version__)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: socket.h,v 1.106 2012/01/29 18:33:07 roy Exp $ */
|
||||
/* $NetBSD: socket.h,v 1.107 2012/06/22 18:26:35 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
@ -495,6 +495,12 @@ struct msghdr {
|
||||
#if defined(_NETBSD_SOURCE)
|
||||
#define MSG_CMSG_CLOEXEC 0x0800 /* close on exec receiving fd */
|
||||
#define MSG_NBIO 0x1000 /* use non-blocking I/O */
|
||||
#define MSG_WAITFORONE 0x2000 /* recvmmsg() wait for one message */
|
||||
|
||||
struct mmsghdr {
|
||||
struct msghdr msg_hdr;
|
||||
unsigned int msg_len;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Extra flags used internally only */
|
||||
@ -629,6 +635,13 @@ __RENAME(__socket30)
|
||||
#endif
|
||||
;
|
||||
int socketpair(int, int, int, int *);
|
||||
|
||||
#if defined(_NETBSD_SOURCE)
|
||||
int sendmmsg(int, struct mmsghdr *, unsigned int, unsigned int);
|
||||
struct timespec;
|
||||
int recvmmsg(int, struct mmsghdr *, unsigned int, unsigned int,
|
||||
struct timespec *);
|
||||
#endif
|
||||
__END_DECLS
|
||||
#endif /* !_KERNEL */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user