56#define POSIX_IPC_ATOMIC_MAX ((size_t)PIPE_BUF)
58#define POSIX_IPC_ATOMIC_MAX ((size_t)_POSIX_PIPE_BUF)
61#define POSIX_IPC_POLL_NS 1000000L
62#define POSIX_IPC_NS_PER_MS 1000000L
63#define POSIX_IPC_NS_PER_S 1000000000L
65#if defined(F_SETPIPE_SZ) && defined(F_GETPIPE_SZ)
67#define POSIX_IPC_EXTRA_SLOTS 3U
76#ifndef RTE_POSIX_IPC_PIPE_CAPACITY
77#define RTE_POSIX_IPC_PIPE_CAPACITY 16384U
90typedef char posix_ipc_storage_fits_[(
sizeof(
posix_ipc_state_t) <=
sizeof(rte_ipc_storage_t)) ? 1 : -1];
93static bool compute_deadline(rte_duration_ms_t timeout_ms,
struct timespec *out_deadline);
94static rte_status_t
read_message(
int fd, uint8_t *dst,
size_t size, rte_duration_ms_t timeout_ms);
95static rte_status_t set_nonblocking(
const int fds[2]);
96#if defined(F_SETPIPE_SZ) && defined(F_GETPIPE_SZ)
97static bool required_pipe_bytes(
size_t message_size,
size_t queue_depth,
size_t *out_bytes);
103 rte_duration_ms_t timeout_ms);
112 if (clock_gettime(CLOCK_MONOTONIC, out_deadline) == 0)
114 rte_duration_ms_t whole_s = timeout_ms / 1000U;
115 rte_duration_ms_t rest_ms = timeout_ms % 1000U;
117 out_deadline->tv_sec += (time_t)whole_s;
121 out_deadline->tv_sec += 1;
132static rte_status_t
read_message(
int fd, uint8_t *dst,
size_t size, rte_duration_ms_t timeout_ms)
134 rte_status_t status = RTE_STATUS_OK;
135 struct timespec deadline;
140 status = RTE_STATUS_INTERNAL_ERROR;
143 while ((status == RTE_STATUS_OK) && (done < size))
145 int wait_ms = posix_remaining_ms(&deadline);
151 status = RTE_STATUS_TIMEOUT;
161 rc = poll(&pfd, 1, wait_ms);
164 status = RTE_STATUS_TIMEOUT;
170 status = RTE_STATUS_INTERNAL_ERROR;
175 ssize_t n = read(fd, &dst[done], size - done);
179 if ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINTR))
181 status = RTE_STATUS_INTERNAL_ERROR;
187 status = RTE_STATUS_INTERNAL_ERROR;
201static rte_status_t set_nonblocking(
const int fds[2])
203 rte_status_t status = RTE_STATUS_INTERNAL_ERROR;
205 if (fcntl(fds[0], F_SETFL, O_NONBLOCK) != -1)
207 if (fcntl(fds[1], F_SETFL, O_NONBLOCK) != -1)
209 status = RTE_STATUS_OK;
215#if defined(F_SETPIPE_SZ) && defined(F_GETPIPE_SZ)
225static bool required_pipe_bytes(
size_t message_size,
size_t queue_depth,
size_t *out_bytes)
228 long page = sysconf(_SC_PAGESIZE);
230 if ((page > 0) && ((
size_t)page >= message_size))
232 size_t page_bytes = (size_t)page;
233 size_t full_slots = queue_depth / (page_bytes / message_size);
235 if (full_slots <= ((SIZE_MAX / page_bytes) - POSIX_IPC_EXTRA_SLOTS))
237 *out_bytes = (full_slots + POSIX_IPC_EXTRA_SLOTS) * page_bytes;
250 rte_status_t status = RTE_STATUS_RESOURCE_EXHAUSTED;
253 if (required_pipe_bytes(message_size, queue_depth, &needed) && (needed <= (
size_t)INT_MAX))
255 if (fcntl(write_fd, F_SETPIPE_SZ, (
int)needed) >= 0)
257 int actual = fcntl(write_fd, F_GETPIPE_SZ);
259 if ((actual >= 0) && ((
size_t)actual >= needed))
261 status = RTE_STATUS_OK;
273 rte_status_t status = RTE_STATUS_RESOURCE_EXHAUSTED;
278 status = RTE_STATUS_OK;
292 int queued_bytes = 0;
294 if (ioctl(state->
read_fd, FIONREAD, &queued_bytes) != 0)
296 status = RTE_STATUS_INTERNAL_ERROR;
298 else if (queued_bytes < 0)
300 status = RTE_STATUS_INTERNAL_ERROR;
304 status = RTE_STATUS_TIMEOUT;
312 if ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINTR))
314 status = RTE_STATUS_TIMEOUT;
318 status = RTE_STATUS_INTERNAL_ERROR;
323 status = RTE_STATUS_OK;
327 status = RTE_STATUS_INTERNAL_ERROR;
339 rte_status_t status = RTE_STATUS_INTERNAL_ERROR;
342 if (clock_gettime(CLOCK_MONOTONIC, &now) == 0)
344 int64_t remaining_ns = (((int64_t)deadline->tv_sec - (int64_t)now.tv_sec) *
POSIX_IPC_NS_PER_S) +
345 ((int64_t)deadline->tv_nsec - (int64_t)now.tv_nsec);
347 if (remaining_ns <= 0)
349 status = RTE_STATUS_TIMEOUT;
358 (void)nanosleep(&nap, NULL);
359 status = RTE_STATUS_OK;
368 rte_duration_ms_t timeout_ms)
371 struct timespec deadline;
375 status = RTE_STATUS_INTERNAL_ERROR;
381 status = RTE_STATUS_TIMEOUT;
385 if (status == RTE_STATUS_TIMEOUT)
389 if (wait_status != RTE_STATUS_OK)
391 status = wait_status;
407static rte_status_t
osadapter_create(rte_ipc_storage_t *storage,
const rte_ipc_config_t *config,
408 rte_ipc_handle_t *out_handle)
413 if ((storage == NULL) || (config == NULL) || (out_handle == NULL) || (config->message_size == 0U)
414 || (config->queue_depth == 0U))
416 status = RTE_STATUS_INVALID_PARAM;
420 status = RTE_STATUS_NOT_SUPPORTED;
422 else if (config->queue_depth > (SIZE_MAX / config->message_size))
424 status = RTE_STATUS_INVALID_PARAM;
426 else if (pipe(fds) != 0)
428 status = RTE_STATUS_INTERNAL_ERROR;
432 status = set_nonblocking(fds);
433 if (status == RTE_STATUS_OK)
438 if (status == RTE_STATUS_OK)
446 *out_handle = (rte_ipc_handle_t)(
void *)storage;
458static rte_status_t backend_send(rte_ipc_handle_t handle,
const void *message,
size_t message_size,
459 rte_duration_ms_t timeout_ms)
464 if ((state == NULL) || (message == NULL) || (message_size == 0U))
466 status = RTE_STATUS_INVALID_PARAM;
470 status = RTE_STATUS_INVALID_PARAM;
480static rte_status_t
backend_receive(rte_ipc_handle_t handle,
void *out_message,
size_t buffer_size,
481 rte_duration_ms_t timeout_ms)
486 if ((state == NULL) || (out_message == NULL) || (buffer_size == 0U))
488 status = RTE_STATUS_INVALID_PARAM;
490 else if (buffer_size < state->message_size)
492 status = RTE_STATUS_INVALID_PARAM;
501static rte_status_t osadapter_destroy(rte_ipc_handle_t handle)
507 return RTE_STATUS_INVALID_PARAM;
511 return RTE_STATUS_OK;
Real POSIX/Linux OSAdapter for every OAL service (ADR-018).
const rte_osadapter_ipc_t * rte_posix_osadapter_ipc(void)
The POSIX rte_ipc OSAdapter (pipe() per channel).
static rte_status_t read_message(int fd, uint8_t *dst, size_t size, rte_duration_ms_t timeout_ms)
static bool compute_deadline(rte_duration_ms_t timeout_ms, struct timespec *out_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 try_send_once(const posix_ipc_state_t *state, const void *message)
#define POSIX_IPC_NS_PER_S
static rte_status_t sleep_before_retry(const struct timespec *deadline)
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 const rte_osadapter_ipc_t s_posix_ipc_osadapter
static rte_status_t ensure_pipe_capacity(int write_fd, size_t message_size, size_t queue_depth)
#define RTE_POSIX_IPC_PIPE_CAPACITY
#define POSIX_IPC_POLL_NS
#define POSIX_IPC_NS_PER_MS
static rte_status_t osadapter_create(rte_ipc_storage_t *storage, const rte_ipc_config_t *config, rte_ipc_handle_t *out_handle)
#define POSIX_IPC_ATOMIC_MAX
Private helpers: millisecond waits for poll()'s int timeout argument.