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 | |