select: Externalize fd_set filling and dispatch
diff mbox

Message ID 1458552626-1358-1-git-send-email-holger@freyther.de
State New
Headers show

Commit Message

Holger Freyther March 21, 2016, 9:30 a.m. UTC
From: Holger Hans Peter Freyther <holger@moiji-mobile.com>

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.
---
 include/osmocom/core/select.h |  6 ++++
 src/select.c                  | 83 ++++++++++++++++++++++++++-----------------
 2 files changed, 57 insertions(+), 32 deletions(-)

Patch
diff mbox

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..c3bac2f 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)
+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();
+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 */