prefetch() has always been a no-op stub in this header so calling it buys nothing at runtime. Drop all call sites and remove the now-dead stub itself.
The macro was copied over from the Linux kernel, where prefetch() is a real, arch-specific cache prefetch hint; here it never was anything but an empty inline function.
llist_for_each_entry() and its variants terminate by comparing &pos->member against head. Once a full traversal reaches the end of a non-empty list (or the list is empty to begin with), pos becomes a pure container_of()-computed sentinel address that was never a real object of typeof(*pos), only ever the plain 'struct llist_head *' passed in as head. Forming 'pos->member' on that address requires pos to satisfy the alignment of typeof(*pos), which the sentinel does not necessarily provide (e.g. embedded struct osmo_timer_list/gprs_nsvc on 32-bit ARM with a 64-bit time_t need 8-byte alignment, while head itself is only pointer-aligned) - tripping -fsanitize=alignment even though no real object is ever misaligned or dereferenced.
Add __llist_member(), computing the same address via 'char *' pointer arithmetic and an explicit cast to 'struct llist_head *', which carries no alignment requirement of its own. Use it for the loop termination check, the "next" pointer computation, and the prefetch() calls (dereferencing the returned struct llist_head * still only requires pointer alignment, so prefetch() keeps working exactly as before without reintroducing the false positive).
llist_for_each_entry() and its variants terminate by comparing &pos->member against head. Once a full traversal reaches the end of a non-empty list (or the list is empty to begin with), pos becomes a pure container_of()-computed sentinel address that was never a real object of typeof(*pos), only ever the plain 'struct llist_head *' passed in as head. Forming 'pos->member' on that address requires pos to satisfy the alignment of typeof(*pos), which the sentinel does not necessarily provide (e.g. embedded struct osmo_timer_list/gprs_nsvc on 32-bit ARM with a 64-bit time_t need 8-byte alignment, while head itself is only pointer-aligned) - tripping -fsanitize=alignment even though no real object is ever misaligned or dereferenced.
Add __llist_member(), computing the same address via 'char *' pointer arithmetic and an explicit cast to 'struct llist_head *', which carries no alignment requirement of its own. Use it for the loop termination check, the "next" pointer computation, and the prefetch() calls (dereferencing the returned struct llist_head * still only requires pointer alignment, so prefetch() keeps working exactly as before without reintroducing the false positive).
prefetch() has always been a no-op stub in this header so calling it buys nothing at runtime. Drop all call sites and remove the now-dead stub itself.
The macro was copied over from the Linux kernel, where prefetch() is a real, arch-specific cache prefetch hint; here it never was anything but an empty inline function.
osmo_io: add osmo_iofd_flush() to transmit the pending Tx queue
osmo_iofd_write_msgb() and friends only enqueue the given message; the actual transmission happens asynchronously from within osmo_select_main(). An application that needs to say 'goodbye' right before calling osmo_iofd_free() (think of a connection teardown datagram, like TRXC "CMD POWEROFF") currently has no way to do so reliably: osmo_iofd_free() discards the Tx queue, so a message enqueued in the same event loop iteration never reaches the socket.
Add osmo_iofd_flush(), which synchronously transmits the pending Tx queue, stopping on -EAGAIN or other errors. Only the poll backend implements it for now; the io_uring backend returns -ENOTSUP, since in-flight SQE submissions make a synchronous flush non-trivial there.