37#define _DARWIN_C_SOURCE
45 fd_set *writefds, fd_set *exceptfds,
46 long long deadline_nsec)
57#if OPENMRN_FEATURE_DEVICE_SELECT
67#if OPENMRN_FEATURE_DEVICE_SELECT
75#elif OPENMRN_HAVE_PSELECT
76 struct timespec timeout;
77 timeout.tv_sec = deadline_nsec / 1000000000;
78 timeout.tv_nsec = deadline_nsec % 1000000000;
80 ::pselect(nfds, readfds, writefds, exceptfds, &timeout, &origMask_);
81#elif OPENMRN_HAVE_SELECT
87 exceptfds = &newexcept;
89 FD_SET(vfsFd_, exceptfds);
95 struct timeval timeout;
97 timeout.tv_sec = (deadline_nsec / 1000) / 1000000LL;
98 timeout.tv_usec = (deadline_nsec / 1000) % 1000000LL;
100 ::select(nfds, readfds, writefds, exceptfds, &timeout);
101#elif !defined(OPENMRN_FEATURE_SINGLE_THREADED)
102 #error no select implementation in multi threaded OS.
116#include "freertos_includes.h"
118#include <esp_system.h>
122#include <sys/types.h>
126static pthread_once_t vfs_init_once = PTHREAD_ONCE_INIT;
130static pthread_key_t select_wakeup_key;
136static constexpr int WAKEUP_VFS_FD = 0;
148static esp_err_t esp_start_select(
int nfds, fd_set *readfds, fd_set *writefds,
149 fd_set *exceptfds, esp_vfs_select_sem_t signal_sem,
void **end_select_args)
154 LOG(
VERBOSE,
"esp start select %p (thr %p parent %p)", signal_sem.sem,
159 if (FD_ISSET(WAKEUP_VFS_FD, exceptfds))
161 parent->esp_start_select(readfds, writefds, exceptfds, signal_sem);
172static esp_err_t esp_end_select(
void *arg)
179 parent->esp_end_select();
186void OSSelectWakeup::esp_start_select(fd_set *readfds, fd_set *writefds,
187 fd_set *exceptfds, esp_vfs_select_sem_t signal_sem)
190 espSem_ = signal_sem;
194 exceptFds_ = exceptfds;
195 exceptFdsOrig_ = *exceptfds;
210void OSSelectWakeup::esp_end_select()
215 FD_ZERO(&exceptFdsOrig_);
220void OSSelectWakeup::esp_wakeup()
225 if (!FD_ISSET(WAKEUP_VFS_FD, &exceptFdsOrig_))
233 FD_SET(WAKEUP_VFS_FD, exceptFds_);
235 LOG(
VERBOSE,
"wakeup es %p %u", espSem_.sem, *(
unsigned*)espSem_.sem);
236 esp_vfs_select_triggered(espSem_);
241void OSSelectWakeup::esp_wakeup_from_isr()
243 BaseType_t woken = pdFALSE;
246 if (!FD_ISSET(WAKEUP_VFS_FD, &exceptFdsOrig_))
254 FD_SET(WAKEUP_VFS_FD, exceptFds_);
256 esp_vfs_select_triggered_isr(espSem_, &woken);
260 portYIELD_FROM_ISR();
264static int esp_wakeup_open(
const char * path,
int flags,
int mode)
267 return WAKEUP_VFS_FD;
270static void esp_vfs_init()
273 memset(&vfs, 0,
sizeof(vfs));
274 vfs.flags = ESP_VFS_FLAG_DEFAULT;
275 vfs.start_select = esp_start_select;
276 vfs.end_select = esp_end_select;
277 vfs.open = esp_wakeup_open;
278 ESP_ERROR_CHECK(esp_vfs_register(
"/dev/wakeup", &vfs,
nullptr));
279 HASSERT(0 == pthread_key_create(&select_wakeup_key,
nullptr));
282void OSSelectWakeup::esp_allocate_vfs_fd()
284 HASSERT(0 == pthread_once(&vfs_init_once, &esp_vfs_init));
285 vfsFd_ = ::open(
"/dev/wakeup/0", 0, 0);
287 HASSERT(0 == pthread_setspecific(select_wakeup_key,
this));
288 LOG(
VERBOSE,
"VFSALLOC wakeup fd %d (thr %p test %p)", vfsFd_,
292void OSSelectWakeup::esp_deallocate_vfs_fd()
void empty_signal_handler(int)
Signal handler that does nothing.
See OSMutexLock in os/OS.hxx.
Helper class that allows a select to be asynchronously woken up.
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, long long deadline_nsec)
Portable call to a select that can be woken up asynchronously from a different thread or an ISR conte...
bool pendingWakeup_
True if there was a wakeup call since the previous select finished.
bool inSelect_
True during the duration of a select operation.
#define LOG(level, message...)
Conditionally write a message to the logging output.
static const int VERBOSE
Loglevel that is usually not printed, reporting debugging information.
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
OS_INLINE os_thread_t os_thread_self(void)
Return a handle to the calling thread.
static int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, long long timeout)
POSIX select().
static void select_clear()
Clears the current thread's select bits.