| 1 | /* |
| 2 | Simple DirectMedia Layer |
| 3 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> |
| 4 | |
| 5 | This software is provided 'as-is', without any express or implied |
| 6 | warranty. In no event will the authors be held liable for any damages |
| 7 | arising from the use of this software. |
| 8 | |
| 9 | Permission is granted to anyone to use this software for any purpose, |
| 10 | including commercial applications, and to alter it and redistribute it |
| 11 | freely, subject to the following restrictions: |
| 12 | |
| 13 | 1. The origin of this software must not be misrepresented; you must not |
| 14 | claim that you wrote the original software. If you use this software |
| 15 | in a product, an acknowledgment in the product documentation would be |
| 16 | appreciated but is not required. |
| 17 | 2. Altered source versions must be plainly marked as such, and must not be |
| 18 | misrepresented as being the original software. |
| 19 | 3. This notice may not be removed or altered from any source distribution. |
| 20 | */ |
| 21 | |
| 22 | #include "SDL_internal.h" |
| 23 | |
| 24 | #include "SDL_poll.h" |
| 25 | |
| 26 | #ifdef HAVE_POLL |
| 27 | #include <poll.h> |
| 28 | #else |
| 29 | #include <sys/time.h> |
| 30 | #include <sys/types.h> |
| 31 | #include <unistd.h> |
| 32 | #endif |
| 33 | #include <errno.h> |
| 34 | |
| 35 | int SDL_IOReady(int fd, int flags, Sint64 timeoutNS) |
| 36 | { |
| 37 | int result; |
| 38 | |
| 39 | SDL_assert(flags & (SDL_IOR_READ | SDL_IOR_WRITE)); |
| 40 | |
| 41 | // Note: We don't bother to account for elapsed time if we get EINTR |
| 42 | do { |
| 43 | #ifdef HAVE_POLL |
| 44 | struct pollfd info; |
| 45 | int timeoutMS; |
| 46 | |
| 47 | info.fd = fd; |
| 48 | info.events = 0; |
| 49 | if (flags & SDL_IOR_READ) { |
| 50 | info.events |= POLLIN | POLLPRI; |
| 51 | } |
| 52 | if (flags & SDL_IOR_WRITE) { |
| 53 | info.events |= POLLOUT; |
| 54 | } |
| 55 | // FIXME: Add support for ppoll() for nanosecond precision |
| 56 | if (timeoutNS > 0) { |
| 57 | timeoutMS = (int)SDL_NS_TO_MS(timeoutNS + (SDL_NS_PER_MS - 1)); |
| 58 | } else if (timeoutNS == 0) { |
| 59 | timeoutMS = 0; |
| 60 | } else { |
| 61 | timeoutMS = -1; |
| 62 | } |
| 63 | result = poll(&info, 1, timeoutMS); |
| 64 | #else |
| 65 | fd_set rfdset, *rfdp = NULL; |
| 66 | fd_set wfdset, *wfdp = NULL; |
| 67 | struct timeval tv, *tvp = NULL; |
| 68 | |
| 69 | // If this assert triggers we'll corrupt memory here |
| 70 | SDL_assert(fd >= 0 && fd < FD_SETSIZE); |
| 71 | |
| 72 | if (flags & SDL_IOR_READ) { |
| 73 | FD_ZERO(&rfdset); |
| 74 | FD_SET(fd, &rfdset); |
| 75 | rfdp = &rfdset; |
| 76 | } |
| 77 | if (flags & SDL_IOR_WRITE) { |
| 78 | FD_ZERO(&wfdset); |
| 79 | FD_SET(fd, &wfdset); |
| 80 | wfdp = &wfdset; |
| 81 | } |
| 82 | |
| 83 | if (timeoutNS >= 0) { |
| 84 | tv.tv_sec = (timeoutNS / SDL_NS_PER_SECOND); |
| 85 | tv.tv_usec = SDL_NS_TO_US((timeoutNS % SDL_NS_PER_SECOND) + (SDL_NS_PER_US - 1)); |
| 86 | tvp = &tv; |
| 87 | } |
| 88 | |
| 89 | result = select(fd + 1, rfdp, wfdp, NULL, tvp); |
| 90 | #endif // HAVE_POLL |
| 91 | |
| 92 | } while (result < 0 && errno == EINTR && !(flags & SDL_IOR_NO_RETRY)); |
| 93 | |
| 94 | return result; |
| 95 | } |
| 96 | |