diff options
author | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2004-04-25 20:42:45 +0000 |
---|---|---|
committer | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2004-04-25 20:42:45 +0000 |
commit | 4ab2b33bfff1628f3c21fbbd43e2db5c568862c5 (patch) | |
tree | 0520b52676690d8c020be12e27ae76e465d192fc /channel.c | |
parent | 5641552590431c923e5eda43d356379a5aa67d8f (diff) |
Properly migrate from select to poll for core asterisk.
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@2760 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channel.c')
-rwxr-xr-x | channel.c | 153 |
1 files changed, 95 insertions, 58 deletions
@@ -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; } |