ESPHome 2026.3.0
Loading...
Searching...
No Matches
lwip_fast_select.h
Go to the documentation of this file.
1#pragma once
2
3// Fast socket monitoring for ESP32 and LibreTiny (LwIP >= 2.1.3)
4// Replaces lwip_select() with direct rcvevent reads and FreeRTOS task notifications.
5
6#include <stdbool.h>
7#include <stdint.h>
8
9// Forward declare lwip_sock for C++ callers that store cached pointers.
10// The full definition is only available in the .c file (lwip/priv/sockets_priv.h
11// conflicts with C++ compilation units).
12struct lwip_sock;
13
14// Byte offset of rcvevent (s16_t) within struct lwip_sock.
15// Verified at compile time in lwip_fast_select.c via _Static_assert.
16// Anonymous enum for a compile-time constant that works in both C and C++.
18
19#ifdef __cplusplus
20extern "C" {
21#endif
22
26
30struct lwip_sock *esphome_lwip_get_sock(int fd);
31
44static inline bool esphome_lwip_socket_has_data(struct lwip_sock *sock) {
45 // Unlocked hint read — no lwIP core lock needed.
46 // volatile prevents the compiler from caching/reordering this cross-thread read.
47 // The write side (TCP/IP thread) commits via SYS_ARCH_UNPROTECT which releases a
48 // FreeRTOS mutex (ESP32) or resumes the scheduler (LibreTiny), ensuring the value
49 // is visible. Aligned 16-bit reads are single-instruction loads (L16SI/LH/LDRH) on
50 // Xtensa/RISC-V/ARM and cannot produce torn values.
51 return *(volatile int16_t *) ((char *) sock + (int) ESPHOME_LWIP_SOCK_RCVEVENT_OFFSET) > 0;
52}
53
58void esphome_lwip_hook_socket(struct lwip_sock *sock);
59
63
67void esphome_lwip_wake_main_loop_from_isr(int *px_higher_priority_task_woken);
68
74bool esphome_lwip_set_nodelay(struct lwip_sock *sock, bool enable);
75
79#ifdef USE_ESP32
81#endif
82
83#ifdef __cplusplus
84}
85#endif
@ ESPHOME_LWIP_SOCK_RCVEVENT_OFFSET
void esphome_lwip_fast_select_init(void)
Initialize fast select — must be called from the main loop task during setup().
void esphome_lwip_wake_main_loop_any_context(void)
Wake the main loop task from any context (ISR, thread, or main loop).
bool esphome_lwip_set_nodelay(struct lwip_sock *sock, bool enable)
Set or clear TCP_NODELAY on a socket's tcp_pcb directly.
void esphome_lwip_hook_socket(struct lwip_sock *sock)
Hook a socket's netconn callback to notify the main loop task on receive events.
struct lwip_sock * esphome_lwip_get_sock(int fd)
Look up a LwIP socket struct from a file descriptor.
void esphome_lwip_wake_main_loop_from_isr(int *px_higher_priority_task_woken)
Wake the main loop task from an ISR — costs <1 us.
void esphome_lwip_wake_main_loop(void)
Wake the main loop task from another FreeRTOS task — costs <1 us.