RTE OSAdapter POSIX 0.1.0 build 41b3eb3
POSIX/Linux OAL OSAdapter for Platform_RTE
Loading...
Searching...
No Matches
rte_posix_osadapter_ipc.c File Reference

POSIX rte_ipc OSAdapter: one pipe() per channel (ADR-018 section 2.2/2.3 - a mutex+condvar ring buffer would not fit rte_ipc's 64-byte opaque storage on glibc; a pipe lets the kernel own the queue instead). More...

#include "rte/posix_osadapter/rte_posix_osadapter.h"
#include "rte_posix_osadapter_poll.h"
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <poll.h>
#include <stdbool.h>
#include <stdint.h>
#include <sys/ioctl.h>
#include <time.h>
#include <unistd.h>
Include dependency graph for rte_posix_osadapter_ipc.c:

Go to the source code of this file.

Data Structures

struct  posix_ipc_state_t

Macros

#define _GNU_SOURCE
#define POSIX_IPC_ATOMIC_MAX   ((size_t)_POSIX_PIPE_BUF)
#define POSIX_IPC_POLL_NS   1000000L
#define POSIX_IPC_NS_PER_MS   1000000L
#define POSIX_IPC_NS_PER_S   1000000000L
#define RTE_POSIX_IPC_PIPE_CAPACITY   16384U

Typedefs

typedef char posix_ipc_storage_fits_[(sizeof(posix_ipc_state_t)<=sizeof(rte_ipc_storage_t)) ? 1 :-1]

Functions

static bool compute_deadline (rte_duration_ms_t timeout_ms, struct timespec *out_deadline)
static rte_status_t read_message (int fd, uint8_t *dst, size_t size, rte_duration_ms_t timeout_ms)
static rte_status_t set_nonblocking (const int fds[2])
static rte_status_t ensure_pipe_capacity (int write_fd, size_t message_size, size_t queue_depth)
static rte_status_t try_send_once (const posix_ipc_state_t *state, const void *message)
static rte_status_t sleep_before_retry (const struct timespec *deadline)
static rte_status_t send_until_deadline (const posix_ipc_state_t *state, const void *message, rte_duration_ms_t timeout_ms)
static rte_status_t osadapter_create (rte_ipc_storage_t *storage, const rte_ipc_config_t *config, rte_ipc_handle_t *out_handle)
static rte_status_t backend_send (rte_ipc_handle_t handle, const void *message, size_t message_size, rte_duration_ms_t timeout_ms)
static rte_status_t backend_receive (rte_ipc_handle_t handle, void *out_message, size_t buffer_size, rte_duration_ms_t timeout_ms)
static rte_status_t osadapter_destroy (rte_ipc_handle_t handle)
const rte_osadapter_ipc_t * rte_posix_osadapter_ipc (void)
 The POSIX rte_ipc OSAdapter (pipe() per channel).

Variables

static const rte_osadapter_ipc_t s_posix_ipc_osadapter

Detailed Description

POSIX rte_ipc OSAdapter: one pipe() per channel (ADR-018 section 2.2/2.3 - a mutex+condvar ring buffer would not fit rte_ipc's 64-byte opaque storage on glibc; a pipe lets the kernel own the queue instead).

Bounded queue of whole messages (OSA rule R5; Platform_RTE REQ-OAL-IPC-001 "bounded, statically sized at creation", REQ-OAL-IPC-011 "TIMEOUT if the queue stays full"):

  • Every message is config->message_size bytes, at most PIPE_BUF (a larger size is refused at create with RTE_STATUS_NOT_SUPPORTED). One non-blocking write() of at most PIPE_BUF bytes to a pipe is all or nothing, so a message is queued whole or not at all, and a receive reads exactly one message.
  • send refuses while queue_depth messages are queued (counted with ioctl(FIONREAD) on the read end): it retries, sleeping at most 1 ms between tries and never past the CLOCK_MONOTONIC deadline, and returns RTE_STATUS_TIMEOUT at the deadline; timeout_ms == 0 is one try.
  • receive waits in poll() for at most min(timeout_ms, INT_MAX) ms (posix_remaining_ms(), rte_posix_osadapter_poll.h); a timeout above INT_MAX ms (about 24.8 days) ends in RTE_STATUS_TIMEOUT after INT_MAX ms.
  • create checks that the pipe holds queue_depth messages: Linux sets the pipe size and reads it back (F_SETPIPE_SZ / F_GETPIPE_SZ), other hosts compare with RTE_POSIX_IPC_PIPE_CAPACITY; too small is RTE_STATUS_RESOURCE_EXHAUSTED.

Known limit: the depth check is exact for one sender per channel. N senders racing on one channel can overshoot queue_depth by at most N-1 messages; the pipe capacity checked at create still bounds the queue (a write past it fails with EAGAIN, so that send ends in RTE_STATUS_TIMEOUT).

Definition in file rte_posix_osadapter_ipc.c.

Macro Definition Documentation

◆ _GNU_SOURCE

#define _GNU_SOURCE

Definition at line 6 of file rte_posix_osadapter_ipc.c.

◆ POSIX_IPC_ATOMIC_MAX

#define POSIX_IPC_ATOMIC_MAX   ((size_t)_POSIX_PIPE_BUF)

Local makros Largest message one write() queues whole (POSIX: a write of at most PIPE_BUF bytes is atomic).

Definition at line 58 of file rte_posix_osadapter_ipc.c.

◆ POSIX_IPC_NS_PER_MS

#define POSIX_IPC_NS_PER_MS   1000000L

Nanoseconds per millisecond.

Definition at line 62 of file rte_posix_osadapter_ipc.c.

◆ POSIX_IPC_NS_PER_S

#define POSIX_IPC_NS_PER_S   1000000000L

Nanoseconds per second.

Definition at line 63 of file rte_posix_osadapter_ipc.c.

◆ POSIX_IPC_POLL_NS

#define POSIX_IPC_POLL_NS   1000000L

Sleep between two send tries while the queue is full (1 ms).

Definition at line 61 of file rte_posix_osadapter_ipc.c.

◆ RTE_POSIX_IPC_PIPE_CAPACITY

#define RTE_POSIX_IPC_PIPE_CAPACITY   16384U

Pipe capacity in bytes this adapter assumes where the pipe size cannot be set (every non-Linux host). Default 16384: a conservative budget, not a size the kernel guarantees - XNU allocates a pipe's buffer on demand and grows it (a non-blocking macOS pipe took 65536 bytes before EAGAIN in a probe). Overridable at compile time like RTE_POSIX_MEM_ARENA_SIZE.

Definition at line 77 of file rte_posix_osadapter_ipc.c.

Typedef Documentation

◆ posix_ipc_storage_fits_

typedef char posix_ipc_storage_fits_[(sizeof(posix_ipc_state_t)<=sizeof(rte_ipc_storage_t)) ? 1 :-1]

Definition at line 90 of file rte_posix_osadapter_ipc.c.

Function Documentation

◆ backend_receive()

rte_status_t backend_receive ( rte_ipc_handle_t handle,
void * out_message,
size_t buffer_size,
rte_duration_ms_t timeout_ms )
static

REQ-OAL-IPC-012: reads exactly one message (message_size bytes) into a buffer of at least that size.

Definition at line 480 of file rte_posix_osadapter_ipc.c.

◆ backend_send()

rte_status_t backend_send ( rte_ipc_handle_t handle,
const void * message,
size_t message_size,
rte_duration_ms_t timeout_ms )
static

REQ-OAL-IPC-011: whole message only, TIMEOUT while queue_depth messages stay queued for the whole timeout.

Definition at line 458 of file rte_posix_osadapter_ipc.c.

◆ compute_deadline()

bool compute_deadline ( rte_duration_ms_t timeout_ms,
struct timespec * out_deadline )
static

Local function declarations

Local functions CLOCK_MONOTONIC now + timeout_ms; false (out_deadline unusable) if the clock cannot be read.

Definition at line 108 of file rte_posix_osadapter_ipc.c.

◆ ensure_pipe_capacity()

rte_status_t ensure_pipe_capacity ( int write_fd,
size_t message_size,
size_t queue_depth )
static

Other hosts: the pipe size cannot be set, so queue_depth messages must fit in RTE_POSIX_IPC_PIPE_CAPACITY bytes (a byte ring, no per-slot waste). The product does not overflow: create checked it.

Definition at line 271 of file rte_posix_osadapter_ipc.c.

◆ osadapter_create()

rte_status_t osadapter_create ( rte_ipc_storage_t * storage,
const rte_ipc_config_t * config,
rte_ipc_handle_t * out_handle )
static

OSAdapter vtable functions REQ-OAL-IPC-001/010: bounded queue of queue_depth whole messages; *out_handle unwritten on error.

Definition at line 407 of file rte_posix_osadapter_ipc.c.

◆ osadapter_destroy()

rte_status_t osadapter_destroy ( rte_ipc_handle_t handle)
static

Definition at line 501 of file rte_posix_osadapter_ipc.c.

◆ read_message()

rte_status_t read_message ( int fd,
uint8_t * dst,
size_t size,
rte_duration_ms_t timeout_ms )
static

Poll-then-read loop until size bytes (one whole message) are read or the deadline passes. A writer queues a message with one atomic write(), so once poll() reports data the whole message is there.

Definition at line 132 of file rte_posix_osadapter_ipc.c.

◆ rte_posix_osadapter_ipc()

const rte_osadapter_ipc_t * rte_posix_osadapter_ipc ( void )

The POSIX rte_ipc OSAdapter (pipe() per channel).

Global functions

A bounded queue of whole messages (OSA rule R5). create returns RTE_STATUS_NOT_SUPPORTED for a message_size above PIPE_BUF (4096 on Linux, 512 on macOS), RTE_STATUS_INVALID_PARAM if message_size * queue_depth overflows, RTE_STATUS_RESOURCE_EXHAUSTED if the pipe cannot hold queue_depth messages (Linux: the pipe size set and read back; other hosts: RTE_POSIX_IPC_PIPE_CAPACITY, default 16384 bytes) and RTE_STATUS_INTERNAL_ERROR if a pipe end cannot be made non-blocking; on every error *out_handle is unwritten. send takes exactly message_size bytes (else RTE_STATUS_INVALID_PARAM) and returns RTE_STATUS_TIMEOUT while queue_depth messages stay queued for the whole timeout (exact for one sender per channel; N concurrent senders can overshoot by N-1). receive needs a buffer of at least message_size bytes (else RTE_STATUS_INVALID_PARAM) and reads exactly one message.

Returns
Pointer to the static IPC OSAdapter vtable; never NULL.

Definition at line 519 of file rte_posix_osadapter_ipc.c.

◆ send_until_deadline()

rte_status_t send_until_deadline ( const posix_ipc_state_t * state,
const void * message,
rte_duration_ms_t timeout_ms )
static

Send tries until one succeeds, fails, or the deadline passes. timeout_ms == 0 is one try: the deadline is already reached after it.

Definition at line 367 of file rte_posix_osadapter_ipc.c.

◆ set_nonblocking()

rte_status_t set_nonblocking ( const int fds[2])
static

O_NONBLOCK on both pipe ends, each fcntl() result checked.

Definition at line 201 of file rte_posix_osadapter_ipc.c.

◆ sleep_before_retry()

rte_status_t sleep_before_retry ( const struct timespec * deadline)
static

Sleeps before the next send try: at most POSIX_IPC_POLL_NS and never past the deadline. RTE_STATUS_OK after a sleep, RTE_STATUS_TIMEOUT once the deadline is reached, RTE_STATUS_INTERNAL_ERROR if the clock cannot be read (never wait unbounded).

Definition at line 337 of file rte_posix_osadapter_ipc.c.

◆ try_send_once()

rte_status_t try_send_once ( const posix_ipc_state_t * state,
const void * message )
static

One send try. RTE_STATUS_TIMEOUT means "try again": queue_depth messages are queued, or the pipe has no room right now (EAGAIN, another sender) or the write was interrupted (EINTR). RTE_STATUS_OK: the whole message was written. RTE_STATUS_INTERNAL_ERROR: FIONREAD failed, a short write (not possible at <= PIPE_BUF) or another write error.

Definition at line 289 of file rte_posix_osadapter_ipc.c.

Variable Documentation

◆ s_posix_ipc_osadapter

const rte_osadapter_ipc_t s_posix_ipc_osadapter
static
Initial value:
osadapter_destroy }
static rte_status_t backend_receive(rte_ipc_handle_t handle, void *out_message, size_t buffer_size, rte_duration_ms_t timeout_ms)
static rte_status_t backend_send(rte_ipc_handle_t handle, const void *message, size_t message_size, rte_duration_ms_t timeout_ms)
static rte_status_t osadapter_create(rte_ipc_storage_t *storage, const rte_ipc_config_t *config, rte_ipc_handle_t *out_handle)

Local variables declarations

Definition at line 515 of file rte_posix_osadapter_ipc.c.