mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
vfs: add support for mutiple selects in eventfd
This commit is contained in:
parent
30e9345bc7
commit
7b911e4641
@ -151,7 +151,7 @@ static spp_slot_t *spp_malloc_slot(void)
|
||||
break;
|
||||
}
|
||||
if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) {
|
||||
if (esp_vfs_register_fd(spp_local_param.spp_vfs_id, &(*slot)->fd) != ESP_OK) {
|
||||
if (esp_vfs_register_fd(spp_local_param.spp_vfs_id, -1, /*permanent=*/true, &(*slot)->fd) != ESP_OK) {
|
||||
BTC_TRACE_ERROR("%s unable to register fd!", __func__);
|
||||
err_no = 3;
|
||||
break;
|
||||
|
@ -325,18 +325,29 @@ esp_err_t esp_vfs_register_with_id(const esp_vfs_t *vfs, void *ctx, esp_vfs_id_t
|
||||
*/
|
||||
esp_err_t esp_vfs_unregister(const char* base_path);
|
||||
|
||||
/**
|
||||
* Unregister a virtual filesystem with the given index
|
||||
*
|
||||
* @param vfs_id The VFS ID returned by esp_vfs_register_with_id
|
||||
* @return ESP_OK if successful, ESP_ERR_INVALID_STATE if VFS for the given index
|
||||
* hasn't been registered
|
||||
*/
|
||||
esp_err_t esp_vfs_unregister_with_id(esp_vfs_id_t vfs_id);
|
||||
|
||||
/**
|
||||
* Special function for registering another file descriptor for a VFS registered
|
||||
* by esp_vfs_register_with_id.
|
||||
*
|
||||
* @param vfs_id VFS identificator returned by esp_vfs_register_with_id.
|
||||
* @param local_fd The fd in the local vfs. Passing -1 will set the local fd as the (*fd) value.
|
||||
* @param permanenent Whether the fd should be treated as permannet (not removed after close())
|
||||
* @param fd The registered file descriptor will be written to this address.
|
||||
*
|
||||
* @return ESP_OK if the registration is successful,
|
||||
* ESP_ERR_NO_MEM if too many file descriptors are registered,
|
||||
* ESP_ERR_INVALID_ARG if the arguments are incorrect.
|
||||
*/
|
||||
esp_err_t esp_vfs_register_fd(esp_vfs_id_t vfs_id, int *fd);
|
||||
esp_err_t esp_vfs_register_fd(esp_vfs_id_t vfs_id, int local_fd, bool permanent, int *fd);
|
||||
|
||||
/**
|
||||
* Special function for unregistering a file descriptor belonging to a VFS
|
||||
|
@ -20,19 +20,22 @@
|
||||
#include "esp_err.h"
|
||||
|
||||
#define EFD_SUPPORT_ISR (1 << 4)
|
||||
#define EVENT_VFS_PREFIX "/dev/event"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
size_t eventfd_max_num;
|
||||
} esp_vfs_eventfd_config_t;
|
||||
|
||||
/**
|
||||
* @brief Registers the event vfs.
|
||||
*
|
||||
* @return ESP_OK if successful, ESP_ERR_NO_MEM if too many VFSes are
|
||||
* registered.
|
||||
*/
|
||||
esp_err_t esp_vfs_eventfd_register(void);
|
||||
esp_err_t esp_vfs_eventfd_register(const esp_vfs_eventfd_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief Unregisters the event vfs.
|
||||
|
@ -19,12 +19,15 @@
|
||||
|
||||
#include "driver/timer.h"
|
||||
#include "esp_vfs.h"
|
||||
#include "sys/_stdint.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "unity.h"
|
||||
|
||||
TEST_CASE("Test eventfd create and close", "[vfs][eventfd]")
|
||||
TEST_CASE("eventfd create and close", "[vfs][eventfd]")
|
||||
{
|
||||
TEST_ESP_OK(esp_vfs_eventfd_register());
|
||||
esp_vfs_eventfd_config_t config = {
|
||||
.eventfd_max_num = 5,
|
||||
};
|
||||
TEST_ESP_OK(esp_vfs_eventfd_register(&config));
|
||||
int fd = eventfd(0, 0);
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(0, fd);
|
||||
TEST_ASSERT_EQUAL(0, close(fd));
|
||||
@ -35,9 +38,13 @@ TEST_CASE("Test eventfd create and close", "[vfs][eventfd]")
|
||||
TEST_ESP_OK(esp_vfs_eventfd_unregister());
|
||||
}
|
||||
|
||||
TEST_CASE("Test eventfd reject unknown flags", "[vfs][eventfd]")
|
||||
TEST_CASE("eventfd reject unknown flags", "[vfs][eventfd]")
|
||||
{
|
||||
TEST_ESP_OK(esp_vfs_eventfd_register());
|
||||
esp_vfs_eventfd_config_t config = {
|
||||
.eventfd_max_num = 5,
|
||||
};
|
||||
TEST_ESP_OK(esp_vfs_eventfd_register(&config));
|
||||
|
||||
int fd = eventfd(0, 1);
|
||||
TEST_ASSERT_LESS_THAN(0, fd);
|
||||
TEST_ASSERT_EQUAL(EINVAL, errno);
|
||||
@ -48,9 +55,13 @@ TEST_CASE("Test eventfd reject unknown flags", "[vfs][eventfd]")
|
||||
TEST_ESP_OK(esp_vfs_eventfd_unregister());
|
||||
}
|
||||
|
||||
TEST_CASE("Test eventfd read", "[vfs][eventfd]")
|
||||
TEST_CASE("eventfd read", "[vfs][eventfd]")
|
||||
{
|
||||
TEST_ESP_OK(esp_vfs_eventfd_register());
|
||||
esp_vfs_eventfd_config_t config = {
|
||||
.eventfd_max_num = 5,
|
||||
};
|
||||
TEST_ESP_OK(esp_vfs_eventfd_register(&config));
|
||||
|
||||
unsigned int initval = 123;
|
||||
int fd = eventfd(initval, 0);
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(0, fd);
|
||||
@ -64,9 +75,13 @@ TEST_CASE("Test eventfd read", "[vfs][eventfd]")
|
||||
TEST_ESP_OK(esp_vfs_eventfd_unregister());
|
||||
}
|
||||
|
||||
TEST_CASE("Test eventfd read invalid size", "[vfs][eventfd]")
|
||||
TEST_CASE("eventfd read invalid size", "[vfs][eventfd]")
|
||||
{
|
||||
TEST_ESP_OK(esp_vfs_eventfd_register());
|
||||
esp_vfs_eventfd_config_t config = {
|
||||
.eventfd_max_num = 5,
|
||||
};
|
||||
TEST_ESP_OK(esp_vfs_eventfd_register(&config));
|
||||
|
||||
int fd = eventfd(0, 0);
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(0, fd);
|
||||
|
||||
@ -77,9 +92,13 @@ TEST_CASE("Test eventfd read invalid size", "[vfs][eventfd]")
|
||||
TEST_ESP_OK(esp_vfs_eventfd_unregister());
|
||||
}
|
||||
|
||||
TEST_CASE("Test eventfd write invalid size", "[vfs][eventfd]")
|
||||
TEST_CASE("eventfd write invalid size", "[vfs][eventfd]")
|
||||
{
|
||||
TEST_ESP_OK(esp_vfs_eventfd_register());
|
||||
esp_vfs_eventfd_config_t config = {
|
||||
.eventfd_max_num = 5,
|
||||
};
|
||||
TEST_ESP_OK(esp_vfs_eventfd_register(&config));
|
||||
|
||||
int fd = eventfd(0, 0);
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(0, fd);
|
||||
|
||||
@ -90,9 +109,13 @@ TEST_CASE("Test eventfd write invalid size", "[vfs][eventfd]")
|
||||
TEST_ESP_OK(esp_vfs_eventfd_unregister());
|
||||
}
|
||||
|
||||
TEST_CASE("Test eventfd write then read", "[vfs][eventfd]")
|
||||
TEST_CASE("eventfd write then read", "[vfs][eventfd]")
|
||||
{
|
||||
TEST_ESP_OK(esp_vfs_eventfd_register());
|
||||
esp_vfs_eventfd_config_t config = {
|
||||
.eventfd_max_num = 5,
|
||||
};
|
||||
TEST_ESP_OK(esp_vfs_eventfd_register(&config));
|
||||
|
||||
int fd = eventfd(0, 0);
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(0, fd);
|
||||
|
||||
@ -110,9 +133,13 @@ TEST_CASE("Test eventfd write then read", "[vfs][eventfd]")
|
||||
TEST_ESP_OK(esp_vfs_eventfd_unregister());
|
||||
}
|
||||
|
||||
TEST_CASE("Test eventfd instant select", "[vfs][eventfd]")
|
||||
TEST_CASE("eventfd instant select", "[vfs][eventfd]")
|
||||
{
|
||||
TEST_ESP_OK(esp_vfs_eventfd_register());
|
||||
esp_vfs_eventfd_config_t config = {
|
||||
.eventfd_max_num = 5,
|
||||
};
|
||||
TEST_ESP_OK(esp_vfs_eventfd_register(&config));
|
||||
|
||||
int fd = eventfd(0, 0);
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(0, fd);
|
||||
|
||||
@ -126,12 +153,12 @@ TEST_CASE("Test eventfd instant select", "[vfs][eventfd]")
|
||||
FD_ZERO(&write_fds);
|
||||
FD_ZERO(&error_fds);
|
||||
FD_SET(fd, &read_fds);
|
||||
printf("fd %d\n", fd);
|
||||
int ret = select(fd + 1, &read_fds, &write_fds, &error_fds, &zero_time);
|
||||
TEST_ASSERT_EQUAL(0, ret);
|
||||
TEST_ASSERT(!FD_ISSET(fd, &read_fds));
|
||||
|
||||
uint64_t val = 1;
|
||||
printf("Write to fd\n");
|
||||
TEST_ASSERT_EQUAL(sizeof(val), write(fd, &val, sizeof(val)));
|
||||
FD_ZERO(&read_fds);
|
||||
FD_ZERO(&write_fds);
|
||||
@ -149,6 +176,7 @@ TEST_CASE("Test eventfd instant select", "[vfs][eventfd]")
|
||||
ret = select(fd + 1, &read_fds, &write_fds, &error_fds, &zero_time);
|
||||
TEST_ASSERT_EQUAL(0, ret);
|
||||
TEST_ASSERT(!FD_ISSET(fd, &read_fds));
|
||||
TEST_ASSERT_EQUAL(0, close(fd));
|
||||
TEST_ESP_OK(esp_vfs_eventfd_unregister());
|
||||
}
|
||||
|
||||
@ -161,47 +189,49 @@ static void signal_task(void *arg)
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("Test eventfd signal from task", "[vfs][eventfd]")
|
||||
TEST_CASE("eventfd signal from task", "[vfs][eventfd]")
|
||||
{
|
||||
TEST_ESP_OK(esp_vfs_eventfd_register());
|
||||
int fd = eventfd(0, 0);
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(0, fd);
|
||||
esp_vfs_eventfd_config_t config = {
|
||||
.eventfd_max_num = 5,
|
||||
};
|
||||
TEST_ESP_OK(esp_vfs_eventfd_register(&config));
|
||||
|
||||
xTaskCreate(signal_task, "signal_task", 2048, &fd, 5, NULL);
|
||||
int fd0 = eventfd(0, 0);
|
||||
int fd1 = eventfd(0, 0);
|
||||
int max_fd = fd1 > fd0 ? fd1 : fd0;
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(0, fd0);
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(0, fd1);
|
||||
|
||||
xTaskCreate(signal_task, "signal_task", 2048, &fd0, 5, NULL);
|
||||
struct timeval wait_time;
|
||||
struct timeval zero_time;
|
||||
fd_set read_fds, write_fds, error_fds;
|
||||
fd_set read_fds;
|
||||
FD_ZERO(&read_fds);
|
||||
FD_ZERO(&write_fds);
|
||||
FD_ZERO(&error_fds);
|
||||
FD_SET(fd, &read_fds);
|
||||
FD_SET(fd0, &read_fds);
|
||||
FD_SET(fd1, &read_fds);
|
||||
wait_time.tv_sec = 2;
|
||||
wait_time.tv_usec = 0;
|
||||
zero_time.tv_sec = 0;
|
||||
zero_time.tv_usec = 0;
|
||||
|
||||
FD_SET(fd, &read_fds);
|
||||
int ret = select(fd + 1, &read_fds, &write_fds, &error_fds, &wait_time);
|
||||
int ret = select(max_fd + 1, &read_fds, NULL, NULL, &wait_time);
|
||||
printf("Frist select returned\n");
|
||||
TEST_ASSERT_EQUAL(1, ret);
|
||||
TEST_ASSERT(FD_ISSET(fd, &read_fds));
|
||||
TEST_ASSERT(FD_ISSET(fd0, &read_fds));
|
||||
|
||||
uint64_t val = 1;
|
||||
TEST_ASSERT_EQUAL(sizeof(val), write(fd1, &val, sizeof(val)));
|
||||
|
||||
FD_ZERO(&read_fds);
|
||||
FD_ZERO(&write_fds);
|
||||
FD_ZERO(&error_fds);
|
||||
FD_SET(fd, &read_fds);
|
||||
ret = select(fd + 1, &read_fds, &write_fds, &error_fds, &zero_time);
|
||||
TEST_ASSERT_EQUAL(1, ret);
|
||||
TEST_ASSERT(FD_ISSET(fd, &read_fds));
|
||||
FD_SET(fd0, &read_fds);
|
||||
FD_SET(fd1, &read_fds);
|
||||
ret = select(max_fd + 1, &read_fds, NULL, NULL, &zero_time);
|
||||
TEST_ASSERT_EQUAL(2, ret);
|
||||
TEST_ASSERT(FD_ISSET(fd0, &read_fds));
|
||||
TEST_ASSERT(FD_ISSET(fd1, &read_fds));
|
||||
|
||||
uint64_t val;
|
||||
TEST_ASSERT_EQUAL(sizeof(val), read(fd, &val, sizeof(val)));
|
||||
FD_ZERO(&read_fds);
|
||||
FD_ZERO(&write_fds);
|
||||
FD_ZERO(&error_fds);
|
||||
FD_SET(fd, &read_fds);
|
||||
ret = select(fd + 1, &read_fds, &write_fds, &error_fds, &zero_time);
|
||||
TEST_ASSERT_EQUAL(0, ret);
|
||||
TEST_ASSERT(!FD_ISSET(fd, &read_fds));
|
||||
TEST_ASSERT_EQUAL(0, close(fd0));
|
||||
TEST_ASSERT_EQUAL(0, close(fd1));
|
||||
TEST_ESP_OK(esp_vfs_eventfd_unregister());
|
||||
}
|
||||
|
||||
@ -214,20 +244,24 @@ static void IRAM_ATTR eventfd_select_test_isr(void *arg)
|
||||
assert(ret == sizeof(val));
|
||||
}
|
||||
|
||||
TEST_CASE("Test eventfd signal from ISR", "[vfs][eventfd]")
|
||||
TEST_CASE("eventfd signal from ISR", "[vfs][eventfd]")
|
||||
{
|
||||
TEST_ESP_OK(esp_vfs_eventfd_register());
|
||||
esp_vfs_eventfd_config_t config = {
|
||||
.eventfd_max_num = 5,
|
||||
};
|
||||
TEST_ESP_OK(esp_vfs_eventfd_register(&config));
|
||||
|
||||
int fd = eventfd(0, EFD_SUPPORT_ISR);
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(0, fd);
|
||||
|
||||
timer_config_t config = {
|
||||
timer_config_t timer_config = {
|
||||
.divider = 16,
|
||||
.counter_dir = TIMER_COUNT_UP,
|
||||
.counter_en = TIMER_PAUSE,
|
||||
.alarm_en = TIMER_ALARM_EN,
|
||||
.auto_reload = false,
|
||||
};
|
||||
TEST_ESP_OK(timer_init(TIMER_GROUP_0, TIMER_0, &config));
|
||||
TEST_ESP_OK(timer_init(TIMER_GROUP_0, TIMER_0, &timer_config));
|
||||
|
||||
TEST_ESP_OK(timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0x00000000ULL));
|
||||
|
||||
@ -251,5 +285,99 @@ TEST_CASE("Test eventfd signal from ISR", "[vfs][eventfd]")
|
||||
TEST_ASSERT_EQUAL(1, ret);
|
||||
TEST_ASSERT(FD_ISSET(fd, &read_fds));
|
||||
timer_deinit(TIMER_GROUP_0, TIMER_0);
|
||||
TEST_ASSERT_EQUAL(0, close(fd));
|
||||
TEST_ESP_OK(esp_vfs_eventfd_unregister());
|
||||
}
|
||||
|
||||
static void close_task(void *arg)
|
||||
{
|
||||
int fd = *((int *)arg);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
TEST_ASSERT_EQUAL(0, close(fd));
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("eventfd select closed fd", "[vfs][eventfd]")
|
||||
{
|
||||
esp_vfs_eventfd_config_t config = {
|
||||
.eventfd_max_num = 5,
|
||||
};
|
||||
TEST_ESP_OK(esp_vfs_eventfd_register(&config));
|
||||
|
||||
int fd = eventfd(0, 0);
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(0, fd);
|
||||
|
||||
xTaskCreate(close_task, "close_task", 2048, &fd, 5, NULL);
|
||||
struct timeval wait_time;
|
||||
fd_set read_fds, write_fds, error_fds;
|
||||
FD_ZERO(&read_fds);
|
||||
FD_ZERO(&write_fds);
|
||||
FD_ZERO(&error_fds);
|
||||
FD_SET(fd, &read_fds);
|
||||
FD_SET(fd, &error_fds);
|
||||
wait_time.tv_sec = 2;
|
||||
wait_time.tv_usec = 0;
|
||||
|
||||
int ret = select(fd + 1, &read_fds, &write_fds, &error_fds, &wait_time);
|
||||
TEST_ASSERT_EQUAL(1, ret);
|
||||
TEST_ASSERT(FD_ISSET(fd, &error_fds));
|
||||
|
||||
TEST_ASSERT_EQUAL(0, close(fd));
|
||||
TEST_ESP_OK(esp_vfs_eventfd_unregister());
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
xQueueHandle queue;
|
||||
int fd;
|
||||
} select_task_args_t;
|
||||
|
||||
static void select_task(void *arg)
|
||||
{
|
||||
select_task_args_t *select_arg = (select_task_args_t *)arg;
|
||||
int fd = select_arg->fd;
|
||||
struct timeval wait_time;
|
||||
fd_set read_fds;
|
||||
FD_ZERO(&read_fds);
|
||||
FD_SET(fd, &read_fds);
|
||||
wait_time.tv_sec = 2;
|
||||
wait_time.tv_usec = 0;
|
||||
|
||||
int ret = select(fd + 1, &read_fds, NULL, NULL, &wait_time);
|
||||
assert(ret == 1);
|
||||
xQueueSend(select_arg->queue, select_arg, 0);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("eventfd multiple selects", "[vfs][eventfd]")
|
||||
{
|
||||
esp_vfs_eventfd_config_t config = {
|
||||
.eventfd_max_num = 5,
|
||||
};
|
||||
TEST_ESP_OK(esp_vfs_eventfd_register(&config));
|
||||
|
||||
int fd = eventfd(0, 0);
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(0, fd);
|
||||
|
||||
select_task_args_t args = {
|
||||
.queue = xQueueCreate(10, sizeof(select_task_args_t)),
|
||||
.fd = fd,
|
||||
};
|
||||
select_task_args_t ret_args;
|
||||
|
||||
xTaskCreate(select_task, "select_task0", 2048, &args, 5, NULL);
|
||||
xTaskCreate(select_task, "select_task1", 2048, &args, 5, NULL);
|
||||
|
||||
uint64_t val = 1;
|
||||
TEST_ASSERT_EQUAL(sizeof(val), write(fd, &val, sizeof(val)));
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
|
||||
TEST_ASSERT(xQueueReceive(args.queue, &ret_args, 0));
|
||||
TEST_ASSERT_EQUAL(ret_args.fd, fd);
|
||||
TEST_ASSERT(xQueueReceive(args.queue, &ret_args, 0));
|
||||
TEST_ASSERT_EQUAL(ret_args.fd, fd);
|
||||
|
||||
vQueueDelete(args.queue);
|
||||
TEST_ASSERT_EQUAL(0, close(fd));
|
||||
TEST_ESP_OK(esp_vfs_eventfd_unregister());
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,10 @@ static void worker_task(void *arg)
|
||||
TEST_CASE("Test eventfd triggered correctly", "[vfs][eventfd]")
|
||||
{
|
||||
xTaskCreate(worker_task, "worker_task", 1024, NULL, 5, NULL);
|
||||
TEST_ESP_OK(esp_vfs_eventfd_register());
|
||||
esp_vfs_eventfd_config_t config = {
|
||||
.eventfd_max_num = 5,
|
||||
};
|
||||
TEST_ESP_OK(esp_vfs_eventfd_register(&config));
|
||||
s_timer_fd = eventfd(0, EFD_SUPPORT_ISR);
|
||||
s_progress_fd = eventfd(0, 0);
|
||||
int maxFd = s_progress_fd > s_timer_fd ? s_progress_fd : s_timer_fd;
|
||||
|
@ -172,6 +172,27 @@ esp_err_t esp_vfs_register_with_id(const esp_vfs_t *vfs, void *ctx, esp_vfs_id_t
|
||||
return esp_vfs_register_common("", LEN_PATH_PREFIX_IGNORED, vfs, ctx, vfs_id);
|
||||
}
|
||||
|
||||
esp_err_t esp_vfs_unregister_with_id(esp_vfs_id_t vfs_id)
|
||||
{
|
||||
if (vfs_id < 0 || vfs_id >= MAX_FDS || s_vfs[vfs_id] == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
vfs_entry_t* vfs = s_vfs[vfs_id];
|
||||
free(vfs);
|
||||
s_vfs[vfs_id] = NULL;
|
||||
|
||||
_lock_acquire(&s_fd_table_lock);
|
||||
// Delete all references from the FD lookup-table
|
||||
for (int j = 0; j < VFS_MAX_COUNT; ++j) {
|
||||
if (s_fd_table[j].vfs_index == vfs_id) {
|
||||
s_fd_table[j] = FD_TABLE_ENTRY_UNUSED;
|
||||
}
|
||||
}
|
||||
_lock_release(&s_fd_table_lock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_vfs_unregister(const char* base_path)
|
||||
{
|
||||
const size_t base_path_len = strlen(base_path);
|
||||
@ -182,25 +203,13 @@ esp_err_t esp_vfs_unregister(const char* base_path)
|
||||
}
|
||||
if (base_path_len == vfs->path_prefix_len &&
|
||||
memcmp(base_path, vfs->path_prefix, vfs->path_prefix_len) == 0) {
|
||||
free(vfs);
|
||||
s_vfs[i] = NULL;
|
||||
|
||||
_lock_acquire(&s_fd_table_lock);
|
||||
// Delete all references from the FD lookup-table
|
||||
for (int j = 0; j < MAX_FDS; ++j) {
|
||||
if (s_fd_table[j].vfs_index == i) {
|
||||
s_fd_table[j] = FD_TABLE_ENTRY_UNUSED;
|
||||
}
|
||||
}
|
||||
_lock_release(&s_fd_table_lock);
|
||||
|
||||
return ESP_OK;
|
||||
return esp_vfs_unregister_with_id(i);
|
||||
}
|
||||
}
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
esp_err_t esp_vfs_register_fd(esp_vfs_id_t vfs_id, int *fd)
|
||||
esp_err_t esp_vfs_register_fd(esp_vfs_id_t vfs_id, int local_fd, bool permanent, int *fd)
|
||||
{
|
||||
if (vfs_id < 0 || vfs_id >= s_vfs_count || fd == NULL) {
|
||||
ESP_LOGD(TAG, "Invalid arguments for esp_vfs_register_fd(%d, 0x%x)", vfs_id, (int) fd);
|
||||
@ -211,9 +220,13 @@ esp_err_t esp_vfs_register_fd(esp_vfs_id_t vfs_id, int *fd)
|
||||
_lock_acquire(&s_fd_table_lock);
|
||||
for (int i = 0; i < MAX_FDS; ++i) {
|
||||
if (s_fd_table[i].vfs_index == -1) {
|
||||
s_fd_table[i].permanent = true;
|
||||
s_fd_table[i].permanent = permanent;
|
||||
s_fd_table[i].vfs_index = vfs_id;
|
||||
s_fd_table[i].local_fd = i;
|
||||
if (local_fd >= 0) {
|
||||
s_fd_table[i].local_fd = local_fd;
|
||||
} else {
|
||||
s_fd_table[i].local_fd = i;
|
||||
}
|
||||
*fd = i;
|
||||
ret = ESP_OK;
|
||||
break;
|
||||
@ -806,21 +819,23 @@ static int set_global_fd_sets(const fds_triple_t *vfs_fds_triple, int size, fd_s
|
||||
const fds_triple_t *item = &vfs_fds_triple[i];
|
||||
if (item->isset) {
|
||||
for (int fd = 0; fd < MAX_FDS; ++fd) {
|
||||
const int local_fd = s_fd_table[fd].local_fd; // single read -> no locking is required
|
||||
if (readfds && esp_vfs_safe_fd_isset(local_fd, &item->readfds)) {
|
||||
ESP_LOGD(TAG, "FD %d in readfds was set from VFS ID %d", fd, i);
|
||||
FD_SET(fd, readfds);
|
||||
++ret;
|
||||
}
|
||||
if (writefds && esp_vfs_safe_fd_isset(local_fd, &item->writefds)) {
|
||||
ESP_LOGD(TAG, "FD %d in writefds was set from VFS ID %d", fd, i);
|
||||
FD_SET(fd, writefds);
|
||||
++ret;
|
||||
}
|
||||
if (errorfds && esp_vfs_safe_fd_isset(local_fd, &item->errorfds)) {
|
||||
ESP_LOGD(TAG, "FD %d in errorfds was set from VFS ID %d", fd, i);
|
||||
FD_SET(fd, errorfds);
|
||||
++ret;
|
||||
if (s_fd_table[fd].vfs_index == i) {
|
||||
const int local_fd = s_fd_table[fd].local_fd; // single read -> no locking is required
|
||||
if (readfds && esp_vfs_safe_fd_isset(local_fd, &item->readfds)) {
|
||||
ESP_LOGD(TAG, "FD %d in readfds was set from VFS ID %d", fd, i);
|
||||
FD_SET(fd, readfds);
|
||||
++ret;
|
||||
}
|
||||
if (writefds && esp_vfs_safe_fd_isset(local_fd, &item->writefds)) {
|
||||
ESP_LOGD(TAG, "FD %d in writefds was set from VFS ID %d", fd, i);
|
||||
FD_SET(fd, writefds);
|
||||
++ret;
|
||||
}
|
||||
if (errorfds && esp_vfs_safe_fd_isset(local_fd, &item->errorfds)) {
|
||||
ESP_LOGD(TAG, "FD %d in errorfds was set from VFS ID %d", fd, i);
|
||||
FD_SET(fd, errorfds);
|
||||
++ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -891,6 +906,7 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds
|
||||
}
|
||||
|
||||
if (is_socket_fd) {
|
||||
assert(false);
|
||||
if (!socket_select) {
|
||||
// no socket_select found yet so take a look
|
||||
if (esp_vfs_safe_fd_isset(fd, readfds) ||
|
||||
|
@ -18,33 +18,66 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_vfs.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/portmacro.h"
|
||||
#include "soc/spinlock.h"
|
||||
|
||||
#define FD_INVALID -1
|
||||
#define NUM_EVENT_FDS 5
|
||||
#define FD_PENDING_SELECT -2
|
||||
|
||||
typedef struct event_select_args_t {
|
||||
int fd;
|
||||
fd_set *read_fds;
|
||||
fd_set *error_fds;
|
||||
esp_vfs_select_sem_t signal_sem;
|
||||
struct event_select_args_t *prev_in_fd;
|
||||
struct event_select_args_t *next_in_fd;
|
||||
struct event_select_args_t *next_in_args;
|
||||
} event_select_args_t;
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
bool support_isr;
|
||||
volatile bool is_set;
|
||||
volatile uint64_t value;
|
||||
fd_set *read_fds;
|
||||
fd_set *write_fds;
|
||||
fd_set *error_fds;
|
||||
esp_vfs_select_sem_t signal_sem;
|
||||
event_select_args_t *select_args;
|
||||
_lock_t lock;
|
||||
spinlock_t data_spin_lock; // only for event fds that support ISR.
|
||||
} Event;
|
||||
} event_context_t;
|
||||
|
||||
static Event s_events[NUM_EVENT_FDS];
|
||||
esp_vfs_id_t s_eventfd_vfs_id = -1;
|
||||
|
||||
static size_t s_event_size;
|
||||
static event_context_t *s_events;
|
||||
|
||||
static void trigger_select_for_event(event_context_t *event)
|
||||
{
|
||||
event_select_args_t *select_args = event->select_args;
|
||||
while (select_args != NULL) {
|
||||
esp_vfs_select_triggered(select_args->signal_sem);
|
||||
select_args = select_args->next_in_fd;
|
||||
}
|
||||
}
|
||||
|
||||
static void trigger_select_for_event_isr(event_context_t *event, BaseType_t *task_woken)
|
||||
{
|
||||
event_select_args_t *select_args = event->select_args;
|
||||
while (select_args != NULL) {
|
||||
BaseType_t local_woken;
|
||||
esp_vfs_select_triggered_isr(select_args->signal_sem, &local_woken);
|
||||
*task_woken = (local_woken || *task_woken);
|
||||
select_args = select_args->next_in_fd;
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t event_start_select(int nfds,
|
||||
fd_set *readfds,
|
||||
@ -55,42 +88,61 @@ static esp_err_t event_start_select(int nfds,
|
||||
{
|
||||
esp_err_t error = ESP_OK;
|
||||
bool should_trigger = false;
|
||||
nfds = nfds < s_event_size ? nfds : (int)s_event_size;
|
||||
event_select_args_t *select_args_list = NULL;
|
||||
|
||||
for (size_t i = 0; i < NUM_EVENT_FDS; i++) {
|
||||
// FIXME: end_select_args should be a list to all select args
|
||||
|
||||
for (int i = 0; i < nfds; i++) {
|
||||
_lock_acquire_recursive(&s_events[i].lock);
|
||||
int fd = s_events[i].fd;
|
||||
|
||||
if (fd != FD_INVALID && fd < nfds) {
|
||||
if (s_events[i].fd == i) {
|
||||
if (s_events[i].support_isr) {
|
||||
portENTER_CRITICAL(&s_events[i].data_spin_lock);
|
||||
}
|
||||
s_events[i].signal_sem = signal_sem;
|
||||
s_events[i].error_fds = exceptfds;
|
||||
// event fds shouldn't report error
|
||||
FD_CLR(fd, exceptfds);
|
||||
|
||||
event_select_args_t *event_select_args = (event_select_args_t *)malloc(sizeof(event_select_args_t));
|
||||
event_select_args->fd = i;
|
||||
event_select_args->signal_sem = signal_sem;
|
||||
|
||||
if (FD_ISSET(i, exceptfds)) {
|
||||
FD_CLR(i, exceptfds);
|
||||
event_select_args->error_fds = exceptfds;
|
||||
} else {
|
||||
event_select_args->error_fds = NULL;
|
||||
}
|
||||
FD_CLR(i, exceptfds);
|
||||
// event fds are always writable
|
||||
if (FD_ISSET(fd, writefds)) {
|
||||
s_events[i].write_fds = writefds;
|
||||
if (FD_ISSET(i, writefds)) {
|
||||
should_trigger = true;
|
||||
}
|
||||
if (FD_ISSET(fd, readfds)) {
|
||||
s_events[i].read_fds = readfds;
|
||||
if (FD_ISSET(i, readfds)) {
|
||||
event_select_args->read_fds = readfds;
|
||||
if (s_events[i].is_set) {
|
||||
should_trigger = true;
|
||||
} else {
|
||||
FD_CLR(fd, readfds);
|
||||
FD_CLR(i, readfds);
|
||||
}
|
||||
} else {
|
||||
event_select_args->read_fds = NULL;
|
||||
}
|
||||
event_select_args->prev_in_fd = NULL;
|
||||
event_select_args->next_in_fd = s_events[i].select_args;
|
||||
if (s_events[i].select_args) {
|
||||
s_events[i].select_args->prev_in_fd = event_select_args;
|
||||
}
|
||||
event_select_args->next_in_args = select_args_list;
|
||||
select_args_list = event_select_args;
|
||||
s_events[i].select_args = event_select_args;
|
||||
|
||||
if (s_events[i].support_isr) {
|
||||
portEXIT_CRITICAL(&s_events[i].data_spin_lock);
|
||||
}
|
||||
|
||||
}
|
||||
_lock_release_recursive(&s_events[i].lock);
|
||||
}
|
||||
|
||||
*end_select_args = select_args_list;
|
||||
|
||||
if (should_trigger) {
|
||||
esp_vfs_select_triggered(signal_sem);
|
||||
}
|
||||
@ -100,61 +152,70 @@ static esp_err_t event_start_select(int nfds,
|
||||
|
||||
static esp_err_t event_end_select(void *end_select_args)
|
||||
{
|
||||
for (size_t i = 0; i < NUM_EVENT_FDS; i++) {
|
||||
_lock_acquire_recursive(&s_events[i].lock);
|
||||
if (s_events[i].support_isr) {
|
||||
portENTER_CRITICAL(&s_events[i].data_spin_lock);
|
||||
}
|
||||
memset(&s_events[i].signal_sem, 0, sizeof(s_events[i].signal_sem));
|
||||
if (s_events[i].read_fds && s_events[i].is_set) {
|
||||
FD_SET(s_events[i].fd, s_events[i].read_fds);
|
||||
s_events[i].read_fds = NULL;
|
||||
}
|
||||
if (s_events[i].write_fds) {
|
||||
FD_SET(s_events[i].fd, s_events[i].write_fds);
|
||||
s_events[i].write_fds = NULL;
|
||||
event_select_args_t *select_args = (event_select_args_t *)end_select_args;
|
||||
|
||||
while (select_args != NULL) {
|
||||
event_context_t *event = &s_events[select_args->fd];
|
||||
|
||||
_lock_acquire_recursive(&event->lock);
|
||||
if (event->support_isr) {
|
||||
portENTER_CRITICAL(&event->data_spin_lock);
|
||||
}
|
||||
|
||||
if (s_events[i].support_isr) {
|
||||
portEXIT_CRITICAL(&s_events[i].data_spin_lock);
|
||||
if (event->fd != select_args->fd) { // already closed
|
||||
if (select_args->error_fds) {
|
||||
FD_SET(select_args->fd, select_args->error_fds);
|
||||
}
|
||||
} else {
|
||||
if (select_args->read_fds && event->is_set) {
|
||||
FD_SET(select_args->fd, select_args->read_fds);
|
||||
}
|
||||
}
|
||||
_lock_release_recursive(&s_events[i].lock);
|
||||
|
||||
event_select_args_t *prev_in_fd = select_args->prev_in_fd;
|
||||
event_select_args_t *next_in_fd = select_args->next_in_fd;
|
||||
event_select_args_t *next_in_args = select_args->next_in_args;
|
||||
if (prev_in_fd != NULL) {
|
||||
prev_in_fd->next_in_fd = next_in_fd;
|
||||
} else {
|
||||
event->select_args = next_in_fd;
|
||||
}
|
||||
if (next_in_fd != NULL) {
|
||||
next_in_fd->prev_in_fd = prev_in_fd;
|
||||
}
|
||||
if (prev_in_fd == NULL && next_in_fd == NULL) { // The last pending select
|
||||
if (event->fd == FD_PENDING_SELECT) {
|
||||
event->fd = FD_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
if (event->support_isr) {
|
||||
portEXIT_CRITICAL(&event->data_spin_lock);
|
||||
}
|
||||
_lock_release_recursive(&event->lock);
|
||||
|
||||
free(select_args);
|
||||
select_args = next_in_args;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static int event_open(const char *path, int flags, int mode)
|
||||
{
|
||||
|
||||
(void)flags;
|
||||
(void)mode;
|
||||
|
||||
if (path == NULL || path[0] != '/') {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *endPath;
|
||||
int fd = strtol(path + 1, &endPath, 10);
|
||||
|
||||
if (endPath == NULL || *endPath != '\0' || fd >= NUM_EVENT_FDS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t signal_event_fd_from_isr(int fd, const void *data, size_t size)
|
||||
{
|
||||
BaseType_t task_woken = pdFALSE;
|
||||
const uint64_t *val = (const uint64_t *)data;
|
||||
ssize_t ret = size;
|
||||
|
||||
portENTER_CRITICAL_ISR(&s_events[fd].data_spin_lock);
|
||||
|
||||
s_events[fd].is_set = true;
|
||||
s_events[fd].value += *val;
|
||||
if (s_events[fd].signal_sem.sem != NULL) {
|
||||
esp_vfs_select_triggered_isr(s_events[fd].signal_sem, &task_woken);
|
||||
if (s_events[fd].fd == fd) {
|
||||
s_events[fd].is_set = true;
|
||||
s_events[fd].value += *val;
|
||||
trigger_select_for_event_isr(&s_events[fd], &task_woken);
|
||||
} else {
|
||||
errno = EBADF;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
portEXIT_CRITICAL_ISR(&s_events[fd].data_spin_lock);
|
||||
@ -162,14 +223,14 @@ static ssize_t signal_event_fd_from_isr(int fd, const void *data, size_t size)
|
||||
if (task_woken) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
return size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t event_write(int fd, const void *data, size_t size)
|
||||
{
|
||||
ssize_t ret = -1;
|
||||
|
||||
if (fd >= NUM_EVENT_FDS || data == NULL || size != sizeof(uint64_t)) {
|
||||
if (fd >= s_event_size || data == NULL || size != sizeof(uint64_t)) {
|
||||
errno = EINVAL;
|
||||
return ret;
|
||||
}
|
||||
@ -182,21 +243,25 @@ static ssize_t event_write(int fd, const void *data, size_t size)
|
||||
ret = signal_event_fd_from_isr(fd, data, size);
|
||||
} else {
|
||||
const uint64_t *val = (const uint64_t *)data;
|
||||
_lock_acquire_recursive(&s_events[fd].lock);
|
||||
|
||||
_lock_acquire_recursive(&s_events[fd].lock);
|
||||
if (s_events[fd].support_isr) {
|
||||
portENTER_CRITICAL(&s_events[fd].data_spin_lock);
|
||||
}
|
||||
s_events[fd].is_set = true;
|
||||
s_events[fd].value += *val;
|
||||
ret = size;
|
||||
if (s_events[fd].signal_sem.sem != NULL) {
|
||||
esp_vfs_select_triggered(s_events[fd].signal_sem);
|
||||
}
|
||||
if (s_events[fd].support_isr) {
|
||||
portEXIT_CRITICAL(&s_events[fd].data_spin_lock);
|
||||
}
|
||||
|
||||
if (s_events[fd].fd == fd) {
|
||||
s_events[fd].is_set = true;
|
||||
s_events[fd].value += *val;
|
||||
ret = size;
|
||||
trigger_select_for_event(&s_events[fd]);
|
||||
|
||||
if (s_events[fd].support_isr) {
|
||||
portEXIT_CRITICAL(&s_events[fd].data_spin_lock);
|
||||
}
|
||||
} else {
|
||||
errno = EBADF;
|
||||
ret = -1;
|
||||
}
|
||||
_lock_release_recursive(&s_events[fd].lock);
|
||||
}
|
||||
return ret;
|
||||
@ -206,32 +271,33 @@ static ssize_t event_read(int fd, void *data, size_t size)
|
||||
{
|
||||
ssize_t ret = -1;
|
||||
|
||||
if (fd >= NUM_EVENT_FDS) {
|
||||
errno = EINVAL;
|
||||
return ret;
|
||||
}
|
||||
if (size != sizeof(uint64_t)) {
|
||||
if (fd >= s_event_size || data == NULL || size != sizeof(uint64_t)) {
|
||||
errno = EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t *val = (uint64_t *)data;
|
||||
|
||||
_lock_acquire_recursive(&s_events[fd].lock);
|
||||
if (s_events[fd].support_isr) {
|
||||
portENTER_CRITICAL(&s_events[fd].data_spin_lock);
|
||||
}
|
||||
|
||||
if (s_events[fd].fd == fd) {
|
||||
uint64_t *val = (uint64_t *)data;
|
||||
if (s_events[fd].support_isr) {
|
||||
portENTER_CRITICAL(&s_events[fd].data_spin_lock);
|
||||
}
|
||||
*val = s_events[fd].value;
|
||||
s_events[fd].is_set = false;
|
||||
ret = size;
|
||||
s_events[fd].value = 0;
|
||||
if (s_events[fd].support_isr) {
|
||||
portEXIT_CRITICAL(&s_events[fd].data_spin_lock);
|
||||
}
|
||||
} else {
|
||||
errno = EBADF;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (s_events[fd].support_isr) {
|
||||
portEXIT_CRITICAL(&s_events[fd].data_spin_lock);
|
||||
}
|
||||
_lock_release_recursive(&s_events[fd].lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -239,40 +305,55 @@ static int event_close(int fd)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
if (fd >= NUM_EVENT_FDS) {
|
||||
if (fd >= s_event_size) {
|
||||
errno = EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
_lock_acquire_recursive(&s_events[fd].lock);
|
||||
|
||||
if (s_events[fd].fd == fd) {
|
||||
if (s_events[fd].support_isr) {
|
||||
portENTER_CRITICAL(&s_events[fd].data_spin_lock);
|
||||
}
|
||||
s_events[fd].fd = FD_INVALID;
|
||||
memset(&s_events[fd].signal_sem, 0, sizeof(s_events[fd].signal_sem));
|
||||
if (s_events[fd].select_args == NULL) {
|
||||
s_events[fd].fd = FD_INVALID;
|
||||
} else {
|
||||
s_events[fd].fd = FD_PENDING_SELECT;
|
||||
trigger_select_for_event(&s_events[fd]);
|
||||
}
|
||||
s_events[fd].value = 0;
|
||||
if (s_events[fd].support_isr) {
|
||||
portEXIT_CRITICAL(&s_events[fd].data_spin_lock);
|
||||
}
|
||||
ret = 0;
|
||||
} else {
|
||||
errno = EBADF;
|
||||
}
|
||||
|
||||
_lock_release_recursive(&s_events[fd].lock);
|
||||
_lock_close_recursive(&s_events[fd].lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_vfs_eventfd_register(void)
|
||||
esp_err_t esp_vfs_eventfd_register(const esp_vfs_eventfd_config_t *config)
|
||||
{
|
||||
for (size_t i = 0; i < NUM_EVENT_FDS; i++) {
|
||||
if (config == NULL || config->eventfd_max_num >= MAX_FDS) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (s_eventfd_vfs_id != -1) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
s_event_size = config->eventfd_max_num;
|
||||
s_events = (event_context_t *)calloc(s_event_size, sizeof(event_context_t));
|
||||
for (size_t i = 0; i < s_event_size; i++) {
|
||||
_lock_init_recursive(&s_events[i].lock);
|
||||
s_events[i].fd = FD_INVALID;
|
||||
}
|
||||
|
||||
esp_vfs_t vfs = {
|
||||
.flags = ESP_VFS_FLAG_DEFAULT,
|
||||
.write = &event_write,
|
||||
.open = &event_open,
|
||||
.open = NULL,
|
||||
.fstat = NULL,
|
||||
.close = &event_close,
|
||||
.read = &event_read,
|
||||
@ -288,30 +369,52 @@ esp_err_t esp_vfs_eventfd_register(void)
|
||||
.tcflush = NULL,
|
||||
#endif // CONFIG_SUPPORT_TERMIOS
|
||||
};
|
||||
return esp_vfs_register(EVENT_VFS_PREFIX, &vfs, NULL);
|
||||
return esp_vfs_register_with_id(&vfs, NULL, &s_eventfd_vfs_id);
|
||||
}
|
||||
|
||||
esp_err_t esp_vfs_eventfd_unregister(void)
|
||||
{
|
||||
return esp_vfs_unregister(EVENT_VFS_PREFIX);
|
||||
if (s_eventfd_vfs_id == -1) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
esp_err_t error = esp_vfs_unregister_with_id(s_eventfd_vfs_id);
|
||||
if (error == ESP_OK) {
|
||||
s_eventfd_vfs_id = -1;
|
||||
}
|
||||
for (size_t i = 0; i < s_event_size; i++) {
|
||||
_lock_close_recursive(&s_events[i].lock);
|
||||
}
|
||||
free(s_events);
|
||||
return error;
|
||||
}
|
||||
|
||||
int eventfd(unsigned int initval, int flags)
|
||||
{
|
||||
int fd = FD_INVALID;
|
||||
int global_fd = FD_INVALID;
|
||||
esp_err_t error = ESP_OK;
|
||||
|
||||
if ((flags & (~EFD_SUPPORT_ISR)) != 0) {
|
||||
errno = EINVAL;
|
||||
return FD_INVALID;
|
||||
}
|
||||
if (s_eventfd_vfs_id == -1) {
|
||||
errno = EACCES;
|
||||
return FD_INVALID;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < NUM_EVENT_FDS; i++) {
|
||||
bool support_isr = flags & EFD_SUPPORT_ISR;
|
||||
bool has_allocated = false;
|
||||
|
||||
_lock_init_recursive(&s_events[i].lock);
|
||||
for (size_t i = 0; i < s_event_size; i++) {
|
||||
_lock_acquire_recursive(&s_events[i].lock);
|
||||
if (s_events[i].fd == FD_INVALID) {
|
||||
|
||||
error = esp_vfs_register_fd(s_eventfd_vfs_id, i, /*permanent=*/false, &global_fd);
|
||||
if (error != ESP_OK) {
|
||||
_lock_release_recursive(&s_events[i].lock);
|
||||
break;
|
||||
}
|
||||
|
||||
bool support_isr = flags & EFD_SUPPORT_ISR;
|
||||
fd = i;
|
||||
s_events[i].fd = i;
|
||||
s_events[i].support_isr = support_isr;
|
||||
spinlock_initialize(&s_events[i].data_spin_lock);
|
||||
@ -321,21 +424,30 @@ int eventfd(unsigned int initval, int flags)
|
||||
}
|
||||
s_events[i].is_set = false;
|
||||
s_events[i].value = initval;
|
||||
memset(&s_events[i].signal_sem, 0, sizeof(s_events[i].signal_sem));
|
||||
s_events[i].select_args = NULL;
|
||||
if (support_isr) {
|
||||
portEXIT_CRITICAL(&s_events[i].data_spin_lock);
|
||||
}
|
||||
|
||||
char fullpath[20];
|
||||
snprintf(fullpath, sizeof(fullpath), EVENT_VFS_PREFIX "/%d", s_events[i].fd);
|
||||
fd = open(fullpath, 0, 0);
|
||||
has_allocated = true;
|
||||
_lock_release_recursive(&s_events[i].lock);
|
||||
break;
|
||||
}
|
||||
_lock_release_recursive(&s_events[i].lock);
|
||||
|
||||
if (has_allocated) {
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
return FD_INVALID;
|
||||
|
||||
switch (error) {
|
||||
case ESP_OK:
|
||||
fd = global_fd;
|
||||
break;
|
||||
case ESP_ERR_NO_MEM:
|
||||
errno = ENOMEM;
|
||||
break;
|
||||
case ESP_ERR_INVALID_ARG:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
default:
|
||||
errno = EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user