1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21: #include <sys/types.h>
22: #include <sys/poll.h>
23: #include <hurd.h>
24: #include <hurd/fd.h>
25: #include <stdlib.h>
26: #include <string.h>
27: #include <assert.h>
28: #include <stdint.h>
29:
30:
31: #define SELECT_ALL (SELECT_READ | SELECT_WRITE | SELECT_URG)
32:
33:
34:
35: #define SELECT_RETURNED ((SELECT_ALL << 1) & ~SELECT_ALL)
36:
37:
38:
39:
40:
41: int
42: _hurd_select (int nfds,
43: struct pollfd *pollfds,
44: fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
45: const struct timespec *timeout, const sigset_t *sigmask)
46: {
47: int i;
48: mach_port_t portset;
49: int got;
50: error_t err;
51: fd_set rfds, wfds, xfds;
52: int firstfd, lastfd;
53: mach_msg_timeout_t to = (timeout != NULL ?
54: (timeout->tv_sec * 1000 +
55: timeout->tv_nsec / 1000000) :
56: 0);
57: struct
58: {
59: struct hurd_userlink ulink;
60: struct hurd_fd *cell;
61: mach_port_t io_port;
62: int type;
63: mach_port_t reply_port;
64: } d[nfds];
65: sigset_t oset;
66:
67: union typeword
68: {
69: mach_msg_type_t type;
70: uint32_t word;
71: };
72: assert (sizeof (union typeword) == sizeof (mach_msg_type_t));
73: assert (sizeof (uint32_t) == sizeof (mach_msg_type_t));
74:
75: if (sigmask && __sigprocmask (SIG_SETMASK, sigmask, &oset))
76: return -1;
77:
78: if (pollfds)
79: {
80:
81:
82:
83:
84:
85: for (i = 0; i < nfds; ++i)
86: if (pollfds[i].fd >= 0)
87: {
88: int type = 0;
89: if (pollfds[i].events & POLLIN)
90: type |= SELECT_READ;
91: if (pollfds[i].events & POLLOUT)
92: type |= SELECT_WRITE;
93: if (pollfds[i].events & POLLPRI)
94: type |= SELECT_URG;
95:
96: d[i].io_port = pollfds[i].fd;
97: d[i].type = type;
98: }
99: else
100: d[i].type = 0;
101:
102: HURD_CRITICAL_BEGIN;
103: __mutex_lock (&_hurd_dtable_lock);
104:
105: for (i = 0; i < nfds; ++i)
106: if (d[i].type != 0)
107: {
108: const int fd = (int) d[i].io_port;
109:
110: if (fd < _hurd_dtablesize)
111: {
112: d[i].cell = _hurd_dtable[fd];
113: d[i].io_port = _hurd_port_get (&d[i].cell->port, &d[i].ulink);
114: if (d[i].io_port != MACH_PORT_NULL)
115: continue;
116: }
117:
118:
119: while (i-- > 0)
120: if (d[i].type != 0)
121: _hurd_port_free (&d[i].cell->port,
122: &d[i].ulink, d[i].io_port);
123: break;
124: }
125:
126: __mutex_unlock (&_hurd_dtable_lock);
127: HURD_CRITICAL_END;
128:
129: if (i < nfds)
130: {
131: if (sigmask)
132: __sigprocmask (SIG_SETMASK, &oset, NULL);
133: errno = EBADF;
134: return -1;
135: }
136:
137: lastfd = i - 1;
138: firstfd = i == 0 ? lastfd : 0;
139: }
140: else
141: {
142:
143:
144:
145: if (readfds == NULL)
146: FD_ZERO (&rfds);
147: else
148: rfds = *readfds;
149: if (writefds == NULL)
150: FD_ZERO (&wfds);
151: else
152: wfds = *writefds;
153: if (exceptfds == NULL)
154: FD_ZERO (&xfds);
155: else
156: xfds = *exceptfds;
157:
158: HURD_CRITICAL_BEGIN;
159: __mutex_lock (&_hurd_dtable_lock);
160:
161: if (nfds > _hurd_dtablesize)
162: nfds = _hurd_dtablesize;
163:
164:
165: firstfd = lastfd = -1;
166: for (i = 0; i < nfds; ++i)
167: {
168: int type = 0;
169: if (readfds != NULL && FD_ISSET (i, &rfds))
170: type |= SELECT_READ;
171: if (writefds != NULL && FD_ISSET (i, &wfds))
172: type |= SELECT_WRITE;
173: if (exceptfds != NULL && FD_ISSET (i, &xfds))
174: type |= SELECT_URG;
175: d[i].type = type;
176: if (type)
177: {
178: d[i].cell = _hurd_dtable[i];
179: d[i].io_port = _hurd_port_get (&d[i].cell->port, &d[i].ulink);
180: if (d[i].io_port == MACH_PORT_NULL)
181: {
182:
183: while (i-- > 0)
184: if (d[i].type != 0)
185: _hurd_port_free (&d[i].cell->port, &d[i].ulink,
186: d[i].io_port);
187: break;
188: }
189: lastfd = i;
190: if (firstfd == -1)
191: firstfd = i;
192: }
193: }
194:
195: __mutex_unlock (&_hurd_dtable_lock);
196: HURD_CRITICAL_END;
197:
198: if (i < nfds)
199: {
200: if (sigmask)
201: __sigprocmask (SIG_SETMASK, &oset, NULL);
202: errno = EBADF;
203: return -1;
204: }
205: }
206:
207:
208: err = 0;
209: got = 0;
210:
211:
212:
213: if (firstfd == -1)
214:
215:
216: portset = __mach_reply_port ();
217: else
218: {
219: portset = MACH_PORT_NULL;
220:
221: for (i = firstfd; i <= lastfd; ++i)
222: if (d[i].type)
223: {
224: int type = d[i].type;
225: d[i].reply_port = __mach_reply_port ();
226: err = __io_select (d[i].io_port, d[i].reply_port,
227:
228: (firstfd == lastfd) ? to : 0,
229: &type);
230: switch (err)
231: {
232: case MACH_RCV_TIMED_OUT:
233:
234: err = 0;
235: if (firstfd == lastfd)
236:
237:
238:
239: portset = d[i].reply_port;
240: else if (got == 0)
241:
242:
243: {
244:
245: if (portset == MACH_PORT_NULL)
246:
247: err = __mach_port_allocate (__mach_task_self (),
248: MACH_PORT_RIGHT_PORT_SET,
249: &portset);
250: if (! err)
251:
252: __mach_port_move_member (__mach_task_self (),
253: d[i].reply_port, portset);
254: }
255: break;
256:
257: default:
258:
259:
260:
261:
262: type = SELECT_ALL;
263:
264:
265: case 0:
266:
267: if ((type & SELECT_ALL) == 0)
268:
269: type = SELECT_ALL;
270:
271:
272: d[i].type &= type;
273: d[i].type |= SELECT_RETURNED;
274: ++got;
275: break;
276: }
277: _hurd_port_free (&d[i].cell->port, &d[i].ulink, d[i].io_port);
278: }
279: }
280:
281:
282: if (!err && got == 0)
283: {
284:
285:
286:
287: union
288: {
289: mach_msg_header_t head;
290: #ifdef MACH_MSG_TRAILER_MINIMUM_SIZE
291: struct
292: {
293: mach_msg_header_t head;
294: NDR_record_t ndr;
295: error_t err;
296: } error;
297: struct
298: {
299: mach_msg_header_t head;
300: NDR_record_t ndr;
301: error_t err;
302: int result;
303: mach_msg_trailer_t trailer;
304: } success;
305: #else
306: struct
307: {
308: mach_msg_header_t head;
309: union typeword err_type;
310: error_t err;
311: } error;
312: struct
313: {
314: mach_msg_header_t head;
315: union typeword err_type;
316: error_t err;
317: union typeword result_type;
318: int result;
319: } success;
320: #endif
321: } msg;
322: mach_msg_option_t options = (timeout == NULL ? 0 : MACH_RCV_TIMEOUT);
323: error_t msgerr;
324: while ((msgerr = __mach_msg (&msg.head,
325: MACH_RCV_MSG | options,
326: 0, sizeof msg, portset, to,
327: MACH_PORT_NULL)) == MACH_MSG_SUCCESS)
328: {
329:
330: #define IO_SELECT_REPLY_MSGID (21012 + 100)
331: #ifdef MACH_MSG_TYPE_BIT
332: const union typeword inttype =
333: { type:
334: { MACH_MSG_TYPE_INTEGER_T, sizeof (integer_t) * 8, 1, 1, 0, 0 }
335: };
336: #endif
337: if (msg.head.msgh_id == IO_SELECT_REPLY_MSGID &&
338: msg.head.msgh_size >= sizeof msg.error &&
339: !(msg.head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
340: #ifdef MACH_MSG_TYPE_BIT
341: msg.error.err_type.word == inttype.word
342: #endif
343: )
344: {
345:
346:
347: if (msg.error.err == EINTR &&
348: msg.head.msgh_size == sizeof msg.error)
349: {
350:
351:
352: err = EINTR;
353: goto poll;
354: }
355: if (msg.error.err ||
356: msg.head.msgh_size != sizeof msg.success ||
357: #ifdef MACH_MSG_TYPE_BIT
358: msg.success.result_type.word != inttype.word ||
359: #endif
360: (msg.success.result & SELECT_ALL) == 0)
361: {
362:
363: __mach_msg_destroy (&msg.head);
364: msg.success.result = SELECT_ALL;
365: }
366:
367:
368:
369: {
370: int had = got;
371: if (firstfd != -1)
372: for (i = firstfd; i <= lastfd; ++i)
373: if (d[i].type
374: && d[i].reply_port == msg.head.msgh_local_port)
375: {
376: d[i].type &= msg.success.result;
377: d[i].type |= SELECT_RETURNED;
378: ++got;
379: }
380: assert (got > had);
381: }
382: }
383:
384: if (msg.head.msgh_remote_port != MACH_PORT_NULL)
385: __mach_port_deallocate (__mach_task_self (),
386: msg.head.msgh_remote_port);
387:
388: if (got)
389: poll:
390: {
391:
392: to = 0;
393: options |= MACH_RCV_TIMEOUT;
394: }
395: }
396:
397: if (err == MACH_RCV_TIMED_OUT)
398:
399:
400:
401:
402:
403: err = 0;
404:
405: if (got)
406:
407:
408: err = 0;
409: }
410:
411: if (firstfd != -1)
412: for (i = firstfd; i <= lastfd; ++i)
413: if (d[i].type)
414: __mach_port_destroy (__mach_task_self (), d[i].reply_port);
415: if (firstfd == -1 || (firstfd != lastfd && portset != MACH_PORT_NULL))
416:
417:
418:
419: __mach_port_destroy (__mach_task_self (), portset);
420:
421: if (err)
422: {
423: if (sigmask)
424: __sigprocmask (SIG_SETMASK, &oset, NULL);
425: return __hurd_fail (err);
426: }
427:
428: if (pollfds)
429:
430: for (i = 0; i < nfds; ++i)
431: {
432: int type = d[i].type;
433: int_fast16_t revents = 0;
434:
435: if (type & SELECT_RETURNED)
436: {
437: if (type & SELECT_READ)
438: revents |= POLLIN;
439: if (type & SELECT_WRITE)
440: revents |= POLLOUT;
441: if (type & SELECT_URG)
442: revents |= POLLPRI;
443: }
444:
445: pollfds[i].revents = revents;
446: }
447: else
448: {
449:
450:
451: got = 0;
452:
453:
454:
455: if (firstfd != -1)
456: for (i = firstfd; i <= lastfd; ++i)
457: {
458: int type = d[i].type;
459:
460: if ((type & SELECT_RETURNED) == 0)
461: type = 0;
462:
463: if (type & SELECT_READ)
464: got++;
465: else if (readfds)
466: FD_CLR (i, readfds);
467: if (type & SELECT_WRITE)
468: got++;
469: else if (writefds)
470: FD_CLR (i, writefds);
471: if (type & SELECT_URG)
472: got++;
473: else if (exceptfds)
474: FD_CLR (i, exceptfds);
475: }
476: }
477:
478: if (sigmask && __sigprocmask (SIG_SETMASK, &oset, NULL))
479: return -1;
480:
481: return got;
482: }