1 /* Copyright (C) 2010 Free Software Foundation, Inc.
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
28 #include "libguile/_scm.h"
29 #include "libguile/bytevectors.h"
30 #include "libguile/numbers.h"
31 #include "libguile/error.h"
32 #include "libguile/validate.h"
34 #include "libguile/poll.h"
46 /* Poll a set of file descriptors, waiting until one or more of them is
47 ready to perform input or output.
49 This is a low-level interface. See the `(ice-9 poll)' module for a more
52 `pollfds' is expected to be a bytevector, laid out in contiguous blocks of 64
53 bits. Each block has the format of one `struct pollfd': a 32-bit int file
54 descriptor, a 16-bit int events mask, and a 16-bit int revents mask.
56 The number of pollfd structures in `pollfds' is specified in
57 `nfds'. `pollfds' must be at least long enough to support that number of
58 structures. It may be longer, in which case the trailing entries are left
61 The pollfds bytevector is modified directly, setting the returned events in
62 the final two bytes (the revents member).
64 Since Scheme ports can buffer input or output in userspace, a Scheme
65 poll interface needs to take that into account as well. The `ports'
66 argument, a vector big enough for `nfds' elements, is given for this
67 purpose. If a pollfd entry has a corresponding open port, that port
68 is scanned for available input or output before dropping into the
69 poll. If any port has buffered I/O available, the poll syscall is
70 still issued, but with a timeout of 0 milliseconds, and a full port
71 scan occurs after the poll returns.
73 If timeout is given and is non-negative, the poll will return after that
74 number of milliseconds if no fd became active.
78 scm_primitive_poll (SCM pollfds
, SCM nfds
, SCM ports
, SCM timeout
)
79 #define FUNC_NAME "primitive-poll"
85 int have_buffered_io
= 0;
88 SCM_VALIDATE_BYTEVECTOR (SCM_ARG1
, pollfds
);
89 c_nfds
= scm_to_uint32 (nfds
);
90 c_timeout
= scm_to_int (timeout
);
92 if (SCM_UNLIKELY (SCM_BYTEVECTOR_LENGTH (pollfds
)
93 < c_nfds
* sizeof(struct pollfd
)))
94 SCM_OUT_OF_RANGE (SCM_ARG2
, nfds
);
96 SCM_VALIDATE_VECTOR (SCM_ARG3
, ports
);
97 if (SCM_UNLIKELY (SCM_SIMPLE_VECTOR_LENGTH (ports
) < c_nfds
))
98 SCM_OUT_OF_RANGE (SCM_ARG3
, ports
);
100 fds
= (struct pollfd
*)SCM_BYTEVECTOR_CONTENTS (pollfds
);
102 for (i
= 0; i
< c_nfds
; i
++)
104 SCM port
= SCM_SIMPLE_VECTOR_REF (ports
, i
);
105 short int revents
= 0;
107 if (SCM_PORTP (port
))
109 if (SCM_CLOSEDP (port
))
113 scm_t_port
*pt
= SCM_PTAB_ENTRY (port
);
115 if (pt
->read_pos
< pt
->read_end
)
116 /* Buffered input waiting to be read. */
118 if (pt
->write_pos
< pt
->write_end
)
119 /* Buffered output possible. */
124 if (revents
& fds
[i
].events
)
126 have_buffered_io
= 1;
132 SCM_SYSCALL (rv
= poll (fds
, c_nfds
, c_timeout
));
137 if (have_buffered_io
)
138 for (i
= 0; i
< c_nfds
; i
++)
140 SCM port
= SCM_SIMPLE_VECTOR_REF (ports
, i
);
141 short int revents
= 0;
143 if (SCM_PORTP (port
))
145 if (SCM_CLOSEDP (port
))
149 scm_t_port
*pt
= SCM_PTAB_ENTRY (port
);
151 if (pt
->read_pos
< pt
->read_end
)
152 /* Buffered input waiting to be read. */
154 if (SCM_OUTPUT_PORT_P (port
) && pt
->write_pos
< pt
->write_end
)
155 /* Buffered output possible. */
160 /* Mask in the events we are interested, and test if any are
162 if ((revents
&= fds
[i
].events
))
164 /* Could be the underlying fd is also ready for reading. */
168 /* In any case, add these events to whatever the syscall
170 fds
[i
].revents
|= revents
;
174 return scm_from_int (rv
);
177 #endif /* HAVE_POLL */
186 scm_c_define_gsubr ("primitive-poll", 4, 0, 0, scm_primitive_poll
);
188 scm_misc_error ("%init-poll", "`poll' unavailable on this platform", SCM_EOL
);
192 scm_c_define ("POLLIN", scm_from_int (POLLIN
));
195 scm_c_define ("POLLPRI", scm_from_int (POLLPRI
));
198 scm_c_define ("POLLOUT", scm_from_int (POLLOUT
));
201 scm_c_define ("POLLRDHUP", scm_from_int (POLLRDHUP
));
204 scm_c_define ("POLLERR", scm_from_int (POLLERR
));
207 scm_c_define ("POLLHUP", scm_from_int (POLLHUP
));
210 scm_c_define ("POLLNVAL", scm_from_int (POLLNVAL
));
216 scm_register_poll (void)
218 scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION
,
220 (scm_t_extension_init_func
) scm_init_poll
,