jack1 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
4.5KB

  1. // fakepoll.h
  2. // poll using select
  3. // Warning: a call to this poll() takes about 4K of stack space.
  4. // Greg Parker gparker-web@sealiesoftware.com December 2000
  5. // This code is in the public domain and may be copied or modified without
  6. // permission.
  7. // Updated May 2002:
  8. // * fix crash when an fd is less than 0
  9. // * set errno=EINVAL if an fd is greater or equal to FD_SETSIZE
  10. // * don't set POLLIN or POLLOUT in revents if it wasn't requested
  11. // in events (only happens when an fd is in the poll set twice)
  12. #ifndef _FAKE_POLL_H
  13. #define _FAKE_POLL_H
  14. #include <limits.h>
  15. #define FD_SETSIZE OPEN_MAX
  16. #include <sys/types.h>
  17. #include <sys/time.h>
  18. #include <unistd.h>
  19. #include <stdlib.h>
  20. #include <errno.h>
  21. typedef struct pollfd {
  22. int fd; /* file desc to poll */
  23. short events; /* events of interest on fd */
  24. short revents; /* events that occurred on fd */
  25. } pollfd_t;
  26. // poll flags
  27. #define POLLIN 0x0001
  28. #define POLLOUT 0x0004
  29. #define POLLERR 0x0008
  30. // synonyms
  31. #define POLLNORM POLLIN
  32. #define POLLPRI POLLIN
  33. #define POLLRDNORM POLLIN
  34. #define POLLRDBAND POLLIN
  35. #define POLLWRNORM POLLOUT
  36. #define POLLWRBAND POLLOUT
  37. // ignored
  38. #define POLLHUP 0x0010
  39. #define POLLNVAL 0x0020
  40. inline int poll(struct pollfd *pollSet, int pollCount, int pollTimeout)
  41. {
  42. struct timeval tv;
  43. struct timeval *tvp;
  44. fd_set readFDs, writeFDs, exceptFDs;
  45. fd_set *readp, *writep, *exceptp;
  46. struct pollfd *pollEnd, *p;
  47. int selected;
  48. int result;
  49. int maxFD;
  50. if (!pollSet) {
  51. pollEnd = NULL;
  52. readp = NULL;
  53. writep = NULL;
  54. exceptp = NULL;
  55. maxFD = 0;
  56. }
  57. else {
  58. pollEnd = pollSet + pollCount;
  59. readp = &readFDs;
  60. writep = &writeFDs;
  61. exceptp = &exceptFDs;
  62. FD_ZERO(readp);
  63. FD_ZERO(writep);
  64. FD_ZERO(exceptp);
  65. // Find the biggest fd in the poll set
  66. maxFD = 0;
  67. for (p = pollSet; p < pollEnd; p++) {
  68. if (p->fd > maxFD) maxFD = p->fd;
  69. }
  70. if (maxFD >= FD_SETSIZE) {
  71. // At least one fd is too big
  72. errno = EINVAL;
  73. return -1;
  74. }
  75. // Transcribe flags from the poll set to the fd sets
  76. for (p = pollSet; p < pollEnd; p++) {
  77. if (p->fd < 0) {
  78. // Negative fd checks nothing and always reports zero
  79. } else {
  80. if (p->events & POLLIN) FD_SET(p->fd, readp);
  81. if (p->events & POLLOUT) FD_SET(p->fd, writep);
  82. if (p->events != 0) {
  83. FD_SET(p->fd, exceptp);
  84. }
  85. // POLLERR is never set coming in; poll() always reports errors
  86. // But don't report if we're not listening to anything at all.
  87. }
  88. }
  89. }
  90. // poll timeout is in milliseconds. Convert to struct timeval.
  91. // poll timeout == -1 : wait forever : select timeout of NULL
  92. // poll timeout == 0 : return immediately : select timeout of zero
  93. if (pollTimeout >= 0) {
  94. tv.tv_sec = pollTimeout / 1000;
  95. tv.tv_usec = (pollTimeout % 1000) * 1000;
  96. tvp = &tv;
  97. } else {
  98. tvp = NULL;
  99. }
  100. selected = select(maxFD+1, readp, writep, exceptp, tvp);
  101. if (selected < 0) {
  102. // Error during select
  103. result = -1;
  104. }
  105. else if (selected > 0) {
  106. // Select found something
  107. // Transcribe result from fd sets to poll set.
  108. // Also count the number of selected fds. poll returns the
  109. // number of ready fds; select returns the number of bits set.
  110. int polled = 0;
  111. for (p = pollSet; p < pollEnd; p++) {
  112. p->revents = 0;
  113. if (p->fd < 0) {
  114. // Negative fd always reports zero
  115. } else {
  116. if ((p->events & POLLIN) && FD_ISSET(p->fd, readp)) {
  117. p->revents |= POLLIN;
  118. }
  119. if ((p->events & POLLOUT) && FD_ISSET(p->fd, writep)) {
  120. p->revents |= POLLOUT;
  121. }
  122. if ((p->events != 0) && FD_ISSET(p->fd, exceptp)) {
  123. p->revents |= POLLERR;
  124. }
  125. if (p->revents) polled++;
  126. }
  127. }
  128. result = polled;
  129. }
  130. else {
  131. // selected == 0, select timed out before anything happened
  132. // Clear all result bits and return zero.
  133. for (p = pollSet; p < pollEnd; p++) {
  134. p->revents = 0;
  135. }
  136. result = 0;
  137. }
  138. return result;
  139. }
  140. #endif