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:
parent
e8a8d12d96
commit
a274ea45fc
@ -22,41 +22,25 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
|
||||
#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 {
|
||||
|
||||
@ -18,6 +18,9 @@
|
||||
#ifndef ASYNC_READ_H
|
||||
#define ASYNC_READ_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <poll.h>
|
||||
|
||||
#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
|
||||
*
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <poll.h>
|
||||
/* 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);
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
@ -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");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user