123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- #define _GNU_SOURCE
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- #include <poll.h>
- #include "libguile/_scm.h"
- #include "libguile/bytevectors.h"
- #include "libguile/numbers.h"
- #include "libguile/error.h"
- #include "libguile/validate.h"
- #include "libguile/poll.h"
- static SCM
- scm_primitive_poll (SCM pollfds, SCM nfds, SCM ports, SCM timeout)
- #define FUNC_NAME "primitive-poll"
- {
- int rv = 0;
- nfds_t i;
- nfds_t c_nfds;
- int c_timeout;
- int have_buffered_io = 0;
- struct pollfd *fds;
- SCM_VALIDATE_BYTEVECTOR (SCM_ARG1, pollfds);
- c_nfds = scm_to_uint32 (nfds);
- c_timeout = scm_to_int (timeout);
-
- if (SCM_UNLIKELY (SCM_BYTEVECTOR_LENGTH (pollfds)
- < c_nfds * sizeof(struct pollfd)))
- SCM_OUT_OF_RANGE (SCM_ARG2, nfds);
-
- SCM_VALIDATE_VECTOR (SCM_ARG3, ports);
- if (SCM_UNLIKELY (SCM_SIMPLE_VECTOR_LENGTH (ports) < c_nfds))
- SCM_OUT_OF_RANGE (SCM_ARG3, ports);
-
- fds = (struct pollfd*)SCM_BYTEVECTOR_CONTENTS (pollfds);
-
- for (i = 0; i < c_nfds; i++)
- {
- SCM port = SCM_SIMPLE_VECTOR_REF (ports, i);
- short int revents = 0;
- if (SCM_PORTP (port))
- {
- if (SCM_CLOSEDP (port))
- revents |= POLLERR;
- else
- {
- scm_t_port *pt = SCM_PTAB_ENTRY (port);
- if (pt->read_pos < pt->read_end)
-
- revents |= POLLIN;
- if (pt->write_pos < pt->write_end)
-
- revents |= POLLOUT;
- }
- }
- if (revents & fds[i].events)
- {
- have_buffered_io = 1;
- c_timeout = 0;
- break;
- }
- }
- SCM_SYSCALL (rv = poll (fds, c_nfds, c_timeout));
- if (rv == -1)
- SCM_SYSERROR;
- if (have_buffered_io)
- for (i = 0; i < c_nfds; i++)
- {
- SCM port = SCM_SIMPLE_VECTOR_REF (ports, i);
- short int revents = 0;
- if (SCM_PORTP (port))
- {
- if (SCM_CLOSEDP (port))
- revents |= POLLERR;
- else
- {
- scm_t_port *pt = SCM_PTAB_ENTRY (port);
- if (pt->read_pos < pt->read_end)
-
- revents |= POLLIN;
- if (SCM_OUTPUT_PORT_P (port) && pt->write_pos < pt->write_end)
-
- revents |= POLLOUT;
- }
- }
-
- if ((revents &= fds[i].events))
- {
-
- if (!fds[i].revents)
- rv++;
-
- fds[i].revents |= revents;
- }
- }
- return scm_from_int (rv);
- }
- #undef FUNC_NAME
- static void
- scm_init_poll (void)
- {
- scm_c_define_gsubr ("primitive-poll", 4, 0, 0, scm_primitive_poll);
- scm_c_define ("%sizeof-struct-pollfd", scm_from_size_t (sizeof (struct pollfd)));
- #ifdef POLLIN
- scm_c_define ("POLLIN", scm_from_int (POLLIN));
- #endif
- #ifdef POLLPRI
- scm_c_define ("POLLPRI", scm_from_int (POLLPRI));
- #endif
- #ifdef POLLOUT
- scm_c_define ("POLLOUT", scm_from_int (POLLOUT));
- #endif
- #ifdef POLLRDHUP
- scm_c_define ("POLLRDHUP", scm_from_int (POLLRDHUP));
- #endif
- #ifdef POLLERR
- scm_c_define ("POLLERR", scm_from_int (POLLERR));
- #endif
- #ifdef POLLHUP
- scm_c_define ("POLLHUP", scm_from_int (POLLHUP));
- #endif
- #ifdef POLLNVAL
- scm_c_define ("POLLNVAL", scm_from_int (POLLNVAL));
- #endif
- }
- void
- scm_register_poll (void)
- {
- scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
- "scm_init_poll",
- (scm_t_extension_init_func) scm_init_poll,
- NULL);
- }
|