[rtems-libbsd commit] Avoid malloc() in getsockaddr()

Sebastian Huber sebh at rtems.org
Fri Jul 6 05:27:58 UTC 2018


Module:    rtems-libbsd
Branch:    master
Commit:    94b5368388f51b535256b65d278998a48b0c4a3f
Changeset: http://git.rtems.org/rtems-libbsd/commit/?id=94b5368388f51b535256b65d278998a48b0c4a3f

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Mon Jul  2 08:21:37 2018 +0200

Avoid malloc() in getsockaddr()

The getsockaddr() function is used to allocate a struct sockaddr of the
right length and initialize it with userspace provided data.  It is used
for the connect(), bind() and sendit() family functions.  In particular,
the sendit() function is used by the UDP send functions.  This means
each UDP send needs a malloc() and free() invocation.  This is a
performance problem in RTEMS (first-fit heap) and may lead to heap
fragmentation.  Replace the malloc() allocation with a stack allocation.
This requires SOCK_MAXADDRLEN (= 255) of additional stack space for
libbsd.

A further optimization would be to get rid of the stack copy of the
socket address.  However, this would require to check each consumer of
the address to ensure that it is not modified.

---

 freebsd/sys/kern/uipc_syscalls.c                   | 45 ++++++++++++++++++++++
 freebsd/sys/sys/socketvar.h                        |  2 +
 .../include/machine/rtems-bsd-kernel-namespace.h   |  1 -
 3 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/freebsd/sys/kern/uipc_syscalls.c b/freebsd/sys/kern/uipc_syscalls.c
index 7970255..338dd5d 100644
--- a/freebsd/sys/kern/uipc_syscalls.c
+++ b/freebsd/sys/kern/uipc_syscalls.c
@@ -87,6 +87,13 @@ static int getsockname1(struct thread *td, struct getsockname_args *uap,
 			int compat);
 static int getpeername1(struct thread *td, struct getpeername_args *uap,
 			int compat);
+#else /* __rtems__ */
+struct getsockaddr_sockaddr {
+	struct sockaddr	header;
+	char		data[SOCK_MAXADDRLEN - sizeof(struct sockaddr)];
+};
+
+static int getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len);
 #endif /* __rtems__ */
 static int sockargs(struct mbuf **, char *, socklen_t, int);
 
@@ -256,11 +263,17 @@ sys_bind(struct thread *td, struct bind_args *uap)
 {
 	struct sockaddr *sa;
 	int error;
+#ifdef __rtems__
+	struct getsockaddr_sockaddr gsa;
+	sa = &gsa.header;
+#endif /* __rtems__ */
 
 	error = getsockaddr(&sa, uap->name, uap->namelen);
 	if (error == 0) {
 		error = kern_bindat(td, AT_FDCWD, uap->s, sa);
+#ifndef __rtems__
 		free(sa, M_SONAME);
+#endif /* __rtems__ */
 	}
 	return (error);
 }
@@ -327,11 +340,17 @@ sys_bindat(struct thread *td, struct bindat_args *uap)
 {
 	struct sockaddr *sa;
 	int error;
+#ifdef __rtems__
+	struct getsockaddr_sockaddr gsa;
+	sa = &gsa.header;
+#endif /* __rtems__ */
 
 	error = getsockaddr(&sa, uap->name, uap->namelen);
 	if (error == 0) {
 		error = kern_bindat(td, uap->fd, uap->s, sa);
+#ifndef __rtems__
 		free(sa, M_SONAME);
+#endif /* __rtems__ */
 	}
 	return (error);
 }
@@ -674,11 +693,17 @@ sys_connect(struct thread *td, struct connect_args *uap)
 {
 	struct sockaddr *sa;
 	int error;
+#ifdef __rtems__
+	struct getsockaddr_sockaddr gsa;
+	sa = &gsa.header;
+#endif /* __rtems__ */
 
 	error = getsockaddr(&sa, uap->name, uap->namelen);
 	if (error == 0) {
 		error = kern_connectat(td, AT_FDCWD, uap->s, sa);
+#ifndef __rtems__
 		free(sa, M_SONAME);
+#endif /* __rtems__ */
 	}
 	return (error);
 }
@@ -773,11 +798,17 @@ sys_connectat(struct thread *td, struct connectat_args *uap)
 {
 	struct sockaddr *sa;
 	int error;
+#ifdef __rtems__
+	struct getsockaddr_sockaddr gsa;
+	sa = &gsa.header;
+#endif /* __rtems__ */
 
 	error = getsockaddr(&sa, uap->name, uap->namelen);
 	if (error == 0) {
 		error = kern_connectat(td, uap->fd, uap->s, sa);
+#ifndef __rtems__
 		free(sa, M_SONAME);
+#endif /* __rtems__ */
 	}
 	return (error);
 }
@@ -930,6 +961,10 @@ sendit(struct thread *td, int s, struct msghdr *mp, int flags)
 	struct mbuf *control;
 	struct sockaddr *to;
 	int error;
+#ifdef __rtems__
+	struct getsockaddr_sockaddr gto;
+	to = &gto.header;
+#endif /* __rtems__ */
 
 #ifdef CAPABILITY_MODE
 	if (IN_CAPABILITY_MODE(td) && (mp->msg_name != NULL))
@@ -978,7 +1013,9 @@ sendit(struct thread *td, int s, struct msghdr *mp, int flags)
 	error = kern_sendit(td, s, mp, flags, control, UIO_USERSPACE);
 
 bad:
+#ifndef __rtems__
 	free(to, M_SONAME);
+#endif /* __rtems__ */
 	return (error);
 }
 
@@ -2111,12 +2148,15 @@ int
 getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len)
 {
 	struct sockaddr *sa;
+#ifndef __rtems__
 	int error;
+#endif /* __rtems__ */
 
 	if (len > SOCK_MAXADDRLEN)
 		return (ENAMETOOLONG);
 	if (len < offsetof(struct sockaddr, sa_data[0]))
 		return (EINVAL);
+#ifndef __rtems__
 	sa = malloc(len, M_SONAME, M_WAITOK);
 	error = copyin(uaddr, sa, len);
 	if (error != 0) {
@@ -2130,4 +2170,9 @@ getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len)
 		*namp = sa;
 	}
 	return (error);
+#else /* __rtems__ */
+	sa = memcpy(*namp, uaddr, len);
+	sa->sa_len = len;
+	return (0);
+#endif /* __rtems__ */
 }
diff --git a/freebsd/sys/sys/socketvar.h b/freebsd/sys/sys/socketvar.h
index dd1ec47..245a687 100644
--- a/freebsd/sys/sys/socketvar.h
+++ b/freebsd/sys/sys/socketvar.h
@@ -342,7 +342,9 @@ struct uio;
 /*
  * From uipc_socket and friends
  */
+#ifndef __rtems__
 int	getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len);
+#endif /* __rtems__ */
 int	getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp,
 	    struct file **fpp, u_int *fflagp, struct filecaps *havecaps);
 void	soabort(struct socket *so);
diff --git a/rtemsbsd/include/machine/rtems-bsd-kernel-namespace.h b/rtemsbsd/include/machine/rtems-bsd-kernel-namespace.h
index 0a9c6bb..7f26578 100644
--- a/rtemsbsd/include/machine/rtems-bsd-kernel-namespace.h
+++ b/rtemsbsd/include/machine/rtems-bsd-kernel-namespace.h
@@ -1178,7 +1178,6 @@
 #define	GetProxyAddress _bsd_GetProxyAddress
 #define	GetProxyPort _bsd_GetProxyPort
 #define	get_random_bytes _bsd_get_random_bytes
-#define	getsockaddr _bsd_getsockaddr
 #define	GetStateIn _bsd_GetStateIn
 #define	GetStateOut _bsd_GetStateOut
 #define	gf128_genmultable _bsd_gf128_genmultable




More information about the vc mailing list