diff --git a/components/vfs/test/test_vfs_eventfd.c b/components/vfs/test/test_vfs_eventfd.c index 35d2ee504f..71a02eefec 100644 --- a/components/vfs/test/test_vfs_eventfd.c +++ b/components/vfs/test/test_vfs_eventfd.c @@ -14,171 +14,242 @@ #include "esp_vfs_eventfd.h" -#include -#include +#include #include -#include "driver/periph_ctrl.h" #include "driver/timer.h" -#include "esp_err.h" -#include "esp_types.h" #include "esp_vfs.h" -#include "freertos/FreeRTOS.h" -#include "freertos/portmacro.h" -#include "freertos/projdefs.h" -#include "freertos/queue.h" -#include "freertos/task.h" -#include "hal/timer_types.h" +#include "sys/_stdint.h" #include "unity.h" -#define TIMER_DIVIDER 16 -#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) -#define TIMER_INTERVAL0_SEC (0.25) -#define TEST_WITHOUT_RELOAD 0 -#define PROGRESS_INTERVAL_MS 350 -#define TIMER_SIGNAL 1 -#define PROGRESS_SIGNAL 2 - -int s_timer_fd; -int s_progress_fd; - -/* - * A simple helper function to print the raw timer counter value - * and the counter value converted to seconds - */ -static void inline print_timer_counter(uint64_t counter_value) +TEST_CASE("Test eventfd create and close", "[vfs][eventfd]") { - printf("Counter: 0x%08x%08x\n", (uint32_t) (counter_value >> 32), - (uint32_t) (counter_value)); - printf("Time : %.8f s\n", (double) counter_value / TIMER_SCALE); + TEST_ESP_OK(esp_vfs_eventfd_register()); + int fd = eventfd(0, 0); + TEST_ASSERT_GREATER_OR_EQUAL(0, fd); + TEST_ASSERT_EQUAL(0, close(fd)); + + fd = eventfd(0, EFD_SUPPORT_ISR); + TEST_ASSERT_GREATER_OR_EQUAL(0, fd); + TEST_ASSERT_EQUAL(0, close(fd)); + TEST_ESP_OK(esp_vfs_eventfd_unregister()); } -void IRAM_ATTR timer_group0_isr(void *para) +TEST_CASE("Test eventfd reject unknown flags", "[vfs][eventfd]") { - timer_spinlock_take(TIMER_GROUP_0); - int timer_idx = (int) para; + TEST_ESP_OK(esp_vfs_eventfd_register()); + int fd = eventfd(0, 1); + TEST_ASSERT_LESS_THAN(0, fd); + TEST_ASSERT_EQUAL(EINVAL, errno); - uint32_t timer_intr = timer_group_get_intr_status_in_isr(TIMER_GROUP_0); - uint64_t timer_counter_value = timer_group_get_counter_value_in_isr(TIMER_GROUP_0, timer_idx); - - if (timer_intr & TIMER_INTR_T0) { - timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0); - timer_counter_value += (uint64_t) (TIMER_INTERVAL0_SEC * TIMER_SCALE); - timer_group_set_alarm_value_in_isr(TIMER_GROUP_0, timer_idx, timer_counter_value); - } - - timer_group_enable_alarm_in_isr(TIMER_GROUP_0, timer_idx); - - uint64_t signal = TIMER_SIGNAL; - ssize_t val = write(s_timer_fd, &signal, sizeof(signal)); - assert(val == sizeof(signal)); - timer_spinlock_give(TIMER_GROUP_0); + fd = eventfd(0, INT_MAX); + TEST_ASSERT_LESS_THAN(0, fd); + TEST_ASSERT_EQUAL(EINVAL, errno); + TEST_ESP_OK(esp_vfs_eventfd_unregister()); } -static void eventfd_timer_init(int timer_idx, double timer_interval_sec) +TEST_CASE("Test eventfd read", "[vfs][eventfd]") { + TEST_ESP_OK(esp_vfs_eventfd_register()); + unsigned int initval = 123; + int fd = eventfd(initval, 0); + TEST_ASSERT_GREATER_OR_EQUAL(0, fd); + + uint64_t val = 0; + TEST_ASSERT_EQUAL(sizeof(val), read(fd, &val, sizeof(val))); + TEST_ASSERT_EQUAL(initval, val); + TEST_ASSERT_EQUAL(sizeof(val), read(fd, &val, sizeof(val))); + TEST_ASSERT_EQUAL(0, val); + TEST_ASSERT_EQUAL(0, close(fd)); + TEST_ESP_OK(esp_vfs_eventfd_unregister()); +} + +TEST_CASE("Test eventfd read invalid size", "[vfs][eventfd]") +{ + TEST_ESP_OK(esp_vfs_eventfd_register()); + int fd = eventfd(0, 0); + TEST_ASSERT_GREATER_OR_EQUAL(0, fd); + + uint32_t val = 0; + TEST_ASSERT_LESS_THAN(0, read(fd, &val, sizeof(val))); + TEST_ASSERT_EQUAL(EINVAL, errno); + TEST_ASSERT_EQUAL(0, close(fd)); + TEST_ESP_OK(esp_vfs_eventfd_unregister()); +} + +TEST_CASE("Test eventfd write invalid size", "[vfs][eventfd]") +{ + TEST_ESP_OK(esp_vfs_eventfd_register()); + int fd = eventfd(0, 0); + TEST_ASSERT_GREATER_OR_EQUAL(0, fd); + + uint32_t val = 0; + TEST_ASSERT_LESS_THAN(0, write(fd, &val, sizeof(val))); + TEST_ASSERT_EQUAL(EINVAL, errno); + TEST_ASSERT_EQUAL(0, close(fd)); + TEST_ESP_OK(esp_vfs_eventfd_unregister()); +} + +TEST_CASE("Test eventfd write then read", "[vfs][eventfd]") +{ + TEST_ESP_OK(esp_vfs_eventfd_register()); + int fd = eventfd(0, 0); + TEST_ASSERT_GREATER_OR_EQUAL(0, fd); + + uint64_t val = 123; + TEST_ASSERT_EQUAL(sizeof(val), write(fd, &val, sizeof(val))); + TEST_ASSERT_EQUAL(sizeof(val), read(fd, &val, sizeof(val))); + TEST_ASSERT_EQUAL(123, val); + val = 4; + TEST_ASSERT_EQUAL(sizeof(val), write(fd, &val, sizeof(val))); + val = 5; + TEST_ASSERT_EQUAL(sizeof(val), write(fd, &val, sizeof(val))); + TEST_ASSERT_EQUAL(sizeof(val), read(fd, &val, sizeof(val))); + TEST_ASSERT_EQUAL(9, val); + TEST_ASSERT_EQUAL(0, close(fd)); + TEST_ESP_OK(esp_vfs_eventfd_unregister()); +} + +TEST_CASE("Test eventfd instant select", "[vfs][eventfd]") +{ + TEST_ESP_OK(esp_vfs_eventfd_register()); + int fd = eventfd(0, 0); + TEST_ASSERT_GREATER_OR_EQUAL(0, fd); + + struct timeval zero_time; + fd_set read_fds, write_fds, error_fds; + + zero_time.tv_sec = 0; + zero_time.tv_usec = 0; + + FD_ZERO(&read_fds); + FD_ZERO(&write_fds); + FD_ZERO(&error_fds); + FD_SET(fd, &read_fds); + 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); + 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)); + + 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_ESP_OK(esp_vfs_eventfd_unregister()); +} + +static void signal_task(void *arg) +{ + int fd = *((int *)arg); + vTaskDelay(pdMS_TO_TICKS(1000)); + uint64_t val = 1; + TEST_ASSERT_EQUAL(sizeof(val), write(fd, &val, sizeof(val))); + vTaskDelete(NULL); +} + +TEST_CASE("Test 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); + + xTaskCreate(signal_task, "signal_task", 2048, &fd, 5, NULL); + struct timeval wait_time; + struct timeval zero_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); + 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); + TEST_ASSERT_EQUAL(1, ret); + TEST_ASSERT(FD_ISSET(fd, &read_fds)); + + 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)); + + 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_ESP_OK(esp_vfs_eventfd_unregister()); +} + +static void IRAM_ATTR eventfd_select_test_isr(void *arg) +{ + int fd = *((int *)arg); + uint64_t val = 1; + timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0); + int ret = write(fd, &val, sizeof(val)); + assert(ret == sizeof(val)); +} + +TEST_CASE("Test eventfd signal from ISR", "[vfs][eventfd]") +{ + TEST_ESP_OK(esp_vfs_eventfd_register()); + int fd = eventfd(0, EFD_SUPPORT_ISR); + TEST_ASSERT_GREATER_OR_EQUAL(0, fd); + timer_config_t config = { - .divider = TIMER_DIVIDER, + .divider = 16, .counter_dir = TIMER_COUNT_UP, .counter_en = TIMER_PAUSE, .alarm_en = TIMER_ALARM_EN, .auto_reload = false, }; - timer_init(TIMER_GROUP_0, timer_idx, &config); + TEST_ESP_OK(timer_init(TIMER_GROUP_0, TIMER_0, &config)); - timer_set_counter_value(TIMER_GROUP_0, timer_idx, 0x00000000ULL); + TEST_ESP_OK(timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0x00000000ULL)); - timer_set_alarm_value(TIMER_GROUP_0, timer_idx, timer_interval_sec * TIMER_SCALE); - timer_enable_intr(TIMER_GROUP_0, timer_idx); - timer_isr_register(TIMER_GROUP_0, timer_idx, timer_group0_isr, - (void *) timer_idx, ESP_INTR_FLAG_IRAM, NULL); + TEST_ESP_OK(timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, TIMER_BASE_CLK / 16)); + TEST_ESP_OK(timer_enable_intr(TIMER_GROUP_0, TIMER_0)); + TEST_ESP_OK(timer_isr_register(TIMER_GROUP_0, TIMER_0, eventfd_select_test_isr, + &fd, ESP_INTR_FLAG_IRAM, NULL)); + TEST_ESP_OK(timer_start(TIMER_GROUP_0, TIMER_0)); - timer_start(TIMER_GROUP_0, timer_idx); -} + 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); + wait_time.tv_sec = 2; + wait_time.tv_usec = 0; -static void eventfd_timer_deinit(int timer_idx) -{ - timer_pause(TIMER_GROUP_0, timer_idx); - timer_deinit(TIMER_GROUP_0, timer_idx); -} - -static void worker_task(void *arg) -{ - for (int i = 0; i < 3; i++) { - vTaskDelay(pdMS_TO_TICKS(PROGRESS_INTERVAL_MS)); - uint64_t signal = PROGRESS_SIGNAL; - ssize_t val = write(s_progress_fd, &signal, sizeof(signal)); - assert(val == sizeof(signal)); - } - vTaskDelete(NULL); -} - -TEST_CASE("Test eventfd triggered correctly", "[vfs][eventfd]") -{ - xTaskCreate(worker_task, "worker_task", 1024, NULL, 5, NULL); - TEST_ESP_OK(esp_vfs_eventfd_register()); - 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; - printf("Timer fd %d progress fd %d\n", s_timer_fd, s_progress_fd); - eventfd_timer_init(TIMER_0, TIMER_INTERVAL0_SEC); - - int selectTimeoutCount = 0; - int timerTriggerCount = 0; - int progressTriggerCount = 0; - - for (size_t i = 0; i < 10; i++) { - struct timeval timeout; - uint64_t signal; - - timeout.tv_sec = 0; - timeout.tv_usec = 200 * 1000; - - fd_set readfds; - fd_set writefds; - fd_set errorfds; - - FD_ZERO(&readfds); - FD_ZERO(&writefds); - FD_ZERO(&errorfds); - - FD_SET(s_timer_fd, &readfds); - FD_SET(s_progress_fd, &readfds); - - select(maxFd + 1, &readfds, &writefds, &errorfds, &timeout); - - printf("-------- TASK TIME --------\n"); - uint64_t task_counter_value; - timer_get_counter_value(TIMER_GROUP_0, TIMER_0, &task_counter_value); - print_timer_counter(task_counter_value); - - if (FD_ISSET(s_progress_fd, &readfds)) { - ssize_t ret = read(s_progress_fd, &signal, sizeof(signal)); - TEST_ASSERT(ret == sizeof(signal)); - TEST_ASSERT(signal == PROGRESS_SIGNAL); - progressTriggerCount++; - printf("Progress fd\n"); - } else if (FD_ISSET(s_timer_fd, &readfds)) { - ssize_t ret = read(s_timer_fd, &signal, sizeof(signal)); - TEST_ASSERT(ret == sizeof(signal)); - TEST_ASSERT(signal == TIMER_SIGNAL); - timerTriggerCount++; - printf("TimerEvent fd\n"); - } else { - selectTimeoutCount++; - printf("Select timeout\n"); - } - } - - printf("Select timeout: %d\n", selectTimeoutCount); - printf("Timer trigger: %d\n", timerTriggerCount); - printf("Progress trigger: %d\n", progressTriggerCount); - TEST_ASSERT(selectTimeoutCount == 3); - TEST_ASSERT(timerTriggerCount == 4); - TEST_ASSERT(progressTriggerCount == 3); - printf("Test done\n"); - close(s_progress_fd); - close(s_timer_fd); - eventfd_timer_deinit(TIMER_0); + FD_SET(fd, &read_fds); + int ret = select(fd + 1, &read_fds, &write_fds, &error_fds, &wait_time); + TEST_ASSERT_EQUAL(1, ret); + TEST_ASSERT(FD_ISSET(fd, &read_fds)); + timer_deinit(TIMER_GROUP_0, TIMER_0); TEST_ESP_OK(esp_vfs_eventfd_unregister()); } diff --git a/components/vfs/test/test_vfs_eventfd_integration.c b/components/vfs/test/test_vfs_eventfd_integration.c new file mode 100644 index 0000000000..4e59822127 --- /dev/null +++ b/components/vfs/test/test_vfs_eventfd_integration.c @@ -0,0 +1,183 @@ +// Copyright 2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License + +#include "esp_vfs_eventfd.h" + +#include +#include +#include + +#include "driver/periph_ctrl.h" +#include "driver/timer.h" +#include "esp_err.h" +#include "esp_types.h" +#include "esp_vfs.h" +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/task.h" +#include "hal/timer_types.h" +#include "unity.h" + +#define TIMER_DIVIDER 16 +#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) +#define TIMER_INTERVAL0_SEC (0.25) +#define TEST_WITHOUT_RELOAD 0 +#define PROGRESS_INTERVAL_MS 350 +#define TIMER_SIGNAL 1 +#define PROGRESS_SIGNAL 2 + +int s_timer_fd; +int s_progress_fd; + +/* + * A simple helper function to print the raw timer counter value + * and the counter value converted to seconds + */ +static void inline print_timer_counter(uint64_t counter_value) +{ + printf("Counter: 0x%08x%08x\n", (uint32_t) (counter_value >> 32), + (uint32_t) (counter_value)); + printf("Time : %.8f s\n", (double) counter_value / TIMER_SCALE); +} + +static void IRAM_ATTR eventfd_timer_group0_isr(void *para) +{ + timer_spinlock_take(TIMER_GROUP_0); + int timer_idx = (int) para; + + uint32_t timer_intr = timer_group_get_intr_status_in_isr(TIMER_GROUP_0); + uint64_t timer_counter_value = timer_group_get_counter_value_in_isr(TIMER_GROUP_0, timer_idx); + + if (timer_intr & TIMER_INTR_T0) { + timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0); + timer_counter_value += (uint64_t) (TIMER_INTERVAL0_SEC * TIMER_SCALE); + timer_group_set_alarm_value_in_isr(TIMER_GROUP_0, timer_idx, timer_counter_value); + } + + timer_group_enable_alarm_in_isr(TIMER_GROUP_0, timer_idx); + + uint64_t signal = TIMER_SIGNAL; + ssize_t val = write(s_timer_fd, &signal, sizeof(signal)); + assert(val == sizeof(signal)); + timer_spinlock_give(TIMER_GROUP_0); +} + +static void eventfd_timer_init(int timer_idx, double timer_interval_sec) +{ + timer_config_t config = { + .divider = TIMER_DIVIDER, + .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_idx, &config)); + + TEST_ESP_OK(timer_set_counter_value(TIMER_GROUP_0, timer_idx, 0x00000000ULL)); + + TEST_ESP_OK(timer_set_alarm_value(TIMER_GROUP_0, timer_idx, timer_interval_sec * TIMER_SCALE)); + TEST_ESP_OK(timer_enable_intr(TIMER_GROUP_0, timer_idx)); + TEST_ESP_OK(timer_isr_register(TIMER_GROUP_0, timer_idx, eventfd_timer_group0_isr, + (void *) timer_idx, ESP_INTR_FLAG_IRAM, NULL)); + + TEST_ESP_OK(timer_start(TIMER_GROUP_0, timer_idx)); +} + +static void eventfd_timer_deinit(int timer_idx) +{ + timer_pause(TIMER_GROUP_0, timer_idx); + timer_deinit(TIMER_GROUP_0, timer_idx); +} + +static void worker_task(void *arg) +{ + for (int i = 0; i < 3; i++) { + vTaskDelay(pdMS_TO_TICKS(PROGRESS_INTERVAL_MS)); + uint64_t signal = PROGRESS_SIGNAL; + ssize_t val = write(s_progress_fd, &signal, sizeof(signal)); + assert(val == sizeof(signal)); + } + vTaskDelete(NULL); +} + +TEST_CASE("Test eventfd triggered correctly", "[vfs][eventfd]") +{ + xTaskCreate(worker_task, "worker_task", 1024, NULL, 5, NULL); + TEST_ESP_OK(esp_vfs_eventfd_register()); + 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; + printf("Timer fd %d progress fd %d\n", s_timer_fd, s_progress_fd); + TEST_ASSERT_GREATER_OR_EQUAL(0, s_timer_fd); + TEST_ASSERT_GREATER_OR_EQUAL(0, s_progress_fd); + eventfd_timer_init(TIMER_0, TIMER_INTERVAL0_SEC); + + int select_timeout_count = 0; + int timer_trigger_count = 0; + int progress_trigger_count = 0; + + for (size_t i = 0; i < 10; i++) { + struct timeval timeout; + uint64_t signal; + + timeout.tv_sec = 0; + timeout.tv_usec = 200 * 1000; + + fd_set readfds; + fd_set writefds; + fd_set errorfds; + + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_ZERO(&errorfds); + + FD_SET(s_timer_fd, &readfds); + FD_SET(s_progress_fd, &readfds); + + select(maxFd + 1, &readfds, &writefds, &errorfds, &timeout); + + printf("-------- TASK TIME --------\n"); + uint64_t task_counter_value; + TEST_ESP_OK(timer_get_counter_value(TIMER_GROUP_0, TIMER_0, &task_counter_value)); + print_timer_counter(task_counter_value); + + if (FD_ISSET(s_progress_fd, &readfds)) { + ssize_t ret = read(s_progress_fd, &signal, sizeof(signal)); + TEST_ASSERT_EQUAL(ret, sizeof(signal)); + TEST_ASSERT_EQUAL(signal, PROGRESS_SIGNAL); + progress_trigger_count++; + printf("Progress fd\n"); + } else if (FD_ISSET(s_timer_fd, &readfds)) { + ssize_t ret = read(s_timer_fd, &signal, sizeof(signal)); + TEST_ASSERT(ret == sizeof(signal)); + TEST_ASSERT(signal == TIMER_SIGNAL); + timer_trigger_count++; + printf("TimerEvent fd\n"); + } else { + select_timeout_count++; + printf("Select timeout\n"); + } + } + + printf("Select timeout: %d\n", select_timeout_count); + printf("Timer trigger: %d\n", timer_trigger_count); + printf("Progress trigger: %d\n", progress_trigger_count); + TEST_ASSERT_EQUAL(3, select_timeout_count); + TEST_ASSERT_EQUAL(4, timer_trigger_count); + TEST_ASSERT_EQUAL(3, progress_trigger_count); + TEST_ASSERT_EQUAL(0, close(s_progress_fd)); + TEST_ASSERT_EQUAL(0, close(s_timer_fd)); + eventfd_timer_deinit(TIMER_0); + TEST_ESP_OK(esp_vfs_eventfd_unregister()); +} diff --git a/components/vfs/vfs_eventfd.c b/components/vfs/vfs_eventfd.c index 65f4d35a52..3aadda17df 100644 --- a/components/vfs/vfs_eventfd.c +++ b/components/vfs/vfs_eventfd.c @@ -15,6 +15,7 @@ #include "esp_vfs_eventfd.h" +#include #include #include #include @@ -59,7 +60,7 @@ static esp_err_t event_start_select(int nfds, _lock_acquire_recursive(&s_events[i].lock); int fd = s_events[i].fd; - if (fd != FD_INVALID) { + if (fd != FD_INVALID && fd < nfds) { if (s_events[i].support_isr) { portENTER_CRITICAL(&s_events[i].data_spin_lock); } @@ -76,7 +77,6 @@ static esp_err_t event_start_select(int nfds, if (FD_ISSET(fd, readfds)) { s_events[i].read_fds = readfds; if (s_events[i].is_set) { - s_events[i].is_set = false; should_trigger = true; } else { FD_CLR(fd, readfds); @@ -108,7 +108,6 @@ static esp_err_t event_end_select(void *end_select_args) 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].is_set = false; s_events[i].read_fds = NULL; } if (s_events[i].write_fds) { @@ -145,7 +144,7 @@ static int event_open(const char *path, int flags, int mode) } -ssize_t esp_signal_event_fd_from_isr(int fd, const void *data, size_t size) +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; @@ -171,14 +170,16 @@ 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)) { + errno = EINVAL; return ret; } if (size != sizeof(uint64_t)) { + errno = EINVAL; return ret; } if (xPortInIsrContext()) { - ret = esp_signal_event_fd_from_isr(fd, data, 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); @@ -206,9 +207,11 @@ 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)) { + errno = EINVAL; return ret; } @@ -220,6 +223,7 @@ static ssize_t event_read(int fd, void *data, size_t size) 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) { @@ -255,7 +259,7 @@ static int event_close(int fd) } _lock_release_recursive(&s_events[fd].lock); - _lock_close(&s_events[fd].lock); + _lock_close_recursive(&s_events[fd].lock); return ret; } @@ -294,12 +298,18 @@ esp_err_t esp_vfs_eventfd_unregister(void) int eventfd(unsigned int initval, int flags) { - int fd = -1; + int fd = FD_INVALID; + + if ((flags & (~EFD_SUPPORT_ISR)) != 0) { + errno = EINVAL; + 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); _lock_acquire_recursive(&s_events[i].lock); if (s_events[i].fd == FD_INVALID) { s_events[i].fd = i; @@ -327,5 +337,5 @@ int eventfd(unsigned int initval, int flags) return fd; } } - return -1; + return FD_INVALID; }