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 are 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. I have confirmed that inlining has an effect on x86
using Debian's gcc-4.9.2-10 compiler
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 @@
 	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();
+	return maxfd;
+}
 
-	if (!polling)
-		osmo_timers_prepare();
-	rc = select(maxfd+1, &readset, &writeset, &exceptset, polling ? &no_time : osmo_timers_nearest());
-	if (rc < 0)
-		return 0;
+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;
 
-	/* fire timers */
-	osmo_timers_update();
-
-	/* 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 @@
 		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)
 {