aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2016-03-21 09:55:05 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2016-03-21 11:29:17 +0100
commit06ec17878e5621b67647ce6e821fd6208456f87f (patch)
tree24f4b68870c983b3f27885f0af9eaef5bf71f581
parent92c4ec293d0b73e5c6306d26e608340edc40b04c (diff)
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
-rw-r--r--include/osmocom/core/select.h6
-rw-r--r--src/select.c83
2 files changed, 57 insertions, 32 deletions
diff --git a/include/osmocom/core/select.h b/include/osmocom/core/select.h
index b9e3b51..2753637 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 477ff66..02bc2cc 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)
{