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().
This commit is contained in:
Koen Zandberg 2017-08-20 10:49:49 +02:00 committed by Benjamin Valentin
parent e8a8d12d96
commit a274ea45fc
4 changed files with 48 additions and 43 deletions

View File

@ -22,41 +22,25 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <poll.h>
#include "async_read.h" #include "async_read.h"
#include "native_internal.h" #include "native_internal.h"
static int _next_index; static int _next_index;
static int _fds[ASYNC_READ_NUMOF]; static struct pollfd _fds[ASYNC_READ_NUMOF];
static void *_args[ASYNC_READ_NUMOF]; static async_read_t pollers[ASYNC_READ_NUMOF];
static native_async_read_callback_t _native_async_read_callbacks[ASYNC_READ_NUMOF];
#ifdef __MACH__ #ifdef __MACH__
static pid_t _sigio_child_pids[ASYNC_READ_NUMOF];
static void _sigio_child(int fd); static void _sigio_child(int fd);
#endif #endif
static void _async_io_isr(void) { static void _async_io_isr(void) {
fd_set rfds; if (real_poll(_fds, _next_index, 0) > 0) {
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) {
for (int i = 0; i < _next_index; i++) { for (int i = 0; i < _next_index; i++) {
if (FD_ISSET(_fds[i], &rfds)) { /* handle if one of the events has happened */
_native_async_read_callbacks[i](_fds[i], _args[i]); 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); unregister_interrupt(SIGIO);
for (int i = 0; i < _next_index; i++) { for (int i = 0; i < _next_index; i++) {
#ifdef __MACH__ if (pollers[i].child_pid) {
kill(_sigio_child_pids[i], SIGKILL); kill(pollers[i].child_pid, SIGKILL);
#endif }
real_close(_fds[i]);
} }
} }
void native_async_read_continue(int fd) { void native_async_read_continue(int fd) {
(void) fd;
#ifdef __MACH__
for (int i = 0; i < _next_index; i++) { for (int i = 0; i < _next_index; i++) {
if (_fds[i] == fd) { if (_fds[i].fd == fd && pollers[i].child_pid) {
kill(_sigio_child_pids[i], SIGCONT); 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) { 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"); err(EXIT_FAILURE, "native_async_read_add_handler(): too many callbacks");
} }
_fds[_next_index] = fd; _add_handler(fd, arg, handler);
_args[_next_index] = arg;
_native_async_read_callbacks[_next_index] = handler;
#ifdef __MACH__
/* tuntap signalled IO is not working in OSX, /* 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); _sigio_child(_next_index);
#else #else
/* configure fds to send signals on io */ /* 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__ #ifdef __MACH__
static void _sigio_child(int index) 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 parent = _native_pid;
pid_t child; pid_t child;
if ((child = real_fork()) == -1) { if ((child = real_fork()) == -1) {
err(EXIT_FAILURE, "sigio_child: fork"); err(EXIT_FAILURE, "sigio_child: fork");
} }
if (child > 0) { if (child > 0) {
_sigio_child_pids[index] = child; poll->child_pid = child;
/* return in parent process */ /* return in parent process */
return; return;
@ -139,11 +129,8 @@ static void _sigio_child(int index)
/* watch tap interface and signal parent process if data is /* watch tap interface and signal parent process if data is
* available */ * available */
fd_set rfds;
while (1) { while (1) {
FD_ZERO(&rfds); if (real_poll(&fds, 1, -1) == 1) {
FD_SET(fd, &rfds);
if (real_select(fd + 1, &rfds, NULL, NULL, NULL) == 1) {
kill(parent, SIGIO); kill(parent, SIGIO);
} }
else { else {

View File

@ -18,6 +18,9 @@
#ifndef ASYNC_READ_H #ifndef ASYNC_READ_H
#define ASYNC_READ_H #define ASYNC_READ_H
#include <stdlib.h>
#include <poll.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -34,6 +37,16 @@ extern "C" {
*/ */
typedef void (*native_async_read_callback_t)(int fd, void *arg); 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 * @brief initialize asynchronus read system
* *

View File

@ -21,6 +21,7 @@
#include <signal.h> #include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <poll.h>
/* enable signal handler register access on different platforms /* enable signal handler register access on different platforms
* check here for more: * check here for more:
* http://sourceforge.net/p/predef/wiki/OperatingSystems/ * http://sourceforge.net/p/predef/wiki/OperatingSystems/
@ -117,6 +118,7 @@ extern int (*real_pause)(void);
extern int (*real_pipe)(int[2]); extern int (*real_pipe)(int[2]);
/* The ... is a hack to save includes: */ /* The ... is a hack to save includes: */
extern int (*real_select)(int nfds, ...); extern int (*real_select)(int nfds, ...);
extern int (*real_poll)(struct pollfd *nfds, ...);
extern int (*real_setitimer)(int which, const struct itimerval extern int (*real_setitimer)(int which, const struct itimerval
*__restrict value, struct itimerval *__restrict ovalue); *__restrict value, struct itimerval *__restrict ovalue);
extern int (*real_setsid)(void); extern int (*real_setsid)(void);

View File

@ -25,6 +25,7 @@
#include <err.h> #include <err.h>
#include <errno.h> #include <errno.h>
#include <poll.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
@ -83,6 +84,7 @@ int (*real_open)(const char *path, int oflag, ...);
int (*real_pause)(void); int (*real_pause)(void);
int (*real_pipe)(int[2]); int (*real_pipe)(int[2]);
int (*real_select)(int nfds, ...); int (*real_select)(int nfds, ...);
int (*real_poll)(struct pollfd *fds, ...);
int (*real_setitimer)(int which, const struct itimerval int (*real_setitimer)(int which, const struct itimerval
*restrict value, struct itimerval *restrict ovalue); *restrict value, struct itimerval *restrict ovalue);
int (*real_setsid)(void); int (*real_setsid)(void);
@ -462,6 +464,7 @@ void _native_init_syscalls(void)
*(void **)(&real_fork) = dlsym(RTLD_NEXT, "fork"); *(void **)(&real_fork) = dlsym(RTLD_NEXT, "fork");
*(void **)(&real_dup2) = dlsym(RTLD_NEXT, "dup2"); *(void **)(&real_dup2) = dlsym(RTLD_NEXT, "dup2");
*(void **)(&real_select) = dlsym(RTLD_NEXT, "select"); *(void **)(&real_select) = dlsym(RTLD_NEXT, "select");
*(void **)(&real_poll) = dlsym(RTLD_NEXT, "poll");
*(void **)(&real_setitimer) = dlsym(RTLD_NEXT, "setitimer"); *(void **)(&real_setitimer) = dlsym(RTLD_NEXT, "setitimer");
*(void **)(&real_setsid) = dlsym(RTLD_NEXT, "setsid"); *(void **)(&real_setsid) = dlsym(RTLD_NEXT, "setsid");
*(void **)(&real_setsockopt) = dlsym(RTLD_NEXT, "setsockopt"); *(void **)(&real_setsockopt) = dlsym(RTLD_NEXT, "setsockopt");