[Asterisk-code-review] utils: Wrap socket() and pipe() to reduce syscalls (asterisk[16])

Sean Bright asteriskteam at digium.com
Fri Dec 7 08:05:31 CST 2018


Sean Bright has uploaded this change for review. ( https://gerrit.asterisk.org/10755


Change subject: utils: Wrap socket() and pipe() to reduce syscalls
......................................................................

utils: Wrap socket() and pipe() to reduce syscalls

Some platforms provide an implementation of socket() and pipe2() that allow the
caller to specify that the resulting file descriptors should be non-blocking.

Using these allows us to potentially elide 3 calls into 1 by avoiding extraneous
calls to fcntl() to set the O_NONBLOCK flag afterwards.

In passing, change ast_alertpipe_init() to use pipe2() directly instead of the
wrapper if it is available.

Change-Id: I3ebe654fb549587537161506c6c950f4ab298bb0
---
M configure
M configure.ac
M include/asterisk/autoconfig.h.in
M include/asterisk/utils.h
M main/alertpipe.c
M main/utils.c
6 files changed, 175 insertions(+), 8 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/55/10755/1

diff --git a/configure b/configure
index 061845f..a69ba62 100755
--- a/configure
+++ b/configure
@@ -1337,6 +1337,7 @@
 docdir
 oldincludedir
 includedir
+runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -1524,6 +1525,7 @@
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
 docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -1776,6 +1778,15 @@
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
 
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+    ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+    runstatedir=$ac_optarg ;;
+
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1913,7 +1924,7 @@
 for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
 		datadir sysconfdir sharedstatedir localstatedir includedir \
 		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-		libdir localedir mandir
+		libdir localedir mandir runstatedir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -2066,6 +2077,7 @@
   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIR            object code libraries [EPREFIX/lib]
   --includedir=DIR        C header files [PREFIX/include]
   --oldincludedir=DIR     C header files for non-gcc [/usr/include]
@@ -14868,7 +14880,7 @@
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -14914,7 +14926,7 @@
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -14938,7 +14950,7 @@
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -14983,7 +14995,7 @@
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -15007,7 +15019,7 @@
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -16307,6 +16319,8 @@
     if (*(data + i) != *(data3 + i))
       return 14;
   close (fd);
+  free (data);
+  free (data3);
   return 0;
 }
 _ACEOF
@@ -16847,7 +16861,7 @@
 done
 
 
-for ac_func in asprintf atexit closefrom dup2 eaccess endpwent euidaccess ffsll ftruncate getcwd gethostbyname gethostname getloadavg gettimeofday glob ioperm inet_ntoa isascii memchr memmove memset mkdir mkdtemp munmap newlocale ppoll putenv re_comp regcomp select setenv socket strcasecmp strcasestr strchr strcspn strdup strerror strlcat strlcpy strncasecmp strndup strnlen strrchr strsep strspn strstr strtod strtol strtold strtoq unsetenv uselocale utime vasprintf getpeereid sysctl swapctl malloc_trim
+for ac_func in asprintf atexit closefrom dup2 eaccess endpwent euidaccess ffsll ftruncate getcwd gethostbyname gethostname getloadavg gettimeofday glob ioperm inet_ntoa isascii memchr memmove memset mkdir mkdtemp munmap newlocale pipe2 ppoll putenv re_comp regcomp select setenv socket strcasecmp strcasestr strchr strcspn strdup strerror strlcat strlcpy strncasecmp strndup strnlen strrchr strsep strspn strstr strtod strtol strtold strtoq unsetenv uselocale utime vasprintf getpeereid sysctl swapctl malloc_trim
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -17924,6 +17938,51 @@
 fi
 
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if socket() accepts SOCK_NONBLOCK" >&5
+$as_echo_n "checking if socket() accepts SOCK_NONBLOCK... " >&6; }
+if test "$cross_compiling" = yes; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: cross-compile" >&5
+$as_echo "cross-compile" >&6; }
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+	#ifdef HAVE_SYS_TYPES_H
+	# include <sys/types.h>
+	#endif
+	#ifdef HAVE_SYS_SOCKET_H
+	# include <sys/socket.h>
+	#endif
+
+int
+main ()
+{
+
+	   if (socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0) < 0) {
+	      return 1;
+	   }
+	   return 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_SOCK_NONBLOCK 1" >>confdefs.h
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can increase the maximum select-able file descriptor" >&5
 $as_echo_n "checking if we can increase the maximum select-able file descriptor... " >&6; }
 if test "$cross_compiling" = yes; then :
diff --git a/configure.ac b/configure.ac
index e541e33..9a016f4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -784,7 +784,7 @@
 AC_FUNC_STRTOD
 AC_FUNC_UTIME_NULL
 AC_FUNC_VPRINTF
-AC_CHECK_FUNCS([asprintf atexit closefrom dup2 eaccess endpwent euidaccess ffsll ftruncate getcwd gethostbyname gethostname getloadavg gettimeofday glob ioperm inet_ntoa isascii memchr memmove memset mkdir mkdtemp munmap newlocale ppoll putenv re_comp regcomp select setenv socket strcasecmp strcasestr strchr strcspn strdup strerror strlcat strlcpy strncasecmp strndup strnlen strrchr strsep strspn strstr strtod strtol strtold strtoq unsetenv uselocale utime vasprintf getpeereid sysctl swapctl malloc_trim])
+AC_CHECK_FUNCS([asprintf atexit closefrom dup2 eaccess endpwent euidaccess ffsll ftruncate getcwd gethostbyname gethostname getloadavg gettimeofday glob ioperm inet_ntoa isascii memchr memmove memset mkdir mkdtemp munmap newlocale pipe2 ppoll putenv re_comp regcomp select setenv socket strcasecmp strcasestr strchr strcspn strdup strerror strlcat strlcpy strncasecmp strndup strnlen strrchr strsep strspn strstr strtod strtol strtold strtoq unsetenv uselocale utime vasprintf getpeereid sysctl swapctl malloc_trim])
 
 AC_MSG_CHECKING(for htonll)
 AC_LINK_IFELSE(
@@ -1124,6 +1124,27 @@
 	AC_MSG_RESULT(unknown)
 )
 
+AC_MSG_CHECKING([if socket() accepts SOCK_NONBLOCK])
+AC_RUN_IFELSE(
+[AC_LANG_PROGRAM([
+	#ifdef HAVE_SYS_TYPES_H
+	# include <sys/types.h>
+	#endif
+	#ifdef HAVE_SYS_SOCKET_H
+	# include <sys/socket.h>
+	#endif
+	], [
+	   if (socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0) < 0) {
+	      return 1;
+	   }
+	   return 0;
+	])],
+	AC_MSG_RESULT(yes)
+	AC_DEFINE([HAVE_SOCK_NONBLOCK], 1, [Define to 1 if your socket() implementation can accept SOCK_NONBLOCK.]),
+	AC_MSG_RESULT(no),
+	AC_MSG_RESULT(cross-compile)
+)
+
 AC_MSG_CHECKING(if we can increase the maximum select-able file descriptor)
 AC_RUN_IFELSE(
 [AC_LANG_PROGRAM([
diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in
index d0141fb..72f6ee0 100644
--- a/include/asterisk/autoconfig.h.in
+++ b/include/asterisk/autoconfig.h.in
@@ -609,6 +609,9 @@
 /* Define to indicate presence of the pg_encoding_to_char API. */
 #undef HAVE_PGSQL_pg_encoding_to_char
 
+/* Define to 1 if you have the `pipe2' function. */
+#undef HAVE_PIPE2
+
 /* Define if your system has the PJPROJECT libraries. */
 #undef HAVE_PJPROJECT
 
@@ -877,6 +880,9 @@
 /* Define to 1 if you have the `socket' function. */
 #undef HAVE_SOCKET
 
+/* Define to 1 if your socket() implementation can accept SOCK_NONBLOCK. */
+#undef HAVE_SOCK_NONBLOCK
+
 /* Define to 1 if your system has soxmix application. */
 #undef HAVE_SOXMIX
 
diff --git a/include/asterisk/utils.h b/include/asterisk/utils.h
index f459b31..c0cce98 100644
--- a/include/asterisk/utils.h
+++ b/include/asterisk/utils.h
@@ -914,6 +914,40 @@
 	const char *file, int lineno, const char *function);
 
 /*!
+ * \brief Create a non-blocking socket
+ * \since 13.25
+ *
+ * Wrapper around socket(2) that sets the O_NONBLOCK flag on the resulting
+ * socket.
+ *
+ * \details
+ * For parameter and return information, see the man page for
+ * socket(2).
+ */
+#ifdef HAVE_SOCK_NONBLOCK
+# define ast_socket_nonblock(domain, type, protocol) socket((domain), (type) | SOCK_NONBLOCK, (protocol))
+#else
+int ast_socket_nonblock(int domain, int type, int protocol);
+#endif
+
+/*!
+ * \brief Create a non-blocking pipe
+ * \since 13.25
+ *
+ * Wrapper around pipe(2) that sets the O_NONBLOCK flag on the resulting
+ * file descriptors.
+ *
+ * \details
+ * For parameter and return information, see the man page for
+ * pipe(2).
+ */
+#ifdef HAVE_PIPE2
+# define ast_pipe_nonblock(filedes) pipe2((filedes), O_NONBLOCK)
+#else
+int ast_pipe_nonblock(int filedes[2]);
+#endif
+
+/*!
  * \brief Set the current thread's user interface status.
  *
  * \param is_user_interface Non-zero to mark the thread as a user interface.
diff --git a/main/alertpipe.c b/main/alertpipe.c
index 7932a73..9ff399d 100644
--- a/main/alertpipe.c
+++ b/main/alertpipe.c
@@ -51,6 +51,15 @@
 
 #endif
 
+#ifdef HAVE_PIPE2
+
+	if (pipe2(alert_pipe, O_NONBLOCK)) {
+		ast_log(LOG_WARNING, "Failed to create alert pipe: %s\n", strerror(errno));
+		return -1;
+	}
+
+#else
+
 	if (pipe(alert_pipe)) {
 		ast_log(LOG_WARNING, "Failed to create alert pipe: %s\n", strerror(errno));
 		return -1;
@@ -62,6 +71,8 @@
 		}
 	}
 
+#endif
+
 	return 0;
 }
 
diff --git a/main/utils.c b/main/utils.c
index a062763..e0b8a6e 100644
--- a/main/utils.c
+++ b/main/utils.c
@@ -2750,6 +2750,42 @@
 	return 0;
 }
 
+#ifndef HAVE_SOCK_NONBLOCK
+int ast_socket_nonblock(int domain, int type, int protocol)
+{
+	int s = socket(domain, type, protocol);
+	if (s < 0) {
+		return -1;
+	}
+
+	if (ast_fd_set_flags(s, O_NONBLOCK)) {
+		close(s);
+		return -1;
+	}
+
+	return s;
+}
+#endif
+
+#ifndef HAVE_PIPE2
+int ast_pipe_nonblock(int filedes[2])
+{
+	int p = pipe(filedes);
+	if (p < 0) {
+		return -1;
+	}
+
+	if (ast_fd_set_flags(filedes[0], O_NONBLOCK)
+	   || ast_fd_set_flags(filedes[1], O_NONBLOCK)) {
+		close(filedes[0]);
+		close(filedes[1]);
+		return -1;
+	}
+
+	return 0;
+}
+#endif
+
 /*!
  * \brief A thread local indicating whether the current thread is a user interface.
  */

-- 
To view, visit https://gerrit.asterisk.org/10755
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: 16
Gerrit-MessageType: newchange
Gerrit-Change-Id: I3ebe654fb549587537161506c6c950f4ab298bb0
Gerrit-Change-Number: 10755
Gerrit-PatchSet: 1
Gerrit-Owner: Sean Bright <sean.bright at gmail.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20181207/a6b792be/attachment-0001.html>


More information about the asterisk-code-review mailing list