From a274ea45fc5b483ea41ae0d1f1993898db30d32a Mon Sep 17 00:00:00 2001 From: Koen Zandberg Date: Sun, 20 Aug 2017 10:49:49 +0200 Subject: [PATCH] cpu/native: async_read: rewrite select() call to poll() select() can not listen to POLLPRI events which are used by the Kernel's GPIO API. In preparation for that, rewrite async_read() to use poll() instead of select(). --- cpu/native/async_read.c | 73 ++++++++++++---------------- cpu/native/include/async_read.h | 13 +++++ cpu/native/include/native_internal.h | 2 + cpu/native/syscalls.c | 3 ++ 4 files changed, 48 insertions(+), 43 deletions(-) diff --git a/cpu/native/async_read.c b/cpu/native/async_read.c index ddbdd048e3..889c4917eb 100644 --- a/cpu/native/async_read.c +++ b/cpu/native/async_read.c @@ -22,41 +22,25 @@ #include #include #include +#include #include "async_read.h" #include "native_internal.h" static int _next_index; -static int _fds[ASYNC_READ_NUMOF]; -static void *_args[ASYNC_READ_NUMOF]; -static native_async_read_callback_t _native_async_read_callbacks[ASYNC_READ_NUMOF]; +static struct pollfd _fds[ASYNC_READ_NUMOF]; +static async_read_t pollers[ASYNC_READ_NUMOF]; #ifdef __MACH__ -static pid_t _sigio_child_pids[ASYNC_READ_NUMOF]; static void _sigio_child(int fd); #endif static void _async_io_isr(void) { - fd_set rfds; - - FD_ZERO(&rfds); - - int max_fd = 0; - - struct timeval timeout = { .tv_usec = 0 }; - - for (int i = 0; i < _next_index; i++) { - FD_SET(_fds[i], &rfds); - - if (max_fd < _fds[i]) { - max_fd = _fds[i]; - } - } - - if (real_select(max_fd + 1, &rfds, NULL, NULL, &timeout) > 0) { + if (real_poll(_fds, _next_index, 0) > 0) { for (int i = 0; i < _next_index; i++) { - if (FD_ISSET(_fds[i], &rfds)) { - _native_async_read_callbacks[i](_fds[i], _args[i]); + /* handle if one of the events has happened */ + if (_fds[i].revents & _fds[i].events) { + pollers[i].cb(_fds[i].fd, pollers[i].arg); } } } @@ -70,22 +54,29 @@ void native_async_read_cleanup(void) { unregister_interrupt(SIGIO); for (int i = 0; i < _next_index; i++) { -#ifdef __MACH__ - kill(_sigio_child_pids[i], SIGKILL); -#endif - real_close(_fds[i]); + if (pollers[i].child_pid) { + kill(pollers[i].child_pid, SIGKILL); + } } } void native_async_read_continue(int fd) { - (void) fd; -#ifdef __MACH__ for (int i = 0; i < _next_index; i++) { - if (_fds[i] == fd) { - kill(_sigio_child_pids[i], SIGCONT); + if (_fds[i].fd == fd && pollers[i].child_pid) { + kill(pollers[i].child_pid, SIGCONT); } } -#endif +} + +static void _add_handler(int fd, void *arg, native_async_read_callback_t handler) { + _fds[_next_index].fd = fd; + _fds[_next_index].events = POLLIN | POLLPRI; + async_read_t *poll = &pollers[_next_index]; + + poll->child_pid = 0; + poll->cb = handler; + poll->arg = arg; + poll->fd = &_fds[_next_index]; } void native_async_read_add_handler(int fd, void *arg, native_async_read_callback_t handler) { @@ -93,13 +84,11 @@ void native_async_read_add_handler(int fd, void *arg, native_async_read_callback err(EXIT_FAILURE, "native_async_read_add_handler(): too many callbacks"); } - _fds[_next_index] = fd; - _args[_next_index] = arg; - _native_async_read_callbacks[_next_index] = handler; + _add_handler(fd, arg, handler); -#ifdef __MACH__ /* tuntap signalled IO is not working in OSX, - * * check http://sourceforge.net/p/tuntaposx/bugs/17/ */ + * * check http://sourceforge.net/p/tuntaposx/bugs/18/ */ +#ifdef __MACH__ _sigio_child(_next_index); #else /* configure fds to send signals on io */ @@ -118,14 +107,15 @@ void native_async_read_add_handler(int fd, void *arg, native_async_read_callback #ifdef __MACH__ static void _sigio_child(int index) { - int fd = _fds[index]; + struct pollfd fds = _fds[index]; + async_read_t *poll = &pollers[_next_index]; pid_t parent = _native_pid; pid_t child; if ((child = real_fork()) == -1) { err(EXIT_FAILURE, "sigio_child: fork"); } if (child > 0) { - _sigio_child_pids[index] = child; + poll->child_pid = child; /* return in parent process */ return; @@ -139,11 +129,8 @@ static void _sigio_child(int index) /* watch tap interface and signal parent process if data is * available */ - fd_set rfds; while (1) { - FD_ZERO(&rfds); - FD_SET(fd, &rfds); - if (real_select(fd + 1, &rfds, NULL, NULL, NULL) == 1) { + if (real_poll(&fds, 1, -1) == 1) { kill(parent, SIGIO); } else { diff --git a/cpu/native/include/async_read.h b/cpu/native/include/async_read.h index fa76d3b0a4..7451046d02 100644 --- a/cpu/native/include/async_read.h +++ b/cpu/native/include/async_read.h @@ -18,6 +18,9 @@ #ifndef ASYNC_READ_H #define ASYNC_READ_H +#include +#include + #ifdef __cplusplus extern "C" { #endif @@ -34,6 +37,16 @@ extern "C" { */ typedef void (*native_async_read_callback_t)(int fd, void *arg); +/** + * @brief Interrupt callback information structure + */ +typedef struct { + pid_t child_pid; /**< PID of the interrupt listener */ + native_async_read_callback_t cb; /**< Interrupt callback funtion */ + void *arg; /**< Argument ptr for the callback */ + struct pollfd *fd; /**< sysfs gpio fd */ +} async_read_t; + /** * @brief initialize asynchronus read system * diff --git a/cpu/native/include/native_internal.h b/cpu/native/include/native_internal.h index 05cb913a24..75b1a0a15e 100644 --- a/cpu/native/include/native_internal.h +++ b/cpu/native/include/native_internal.h @@ -21,6 +21,7 @@ #include #include +#include /* enable signal handler register access on different platforms * check here for more: * http://sourceforge.net/p/predef/wiki/OperatingSystems/ @@ -117,6 +118,7 @@ extern int (*real_pause)(void); extern int (*real_pipe)(int[2]); /* The ... is a hack to save includes: */ extern int (*real_select)(int nfds, ...); +extern int (*real_poll)(struct pollfd *nfds, ...); extern int (*real_setitimer)(int which, const struct itimerval *__restrict value, struct itimerval *__restrict ovalue); extern int (*real_setsid)(void); diff --git a/cpu/native/syscalls.c b/cpu/native/syscalls.c index 821535feda..9b6d2f7acf 100644 --- a/cpu/native/syscalls.c +++ b/cpu/native/syscalls.c @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -83,6 +84,7 @@ int (*real_open)(const char *path, int oflag, ...); int (*real_pause)(void); int (*real_pipe)(int[2]); int (*real_select)(int nfds, ...); +int (*real_poll)(struct pollfd *fds, ...); int (*real_setitimer)(int which, const struct itimerval *restrict value, struct itimerval *restrict ovalue); int (*real_setsid)(void); @@ -462,6 +464,7 @@ void _native_init_syscalls(void) *(void **)(&real_fork) = dlsym(RTLD_NEXT, "fork"); *(void **)(&real_dup2) = dlsym(RTLD_NEXT, "dup2"); *(void **)(&real_select) = dlsym(RTLD_NEXT, "select"); + *(void **)(&real_poll) = dlsym(RTLD_NEXT, "poll"); *(void **)(&real_setitimer) = dlsym(RTLD_NEXT, "setitimer"); *(void **)(&real_setsid) = dlsym(RTLD_NEXT, "setsid"); *(void **)(&real_setsockopt) = dlsym(RTLD_NEXT, "setsockopt");