select.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2010, Digium, Inc.
  5. *
  6. * Tilghman Lesher <tlesher AT digium DOT com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*!\file
  19. * \brief Bitfield expansions for ast_select
  20. */
  21. #ifndef __AST_SELECT_H
  22. #define __AST_SELECT_H
  23. #include <sys/time.h>
  24. #include <sys/select.h>
  25. #include <errno.h>
  26. #include "asterisk/compat.h"
  27. #ifdef __cplusplus
  28. extern "C" {
  29. #endif
  30. extern unsigned int ast_FD_SETSIZE;
  31. #if !defined(HAVE_VARIABLE_FDSET) && defined(CONFIGURE_RAN_AS_ROOT)
  32. #define ast_fdset fd_set
  33. #else
  34. #define ast_FDMAX 32768
  35. typedef struct {
  36. TYPEOF_FD_SET_FDS_BITS fds_bits[ast_FDMAX / 8 / SIZEOF_FD_SET_FDS_BITS]; /* 32768 bits */
  37. } ast_fdset;
  38. #define _bitsize(a) (sizeof(a) * 8)
  39. #undef FD_ZERO
  40. #define FD_ZERO(a) \
  41. do { \
  42. TYPEOF_FD_SET_FDS_BITS *bytes = (TYPEOF_FD_SET_FDS_BITS *) a; \
  43. int i; \
  44. for (i = 0; i < ast_FDMAX / _bitsize(TYPEOF_FD_SET_FDS_BITS); i++) { \
  45. bytes[i] = 0; \
  46. } \
  47. } while (0)
  48. #undef FD_SET
  49. #define FD_SET(fd, fds) \
  50. do { \
  51. TYPEOF_FD_SET_FDS_BITS *bytes = (TYPEOF_FD_SET_FDS_BITS *) fds; \
  52. if (fd < ast_FDMAX) { \
  53. bytes[fd / _bitsize(*bytes)] |= ((TYPEOF_FD_SET_FDS_BITS) 1) << (fd % _bitsize(*bytes)); \
  54. } else { \
  55. fprintf(stderr, "FD %d exceeds the maximum size of ast_fdset!\n", fd); \
  56. } \
  57. } while (0)
  58. #endif /* HAVE_VARIABLE_FDSET */
  59. /*! \brief Waits for activity on a group of channels
  60. * \param nfds the maximum number of file descriptors in the sets
  61. * \param rfds file descriptors to check for read availability
  62. * \param wfds file descriptors to check for write availability
  63. * \param efds file descriptors to check for exceptions (OOB data)
  64. * \param tvp timeout while waiting for events
  65. * This is the same as a standard select(), except it guarantees the
  66. * behaviour where the passed struct timeval is updated with how much
  67. * time was not slept while waiting for the specified events
  68. */
  69. static inline int ast_select(int nfds, ast_fdset *rfds, ast_fdset *wfds, ast_fdset *efds, struct timeval *tvp)
  70. {
  71. #ifdef __linux__
  72. return select(nfds, (fd_set *) rfds, (fd_set *) wfds, (fd_set *) efds, tvp);
  73. #else
  74. int save_errno = 0;
  75. if (tvp) {
  76. struct timeval tv, tvstart, tvend, tvlen;
  77. int res;
  78. tv = *tvp;
  79. gettimeofday(&tvstart, NULL);
  80. res = select(nfds, (fd_set *) rfds, (fd_set *) wfds, (fd_set *) efds, tvp);
  81. save_errno = errno;
  82. gettimeofday(&tvend, NULL);
  83. timersub(&tvend, &tvstart, &tvlen);
  84. timersub(&tv, &tvlen, tvp);
  85. if (tvp->tv_sec < 0 || (tvp->tv_sec == 0 && tvp->tv_usec < 0)) {
  86. tvp->tv_sec = 0;
  87. tvp->tv_usec = 0;
  88. }
  89. errno = save_errno;
  90. return res;
  91. }
  92. else
  93. return select(nfds, (fd_set *) rfds, (fd_set *) wfds, (fd_set *) efds, NULL);
  94. #endif
  95. }
  96. #ifdef __cplusplus
  97. }
  98. #endif
  99. #endif /* __AST_SELECT_H */