lib: posix: Add support for eventfd
This implements a file descriptor used for event notification that behaves like the eventfd in Linux. The eventfd supports nonblocking operation by setting the EFD_NONBLOCK flag and semaphore operation by settings the EFD_SEMAPHORE flag. The major use case for this is when using poll() and the sockets that you poll are dynamic. When a new socket needs to be added to the poll, there must be some way to wake the thread and update the pollfds before calling poll again. One way to solve it is to have a timeout set in the poll call and only update the pollfds during a timeout but that is not a very nice solution. By instead including an eventfd in the pollfds, it is possible to wake the polling thread by simply writing to the eventfd. Signed-off-by: Tobias Svehagen <tobias.svehagen@gmail.com>
This commit is contained in:
parent
773de88db0
commit
ca872a44c1
9 changed files with 559 additions and 0 deletions
91
include/posix/sys/eventfd.h
Normal file
91
include/posix/sys/eventfd.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Tobias Svehagen
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_POSIX_SYS_EVENTFD_H_
|
||||
#define ZEPHYR_INCLUDE_POSIX_SYS_EVENTFD_H_
|
||||
|
||||
#include <sys/fdtable.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define EFD_IN_USE 0x1
|
||||
#define EFD_SEMAPHORE 0x2
|
||||
#define EFD_NONBLOCK O_NONBLOCK
|
||||
#define EFD_FLAGS_SET (EFD_SEMAPHORE | EFD_NONBLOCK)
|
||||
|
||||
typedef u64_t eventfd_t;
|
||||
|
||||
/**
|
||||
* @brief Create a file descriptor for event notification
|
||||
*
|
||||
* The returned file descriptor can be used with POSIX read/write calls or
|
||||
* with the eventfd_read/eventfd_write functions.
|
||||
*
|
||||
* It also supports polling and by including an eventfd in a call to poll,
|
||||
* it is possible to signal and wake the polling thread by simply writing to
|
||||
* the eventfd.
|
||||
*
|
||||
* When using read() and write() on an eventfd, the size must always be at
|
||||
* least 8 bytes or the operation will fail with EINVAL.
|
||||
*
|
||||
* @return New eventfd file descriptor on success, -1 on error
|
||||
*/
|
||||
int eventfd(unsigned int initval, int flags);
|
||||
|
||||
/**
|
||||
* @brief Read from an eventfd
|
||||
*
|
||||
* If call is successful, the value parameter will have the value 1
|
||||
*
|
||||
* @param fd File descriptor
|
||||
* @param value Pointer for storing the read value
|
||||
*
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
static inline int eventfd_read(int fd, eventfd_t *value)
|
||||
{
|
||||
const struct fd_op_vtable *efd_vtable;
|
||||
ssize_t ret;
|
||||
void *obj;
|
||||
|
||||
obj = z_get_fd_obj_and_vtable(fd, &efd_vtable);
|
||||
|
||||
ret = efd_vtable->read(obj, value, sizeof(*value));
|
||||
|
||||
return ret == sizeof(eventfd_t) ? 0 : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write to an eventfd
|
||||
*
|
||||
* @param fd File descriptor
|
||||
* @param value Value to write
|
||||
*
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
static inline int eventfd_write(int fd, eventfd_t value)
|
||||
{
|
||||
const struct fd_op_vtable *efd_vtable;
|
||||
ssize_t ret;
|
||||
void *obj;
|
||||
|
||||
obj = z_get_fd_obj_and_vtable(fd, &efd_vtable);
|
||||
|
||||
ret = efd_vtable->write(obj, &value, sizeof(value));
|
||||
|
||||
return ret == sizeof(eventfd_t) ? 0 : -1;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_POSIX_SYS_EVENTFD_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue