Properly migrate from select to poll for core asterisk.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@2760 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Mark Spencer
2004-04-25 20:42:45 +00:00
parent 0eca3cf384
commit 435e55958f
4 changed files with 151 additions and 101 deletions

153
channel.c
View File

@@ -20,6 +20,7 @@
#include <errno.h>
#include <unistd.h>
#include <math.h> /* For PI */
#include <sys/poll.h>
#include <asterisk/pbx.h>
#include <asterisk/frame.h>
#include <asterisk/sched.h>
@@ -776,29 +777,29 @@ int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen,
int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
{
/* Wait for x amount of time on a file descriptor to have input. */
struct timeval tv;
fd_set rfds, efds;
struct timeval start, now;
int res;
int x, max=-1;
int x, y;
int winner = -1;
int spoint;
struct pollfd *pfds;
tv.tv_sec = *ms / 1000;
tv.tv_usec = (*ms % 1000) * 1000;
FD_ZERO(&rfds);
FD_ZERO(&efds);
pfds = alloca(sizeof(struct pollfd) * n);
if (!pfds) {
ast_log(LOG_WARNING, "alloca failed! bad things will happen.\n");
return -1;
}
if (*ms > 0)
gettimeofday(&start, NULL);
y = 0;
for (x=0;x<n;x++) {
if (fds[x] > -1) {
FD_SET(fds[x], &rfds);
FD_SET(fds[x], &efds);
if (fds[x] > max)
max = fds[x];
pfds[y].fd = fds[x];
pfds[y].events = POLLIN | POLLPRI;
y++;
}
}
if (*ms >= 0)
res = ast_select(max + 1, &rfds, NULL, &efds, &tv);
else
res = ast_select(max + 1, &rfds, NULL, &efds, NULL);
res = poll(pfds, y, *ms);
if (res < 0) {
/* Simulate a timeout if we were interrupted */
if (errno != EINTR)
@@ -807,15 +808,30 @@ int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
*ms = 0;
return -1;
}
spoint = 0;
for (x=0;x<n;x++) {
if ((fds[x] > -1) && (FD_ISSET(fds[x], &rfds) || FD_ISSET(fds[x], &efds)) && (winner < 0)) {
if (exception)
*exception = FD_ISSET(fds[x], &efds);
winner = fds[x];
if (fds[x] > -1) {
if ((res = ast_fdisset(pfds, fds[x], y, &spoint))) {
winner = fds[x];
if (exception) {
if (res & POLLPRI)
*exception = -1;
else
*exception = 0;
}
}
}
}
*ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
if (*ms > 0) {
long passed;
gettimeofday(&now, NULL);
passed = (now.tv_sec - start.tv_sec) * 1000;
passed += (now.tv_usec - start.tv_usec) / 1000;
if (passed <= *ms)
*ms -= passed;
else
*ms = 0;
}
return winner;
}
@@ -823,13 +839,23 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
int *exception, int *outfd, int *ms)
{
/* Wait for x amount of time on a file descriptor to have input. */
struct timeval tv;
fd_set rfds, efds;
struct timeval start, end;
struct pollfd *pfds;
int res;
int x, y, max=-1;
long rms;
int x, y, max;
int spoint;
time_t now = 0;
long whentohangup = 0, havewhen = 0, diff;
struct ast_channel *winner = NULL;
pfds = alloca(sizeof(struct pollfd) * (n * AST_MAX_FDS + nfds));
if (!pfds) {
ast_log(LOG_WARNING, "alloca failed! bad things will happen.\n");
*outfd = -1;
return NULL;
}
if (outfd)
*outfd = -99999;
if (exception)
@@ -857,41 +883,35 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
}
ast_mutex_unlock(&c[x]->lock);
}
tv.tv_sec = *ms / 1000;
tv.tv_usec = (*ms % 1000) * 1000;
rms = *ms;
if (havewhen) {
if ((*ms < 0) || (whentohangup * 1000 < *ms)) {
tv.tv_sec = whentohangup;
tv.tv_usec = 0;
rms = whentohangup * 1000;
}
}
FD_ZERO(&rfds);
FD_ZERO(&efds);
max = 0;
for (x=0;x<n;x++) {
for (y=0;y<AST_MAX_FDS;y++) {
if (c[x]->fds[y] > -1) {
FD_SET(c[x]->fds[y], &rfds);
FD_SET(c[x]->fds[y], &efds);
if (c[x]->fds[y] > max)
max = c[x]->fds[y];
pfds[max].fd = c[x]->fds[y];
pfds[max].events = POLLIN | POLLPRI;
max++;
}
}
CHECK_BLOCKING(c[x]);
}
for (x=0;x<nfds; x++) {
FD_SET(fds[x], &rfds);
FD_SET(fds[x], &efds);
if (fds[x] > max)
max = fds[x];
if (fds[x] > -1) {
pfds[max].fd = fds[x];
pfds[max].events = POLLIN | POLLPRI;
max++;
}
}
if ((*ms >= 0) || (havewhen))
res = ast_select(max + 1, &rfds, NULL, &efds, &tv);
else
res = ast_select(max + 1, &rfds, NULL, &efds, NULL);
if (*ms > 0)
gettimeofday(&start, NULL);
res = poll(pfds, max, rms);
if (res < 0) {
for (x=0;x<n;x++)
c[x]->blocking = 0;
@@ -909,6 +929,7 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
if (havewhen)
time(&now);
spoint = 0;
for (x=0;x<n;x++) {
c[x]->blocking = 0;
if (havewhen && c[x]->whentohangup && (now > c[x]->whentohangup)) {
@@ -918,10 +939,11 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
}
for (y=0;y<AST_MAX_FDS;y++) {
if (c[x]->fds[y] > -1) {
if ((FD_ISSET(c[x]->fds[y], &rfds) || FD_ISSET(c[x]->fds[y], &efds)) && !winner) {
/* Set exception flag if appropriate */
if (FD_ISSET(c[x]->fds[y], &efds))
c[x]->exception = 1;
if ((res = ast_fdisset(pfds, c[x]->fds[y], max, &spoint))) {
if (res & POLLPRI)
c[x]->exception = -1;
else
c[x]->exception = 0;
c[x]->fdno = y;
winner = c[x];
}
@@ -929,15 +951,30 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
}
}
for (x=0;x<nfds;x++) {
if ((FD_ISSET(fds[x], &rfds) || FD_ISSET(fds[x], &efds)) && !winner) {
if (outfd)
*outfd = fds[x];
if (FD_ISSET(fds[x], &efds) && exception)
*exception = 1;
winner = NULL;
}
if (fds[x] > -1) {
if ((res = ast_fdisset(pfds, fds[x], max, &spoint))) {
if (outfd)
*outfd = fds[x];
if (exception) {
if (res & POLLPRI)
*exception = -1;
else
*exception = 0;
}
winner = NULL;
}
}
}
if (*ms > 0) {
long diff;
gettimeofday(&end, NULL);
diff = (end.tv_sec - start.tv_sec) * 1000;
diff += (end.tv_usec - start.tv_usec) / 1000;
if (diff < *ms)
*ms -= diff;
else
*ms = 0;
}
*ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
return winner;
}