PS2SDK
PS2 Homebrew Libraries
select.c
1 /*
2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Copyright ps2dev - http://www.ps2dev.org
7 # Licenced under Academic Free License version 2.0
8 # Review ps2sdk README & LICENSE files for further details.
9 */
10 
11 #define LIBCGLUE_SYS_SOCKET_NO_ALIASES
12 #define LIBCGLUE_ARPA_INET_NO_ALIASES
13 #include <sys/socket.h>
14 #include <ps2sdkapi.h>
15 #include <errno.h>
16 
17 #include "ps2sdkapi.h"
18 
19 #ifdef F_select
20 /* FIXME: This function currently cannot handle heterogeneous fds */
21 int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
22 {
23  int fd;
24  int ret;
25  int iop_max_fd = -1;
26  fd_set ready_readfds, ready_writefds, ready_exceptfds;
27  fd_set iop_readfds, iop_writefds, iop_exceptfds;
28 
29  if (_libcglue_fdman_socket_ops == NULL || _libcglue_fdman_socket_ops->select == NULL)
30  {
31  errno = ENOSYS;
32  return -1;
33  }
34 
35  FD_ZERO(&ready_readfds);
36  FD_ZERO(&ready_writefds);
37  FD_ZERO(&ready_exceptfds);
38 
39  FD_ZERO(&iop_readfds);
40  FD_ZERO(&iop_writefds);
41  FD_ZERO(&iop_exceptfds);
42 
43  for (fd = 0; fd < n; fd += 1)
44  {
45  int in_read = readfds && FD_ISSET(fd, readfds);
46  int in_write = writefds && FD_ISSET(fd, writefds);
47  int in_except = exceptfds && FD_ISSET(fd, exceptfds);
48  int iop_fd;
49 
50  if (!in_read && !in_write && !in_except)
51  {
52  continue;
53  }
54 
55  iop_fd = ps2sdk_get_iop_fd(fd);
56  if (iop_fd < 0)
57  {
58  errno = EBADF;
59  return -1;
60  }
61  if (iop_fd > iop_max_fd)
62  {
63  iop_max_fd = iop_fd;
64  }
65  if (in_read)
66  {
67  FD_SET(iop_fd, &iop_readfds);
68  }
69  if (in_write)
70  {
71  FD_SET(iop_fd, &iop_writefds);
72  }
73  if (in_except)
74  {
75  FD_SET(iop_fd, &iop_exceptfds);
76  }
77  }
78 
79  /* Pass max(iop_fd)+1 to the underlying select, not the EE-side n.
80  * The bits in iop_*fds are at iop_fd positions; if iop_fd > n-1 the
81  * underlying select would iterate an empty range and block forever
82  * waiting for events on bits it isn't watching. */
83  ret = _libcglue_fdman_socket_ops->select(iop_max_fd + 1, &iop_readfds, &iop_writefds, &iop_exceptfds, timeout);
84 
85  for (fd = 0; fd < n; fd += 1)
86  {
87  int in_read = readfds && FD_ISSET(fd, readfds);
88  int in_write = writefds && FD_ISSET(fd, writefds);
89  int in_except = exceptfds && FD_ISSET(fd, exceptfds);
90  int iop_fd;
91 
92  if (!in_read && !in_write && !in_except)
93  {
94  continue;
95  }
96 
97  iop_fd = ps2sdk_get_iop_fd(fd);
98  if (iop_fd < 0)
99  {
100  continue;
101  }
102  if (in_read && FD_ISSET(iop_fd, &iop_readfds))
103  {
104  FD_SET(fd, &ready_readfds);
105  }
106  if (in_write && FD_ISSET(iop_fd, &iop_writefds))
107  {
108  FD_SET(fd, &ready_writefds);
109  }
110  if (in_except && FD_ISSET(iop_fd, &iop_exceptfds))
111  {
112  FD_SET(fd, &ready_exceptfds);
113  }
114  }
115 
116  if (readfds)
117  {
118  *readfds = ready_readfds;
119  }
120  if (writefds)
121  {
122  *writefds = ready_writefds;
123  }
124  if (exceptfds)
125  {
126  *exceptfds = ready_exceptfds;
127  }
128 
129  return ret;
130 }
131 #endif
EBADF
#define EBADF
Definition: errno.h:37
timeval
Definition: time.h:29
fd_set
Definition: tcpip.h:1838
ENOSYS
#define ENOSYS
Definition: errno.h:185
errno.h