From: Holger Hans Peter Freyther <[email protected]>

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 b6b9e82..d71e903 100644
--- a/include/osmocom/core/select.h
+++ b/include/osmocom/core/select.h
@@ -39,4 +39,10 @@ int osmo_fd_register(struct osmo_fd *fd);
 void osmo_fd_unregister(struct osmo_fd *fd);
 int osmo_select_main(int polling);

+/*
+ * 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 5421c77..5826a4d 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);
+}
+
 /*! @} */

 #endif /* _HAVE_SYS_SELECT_H */
-- 
2.6.3

Reply via email to