esp-idf/components/freertos/esp_additions/arch/linux/FreeRTOSSimulator_wrappers.c

52 wiersze
1.7 KiB
C

/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <pthread.h>
#include "esp_err.h"
#include "errno.h"
/** This module addresses the FreeRTOS simulator's coexistence with linux system calls from user apps.
* It's only included when building without lwIP, so we need to use linux system's select() which would receive
* EINTR event on every FreeRTOS interrupt; we workaround this problem by wrapping select()
* to bypass and silence these events.
*/
extern int __real_select (int fd, fd_set * rfds, fd_set * wfds, fd_set *efds, struct timeval *tval);
static inline int64_t get_us(void)
{
struct timespec spec;
clock_gettime(CLOCK_REALTIME, &spec);
return spec.tv_nsec / 1000 + spec.tv_sec * 1000000;
}
int __wrap_select (int fd, fd_set * rfds, fd_set * wfds, fd_set *efds, struct timeval *tval)
{
int ret;
struct timeval *tv = tval;
int64_t start = 0;
int64_t timeout_us = 0;
if (tv != NULL) {
start = get_us();
timeout_us = tval->tv_sec * 1000000 + tval->tv_usec;
struct timeval timeval_local = { .tv_sec = tval->tv_sec, .tv_usec = tval->tv_usec };
tv = &timeval_local; // this (tv != NULL) indicates that we should handle timeouts
}
while ((ret = __real_select(fd, rfds, wfds, efds, tv)) < 0 && errno == EINTR) {
if (tv != NULL) {
int64_t now = get_us();
timeout_us -= now - start;
if (timeout_us < 0) {
errno = 0;
ret = 0;
break;
}
start = now;
tv->tv_usec = timeout_us % 1000000;
tv->tv_sec = timeout_us / 1000000;
}
}
return ret;
}