mirror of https://gerrit.osmocom.org/libosmocore
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
This commit is contained in:
parent
fb348eeff2
commit
61f28880d5
|
@ -41,4 +41,10 @@ int osmo_select_main(int polling);
|
||||||
|
|
||||||
struct osmo_fd *osmo_fd_get_by_fd(int fd);
|
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);
|
||||||
|
|
||||||
/*! @} */
|
/*! @} */
|
||||||
|
|
83
src/select.c
83
src/select.c
|
@ -98,62 +98,49 @@ void osmo_fd_unregister(struct osmo_fd *fd)
|
||||||
llist_del(&fd->list);
|
llist_del(&fd->list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief select main loop integration
|
inline int osmo_fd_fill_fds(void *_rset, void *_wset, void *_eset)
|
||||||
* \param[in] polling should we pollonly (1) or block on select (0)
|
|
||||||
*/
|
|
||||||
int osmo_select_main(int polling)
|
|
||||||
{
|
{
|
||||||
struct osmo_fd *ufd, *tmp;
|
fd_set *readset = _rset, *writeset = _wset, *exceptset = _eset;
|
||||||
fd_set readset, writeset, exceptset;
|
struct osmo_fd *ufd;
|
||||||
int work = 0, rc;
|
|
||||||
struct timeval no_time = {0, 0};
|
|
||||||
|
|
||||||
FD_ZERO(&readset);
|
|
||||||
FD_ZERO(&writeset);
|
|
||||||
FD_ZERO(&exceptset);
|
|
||||||
|
|
||||||
/* prepare read and write fdsets */
|
|
||||||
llist_for_each_entry(ufd, &osmo_fds, list) {
|
llist_for_each_entry(ufd, &osmo_fds, list) {
|
||||||
if (ufd->when & BSC_FD_READ)
|
if (ufd->when & BSC_FD_READ)
|
||||||
FD_SET(ufd->fd, &readset);
|
FD_SET(ufd->fd, readset);
|
||||||
|
|
||||||
if (ufd->when & BSC_FD_WRITE)
|
if (ufd->when & BSC_FD_WRITE)
|
||||||
FD_SET(ufd->fd, &writeset);
|
FD_SET(ufd->fd, writeset);
|
||||||
|
|
||||||
if (ufd->when & BSC_FD_EXCEPT)
|
if (ufd->when & BSC_FD_EXCEPT)
|
||||||
FD_SET(ufd->fd, &exceptset);
|
FD_SET(ufd->fd, exceptset);
|
||||||
}
|
}
|
||||||
|
|
||||||
osmo_timers_check();
|
return maxfd;
|
||||||
|
}
|
||||||
|
|
||||||
if (!polling)
|
inline int osmo_fd_disp_fds(void *_rset, void *_wset, void *_eset)
|
||||||
osmo_timers_prepare();
|
{
|
||||||
rc = select(maxfd+1, &readset, &writeset, &exceptset, polling ? &no_time : osmo_timers_nearest());
|
struct osmo_fd *ufd, *tmp;
|
||||||
if (rc < 0)
|
int work = 0;
|
||||||
return 0;
|
fd_set *readset = _rset, *writeset = _wset, *exceptset = _eset;
|
||||||
|
|
||||||
/* fire timers */
|
|
||||||
osmo_timers_update();
|
|
||||||
|
|
||||||
/* call registered callback functions */
|
|
||||||
restart:
|
restart:
|
||||||
unregistered_count = 0;
|
unregistered_count = 0;
|
||||||
llist_for_each_entry_safe(ufd, tmp, &osmo_fds, list) {
|
llist_for_each_entry_safe(ufd, tmp, &osmo_fds, list) {
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
|
||||||
if (FD_ISSET(ufd->fd, &readset)) {
|
if (FD_ISSET(ufd->fd, readset)) {
|
||||||
flags |= BSC_FD_READ;
|
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;
|
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;
|
flags |= BSC_FD_EXCEPT;
|
||||||
FD_CLR(ufd->fd, &exceptset);
|
FD_CLR(ufd->fd, exceptset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags) {
|
if (flags) {
|
||||||
|
@ -167,9 +154,41 @@ restart:
|
||||||
if (unregistered_count >= 1)
|
if (unregistered_count >= 1)
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
|
|
||||||
return work;
|
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 */
|
/*! \brief find an osmo_fd based on the integer fd */
|
||||||
struct osmo_fd *osmo_fd_get_by_fd(int fd)
|
struct osmo_fd *osmo_fd_get_by_fd(int fd)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue