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 <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++) {
|
for (int i = 0; i < _next_index; i++) {
|
||||||
FD_SET(_fds[i], &rfds);
|
/* handle if one of the events has happened */
|
||||||
|
if (_fds[i].revents & _fds[i].events) {
|
||||||
if (max_fd < _fds[i]) {
|
pollers[i].cb(_fds[i].fd, pollers[i].arg);
|
||||||
max_fd = _fds[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (real_select(max_fd + 1, &rfds, NULL, NULL, &timeout) > 0) {
|
|
||||||
for (int i = 0; i < _next_index; i++) {
|
|
||||||
if (FD_ISSET(_fds[i], &rfds)) {
|
|
||||||
_native_async_read_callbacks[i](_fds[i], _args[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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 {
|
||||||
|
|||||||
@ -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
|
||||||
*
|
*
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user