[asterisk-commits] kpfleming: branch kpfleming/eventfd r340162 - in /team/kpfleming/eventfd: ./ ...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Oct 10 11:51:44 CDT 2011


Author: kpfleming
Date: Mon Oct 10 11:51:38 2011
New Revision: 340162

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=340162
Log:
Create a branch to test out usage of eventfd() instead of pipes for alerting
channel threads.


Added:
    team/kpfleming/eventfd/
      - copied from r340161, trunk/
Modified:
    team/kpfleming/eventfd/channels/console_video.c
    team/kpfleming/eventfd/configure
    team/kpfleming/eventfd/configure.ac
    team/kpfleming/eventfd/include/asterisk/autoconfig.h.in
    team/kpfleming/eventfd/include/asterisk/channel.h
    team/kpfleming/eventfd/main/channel.c

Modified: team/kpfleming/eventfd/channels/console_video.c
URL: http://svnview.digium.com/svn/asterisk/team/kpfleming/eventfd/channels/console_video.c?view=diff&rev=340162&r1=340161&r2=340162
==============================================================================
--- team/kpfleming/eventfd/channels/console_video.c (original)
+++ team/kpfleming/eventfd/channels/console_video.c Mon Oct 10 11:51:38 2011
@@ -965,36 +965,14 @@
 		chan = env->owner;
 		if (chan == NULL) {
 			/* drop the chain of frames, nobody uses them */
-			while (f) {
-				struct ast_frame *g = AST_LIST_NEXT(f, frame_list);
-				ast_frfree(f);
-				f = g;
-			}
+			ast_frfree(f);
 			continue;
 		}
-		fd = chan->alertpipe[1];
-		ast_channel_lock(chan);
-
-		/* AST_LIST_INSERT_TAIL is only good for one frame, cannot use here */
-		if (chan->readq.first == NULL) {
-			chan->readq.first = f;
-		} else {
-			chan->readq.last->frame_list.next = f;
-		}
-		chan->readq.last = p;
-		/*
-		 * more or less same as ast_queue_frame, but extra
-		 * write on the alertpipe to signal frames.
-		 */
-		if (fd > -1) {
-			int blah = 1, l = sizeof(blah);
-			for (p = f; p; p = AST_LIST_NEXT(p, frame_list)) {
-				if (write(fd, &blah, l) != l)
-					ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d: %s!\n",
-						chan->name, f->frametype, f->subclass, strerror(errno));
-			}
-		}
-		ast_channel_unlock(chan);
+
+		/* Queue the chain of frames, and poke the alertpipe/eventfd if
+		   necessary.
+		*/
+		ast_queue_frame(chan, f);
 	}
 	/* thread terminating, here could call the uninit */
 	/* uninitialize the local and remote video environments */

Modified: team/kpfleming/eventfd/configure.ac
URL: http://svnview.digium.com/svn/asterisk/team/kpfleming/eventfd/configure.ac?view=diff&rev=340162&r1=340161&r2=340162
==============================================================================
--- team/kpfleming/eventfd/configure.ac (original)
+++ team/kpfleming/eventfd/configure.ac Mon Oct 10 11:51:38 2011
@@ -210,7 +210,7 @@
 )
 
 # cross-compile checks
-if test "${cross_compiling}" = "yes"; 
+if test "${cross_compiling}" = "yes";
 then
    AC_CHECK_TOOL(CC, gcc, :)
    AC_CHECK_TOOL(CXX, g++, :)
@@ -323,7 +323,7 @@
 AC_CHECK_PROGS([MD5], [md5 md5sum gmd5sum digest])
 
 if test "${MD5}" = "digest" ; then
-   MD5="${MD5} -a md5"   
+   MD5="${MD5} -a md5"
 fi
 
 ACX_PTHREAD
@@ -334,7 +334,7 @@
 	[AS_HELP_STRING([--enable-dev-mode],
 		[Turn on developer mode])],
 	[case "${enableval}" in
-	      y|ye|yes) AST_DEVMODE=yes ;;
+	      y|yes) AST_DEVMODE=yes ;;
 	      n|no)  AST_DEVMODE=no ;;
 	      noisy)
 	      AST_DEVMODE=yes
@@ -350,7 +350,7 @@
 	[AS_HELP_STRING([--enable-coverage],
 		[Turn on code coverage tracking (for gcov)])],
 	[case "${enableval}" in
-	      y|ye|yes) AST_CODE_COVERAGE=yes ;;
+	      y|yes) AST_CODE_COVERAGE=yes ;;
 	      n|no) AST_CODE_COVERAGE=no ;;
 	      *) AC_MSG_ERROR(bad value ${enableval} for --enable-coverage)  ;;
 	esac])
@@ -500,7 +500,7 @@
 	[AS_HELP_STRING([--disable-xmldoc],
 		[Explicity disable XML documentation])],
 	[case "${enableval}" in
-		y|ye|yes) disable_xmldoc=no ;;
+		y|yes) disable_xmldoc=no ;;
 		n|no)  disable_xmldoc=yes ;;
 		*) AC_MSG_ERROR(bad value ${enableval} for --disable-xmldoc)  ;;
 	esac], [disable_xmldoc=no])
@@ -572,6 +572,17 @@
 AC_FUNC_VPRINTF
 AC_CHECK_FUNCS([asprintf atexit closefrom dup2 eaccess endpwent euidaccess ffsll ftruncate getcwd gethostbyname gethostname getloadavg gettimeofday glob htonll ioperm inet_ntoa isascii memchr memmove memset mkdir mkdtemp munmap ntohll 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 utime vasprintf getpeereid sysctl swapctl])
 
+AC_ARG_ENABLE([eventfd],
+	[AS_HELP_STRING([--disable-eventfd],
+		[Disable usage of eventfd()])],
+	[case "${enableval}" in
+		y|yes) AC_CHECK_FUNCS([eventfd]) ;;
+		n|no) ;;
+		*) AC_MSG_ERROR(bad value ${enableval} for --disable-eventfd) ;;
+	esac],
+	AC_CHECK_FUNCS([eventfd])
+)
+
 # NOTE: we use AC_CHECK_LIB to get -lm into the arguments for later checks,
 # so that AC_CHECK_FUNCS can detect functions in that library.
 AC_CHECK_LIB([m], [sqrt])
@@ -621,7 +632,7 @@
 LDFLAGS=${old_LDFLAGS}
 rm -f conftest.dynamics
 
-AC_CHECK_HEADER([sys/poll.h], 
+AC_CHECK_HEADER([sys/poll.h],
    [HAS_POLL=1]
    AC_DEFINE([HAVE_SYS_POLL_H], 1, [Define to 1 if your system has working sys/poll.h]),
    )
@@ -630,7 +641,7 @@
 	[AS_HELP_STRING([--enable-internal-poll],
 		[Use Asterisk's poll implementation])],
 	[case "${enableval}" in
-		y|ye|yes) HAS_POLL="";;
+		y|yes) HAS_POLL="";;
 		n|no) HAS_POLL="${HAS_POLL}" ;;
 		*) AC_MSG_ERROR(bad value ${enableval} for --enable-internal-poll) ;;
 	esac])
@@ -1453,7 +1464,7 @@
 				fi
 			fi
 		fi
-	fi 
+	fi
 	if test "${IMAP_TK_DIR}" = "system"; then
 		#We will enter here if user specified "system" or if any of above checks failed
 		AC_MSG_CHECKING([for system c-client library...])
@@ -1711,7 +1722,7 @@
 			AC_DEFINE([HAVE_IMAP_TK2006], 1, [Define if your system has the UW IMAP Toolkit c-client library version 2006 or greater.])
 		fi
 	else
-		AC_MSG_RESULT(no) 
+		AC_MSG_RESULT(no)
 	fi
 	CPPFLAGS="${saved_cppflags}"
 	LIBS="${saved_libs}"
@@ -1782,7 +1793,7 @@
 AST_EXT_LIB_CHECK([OSS], [ossaudio], [oss_ioctl_mixer], [soundcard.h])
 
 PG_CONFIG=No
-if test "${USE_PGSQL}" != "no"; then	
+if test "${USE_PGSQL}" != "no"; then
    if test "x${PGSQL_DIR}" != "x"; then
       AC_PATH_TOOL([PG_CONFIG], [pg_config], No, [${PGSQL_DIR}/bin])
       if test x"${PG_CONFIG}" = xNo; then
@@ -1808,7 +1819,7 @@
          AC_MSG_NOTICE([*** including --without-postgres])
          exit 1
 	  fi
-   else 
+   else
       AC_CHECK_LIB([pq], [PQescapeStringConn], AC_DEFINE_UNQUOTED([HAVE_PGSQL], 1,
       [Define to indicate the PostgreSQL library]), [], -L${PGSQL_libdir} -lz)
 
@@ -1901,7 +1912,7 @@
 	fi
 	AST_CHECK_PWLIB()
 	AST_CHECK_PWLIB_VERSION([PWLib], [PWLIB], [ptbuildopts.h], [1], [9], [2], [P[[WT]]LIB_VERSION])
-		
+
 	if test "${HAS_PWLIB:-unset}" != "unset"; then
 		AST_CHECK_PWLIB_PLATFORM()
 
@@ -1931,7 +1942,7 @@
 		[${PWLIB_INCLUDE}], [${PWLIB_LIB}])
 fi
 
-AST_EXT_LIB_CHECK([LUA], [lua5.1], [luaL_newstate], [lua5.1/lua.h], [-lm]) 
+AST_EXT_LIB_CHECK([LUA], [lua5.1], [luaL_newstate], [lua5.1/lua.h], [-lm])
 if test "x${PBX_LUA}" = "x1" ; then
 	if test x"${LUA_DIR}" = x; then
 		LUA_INCLUDE="${LUA_INCLUDE} -I/usr/include/lua5.1"
@@ -1939,9 +1950,9 @@
 		LUA_INCLUDE="${LUA_INCLUDE} -I${LUA_DIR}/lua5.1"
 	fi
 fi
-	
+
 # Some distributions (like SuSE) remove the 5.1 suffix.
-AST_EXT_LIB_CHECK([LUA], [lua], [luaL_register], [lua.h], [-lm]) 
+AST_EXT_LIB_CHECK([LUA], [lua], [luaL_register], [lua.h], [-lm])
 
 AST_EXT_LIB_CHECK([RADIUS], [radiusclient-ng], [rc_read_config], [radiusclient-ng.h])
 
@@ -2107,11 +2118,11 @@
 	[#include <vpbapi.h>],
 	[int q = vpb_open(0,0);])
 	],
-	[	AC_MSG_RESULT(yes) 
-		ac_cv_lib_vpb_vpb_open="yes" 
+	[	AC_MSG_RESULT(yes)
+		ac_cv_lib_vpb_vpb_open="yes"
 	],
-	[	AC_MSG_RESULT(no) 
-		ac_cv_lib_vpb_vpb_open="no" 
+	[	AC_MSG_RESULT(no)
+		ac_cv_lib_vpb_vpb_open="no"
 	]
 	)
    LIBS="${saved_libs}"
@@ -2293,8 +2304,8 @@
 AC_MSG_NOTICE(Package configured for: )
 AC_MSG_NOTICE( OS type  : $host_os)
 AC_MSG_NOTICE( Host CPU : $host_cpu)
-AC_MSG_NOTICE( build-cpu:vendor:os: $build_cpu : $build_vendor : $build_os :) 
-AC_MSG_NOTICE( host-cpu:vendor:os: $host_cpu : $host_vendor : $host_os :) 
+AC_MSG_NOTICE( build-cpu:vendor:os: $build_cpu : $build_vendor : $build_os :)
+AC_MSG_NOTICE( host-cpu:vendor:os: $host_cpu : $host_vendor : $host_os :)
 if test "${cross_compiling}" = "yes"; then
    AC_MSG_NOTICE( Cross Compilation = YES)
 fi

Modified: team/kpfleming/eventfd/include/asterisk/autoconfig.h.in
URL: http://svnview.digium.com/svn/asterisk/team/kpfleming/eventfd/include/asterisk/autoconfig.h.in?view=diff&rev=340162&r1=340161&r2=340162
==============================================================================
--- team/kpfleming/eventfd/include/asterisk/autoconfig.h.in (original)
+++ team/kpfleming/eventfd/include/asterisk/autoconfig.h.in Mon Oct 10 11:51:38 2011
@@ -192,6 +192,9 @@
 /* Define to 1 if you have the `euidaccess' function. */
 #undef HAVE_EUIDACCESS
 
+/* Define to 1 if you have the `eventfd' function. */
+#undef HAVE_EVENTFD
+
 /* Define to 1 if you have the `exp' function. */
 #undef HAVE_EXP
 
@@ -836,16 +839,16 @@
 /* Define to 1 if you have the `strtoq' function. */
 #undef HAVE_STRTOQ
 
-/* Define to 1 if `ifr_ifru.ifru_hwaddr' is member of `struct ifreq'. */
+/* Define to 1 if `ifr_ifru.ifru_hwaddr' is a member of `struct ifreq'. */
 #undef HAVE_STRUCT_IFREQ_IFR_IFRU_IFRU_HWADDR
 
-/* Define to 1 if `st_blksize' is member of `struct stat'. */
+/* Define to 1 if `st_blksize' is a member of `struct stat'. */
 #undef HAVE_STRUCT_STAT_ST_BLKSIZE
 
-/* Define to 1 if `cr_uid' is member of `struct ucred'. */
+/* Define to 1 if `cr_uid' is a member of `struct ucred'. */
 #undef HAVE_STRUCT_UCRED_CR_UID
 
-/* Define to 1 if `uid' is member of `struct ucred'. */
+/* Define to 1 if `uid' is a member of `struct ucred'. */
 #undef HAVE_STRUCT_UCRED_UID
 
 /* Define to 1 if you have the mISDN Supplemental Services library. */
@@ -1122,6 +1125,9 @@
 
 /* Define to the one symbol short name of this package. */
 #undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
 
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION

Modified: team/kpfleming/eventfd/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/team/kpfleming/eventfd/include/asterisk/channel.h?view=diff&rev=340162&r1=340161&r2=340162
==============================================================================
--- team/kpfleming/eventfd/include/asterisk/channel.h (original)
+++ team/kpfleming/eventfd/include/asterisk/channel.h Mon Oct 10 11:51:38 2011
@@ -159,7 +159,7 @@
  * We have AST_MAX_FDS file descriptors in a channel.
  * Some of them have a fixed use:
  */
-#define AST_ALERT_FD	(AST_MAX_FDS-1)		/*!< used for alertpipe */
+#define AST_ALERT_FD	(AST_MAX_FDS-1)		/*!< used for alertpipe or eventfd */
 #define AST_TIMING_FD	(AST_MAX_FDS-2)		/*!< used for timingfd */
 #define AST_AGENT_FD	(AST_MAX_FDS-3)		/*!< used by agents for pass through */
 #define AST_GENERATOR_FD	(AST_MAX_FDS-4)	/*!< used by generator */
@@ -832,7 +832,7 @@
 	int fdno;					/*!< Which fd had an event detected on */
 	int streamid;					/*!< For streaming playback, the schedule ID */
 	int vstreamid;					/*!< For streaming video playback, the schedule ID */
-	struct ast_format oldwriteformat;  /*!< Original writer format */
+	struct ast_format oldwriteformat;               /*!< Original writer format */
 	int timingfd;					/*!< Timing fd */
 	enum ast_channel_state _state;			/*!< State of line -- Don't write directly, use ast_setstate() */
 	int rings;					/*!< Number of rings so far */
@@ -846,12 +846,12 @@
 							 *   the counter is only in the remaining bits */
 	int hangupcause;				/*!< Why is the channel hanged up. See causes.h */
 	unsigned int flags;				/*!< channel flags of AST_FLAG_ type */
-	int alertpipe[2];
-	struct ast_format_cap *nativeformats;         /*!< Kinds of data this channel can natively handle */
-	struct ast_format readformat;            /*!< Requested read format (after translation) */
-	struct ast_format writeformat;           /*!< Requested write format (after translation) */
-	struct ast_format rawreadformat;         /*!< Raw read format (before translation) */
-	struct ast_format rawwriteformat;        /*!< Raw write format (before translation) */
+	int alertpipe[2];				/*!< not used if HAVE_EVENTFD */
+	struct ast_format_cap *nativeformats;           /*!< Kinds of data this channel can natively handle */
+	struct ast_format readformat;                   /*!< Requested read format (after translation) */
+	struct ast_format writeformat;                  /*!< Requested write format (after translation) */
+	struct ast_format rawreadformat;                /*!< Raw read format (before translation) */
+	struct ast_format rawwriteformat;               /*!< Raw write format (before translation) */
 	unsigned int emulate_dtmf_duration;		/*!< Number of ms left to emulate DTMF for */
 #ifdef HAVE_EPOLL
 	int epfd;

Modified: team/kpfleming/eventfd/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/kpfleming/eventfd/main/channel.c?view=diff&rev=340162&r1=340161&r2=340162
==============================================================================
--- team/kpfleming/eventfd/main/channel.c (original)
+++ team/kpfleming/eventfd/main/channel.c Mon Oct 10 11:51:38 2011
@@ -32,6 +32,14 @@
 #include <sys/time.h>
 #include <signal.h>
 #include <math.h>
+
+#ifdef HAVE_EPOLL
+#include <sys/epoll.h>
+#endif
+
+#ifdef HAVE_EVENTFD
+#include <sys/eventfd.h>
+#endif
 
 #include "asterisk/paths.h"	/* use ast_config_AST_SYSTEM_NAME */
 
@@ -68,10 +76,6 @@
 #include "asterisk/stringfields.h"
 #include "asterisk/global_datastores.h"
 #include "asterisk/data.h"
-
-#ifdef HAVE_EPOLL
-#include <sys/epoll.h>
-#endif
 
 #if defined(KEEP_TILL_CHANNEL_PARTY_NUMBER_INFO_NEEDED)
 #if defined(HAVE_PRI)
@@ -1124,7 +1128,6 @@
 {
 	struct ast_channel *tmp;
 	int x;
-	int flags;
 	struct varshead *headp;
 	char *tech = "", *tech2 = NULL;
 
@@ -1158,9 +1161,11 @@
 	 * the destructor can know not to close them.
 	 */
 	tmp->timingfd = -1;
+#ifndef HAVE_EVENTFD
 	for (x = 0; x < ARRAY_LEN(tmp->alertpipe); ++x) {
 		tmp->alertpipe[x] = -1;
 	}
+#endif
 	for (x = 0; x < ARRAY_LEN(tmp->fds); ++x) {
 		tmp->fds[x] = -1;
 	}
@@ -1200,23 +1205,43 @@
 		tmp->timingfd = ast_timer_fd(tmp->timer);
 	}
 
+#ifndef HAVE_EVENTFD
 	if (needqueue) {
+		int flags;
+
 		if (pipe(tmp->alertpipe)) {
-			ast_log(LOG_WARNING, "Channel allocation failed: Can't create alert pipe! Try increasing max file descriptors with ulimit -n\n");
+			ast_log(LOG_WARNING, "Channel allocation failed: Can't create alert pipe! Try increasing max file descriptors with ulimit -n: %s\n", strerror(errno));
 			return ast_channel_unref(tmp);
-		} else {
-			flags = fcntl(tmp->alertpipe[0], F_GETFL);
-			if (fcntl(tmp->alertpipe[0], F_SETFL, flags | O_NONBLOCK) < 0) {
-				ast_log(LOG_WARNING, "Channel allocation failed: Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno));
-				return ast_channel_unref(tmp);
-			}
-			flags = fcntl(tmp->alertpipe[1], F_GETFL);
-			if (fcntl(tmp->alertpipe[1], F_SETFL, flags | O_NONBLOCK) < 0) {
-				ast_log(LOG_WARNING, "Channel allocation failed: Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno));
-				return ast_channel_unref(tmp);
-			}
-		}
-	}
+		}
+
+		flags = fcntl(tmp->alertpipe[0], F_GETFL);
+		if (fcntl(tmp->alertpipe[0], F_SETFL, flags | O_NONBLOCK) < 0) {
+			ast_log(LOG_WARNING, "Channel allocation failed: Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno));
+			return ast_channel_unref(tmp);
+		}
+
+		flags = fcntl(tmp->alertpipe[1], F_GETFL);
+		if (fcntl(tmp->alertpipe[1], F_SETFL, flags | O_NONBLOCK) < 0) {
+			ast_log(LOG_WARNING, "Channel allocation failed: Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno));
+			return ast_channel_unref(tmp);
+		}
+
+		/* Always watch the alertpipe */
+		ast_channel_set_fd(tmp, AST_ALERT_FD, tmp->alertpipe[0]);
+	}
+#else
+	if (needqueue) {
+		int efd;
+
+		if ((efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK | EFD_SEMAPHORE)) == -1) {
+			ast_log(LOG_WARNING, "Channel allocation failed: Can't create eventfd! Try increasing max file descriptors with ulimit -n: %s\n", strerror(errno));
+			return ast_channel_unref(tmp);
+		}
+
+		/* Always watch the eventfd */
+		ast_channel_set_fd(tmp, AST_ALERT_FD, efd);
+	}
+#endif
 
 	/*
 	 * This is the last place the channel constructor can fail.
@@ -1229,8 +1254,6 @@
 		return ast_channel_unref(tmp);
 	}
 
-	/* Always watch the alertpipe */
-	ast_channel_set_fd(tmp, AST_ALERT_FD, tmp->alertpipe[0]);
 	/* And timing pipe */
 	ast_channel_set_fd(tmp, AST_TIMING_FD, tmp->timingfd);
 
@@ -1414,7 +1437,6 @@
 {
 	struct ast_frame *f;
 	struct ast_frame *cur;
-	int blah = 1;
 	unsigned int new_frames = 0;
 	unsigned int new_voice_frames = 0;
 	unsigned int queued_frames = 0;
@@ -1512,11 +1534,23 @@
 		AST_LIST_APPEND_LIST(&chan->readq, &frames, frame_list);
 	}
 
-	if (chan->alertpipe[1] > -1) {
-		if (write(chan->alertpipe[1], &blah, new_frames * sizeof(blah)) != (new_frames * sizeof(blah))) {
+	if (chan->fds[AST_ALERT_FD] > -1) {
+#ifndef HAVE_EVENTFD
+		int blah[new_frames];
+
+		memset(blah, 1, sizeof(blah));
+		if (write(chan->alertpipe[1], &blah, sizeof(blah)) != sizeof(blah)) {
 			ast_log(LOG_WARNING, "Unable to write to alert pipe on %s (qlen = %d): %s!\n",
 				chan->name, queued_frames, strerror(errno));
 		}
+#else
+		uint64_t blah = new_frames;
+
+		if (write(chan->fds[AST_ALERT_FD], &blah, sizeof(blah)) != sizeof(blah)) {
+			ast_log(LOG_WARNING, "Unable to write to eventfd on %s (qlen = %d): %s!\n",
+				chan->name, queued_frames, strerror(errno));
+		}
+#endif
 	} else if (chan->timingfd > -1) {
 		ast_timer_enable_continuous(chan->timer);
 	} else if (ast_test_flag(chan, AST_FLAG_BLOCKING)) {
@@ -2451,11 +2485,17 @@
 	ast_party_connected_line_free(&chan->connected);
 	ast_party_redirecting_free(&chan->redirecting);
 
+#ifndef HAVE_EVENTFD
 	/* Close pipes if appropriate */
 	if ((fd = chan->alertpipe[0]) > -1)
 		close(fd);
 	if ((fd = chan->alertpipe[1]) > -1)
 		close(fd);
+#else
+	if ((fd = chan->fds[AST_ALERT_FD]) > -1) {
+		close(fd);
+	}
+#endif
 	if (chan->timer) {
 		ast_timer_close(chan->timer);
 	}
@@ -3764,7 +3804,6 @@
 static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
 {
 	struct ast_frame *f = NULL;	/* the return value */
-	int blah;
 	int prestate;
 	int cause = 0;
 
@@ -3826,78 +3865,8 @@
 
 	prestate = chan->_state;
 
-	/* Read and ignore anything on the alertpipe, but read only
-	   one sizeof(blah) per frame that we send from it */
-	if (chan->alertpipe[0] > -1) {
-		int flags = fcntl(chan->alertpipe[0], F_GETFL);
-		/* For some odd reason, the alertpipe occasionally loses nonblocking status,
-		 * which immediately causes a deadlock scenario.  Detect and prevent this. */
-		if ((flags & O_NONBLOCK) == 0) {
-			ast_log(LOG_ERROR, "Alertpipe on channel %s lost O_NONBLOCK?!!\n", chan->name);
-			if (fcntl(chan->alertpipe[0], F_SETFL, flags | O_NONBLOCK) < 0) {
-				ast_log(LOG_WARNING, "Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno));
-				f = &ast_null_frame;
-				goto done;
-			}
-		}
-		if (read(chan->alertpipe[0], &blah, sizeof(blah)) < 0) {
-			if (errno != EINTR && errno != EAGAIN)
-				ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
-		}
-	}
-
-	if (chan->timingfd > -1 && chan->fdno == AST_TIMING_FD) {
-		enum ast_timer_event res;
-
-		ast_clear_flag(chan, AST_FLAG_EXCEPTION);
-
-		res = ast_timer_get_event(chan->timer);
-
-		switch (res) {
-		case AST_TIMING_EVENT_EXPIRED:
-			ast_timer_ack(chan->timer, 1);
-
-			if (chan->timingfunc) {
-				/* save a copy of func/data before unlocking the channel */
-				int (*func)(const void *) = chan->timingfunc;
-				void *data = chan->timingdata;
-				chan->fdno = -1;
-				ast_channel_unlock(chan);
-				func(data);
-			} else {
-				ast_timer_set_rate(chan->timer, 0);
-				chan->fdno = -1;
-				ast_channel_unlock(chan);
-			}
-
-			/* cannot 'goto done' because the channel is already unlocked */
-			return &ast_null_frame;
-
-		case AST_TIMING_EVENT_CONTINUOUS:
-			if (AST_LIST_EMPTY(&chan->readq) || 
-				!AST_LIST_NEXT(AST_LIST_FIRST(&chan->readq), frame_list)) {
-				ast_timer_disable_continuous(chan->timer);
-			}
-			break;
-		}
-
-	} else if (chan->fds[AST_GENERATOR_FD] > -1 && chan->fdno == AST_GENERATOR_FD) {
-		/* if the AST_GENERATOR_FD is set, call the generator with args
-		 * set to -1 so it can do whatever it needs to.
-		 */
-		void *tmp = chan->generatordata;
-		chan->generatordata = NULL;     /* reset to let ast_write get through */
-		chan->generator->generate(chan, tmp, -1, -1);
-		chan->generatordata = tmp;
-		f = &ast_null_frame;
-		chan->fdno = -1;
-		goto done;
-	} else if (chan->fds[AST_JITTERBUFFER_FD] > -1 && chan->fdno == AST_JITTERBUFFER_FD) {
-		ast_clear_flag(chan, AST_FLAG_EXCEPTION);
-	}
-
-	/* Check for pending read queue */
-	if (!AST_LIST_EMPTY(&chan->readq)) {
+	if ((chan->fds[AST_ALERT_FD] > -1) &&
+	    (chan->fdno == AST_ALERT_FD)) {
 		int skip_dtmf = should_skip_dtmf(chan);
 
 		AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->readq, f, frame_list) {
@@ -3905,7 +3874,7 @@
 			 * there are cases where we want to leave DTMF frames on the queue until
 			 * some later time. */
 
-			if ( (f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END) && skip_dtmf) {
+			if ((f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END) && skip_dtmf) {
 				continue;
 			}
 
@@ -3913,18 +3882,40 @@
 			break;
 		}
 		AST_LIST_TRAVERSE_SAFE_END;
-		
+
+#ifndef HAVE_EVENTFD
+		if (f) {
+			int blah;
+			int flags = fcntl(chan->alertpipe[0], F_GETFL);
+			/* For some odd reason, the alertpipe occasionally loses nonblocking status,
+			 * which immediately causes a deadlock scenario.  Detect and prevent this. */
+			if ((flags & O_NONBLOCK) == 0) {
+				ast_log(LOG_ERROR, "Alertpipe on channel %s lost O_NONBLOCK?!!\n", chan->name);
+				if (fcntl(chan->alertpipe[0], F_SETFL, flags | O_NONBLOCK) < 0) {
+					ast_log(LOG_WARNING, "Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno));
+					f = &ast_null_frame;
+					goto done;
+				}
+			}
+			if (read(chan->alertpipe[0], &blah, sizeof(blah)) != sizeof(blah)) {
+				if (errno != EINTR && errno != EAGAIN) {
+					ast_log(LOG_WARNING, "read() on alertpipe failed: %s\n", strerror(errno));
+				}
+			}
+		}
+#else
+		if (f) {
+			uint64_t blah;
+			if (read(chan->fds[AST_ALERT_FD], &blah, sizeof(blah)) != sizeof(blah)) {
+				if (errno != EINTR && errno != EAGAIN) {
+					ast_log(LOG_WARNING, "read() on eventfd failed: %s\n", strerror(errno));
+				}
+			}
+		}
+#endif
+
 		if (!f) {
-			/* There were no acceptable frames on the readq. */
 			f = &ast_null_frame;
-			if (chan->alertpipe[0] > -1) {
-				int poke = 0;
-				/* Restore the state of the alertpipe since we aren't ready for any
-				 * of the frames in the readq. */
-				if (write(chan->alertpipe[1], &poke, sizeof(poke)) != sizeof(poke)) {
-					ast_log(LOG_ERROR, "Failed to write to alertpipe: %s\n", strerror(errno));
-				}
-			}
 		}
 
 		/* Interpret hangup and end-of-Q frames to return NULL */
@@ -3943,21 +3934,72 @@
 				break;
 			}
 		}
+	} else if ((chan->fds[AST_TIMING_FD] > -1) &&
+		   (chan->fdno == AST_TIMING_FD)) {
+		enum ast_timer_event res;
+
+		ast_clear_flag(chan, AST_FLAG_EXCEPTION);
+
+		res = ast_timer_get_event(chan->timer);
+
+		switch (res) {
+		case AST_TIMING_EVENT_EXPIRED:
+			ast_timer_ack(chan->timer, 1);
+
+			if (chan->timingfunc) {
+				/* save a copy of func/data before unlocking the channel */
+				int (*func)(const void *) = chan->timingfunc;
+				void *data = chan->timingdata;
+				chan->fdno = -1;
+				ast_channel_unlock(chan);
+				func(data);
+			} else {
+				ast_timer_set_rate(chan->timer, 0);
+				chan->fdno = -1;
+				ast_channel_unlock(chan);
+			}
+
+			/* cannot 'goto done' because the channel is already unlocked */
+			return &ast_null_frame;
+
+		case AST_TIMING_EVENT_CONTINUOUS:
+			if (AST_LIST_EMPTY(&chan->readq) ||
+			    !AST_LIST_NEXT(AST_LIST_FIRST(&chan->readq), frame_list)) {
+				ast_timer_disable_continuous(chan->timer);
+			}
+			break;
+		}
+	} else if ((chan->fds[AST_GENERATOR_FD] > -1) &&
+		   (chan->fdno == AST_GENERATOR_FD)) {
+		/* if the AST_GENERATOR_FD is set, call the generator with args
+		 * set to -1 so it can do whatever it needs to.
+		 */
+		void *tmp = chan->generatordata;
+		chan->generatordata = NULL;     /* reset to let ast_write get through */
+		chan->generator->generate(chan, tmp, -1, -1);
+		chan->generatordata = tmp;
+		f = &ast_null_frame;
+		chan->fdno = -1;
+		goto done;
+	} else if ((chan->fds[AST_JITTERBUFFER_FD] > -1) &&
+		   (chan->fdno == AST_JITTERBUFFER_FD)) {
+		ast_clear_flag(chan, AST_FLAG_EXCEPTION);
 	} else {
 		chan->blocker = pthread_self();
 		if (ast_test_flag(chan, AST_FLAG_EXCEPTION)) {
-			if (chan->tech->exception)
+			if (chan->tech->exception) {
 				f = chan->tech->exception(chan);
-			else {
+			} else {
 				ast_log(LOG_WARNING, "Exception flag set on '%s', but no exception handler\n", chan->name);
 				f = &ast_null_frame;
 			}
 			/* Clear the exception flag */
 			ast_clear_flag(chan, AST_FLAG_EXCEPTION);
-		} else if (chan->tech && chan->tech->read)
+		} else if (chan->tech && chan->tech->read) {
 			f = chan->tech->read(chan);
-		else
+		} else {
 			ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name);
+		}
 	}
 
 	/* Perform the framehook read event here. After the frame enters the framehook list
@@ -6550,7 +6592,7 @@
  */
 int ast_do_masquerade(struct ast_channel *original)
 {
-	int x, i;
+	int x;
 	int res=0;
 	int origstate;
 	int visible_indication;
@@ -6710,14 +6752,25 @@
 	original->tech_pvt = clonechan->tech_pvt;
 	clonechan->tech_pvt = t_pvt;
 
-	/* Swap the alertpipes */
-	for (i = 0; i < 2; i++) {
-		x = original->alertpipe[i];
-		original->alertpipe[i] = clonechan->alertpipe[i];
-		clonechan->alertpipe[i] = x;
-	}
-
-	/* 
+#ifndef HAVE_EVENTFD
+	{
+		int i;
+
+		/* Swap the alertpipes */
+		for (i = 0; i < 2; i++) {
+			x = original->alertpipe[i];
+			original->alertpipe[i] = clonechan->alertpipe[i];
+			clonechan->alertpipe[i] = x;
+		}
+	}
+#else
+	/* Swap the eventfds */
+	x = original->fds[AST_ALERT_FD];
+	original->fds[AST_ALERT_FD] = clonechan->fds[AST_ALERT_FD];
+	clonechan->fds[AST_ALERT_FD] = x;
+#endif
+
+	/*
 	 * Swap the readq's.  The end result should be this:
 	 *
 	 *  1) All frames should be on the new (original) channel.
@@ -6729,6 +6782,8 @@
 	 *     old (clone) channel.
 	 */
 	{
+		unsigned int moved_frames = 0;
+
 		AST_LIST_HEAD_NOLOCK(, ast_frame) tmp_readq;
 		AST_LIST_HEAD_SET_NOLOCK(&tmp_readq, NULL);
 
@@ -6737,14 +6792,27 @@
 
 		while ((current = AST_LIST_REMOVE_HEAD(&tmp_readq, frame_list))) {
 			AST_LIST_INSERT_TAIL(&original->readq, current, frame_list);
-			if (original->alertpipe[1] > -1) {
-				int poke = 0;
-
-				if (write(original->alertpipe[1], &poke, sizeof(poke)) < 0) {
-					ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
-				}
-			}
-		}
+			moved_frames++;
+		}
+
+#ifndef HAVE_EVENTFD
+		if (original->alertpipe[1] > -1) {
+			int poke[moved_frames];
+
+			memset(poke, 0, sizeof(poke));
+			if (write(original->alertpipe[1], &poke, sizeof(poke)) < 0) {
+				ast_log(LOG_WARNING, "write() on alertpipe failed: %s\n", strerror(errno));
+			}
+		}
+#else
+		if (original->fds[AST_ALERT_FD] > -1) {
+			uint64_t poke = moved_frames;
+
+			if (write(original->fds[AST_ALERT_FD], &poke, sizeof(poke)) < 0) {
+				ast_log(LOG_WARNING, "write() on eventfd failed: %s\n", strerror(errno));
+			}
+		}
+#endif
 	}
 
 	/* Swap the raw formats */




More information about the asterisk-commits mailing list