fs_poll.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. /****************************************************************************
  2. * fs/vfs/fs_poll.c
  3. *
  4. * Copyright (C) 2008-2009, 2012-2018 Gregory Nutt. All rights reserved.
  5. * Author: Gregory Nutt <gnutt@nuttx.org>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Included Files
  37. ****************************************************************************/
  38. #include <nuttx/config.h>
  39. #include <stdbool.h>
  40. #include <poll.h>
  41. #include <time.h>
  42. #include <semaphore.h>
  43. #include <assert.h>
  44. #include <errno.h>
  45. #include <nuttx/clock.h>
  46. #include <nuttx/semaphore.h>
  47. #include <nuttx/cancelpt.h>
  48. #include <nuttx/fs/fs.h>
  49. #include <nuttx/net/net.h>
  50. #include <arch/irq.h>
  51. #include "inode/inode.h"
  52. #ifndef CONFIG_DISABLE_POLL
  53. /****************************************************************************
  54. * Pre-processor Definitions
  55. ****************************************************************************/
  56. #define poll_semgive(sem) nxsem_post(sem)
  57. /****************************************************************************
  58. * Private Functions
  59. ****************************************************************************/
  60. /****************************************************************************
  61. * Name: poll_semtake
  62. ****************************************************************************/
  63. static int poll_semtake(FAR sem_t *sem)
  64. {
  65. int ret;
  66. /* Take the semaphore (perhaps waiting) */
  67. ret = nxsem_wait(sem);
  68. /* The only case that an error should occur here is if the wait were
  69. * awakened by a signal.
  70. */
  71. DEBUGASSERT(ret == OK || ret == -EINTR);
  72. return ret;
  73. }
  74. /****************************************************************************
  75. * Name: poll_fdsetup
  76. *
  77. * Description:
  78. * Configure (or unconfigure) one file/socket descriptor for the poll
  79. * operation. If fds and sem are non-null, then the poll is being setup.
  80. * if fds and sem are NULL, then the poll is being torn down.
  81. *
  82. ****************************************************************************/
  83. static int poll_fdsetup(int fd, FAR struct pollfd *fds, bool setup)
  84. {
  85. /* Check for a valid file descriptor */
  86. if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
  87. {
  88. /* Perform the socket ioctl */
  89. #ifdef CONFIG_NET
  90. if ((unsigned int)fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS))
  91. {
  92. return net_poll(fd, fds, setup);
  93. }
  94. else
  95. #endif
  96. {
  97. return -EBADF;
  98. }
  99. }
  100. return fdesc_poll(fd, fds, setup);
  101. }
  102. /****************************************************************************
  103. * Name: poll_setup
  104. *
  105. * Description:
  106. * Setup the poll operation for each descriptor in the list.
  107. *
  108. ****************************************************************************/
  109. static inline int poll_setup(FAR struct pollfd *fds, nfds_t nfds, sem_t *sem)
  110. {
  111. unsigned int i;
  112. unsigned int j;
  113. int ret = OK;
  114. /* Process each descriptor in the list */
  115. for (i = 0; i < nfds; i++)
  116. {
  117. /* Setup the poll descriptor */
  118. fds[i].sem = sem;
  119. fds[i].revents = 0;
  120. fds[i].priv = NULL;
  121. /* Check for invalid descriptors. "If the value of fd is less than 0,
  122. * events shall be ignored, and revents shall be set to 0 in that entry
  123. * on return from poll()."
  124. *
  125. * NOTE: There is a potential problem here. If there is only one fd
  126. * and if it is negative, then poll will hang. From my reading of the
  127. * spec, that appears to be the correct behavior.
  128. */
  129. switch (fds[i].events & POLLMASK)
  130. {
  131. case POLLFD:
  132. if (fds[i].fd >= 0)
  133. {
  134. ret = poll_fdsetup(fds[i].fd, &fds[i], true);
  135. }
  136. break;
  137. case POLLFILE:
  138. if (fds[i].ptr != NULL)
  139. {
  140. ret = file_poll(fds[i].ptr, &fds[i], true);
  141. }
  142. break;
  143. #ifdef CONFIG_NET
  144. case POLLSOCK:
  145. if (fds[i].ptr != NULL)
  146. {
  147. ret = psock_poll(fds[i].ptr, &fds[i], true);
  148. }
  149. break;
  150. #endif
  151. default:
  152. ret = -EINVAL;
  153. break;
  154. }
  155. if (ret < 0)
  156. {
  157. /* Setup failed for fds[i]. We now need to teardown previously
  158. * setup fds[0 .. (i - 1)] to release allocated resources and
  159. * to prevent memory corruption by access to freed/released 'fds'
  160. * and 'sem'.
  161. */
  162. for (j = 0; j < i; j++)
  163. {
  164. switch (fds[j].events & POLLMASK)
  165. {
  166. case POLLFD:
  167. (void)poll_fdsetup(fds[j].fd, &fds[j], false);
  168. break;
  169. case POLLFILE:
  170. (void)file_poll(fds[j].ptr, &fds[j], false);
  171. break;
  172. #ifdef CONFIG_NET
  173. case POLLSOCK:
  174. (void)psock_poll(fds[j].ptr, &fds[j], false);
  175. break;
  176. #endif
  177. default:
  178. break;
  179. }
  180. }
  181. /* Indicate an error on the file descriptor */
  182. fds[i].revents |= POLLERR;
  183. return ret;
  184. }
  185. }
  186. return OK;
  187. }
  188. /****************************************************************************
  189. * Name: poll_teardown
  190. *
  191. * Description:
  192. * Teardown the poll operation for each descriptor in the list and return
  193. * the count of non-zero poll events.
  194. *
  195. ****************************************************************************/
  196. static inline int poll_teardown(FAR struct pollfd *fds, nfds_t nfds,
  197. FAR int *count, int ret)
  198. {
  199. unsigned int i;
  200. int status = OK;
  201. /* Process each descriptor in the list */
  202. *count = 0;
  203. for (i = 0; i < nfds; i++)
  204. {
  205. switch (fds[i].events & POLLMASK)
  206. {
  207. case POLLFD:
  208. if (fds[i].fd >= 0)
  209. {
  210. status = poll_fdsetup(fds[i].fd, &fds[i], false);
  211. }
  212. break;
  213. case POLLFILE:
  214. if (fds[i].ptr != NULL)
  215. {
  216. status = file_poll(fds[i].ptr, &fds[i], false);
  217. }
  218. break;
  219. #ifdef CONFIG_NET
  220. case POLLSOCK:
  221. if (fds[i].ptr != NULL)
  222. {
  223. status = psock_poll(fds[i].ptr, &fds[i], false);
  224. }
  225. break;
  226. #endif
  227. default:
  228. status = -EINVAL;
  229. break;
  230. }
  231. if (status < 0)
  232. {
  233. ret = status;
  234. }
  235. /* Check if any events were posted */
  236. if (fds[i].revents != 0)
  237. {
  238. (*count)++;
  239. }
  240. /* Un-initialize the poll structure */
  241. fds[i].sem = NULL;
  242. }
  243. return ret;
  244. }
  245. /****************************************************************************
  246. * Public Functions
  247. ****************************************************************************/
  248. /****************************************************************************
  249. * Name: file_poll
  250. *
  251. * Description:
  252. * Low-level poll operation based on struct file. This is used both to (1)
  253. * support detached file, and also (2) by fdesc_poll() to perform all
  254. * normal operations on file descriptors descriptors.
  255. *
  256. * Input Parameters:
  257. * file File structure instance
  258. * fds - The structure describing the events to be monitored, OR NULL if
  259. * this is a request to stop monitoring events.
  260. * setup - true: Setup up the poll; false: Teardown the poll
  261. *
  262. * Returned Value:
  263. * 0: Success; Negated errno on failure
  264. *
  265. ****************************************************************************/
  266. int file_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup)
  267. {
  268. FAR struct inode *inode;
  269. int ret = -ENOSYS;
  270. DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
  271. inode = filep->f_inode;
  272. if (inode != NULL)
  273. {
  274. /* Is a driver registered? Does it support the poll method?
  275. * If not, return -ENOSYS
  276. */
  277. if (INODE_IS_DRIVER(inode) &&
  278. inode->u.i_ops != NULL && inode->u.i_ops->poll != NULL)
  279. {
  280. /* Yes, it does... Setup the poll */
  281. ret = (int)inode->u.i_ops->poll(filep, fds, setup);
  282. }
  283. /* Regular files (and block devices) are always readable and
  284. * writable. Open Group: "Regular files shall always poll TRUE for
  285. * reading and writing."
  286. */
  287. if (INODE_IS_MOUNTPT(inode) || INODE_IS_BLOCK(inode) ||
  288. INODE_IS_MTD(inode))
  289. {
  290. if (setup)
  291. {
  292. fds->revents |= (fds->events & (POLLIN | POLLOUT));
  293. if (fds->revents != 0)
  294. {
  295. nxsem_post(fds->sem);
  296. }
  297. }
  298. ret = OK;
  299. }
  300. }
  301. return ret;
  302. }
  303. /****************************************************************************
  304. * Name: fdesc_poll
  305. *
  306. * Description:
  307. * The standard poll() operation redirects operations on file descriptors
  308. * to this function.
  309. *
  310. * Input Parameters:
  311. * fd - The file descriptor of interest
  312. * fds - The structure describing the events to be monitored, OR NULL if
  313. * this is a request to stop monitoring events.
  314. * setup - true: Setup up the poll; false: Teardown the poll
  315. *
  316. * Returned Value:
  317. * Zero (OK) is returned on success; a negated errno value is returned on
  318. * any failure.
  319. *
  320. ****************************************************************************/
  321. int fdesc_poll(int fd, FAR struct pollfd *fds, bool setup)
  322. {
  323. FAR struct file *filep;
  324. int ret;
  325. /* Get the file pointer corresponding to this file descriptor */
  326. ret = fs_getfilep(fd, &filep);
  327. if (ret < 0)
  328. {
  329. return ret;
  330. }
  331. DEBUGASSERT(filep != NULL);
  332. /* Let file_poll() do the rest */
  333. return file_poll(filep, fds, setup);
  334. }
  335. /****************************************************************************
  336. * Name: poll
  337. *
  338. * Description:
  339. * poll() waits for one of a set of file descriptors to become ready to
  340. * perform I/O. If none of the events requested (and no error) has
  341. * occurred for any of the file descriptors, then poll() blocks until
  342. * one of the events occurs.
  343. *
  344. * Input Parameters:
  345. * fds - List of structures describing file descriptors to be monitored
  346. * nfds - The number of entries in the list
  347. * timeout - Specifies an upper limit on the time for which poll() will
  348. * block in milliseconds. A negative value of timeout means an infinite
  349. * timeout.
  350. *
  351. * Returned Value:
  352. * On success, the number of structures that have non-zero revents fields.
  353. * A value of 0 indicates that the call timed out and no file descriptors
  354. * were ready. On error, -1 is returned, and errno is set appropriately:
  355. *
  356. * EBADF - An invalid file descriptor was given in one of the sets.
  357. * EFAULT - The fds address is invalid
  358. * EINTR - A signal occurred before any requested event.
  359. * EINVAL - The nfds value exceeds a system limit.
  360. * ENOMEM - There was no space to allocate internal data structures.
  361. * ENOSYS - One or more of the drivers supporting the file descriptor
  362. * does not support the poll method.
  363. *
  364. ****************************************************************************/
  365. int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout)
  366. {
  367. sem_t sem;
  368. int count = 0;
  369. int errcode;
  370. int ret;
  371. DEBUGASSERT(nfds == 0 || fds != NULL);
  372. /* poll() is a cancellation point */
  373. (void)enter_cancellation_point();
  374. /* This semaphore is used for signaling and, hence, should not have
  375. * priority inheritance enabled.
  376. */
  377. nxsem_init(&sem, 0, 0);
  378. nxsem_setprotocol(&sem, SEM_PRIO_NONE);
  379. ret = poll_setup(fds, nfds, &sem);
  380. if (ret >= 0)
  381. {
  382. if (timeout == 0)
  383. {
  384. /* Poll returns immediately whether we have a poll event or not. */
  385. ret = OK;
  386. }
  387. else if (timeout > 0)
  388. {
  389. clock_t ticks;
  390. /* "Implementations may place limitations on the granularity of
  391. * timeout intervals. If the requested timeout interval requires
  392. * a finer granularity than the implementation supports, the
  393. * actual timeout interval will be rounded up to the next
  394. * supported value." -- opengroup.org
  395. *
  396. * Round timeout up to next full tick.
  397. */
  398. #if (MSEC_PER_TICK * USEC_PER_MSEC) != USEC_PER_TICK && \
  399. defined(CONFIG_HAVE_LONG_LONG)
  400. ticks = (((unsigned long long)timeout * USEC_PER_MSEC) + (USEC_PER_TICK - 1)) /
  401. USEC_PER_TICK;
  402. #else
  403. ticks = ((unsigned int)timeout + (MSEC_PER_TICK - 1)) / MSEC_PER_TICK;
  404. #endif
  405. /* Either wait for either a poll event(s), for a signal to occur,
  406. * or for the specified timeout to elapse with no event.
  407. *
  408. * NOTE: If a poll event is pending (i.e., the semaphore has already
  409. * been incremented), nxsem_tickwait() will not wait, but will return
  410. * immediately.
  411. */
  412. ret = nxsem_tickwait(&sem, clock_systimer(), ticks);
  413. if (ret < 0)
  414. {
  415. if (ret == -ETIMEDOUT)
  416. {
  417. /* Return zero (OK) in the event of a timeout */
  418. ret = OK;
  419. }
  420. /* EINTR is the only other error expected in normal operation */
  421. }
  422. }
  423. else
  424. {
  425. /* Wait for the poll event or signal with no timeout */
  426. ret = poll_semtake(&sem);
  427. }
  428. /* Teardown the poll operation and get the count of events. Zero will be
  429. * returned in the case of a timeout.
  430. *
  431. * Preserve ret, if negative, since it holds the result of the wait.
  432. */
  433. errcode = poll_teardown(fds, nfds, &count, ret);
  434. if (errcode < 0 && ret >= 0)
  435. {
  436. ret = errcode;
  437. }
  438. }
  439. nxsem_destroy(&sem);
  440. leave_cancellation_point();
  441. /* Check for errors */
  442. if (ret < 0)
  443. {
  444. set_errno(-ret);
  445. return ERROR;
  446. }
  447. return count;
  448. }
  449. #endif /* CONFIG_DISABLE_POLL */