From 06ec17878e5621b67647ce6e821fd6208456f87f Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 21 Mar 2016 09:55:05 +0100 Subject: select: Externalize fd_set filling and dispatch To integrate with an external event loop (in this case glib) we need to allow an application to get a filled out fd_set and then dispatch it. osmo_fds and maxfds is static and I decided to keep it that way and instead create two routines to fill the fdset and then one to dispatch the result. The public header file does not include sys/select.h and we can compile the library without select so I didn't want to require having to include this file and used void * for the parameter. Mark the routines as inline to avoid a call from the select function. Confirmed that inlining has an effect on x86 using Debian's gcc-4.9.2-10 compiler --- include/osmocom/core/select.h | 6 ++++ src/select.c | 83 ++++++++++++++++++++++++++----------------- 2 files changed, 57 insertions(+), 32 deletions(-) diff --git a/include/osmocom/core/select.h b/include/osmocom/core/select.h index b9e3b51a..2753637a 100644 --- a/include/osmocom/core/select.h +++ b/include/osmocom/core/select.h @@ -41,4 +41,10 @@ int osmo_select_main(int polling); struct osmo_fd *osmo_fd_get_by_fd(int fd); +/* + * foreign event loop integration + */ +int osmo_fd_fill_fds(void *readset, void *writeset, void *exceptset); +int osmo_fd_disp_fds(void *readset, void *writeset, void *exceptset); + /*! @} */ diff --git a/src/select.c b/src/select.c index 477ff662..02bc2cc3 100644 --- a/src/select.c +++ b/src/select.c @@ -98,62 +98,49 @@ void osmo_fd_unregister(struct osmo_fd *fd) llist_del(&fd->list); } -/*! \brief select main loop integration - * \param[in] polling should we pollonly (1) or block on select (0) - */ -int osmo_select_main(int polling) +inline int osmo_fd_fill_fds(void *_rset, void *_wset, void *_eset) { - struct osmo_fd *ufd, *tmp; - fd_set readset, writeset, exceptset; - int work = 0, rc; - struct timeval no_time = {0, 0}; + fd_set *readset = _rset, *writeset = _wset, *exceptset = _eset; + struct osmo_fd *ufd; - FD_ZERO(&readset); - FD_ZERO(&writeset); - FD_ZERO(&exceptset); - - /* prepare read and write fdsets */ llist_for_each_entry(ufd, &osmo_fds, list) { if (ufd->when & BSC_FD_READ) - FD_SET(ufd->fd, &readset); + FD_SET(ufd->fd, readset); if (ufd->when & BSC_FD_WRITE) - FD_SET(ufd->fd, &writeset); + FD_SET(ufd->fd, writeset); if (ufd->when & BSC_FD_EXCEPT) - FD_SET(ufd->fd, &exceptset); + FD_SET(ufd->fd, exceptset); } - osmo_timers_check(); - - if (!polling) - osmo_timers_prepare(); - rc = select(maxfd+1, &readset, &writeset, &exceptset, polling ? &no_time : osmo_timers_nearest()); - if (rc < 0) - return 0; + return maxfd; +} - /* fire timers */ - osmo_timers_update(); +inline int osmo_fd_disp_fds(void *_rset, void *_wset, void *_eset) +{ + struct osmo_fd *ufd, *tmp; + int work = 0; + fd_set *readset = _rset, *writeset = _wset, *exceptset = _eset; - /* call registered callback functions */ restart: unregistered_count = 0; llist_for_each_entry_safe(ufd, tmp, &osmo_fds, list) { int flags = 0; - if (FD_ISSET(ufd->fd, &readset)) { + if (FD_ISSET(ufd->fd, readset)) { flags |= BSC_FD_READ; - FD_CLR(ufd->fd, &readset); + FD_CLR(ufd->fd, readset); } - if (FD_ISSET(ufd->fd, &writeset)) { + if (FD_ISSET(ufd->fd, writeset)) { flags |= BSC_FD_WRITE; - FD_CLR(ufd->fd, &writeset); + FD_CLR(ufd->fd, writeset); } - if (FD_ISSET(ufd->fd, &exceptset)) { + if (FD_ISSET(ufd->fd, exceptset)) { flags |= BSC_FD_EXCEPT; - FD_CLR(ufd->fd, &exceptset); + FD_CLR(ufd->fd, exceptset); } if (flags) { @@ -167,9 +154,41 @@ restart: if (unregistered_count >= 1) goto restart; } + return work; } +/*! \brief select main loop integration + * \param[in] polling should we pollonly (1) or block on select (0) + */ +int osmo_select_main(int polling) +{ + fd_set readset, writeset, exceptset; + int rc; + struct timeval no_time = {0, 0}; + + FD_ZERO(&readset); + FD_ZERO(&writeset); + FD_ZERO(&exceptset); + + /* prepare read and write fdsets */ + osmo_fd_fill_fds(&readset, &writeset, &exceptset); + + osmo_timers_check(); + + if (!polling) + osmo_timers_prepare(); + rc = select(maxfd+1, &readset, &writeset, &exceptset, polling ? &no_time : osmo_timers_nearest()); + if (rc < 0) + return 0; + + /* fire timers */ + osmo_timers_update(); + + /* call registered callback functions */ + return osmo_fd_disp_fds(&readset, &writeset, &exceptset); +} + /*! \brief find an osmo_fd based on the integer fd */ struct osmo_fd *osmo_fd_get_by_fd(int fd) { -- cgit v1.2.3