mirror of https://gerrit.osmocom.org/libosmocore
Add osmo_timerfd_* functions for osmo_fd-wrapped timerfd
Linux offers file descriptor based periodic (interval) timers, which can achieve a higher precision than our userspace based timers and which can be slave'd to CLOCK_MONOTINIC or other clock sources. Let's add some code for osmo_fd wrapped versions that integrate well with our select() abstraction. The code has been used in osmo-bts-trx since June 2017 (change-id I51b19adde14ebb7ef3bb863d45e06243c323e22e), and I'm just renaming and moving it to libosmocore here. After a merge, the osmo-bts implementations can be removed in favor if this one. Change-Id: Ibeffba7c997252c003723bcd5d14122c4ded2fe7
This commit is contained in:
parent
b82a407a49
commit
ea4d8939af
|
@ -55,7 +55,7 @@ AC_SUBST(LTLDFLAGS_OSMOCODING)
|
|||
|
||||
dnl checks for header files
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS(execinfo.h sys/select.h sys/socket.h syslog.h ctype.h netinet/tcp.h)
|
||||
AC_CHECK_HEADERS(execinfo.h sys/select.h sys/socket.h sys/timerfd.h syslog.h ctype.h netinet/tcp.h)
|
||||
# for src/conv.c
|
||||
AC_FUNC_ALLOCA
|
||||
AC_SEARCH_LIBS([dlopen], [dl dld], [LIBRARY_DLOPEN="$LIBS";LIBS=""])
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
|
||||
/*! \defgroup select Select loop abstraction
|
||||
* @{
|
||||
|
@ -54,4 +55,10 @@ struct osmo_fd *osmo_fd_get_by_fd(int fd);
|
|||
int osmo_fd_fill_fds(void *readset, void *writeset, void *exceptset);
|
||||
int osmo_fd_disp_fds(void *readset, void *writeset, void *exceptset);
|
||||
|
||||
/* timerfd integration */
|
||||
int osmo_timerfd_disable(struct osmo_fd *ofd);
|
||||
int osmo_timerfd_schedule(struct osmo_fd *ofd, const struct timespec *first,
|
||||
const struct timespec *interval);
|
||||
int osmo_timerfd_setup(struct osmo_fd *ofd, int (*cb)(struct osmo_fd *, unsigned int), void *data);
|
||||
|
||||
/*! @} */
|
||||
|
|
66
src/select.c
66
src/select.c
|
@ -30,6 +30,7 @@
|
|||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <osmocom/core/select.h>
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
|
@ -270,6 +271,71 @@ struct osmo_fd *osmo_fd_get_by_fd(int fd)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SYS_TIMERFD_H
|
||||
#include <sys/timerfd.h>
|
||||
|
||||
/*! disable the osmocom-wrapped timerfd */
|
||||
int osmo_timerfd_disable(struct osmo_fd *ofd)
|
||||
{
|
||||
const struct itimerspec its_null = {
|
||||
.it_value = { 0, 0 },
|
||||
.it_interval = { 0, 0 },
|
||||
};
|
||||
return timerfd_settime(ofd->fd, 0, &its_null, NULL);
|
||||
}
|
||||
|
||||
/*! schedule the osmcoom-wrapped timerfd to occur first at \a first, then periodically at \a interval
|
||||
* \param[in] ofd Osmocom wrapped timerfd
|
||||
* \param[in] first Relative time at which the timer should first execute (NULL = \a interval)
|
||||
* \param[in] interval Time interval at which subsequent timer shall fire
|
||||
* \returns 0 on success; negative on error */
|
||||
int osmo_timerfd_schedule(struct osmo_fd *ofd, const struct timespec *first,
|
||||
const struct timespec *interval)
|
||||
{
|
||||
struct itimerspec its;
|
||||
|
||||
if (ofd->fd < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* first expiration */
|
||||
if (first)
|
||||
its.it_value = *first;
|
||||
else
|
||||
its.it_value = *interval;
|
||||
/* repeating interval */
|
||||
its.it_interval = *interval;
|
||||
|
||||
return timerfd_settime(ofd->fd, 0, &its, NULL);
|
||||
}
|
||||
|
||||
/*! setup osmocom-wrapped timerfd
|
||||
* \param[inout] ofd Osmocom-wrapped timerfd on which to operate
|
||||
* \param[in] cb Call-back function called when timerfd becomes readable
|
||||
* \param[in] data Opaque data to be passed on to call-back
|
||||
* \returns 0 on success; negative on error
|
||||
*
|
||||
* We simply initialize the data structures here, but do not yet
|
||||
* schedule the timer.
|
||||
*/
|
||||
int osmo_timerfd_setup(struct osmo_fd *ofd, int (*cb)(struct osmo_fd *, unsigned int), void *data)
|
||||
{
|
||||
ofd->cb = cb;
|
||||
ofd->data = data;
|
||||
ofd->when = BSC_FD_READ;
|
||||
|
||||
if (ofd->fd < 0) {
|
||||
ofd->fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
|
||||
if (ofd->fd < 0)
|
||||
return ofd->fd;
|
||||
|
||||
osmo_fd_register(ofd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* HAVE_SYS_TIMERFD_H */
|
||||
|
||||
|
||||
/*! @} */
|
||||
|
||||
#endif /* _HAVE_SYS_SELECT_H */
|
||||
|
|
Loading…
Reference in New Issue