kopia lustrzana https://github.com/espressif/esp-idf
vfs: add eventfd support
eventfd imitates the behavior of POSIX api `man(2) eventfd`. This api can be used to pass events to a select based message loop.pull/6974/head
rodzic
ab831ee9bf
commit
f6fd2eb164
|
@ -1,4 +1,5 @@
|
|||
idf_component_register(SRCS "vfs.c"
|
||||
"vfs_eventfd.c"
|
||||
"vfs_uart.c"
|
||||
"vfs_semihost.c"
|
||||
INCLUDE_DIRS include)
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
// 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
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
#define EFD_SUPPORT_ISR (1 << 4)
|
||||
#define EVENT_VFS_PREFIX "/dev/event"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @brief Unregisters the event vfs.
|
||||
*
|
||||
* @return ESP_OK if successful, ESP_ERR_INVALID_STATE if VFS for given prefix
|
||||
* hasn't been registered
|
||||
*/
|
||||
esp_err_t esp_vfs_eventfd_unregister(void);
|
||||
|
||||
/*
|
||||
* @brief Creates an event file descirptor.
|
||||
*
|
||||
* The behavior of read, write and select is the same as man(2) eventfd with
|
||||
* EFD_SEMAPHORE **NOT** specified. A new flag EFD_SUPPORT_ISR has been added.
|
||||
* This flag is required to write to event fds in interrupt handlers. Accessing
|
||||
* the control blocks of event fds with EFD_SUPPORT_ISR will cause interrupts to
|
||||
* be temporarily blocked (e.g. during read, write and beginning and ending of
|
||||
* the * select).
|
||||
*
|
||||
* @return The file descriptor if successful, -1 if error happens.
|
||||
*/
|
||||
int eventfd(unsigned int initval, int flags);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,184 @@
|
|||
// 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 <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#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 "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);
|
||||
}
|
||||
|
||||
void IRAM_ATTR 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,
|
||||
};
|
||||
timer_init(TIMER_GROUP_0, timer_idx, &config);
|
||||
|
||||
timer_set_counter_value(TIMER_GROUP_0, timer_idx, 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);
|
||||
|
||||
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);
|
||||
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);
|
||||
TEST_ESP_OK(esp_vfs_eventfd_unregister());
|
||||
}
|
|
@ -0,0 +1,331 @@
|
|||
// 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 <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_vfs.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "soc/spinlock.h"
|
||||
|
||||
#define FD_INVALID -1
|
||||
#define NUM_EVENT_FDS 5
|
||||
|
||||
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;
|
||||
_lock_t lock;
|
||||
spinlock_t data_spin_lock; // only for event fds that support ISR.
|
||||
} Event;
|
||||
|
||||
static Event s_events[NUM_EVENT_FDS];
|
||||
|
||||
static esp_err_t event_start_select(int nfds,
|
||||
fd_set *readfds,
|
||||
fd_set *writefds,
|
||||
fd_set *exceptfds,
|
||||
esp_vfs_select_sem_t signal_sem,
|
||||
void **end_select_args)
|
||||
{
|
||||
esp_err_t error = ESP_OK;
|
||||
bool should_trigger = false;
|
||||
|
||||
for (size_t i = 0; i < NUM_EVENT_FDS; i++) {
|
||||
_lock_acquire_recursive(&s_events[i].lock);
|
||||
int fd = s_events[i].fd;
|
||||
|
||||
if (fd != FD_INVALID) {
|
||||
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 fds are always writable
|
||||
if (FD_ISSET(fd, writefds)) {
|
||||
s_events[i].write_fds = writefds;
|
||||
should_trigger = true;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (s_events[i].support_isr) {
|
||||
portEXIT_CRITICAL(&s_events[i].data_spin_lock);
|
||||
}
|
||||
|
||||
}
|
||||
_lock_release_recursive(&s_events[i].lock);
|
||||
}
|
||||
|
||||
if (should_trigger) {
|
||||
esp_vfs_select_triggered(signal_sem);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
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].is_set = false;
|
||||
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;
|
||||
}
|
||||
|
||||
if (s_events[i].support_isr) {
|
||||
portEXIT_CRITICAL(&s_events[i].data_spin_lock);
|
||||
}
|
||||
_lock_release_recursive(&s_events[i].lock);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
ssize_t esp_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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
portEXIT_CRITICAL_ISR(&s_events[fd].data_spin_lock);
|
||||
|
||||
if (task_woken) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
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)) {
|
||||
return ret;
|
||||
}
|
||||
if (size != sizeof(uint64_t)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (xPortInIsrContext()) {
|
||||
ret = esp_signal_event_fd_from_isr(fd, data, size);
|
||||
} else {
|
||||
const uint64_t *val = (const uint64_t *)data;
|
||||
_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);
|
||||
}
|
||||
|
||||
_lock_release_recursive(&s_events[fd].lock);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t event_read(int fd, void *data, size_t size)
|
||||
{
|
||||
ssize_t ret = -1;
|
||||
|
||||
if (fd >= NUM_EVENT_FDS) {
|
||||
return ret;
|
||||
}
|
||||
if (size != sizeof(uint64_t)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
_lock_acquire_recursive(&s_events[fd].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;
|
||||
ret = size;
|
||||
s_events[fd].value = 0;
|
||||
if (s_events[fd].support_isr) {
|
||||
portEXIT_CRITICAL(&s_events[fd].data_spin_lock);
|
||||
}
|
||||
}
|
||||
|
||||
_lock_release_recursive(&s_events[fd].lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int event_close(int fd)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
if (fd >= NUM_EVENT_FDS) {
|
||||
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));
|
||||
s_events[fd].value = 0;
|
||||
if (s_events[fd].support_isr) {
|
||||
portEXIT_CRITICAL(&s_events[fd].data_spin_lock);
|
||||
}
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
_lock_release_recursive(&s_events[fd].lock);
|
||||
_lock_close(&s_events[fd].lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_vfs_eventfd_register(void)
|
||||
{
|
||||
for (size_t i = 0; i < NUM_EVENT_FDS; i++) {
|
||||
s_events[i].fd = FD_INVALID;
|
||||
}
|
||||
|
||||
esp_vfs_t vfs = {
|
||||
.flags = ESP_VFS_FLAG_DEFAULT,
|
||||
.write = &event_write,
|
||||
.open = &event_open,
|
||||
.fstat = NULL,
|
||||
.close = &event_close,
|
||||
.read = &event_read,
|
||||
.fcntl = NULL,
|
||||
.fsync = NULL,
|
||||
.access = NULL,
|
||||
.start_select = &event_start_select,
|
||||
.end_select = &event_end_select,
|
||||
#ifdef CONFIG_SUPPORT_TERMIOS
|
||||
.tcsetattr = NULL,
|
||||
.tcgetattr = NULL,
|
||||
.tcdrain = NULL,
|
||||
.tcflush = NULL,
|
||||
#endif // CONFIG_SUPPORT_TERMIOS
|
||||
};
|
||||
return esp_vfs_register(EVENT_VFS_PREFIX, &vfs, NULL);
|
||||
}
|
||||
|
||||
esp_err_t esp_vfs_eventfd_unregister(void)
|
||||
{
|
||||
return esp_vfs_unregister(EVENT_VFS_PREFIX);
|
||||
}
|
||||
|
||||
int eventfd(unsigned int initval, int flags)
|
||||
{
|
||||
int fd = -1;
|
||||
|
||||
for (size_t i = 0; i < NUM_EVENT_FDS; i++) {
|
||||
bool support_isr = flags & EFD_SUPPORT_ISR;
|
||||
bool has_allocated = false;
|
||||
|
||||
_lock_acquire_recursive(&s_events[i].lock);
|
||||
if (s_events[i].fd == FD_INVALID) {
|
||||
s_events[i].fd = i;
|
||||
s_events[i].support_isr = support_isr;
|
||||
spinlock_initialize(&s_events[i].data_spin_lock);
|
||||
|
||||
if (support_isr) {
|
||||
portENTER_CRITICAL(&s_events[i].data_spin_lock);
|
||||
}
|
||||
s_events[i].is_set = false;
|
||||
s_events[i].value = initval;
|
||||
memset(&s_events[i].signal_sem, 0, sizeof(s_events[i].signal_sem));
|
||||
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);
|
||||
|
||||
if (has_allocated) {
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
Ładowanie…
Reference in New Issue