Sat Aug 6 00:39:31 2011

Asterisk developer's documentation


poll.c

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   $Id: poll.c 285266 2010-09-07 19:04:50Z tilghman $
00003 
00004   NAME
00005 
00006    poll - select(2)-based poll() emulation function for BSD systems.
00007 
00008   SYNOPSIS
00009    #include "poll.h"
00010 
00011    struct pollfd
00012    {
00013       int    fd;
00014       short   events;
00015       short   revents;
00016    }
00017 
00018    int poll (struct pollfd *pArray, unsigned long n_fds, int timeout)
00019 
00020   DESCRIPTION
00021 
00022    This file, and the accompanying "poll.h", implement the System V
00023    poll(2) system call for BSD systems (which typically do not provide
00024    poll()).  Poll() provides a method for multiplexing input and output
00025    on multiple open file descriptors; in traditional BSD systems, that
00026    capability is provided by select().  While the semantics of select()
00027    differ from those of poll(), poll() can be readily emulated in terms
00028    of select() -- which is how this function is implemented.
00029 
00030   REFERENCES
00031    Stevens, W. Richard. Unix Network Programming.  Prentice-Hall, 1990.
00032 
00033   NOTES
00034    1. This software requires an ANSI C compiler.
00035 
00036   LICENSE
00037 
00038    This software is released under the following license:
00039 
00040       Copyright (c) 1995-2002 Brian M. Clapper
00041       All rights reserved.
00042 
00043       Redistribution and use in source and binary forms are
00044       permitted provided that: (1) source distributions retain
00045       this entire copyright notice and comment; (2) modifications
00046       made to the software are prominently mentioned, and a copy
00047       of the original software (or a pointer to its location) are
00048       included; and (3) distributions including binaries display
00049       the following acknowledgement: "This product includes
00050       software developed by Brian M. Clapper <bmc@clapper.org>"
00051       in the documentation or other materials provided with the
00052       distribution. The name of the author may not be used to
00053       endorse or promote products derived from this software
00054       without specific prior written permission.
00055 
00056       THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS
00057       OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE
00058       IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00059       PARTICULAR PURPOSE.
00060 
00061    Effectively, this means you can do what you want with the software
00062    except remove this notice or take advantage of the author's name.
00063    If you modify the software and redistribute your modified version,
00064    you must indicate that your version is a modification of the
00065    original, and you must provide either a pointer to or a copy of the
00066    original.
00067 \*---------------------------------------------------------------------------*/
00068 
00069 
00070 /*---------------------------------------------------------------------------*\
00071              Includes
00072 \*---------------------------------------------------------------------------*/
00073 
00074 #include "asterisk.h"
00075 
00076 #include <unistd.h>            /* standard Unix definitions */
00077 #include <sys/types.h>                 /* system types */
00078 #include <sys/time.h>                  /* time definitions */
00079 #include <assert.h>                   /* assertion macros */
00080 #include <string.h>                   /* string functions */
00081 #include <errno.h>
00082 
00083 #include "asterisk/poll-compat.h"                     /* this package */
00084 
00085 /*---------------------------------------------------------------------------*\
00086               Macros
00087 \*---------------------------------------------------------------------------*/
00088 
00089 #ifndef MAX
00090 #define MAX(a,b)  ((a) > (b) ? (a) : (b))
00091 #endif
00092 
00093 /*---------------------------------------------------------------------------*\
00094              Private Functions
00095 \*---------------------------------------------------------------------------*/
00096 
00097 #if defined(AST_POLL_COMPAT)
00098 static int map_poll_spec(struct pollfd *pArray, unsigned long n_fds,
00099       ast_fdset *pReadSet, ast_fdset *pWriteSet, ast_fdset *pExceptSet)
00100 {
00101    register unsigned long  i;     /* loop control */
00102    register struct pollfd *pCur;  /* current array element */
00103    register int max_fd = -1;      /* return value */
00104 
00105    /*
00106     * Map the poll() structures into the file descriptor sets required
00107     * by select().
00108     */
00109    for (i = 0, pCur = pArray; i < n_fds; i++, pCur++) {
00110       /* Skip any bad FDs in the array. */
00111 
00112       if (pCur->fd < 0) {
00113          continue;
00114       }
00115 
00116       if (pCur->events & POLLIN) {
00117          /* "Input Ready" notification desired. */
00118          FD_SET(pCur->fd, pReadSet);
00119       }
00120 
00121       if (pCur->events & POLLOUT) {
00122          /* "Output Possible" notification desired. */
00123          FD_SET(pCur->fd, pWriteSet);
00124       }
00125 
00126       if (pCur->events & POLLPRI) {
00127          /*
00128           * "Exception Occurred" notification desired.  (Exceptions
00129           * include out of band data.
00130           */
00131          FD_SET(pCur->fd, pExceptSet);
00132       }
00133 
00134       max_fd = MAX(max_fd, pCur->fd);
00135    }
00136 
00137    return max_fd;
00138 }
00139 
00140 #ifdef AST_POLL_COMPAT
00141 static struct timeval *map_timeout(int poll_timeout, struct timeval *pSelTimeout)
00142 {
00143    struct timeval *pResult;
00144 
00145    /*
00146       Map the poll() timeout value into a select() timeout.  The possible
00147       values of the poll() timeout value, and their meanings, are:
00148 
00149       VALUE MEANING
00150 
00151       -1 wait indefinitely (until signal occurs)
00152       0  return immediately, don't block
00153       >0 wait specified number of milliseconds
00154 
00155       select() uses a "struct timeval", which specifies the timeout in
00156       seconds and microseconds, so the milliseconds value has to be mapped
00157       accordingly.
00158    */
00159 
00160    assert(pSelTimeout != NULL);
00161 
00162    switch (poll_timeout) {
00163    case -1:
00164       /*
00165        * A NULL timeout structure tells select() to wait indefinitely.
00166        */
00167       pResult = (struct timeval *) NULL;
00168       break;
00169 
00170    case 0:
00171       /*
00172        * "Return immediately" (test) is specified by all zeros in
00173        * a timeval structure.
00174        */
00175       pSelTimeout->tv_sec  = 0;
00176       pSelTimeout->tv_usec = 0;
00177       pResult = pSelTimeout;
00178       break;
00179 
00180    default:
00181       /* Wait the specified number of milliseconds. */
00182       pSelTimeout->tv_sec  = poll_timeout / 1000; /* get seconds */
00183       poll_timeout        %= 1000;                /* remove seconds */
00184       pSelTimeout->tv_usec = poll_timeout * 1000; /* get microseconds */
00185       pResult = pSelTimeout;
00186       break;
00187    }
00188 
00189    return pResult;
00190 }
00191 #endif /* AST_POLL_COMPAT */
00192 
00193 static void map_select_results(struct pollfd *pArray, unsigned long n_fds,
00194            ast_fdset *pReadSet, ast_fdset *pWriteSet, ast_fdset *pExceptSet)
00195 {
00196    register unsigned long  i;    /* loop control */
00197    register struct pollfd *pCur; /* current array element */
00198 
00199    for (i = 0, pCur = pArray; i < n_fds; i++, pCur++) {
00200       /* Skip any bad FDs in the array. */
00201 
00202       if (pCur->fd < 0) {
00203          continue;
00204       }
00205 
00206       /* Exception events take priority over input events. */
00207       pCur->revents = 0;
00208       if (FD_ISSET(pCur->fd, (fd_set *) pExceptSet)) {
00209          pCur->revents |= POLLPRI;
00210       } else if (FD_ISSET(pCur->fd, (fd_set *) pReadSet)) {
00211          pCur->revents |= POLLIN;
00212       }
00213 
00214       if (FD_ISSET(pCur->fd, (fd_set *) pWriteSet)) {
00215          pCur->revents |= POLLOUT;
00216       }
00217    }
00218 
00219    return;
00220 }
00221 #endif /* defined(AST_POLL_COMPAT) || !defined(HAVE_PPOLL) */
00222 
00223 /*---------------------------------------------------------------------------*\
00224              Public Functions
00225 \*---------------------------------------------------------------------------*/
00226 #ifdef AST_POLL_COMPAT
00227 int ast_internal_poll(struct pollfd *pArray, unsigned long n_fds, int timeout)
00228 {
00229    ast_fdset  read_descs;                       /* input file descs */
00230    ast_fdset  write_descs;                      /* output file descs */
00231    ast_fdset  except_descs;                     /* exception descs */
00232    struct  timeval stime;                       /* select() timeout value */
00233    int     ready_descriptors;                   /* function result */
00234    int     max_fd = 0;                          /* maximum fd value */
00235    struct  timeval *pTimeout;                   /* actually passed */
00236    int save_errno;
00237 
00238    FD_ZERO(&read_descs);
00239    FD_ZERO(&write_descs);
00240    FD_ZERO(&except_descs);
00241 
00242    /* Map the poll() file descriptor list in the select() data structures. */
00243 
00244    if (pArray) {
00245       max_fd = map_poll_spec (pArray, n_fds,
00246             &read_descs, &write_descs, &except_descs);
00247    }
00248 
00249    /* Map the poll() timeout value in the select() timeout structure. */
00250 
00251    pTimeout = map_timeout (timeout, &stime);
00252 
00253    /* Make the select() call. */
00254 
00255    ready_descriptors = ast_select(max_fd + 1, &read_descs, &write_descs,
00256             &except_descs, pTimeout);
00257    save_errno = errno;
00258 
00259    if (ready_descriptors >= 0) {
00260       map_select_results (pArray, n_fds,
00261             &read_descs, &write_descs, &except_descs);
00262    }
00263 
00264    errno = save_errno;
00265    return ready_descriptors;
00266 }
00267 #endif /* AST_POLL_COMPAT */
00268 
00269 int ast_poll2(struct pollfd *pArray, unsigned long n_fds, struct timeval *tv)
00270 {
00271 #if !defined(AST_POLL_COMPAT)
00272    struct timeval start = ast_tvnow();
00273 #if defined(HAVE_PPOLL)
00274    struct timespec ts = { tv ? tv->tv_sec : 0, tv ? tv->tv_usec * 1000 : 0 };
00275    int res = ppoll(pArray, n_fds, tv ? &ts : NULL, NULL);
00276 #else
00277    int res = poll(pArray, n_fds, tv ? tv->tv_sec * 1000 + tv->tv_usec / 1000 : -1);
00278 #endif
00279    struct timeval after = ast_tvnow();
00280    if (res > 0 && tv && ast_tvdiff_ms(ast_tvadd(*tv, start), after) > 0) {
00281       *tv = ast_tvsub(*tv, ast_tvsub(after, start));
00282    } else if (res > 0 && tv) {
00283       *tv = ast_tv(0, 0);
00284    }
00285    return res;
00286 #else
00287    ast_fdset read_descs, write_descs, except_descs;
00288    int ready_descriptors, max_fd = 0;
00289 
00290    FD_ZERO(&read_descs);
00291    FD_ZERO(&write_descs);
00292    FD_ZERO(&except_descs);
00293 
00294    if (pArray) {
00295       max_fd = map_poll_spec(pArray, n_fds, &read_descs, &write_descs, &except_descs);
00296    }
00297 
00298    ready_descriptors = ast_select(max_fd + 1, &read_descs, &write_descs, &except_descs, tv);
00299 
00300    if (ready_descriptors >= 0) {
00301       map_select_results(pArray, n_fds, &read_descs, &write_descs, &except_descs);
00302    }
00303 
00304    return ready_descriptors;
00305 #endif
00306 }
00307 
00308 

Generated on Sat Aug 6 00:39:31 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7