[asterisk-commits] tilghman: branch tilghman/ast_select r281685 - in /team/tilghman/ast_select: ...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Aug 10 23:59:43 CDT 2010
Author: tilghman
Date: Tue Aug 10 23:59:27 2010
New Revision: 281685
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=281685
Log:
Create a poll variation for use with chan_phone
Modified:
team/tilghman/ast_select/channels/chan_phone.c
team/tilghman/ast_select/include/asterisk/poll-compat.h
team/tilghman/ast_select/main/poll.c
team/tilghman/ast_select/res/res_features.c
Modified: team/tilghman/ast_select/channels/chan_phone.c
URL: http://svnview.digium.com/svn/asterisk/team/tilghman/ast_select/channels/chan_phone.c?view=diff&rev=281685&r1=281684&r2=281685
==============================================================================
--- team/tilghman/ast_select/channels/chan_phone.c (original)
+++ team/tilghman/ast_select/channels/chan_phone.c Tue Aug 10 23:59:27 2010
@@ -997,12 +997,12 @@
static void *do_monitor(void *data)
{
- ast_fdset rfds, efds;
- int n, res;
+ struct pollfd *fds = NULL;
+ int nfds = 0, inuse_fds = 0, res;
struct phone_pvt *i;
int tonepos = 0;
/* The tone we're playing this round */
- struct timeval tv = {0,0};
+ struct timeval tv = { 0, 0 };
int dotone;
/* This thread monitors all the frame relay interfaces which are not yet in use
(and thus do not have a separate thread) indefinitely */
@@ -1016,33 +1016,37 @@
}
/* Build the stuff we're going to select on, that is the socket of every
phone_pvt that does not have an associated owner channel */
- n = -1;
- FD_ZERO(&rfds);
- FD_ZERO(&efds);
i = iflist;
dotone = 0;
- while (i) {
- if (FD_ISSET(i->fd, &rfds))
- ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev);
+ inuse_fds = 0;
+ for (i = iflist; i; i = i->next) {
if (!i->owner) {
/* This needs to be watched, as it lacks an owner */
- FD_SET(i->fd, &rfds);
- FD_SET(i->fd, &efds);
- if (i->fd > n)
- n = i->fd;
+ if (inuse_fds == nfds) {
+ void *tmp = ast_realloc(fds, (nfds + 1) * sizeof(*fds));
+ if (!tmp) {
+ /* Avoid leaking */
+ continue;
+ }
+ fds = tmp;
+ nfds++;
+ }
+ fds[inuse_fds].fd = i->fd;
+ fds[inuse_fds].events = POLLIN | POLLERR;
+ inuse_fds++;
+
if (i->dialtone && i->mode != MODE_SIGMA) {
/* Remember we're going to have to come back and play
more dialtones */
if (ast_tvzero(tv)) {
/* If we're due for a dialtone, play one */
- if (write(i->fd, DialTone + tonepos, 240) != 240)
+ if (write(i->fd, DialTone + tonepos, 240) != 240) {
ast_log(LOG_WARNING, "Dial tone write error\n");
+ }
}
dotone++;
}
}
-
- i = i->next;
}
/* Okay, now that we know what to do, release the interface lock */
ast_mutex_unlock(&iflock);
@@ -1051,26 +1055,28 @@
if (dotone && i && i->mode != MODE_SIGMA) {
/* If we're ready to recycle the time, set it to 30 ms */
tonepos += 240;
- if (tonepos >= sizeof(DialTone))
- tonepos = 0;
+ if (tonepos >= sizeof(DialTone)) {
+ tonepos = 0;
+ }
if (ast_tvzero(tv)) {
- tv = ast_tv(30000, 0);
- }
- res = ast_select(n + 1, &rfds, NULL, &efds, &tv);
+ tv = ast_tv(0, 30000);
+ }
+ res = ast_poll2(fds, inuse_fds, &tv);
} else {
- res = ast_select(n + 1, &rfds, NULL, &efds, NULL);
- tv = ast_tv(0,0);
+ res = ast_poll(fds, inuse_fds, -1);
+ tv = ast_tv(0, 0);
tonepos = 0;
}
/* Okay, select has finished. Let's see what happened. */
if (res < 0) {
- ast_log(LOG_DEBUG, "select return %d: %s\n", res, strerror(errno));
+ ast_log(LOG_DEBUG, "poll returned %d: %s\n", res, strerror(errno));
continue;
}
/* If there are no fd's changed, just continue, it's probably time
to play some more dialtones */
- if (!res)
+ if (!res) {
continue;
+ }
/* Alright, lock the interface list again, and let's look and see what has
happened */
if (ast_mutex_lock(&iflock)) {
@@ -1078,15 +1084,27 @@
continue;
}
- i = iflist;
- for(; i; i=i->next) {
- if (FD_ISSET(i->fd, &rfds)) {
+ for (i = iflist; i; i = i->next) {
+ int j;
+ /* Find the record */
+ for (j = 0; j < inuse_fds; j++) {
+ if (fds[j].fd == i->fd) {
+ break;
+ }
+ }
+
+ /* Not found? */
+ if (j == inuse_fds) {
+ continue;
+ }
+
+ if (fds[j].revents & POLLIN) {
if (i->owner) {
continue;
}
phone_mini_packet(i);
}
- if (FD_ISSET(i->fd, &efds)) {
+ if (fds[j].revents & POLLERR) {
if (i->owner) {
continue;
}
@@ -1096,7 +1114,6 @@
ast_mutex_unlock(&iflock);
}
return NULL;
-
}
static int restart_monitor()
Modified: team/tilghman/ast_select/include/asterisk/poll-compat.h
URL: http://svnview.digium.com/svn/asterisk/team/tilghman/ast_select/include/asterisk/poll-compat.h?view=diff&rev=281685&r1=281684&r2=281685
==============================================================================
--- team/tilghman/ast_select/include/asterisk/poll-compat.h (original)
+++ team/tilghman/ast_select/include/asterisk/poll-compat.h Tue Aug 10 23:59:27 2010
@@ -116,4 +116,10 @@
#endif /* AST_POLL_COMPAT */
+/*!
+ * \brief Same as poll(2), except the time is specified in microseconds and
+ * the tv argument is modified to indicate the time remaining.
+ */
+int ast_poll2(struct pollfd *pArray, unsigned long n_fds, struct timeval *tv);
+
#endif /* __AST_POLL_COMPAT_H */
Modified: team/tilghman/ast_select/main/poll.c
URL: http://svnview.digium.com/svn/asterisk/team/tilghman/ast_select/main/poll.c?view=diff&rev=281685&r1=281684&r2=281685
==============================================================================
--- team/tilghman/ast_select/main/poll.c (original)
+++ team/tilghman/ast_select/main/poll.c Tue Aug 10 23:59:27 2010
@@ -10,9 +10,9 @@
struct pollfd
{
- int fd;
- short events;
- short revents;
+ int fd;
+ short events;
+ short revents;
}
int poll (struct pollfd *pArray, unsigned long n_fds, int timeout)
@@ -73,15 +73,13 @@
#include "asterisk.h"
-#include <unistd.h> /* standard Unix definitions */
-#include <sys/types.h> /* system types */
-#include <sys/time.h> /* time definitions */
-#include <assert.h> /* assertion macros */
-#include <string.h> /* string functions */
-
-#include "asterisk/poll-compat.h" /* this package */
-
-#ifdef AST_POLL_COMPAT
+#include <unistd.h> /* standard Unix definitions */
+#include <sys/types.h> /* system types */
+#include <sys/time.h> /* time definitions */
+#include <assert.h> /* assertion macros */
+#include <string.h> /* string functions */
+
+#include "asterisk/poll-compat.h" /* this package */
/*---------------------------------------------------------------------------*\
Macros
@@ -92,210 +90,201 @@
#endif
/*---------------------------------------------------------------------------*\
- Private Functions
-\*---------------------------------------------------------------------------*/
-
-static int map_poll_spec
-#if __STDC__ > 0
- (struct pollfd *pArray,
- unsigned long n_fds,
- ast_fdset *pReadSet,
- ast_fdset *pWriteSet,
- ast_fdset *pExceptSet)
-#else
- (pArray, n_fds, pReadSet, pWriteSet, pExceptSet)
- struct pollfd *pArray;
- unsigned long n_fds;
- ast_fdset *pReadSet;
- ast_fdset *pWriteSet;
- ast_fdset *pExceptSet;
-#endif
-{
- register unsigned long i; /* loop control */
- register struct pollfd *pCur; /* current array element */
- register int max_fd = -1; /* return value */
-
- /*
- Map the poll() structures into the file descriptor sets required
- by select().
- */
- for (i = 0, pCur = pArray; i < n_fds; i++, pCur++)
- {
- /* Skip any bad FDs in the array. */
-
- if (pCur->fd < 0)
- continue;
-
- if (pCur->events & POLLIN)
- {
- /* "Input Ready" notification desired. */
- FD_SET (pCur->fd, pReadSet);
- }
-
- if (pCur->events & POLLOUT)
- {
- /* "Output Possible" notification desired. */
- FD_SET (pCur->fd, pWriteSet);
- }
-
- if (pCur->events & POLLPRI)
- {
- /*
- "Exception Occurred" notification desired. (Exceptions
- include out of band data.
- */
- FD_SET (pCur->fd, pExceptSet);
- }
-
- max_fd = MAX (max_fd, pCur->fd);
- }
-
- return max_fd;
-}
-
-static struct timeval *map_timeout
-#if __STDC__ > 0
- (int poll_timeout, struct timeval *pSelTimeout)
-#else
- (poll_timeout, pSelTimeout)
- int poll_timeout;
- struct timeval *pSelTimeout;
-#endif
-{
- struct timeval *pResult;
-
- /*
- Map the poll() timeout value into a select() timeout. The possible
- values of the poll() timeout value, and their meanings, are:
-
- VALUE MEANING
-
- -1 wait indefinitely (until signal occurs)
- 0 return immediately, don't block
- >0 wait specified number of milliseconds
-
- select() uses a "struct timeval", which specifies the timeout in
- seconds and microseconds, so the milliseconds value has to be mapped
- accordingly.
- */
-
- assert (pSelTimeout != (struct timeval *) NULL);
-
- switch (poll_timeout)
- {
+ Private Functions
+\*---------------------------------------------------------------------------*/
+
+static int map_poll_spec(struct pollfd *pArray, unsigned long n_fds,
+ ast_fdset *pReadSet, ast_fdset *pWriteSet, ast_fdset *pExceptSet)
+{
+ register unsigned long i; /* loop control */
+ register struct pollfd *pCur; /* current array element */
+ register int max_fd = -1; /* return value */
+
+ /*
+ * Map the poll() structures into the file descriptor sets required
+ * by select().
+ */
+ for (i = 0, pCur = pArray; i < n_fds; i++, pCur++) {
+ /* Skip any bad FDs in the array. */
+
+ if (pCur->fd < 0) {
+ continue;
+ }
+
+ if (pCur->events & POLLIN) {
+ /* "Input Ready" notification desired. */
+ FD_SET(pCur->fd, pReadSet);
+ }
+
+ if (pCur->events & POLLOUT) {
+ /* "Output Possible" notification desired. */
+ FD_SET(pCur->fd, pWriteSet);
+ }
+
+ if (pCur->events & POLLPRI) {
+ /*
+ * "Exception Occurred" notification desired. (Exceptions
+ * include out of band data.
+ */
+ FD_SET(pCur->fd, pExceptSet);
+ }
+
+ max_fd = MAX(max_fd, pCur->fd);
+ }
+
+ return max_fd;
+}
+
+#ifdef AST_POLL_COMPAT
+static struct timeval *map_timeout(int poll_timeout, struct timeval *pSelTimeout)
+{
+ struct timeval *pResult;
+
+ /*
+ Map the poll() timeout value into a select() timeout. The possible
+ values of the poll() timeout value, and their meanings, are:
+
+ VALUE MEANING
+
+ -1 wait indefinitely (until signal occurs)
+ 0 return immediately, don't block
+ >0 wait specified number of milliseconds
+
+ select() uses a "struct timeval", which specifies the timeout in
+ seconds and microseconds, so the milliseconds value has to be mapped
+ accordingly.
+ */
+
+ assert(pSelTimeout != NULL);
+
+ switch (poll_timeout) {
case -1:
- /*
- A NULL timeout structure tells select() to wait indefinitely.
- */
- pResult = (struct timeval *) NULL;
- break;
+ /*
+ * A NULL timeout structure tells select() to wait indefinitely.
+ */
+ pResult = (struct timeval *) NULL;
+ break;
case 0:
- /*
- "Return immediately" (test) is specified by all zeros in
- a timeval structure.
- */
- pSelTimeout->tv_sec = 0;
- pSelTimeout->tv_usec = 0;
- pResult = pSelTimeout;
- break;
+ /*
+ * "Return immediately" (test) is specified by all zeros in
+ * a timeval structure.
+ */
+ pSelTimeout->tv_sec = 0;
+ pSelTimeout->tv_usec = 0;
+ pResult = pSelTimeout;
+ break;
default:
- /* Wait the specified number of milliseconds. */
- pSelTimeout->tv_sec = poll_timeout / 1000; /* get seconds */
- poll_timeout %= 1000; /* remove seconds */
- pSelTimeout->tv_usec = poll_timeout * 1000; /* get microseconds */
- pResult = pSelTimeout;
- break;
- }
-
-
- return pResult;
-}
-
-static void map_select_results
-#if __STDC__ > 0
- (struct pollfd *pArray,
- unsigned long n_fds,
- ast_fdset *pReadSet,
- ast_fdset *pWriteSet,
- ast_fdset *pExceptSet)
-#else
- (pArray, n_fds, pReadSet, pWriteSet, pExceptSet)
- struct pollfd *pArray;
- unsigned long n_fds;
- ast_fdset *pReadSet;
- ast_fdset *pWriteSet;
- ast_fdset *pExceptSet;
-#endif
-{
- register unsigned long i; /* loop control */
- register struct pollfd *pCur; /* current array element */
-
- for (i = 0, pCur = pArray; i < n_fds; i++, pCur++)
- {
- /* Skip any bad FDs in the array. */
-
- if (pCur->fd < 0)
- continue;
-
- /* Exception events take priority over input events. */
-
- pCur->revents = 0;
- if (FD_ISSET (pCur->fd, pExceptSet))
- pCur->revents |= POLLPRI;
-
- else if (FD_ISSET (pCur->fd, pReadSet))
- pCur->revents |= POLLIN;
-
- if (FD_ISSET (pCur->fd, pWriteSet))
- pCur->revents |= POLLOUT;
- }
-
- return;
-}
-
-/*---------------------------------------------------------------------------*\
- Public Functions
-\*---------------------------------------------------------------------------*/
-
+ /* Wait the specified number of milliseconds. */
+ pSelTimeout->tv_sec = poll_timeout / 1000; /* get seconds */
+ poll_timeout %= 1000; /* remove seconds */
+ pSelTimeout->tv_usec = poll_timeout * 1000; /* get microseconds */
+ pResult = pSelTimeout;
+ break;
+ }
+
+ return pResult;
+}
+#endif /* AST_POLL_COMPAT */
+
+static void map_select_results(struct pollfd *pArray, unsigned long n_fds,
+ ast_fdset *pReadSet, ast_fdset *pWriteSet, ast_fdset *pExceptSet)
+{
+ register unsigned long i; /* loop control */
+ register struct pollfd *pCur; /* current array element */
+
+ for (i = 0, pCur = pArray; i < n_fds; i++, pCur++) {
+ /* Skip any bad FDs in the array. */
+
+ if (pCur->fd < 0) {
+ continue;
+ }
+
+ /* Exception events take priority over input events. */
+ pCur->revents = 0;
+ if (FD_ISSET(pCur->fd, pExceptSet)) {
+ pCur->revents |= POLLPRI;
+ } else if (FD_ISSET(pCur->fd, pReadSet)) {
+ pCur->revents |= POLLIN;
+ }
+
+ if (FD_ISSET(pCur->fd, pWriteSet)) {
+ pCur->revents |= POLLOUT;
+ }
+ }
+
+ return;
+}
+
+/*---------------------------------------------------------------------------*\
+ Public Functions
+\*---------------------------------------------------------------------------*/
+#ifdef AST_POLL_COMPAT
int ast_internal_poll(struct pollfd *pArray, unsigned long n_fds, int timeout)
{
- ast_fdset read_descs; /* input file descs */
- ast_fdset write_descs; /* output file descs */
- ast_fdset except_descs; /* exception descs */
- struct timeval stime; /* select() timeout value */
- int ready_descriptors; /* function result */
- int max_fd = 0; /* maximum fd value */
- struct timeval *pTimeout; /* actually passed */
-
- FD_ZERO (&read_descs);
- FD_ZERO (&write_descs);
- FD_ZERO (&except_descs);
-
- /* Map the poll() file descriptor list in the select() data structures. */
+ ast_fdset read_descs; /* input file descs */
+ ast_fdset write_descs; /* output file descs */
+ ast_fdset except_descs; /* exception descs */
+ struct timeval stime; /* select() timeout value */
+ int ready_descriptors; /* function result */
+ int max_fd = 0; /* maximum fd value */
+ struct timeval *pTimeout; /* actually passed */
+
+ FD_ZERO(&read_descs);
+ FD_ZERO(&write_descs);
+ FD_ZERO(&except_descs);
+
+ /* Map the poll() file descriptor list in the select() data structures. */
if (pArray) {
max_fd = map_poll_spec (pArray, n_fds,
&read_descs, &write_descs, &except_descs);
}
- /* Map the poll() timeout value in the select() timeout structure. */
-
- pTimeout = map_timeout (timeout, &stime);
-
- /* Make the select() call. */
-
- ready_descriptors = ast_select(max_fd + 1, &read_descs, &write_descs,
+ /* Map the poll() timeout value in the select() timeout structure. */
+
+ pTimeout = map_timeout (timeout, &stime);
+
+ /* Make the select() call. */
+
+ ready_descriptors = ast_select(max_fd + 1, &read_descs, &write_descs,
&except_descs, pTimeout);
- if (ready_descriptors >= 0)
- {
+ if (ready_descriptors >= 0) {
map_select_results (pArray, n_fds,
- &read_descs, &write_descs, &except_descs);
- }
-
- return ready_descriptors;
-}
-
+ &read_descs, &write_descs, &except_descs);
+ }
+
+ return ready_descriptors;
+}
#endif /* AST_POLL_COMPAT */
+
+/* Note: we intentionally do not use the ppoll(2) call on Linux, because while the
+ * kernel modifies the tv argument, glibc hides the change from us, and we WANT to
+ * be able to check how much time remains. Chan_phone, in particular, depends upon
+ * this behavior.
+ */
+int ast_poll2(struct pollfd *pArray, unsigned long n_fds, struct timeval *tv)
+{
+ ast_fdset read_descs, write_descs, except_descs;
+ int ready_descriptors, max_fd = 0;
+
+ FD_ZERO(&read_descs);
+ FD_ZERO(&write_descs);
+ FD_ZERO(&except_descs);
+
+ if (pArray) {
+ max_fd = map_poll_spec(pArray, n_fds, &read_descs, &write_descs, &except_descs);
+ }
+
+ ready_descriptors = ast_select(max_fd + 1, &read_descs, &write_descs, &except_descs, tv);
+
+ if (ready_descriptors >= 0) {
+ map_select_results(pArray, n_fds, &read_descs, &write_descs, &except_descs);
+ }
+
+ return ready_descriptors;
+}
+
+
Modified: team/tilghman/ast_select/res/res_features.c
URL: http://svnview.digium.com/svn/asterisk/team/tilghman/ast_select/res/res_features.c?view=diff&rev=281685&r1=281684&r2=281685
==============================================================================
--- team/tilghman/ast_select/res/res_features.c (original)
+++ team/tilghman/ast_select/res/res_features.c Tue Aug 10 23:59:27 2010
@@ -2314,7 +2314,7 @@
ast_indicate(chan, AST_CONTROL_UNHOLD);
/* Get chan, exten from derived kludge */
if (pu->peername[0]) {
- char *peername = ast_strdupa(pu->peername);
+ char *peername = ast_strdup(pu->peername);
char *cp = strrchr(peername, '-');
if (cp)
*cp = 0;
@@ -2351,6 +2351,7 @@
ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), ast_free_ptr, registrar);
}
set_c_e_p(chan, parking_con_dial, peername, 1);
+ ast_free(peername);
} else {
/* They've been waiting too long, send them back to where they came. Theoretically they
should have their original extensions and such, but we copy to be on the safe side */
More information about the asterisk-commits
mailing list