34typedef char posix_ipc_storage_fits_[(
sizeof(
posix_ipc_state_t) <=
sizeof(sapi_ipc_storage_t)) ? 1 : -1];
43 if (clock_gettime(CLOCK_MONOTONIC, &now) != 0)
47 delta_ms = ((int64_t)deadline->tv_sec - (int64_t)now.tv_sec) * 1000;
48 delta_ms += ((int64_t)deadline->tv_nsec - (int64_t)now.tv_nsec) / 1000000;
56static void compute_deadline(sapi_duration_ms_t timeout_ms,
struct timespec *out_deadline)
58 (void)clock_gettime(CLOCK_MONOTONIC, out_deadline);
59 out_deadline->tv_sec += (time_t)(timeout_ms / 1000U);
60 out_deadline->tv_nsec += (long)((timeout_ms % 1000U) * 1000000L);
61 if (out_deadline->tv_nsec >= 1000000000L)
63 out_deadline->tv_sec += 1;
64 out_deadline->tv_nsec -= 1000000000L;
73static sapi_status_t
transfer_all(
int fd,
const void *write_src,
void *read_dst,
size_t size,
74 sapi_duration_ms_t timeout_ms,
bool read_not_write)
76 struct timespec deadline;
78 const uint8_t *src_bytes = (
const uint8_t *)write_src;
79 uint8_t *dst_bytes = (uint8_t *)read_dst;
81 compute_deadline(timeout_ms, &deadline);
92 return SAPI_STATUS_TIMEOUT;
96 pfd.events = read_not_write ? POLLIN : POLLOUT;
98 rc = poll(&pfd, 1, wait_ms);
101 return SAPI_STATUS_TIMEOUT;
109 return SAPI_STATUS_INTERNAL_ERROR;
112 n = read_not_write ? read(fd, dst_bytes + done, size - done) : write(fd, src_bytes + done, size - done);
115 if ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINTR))
119 return SAPI_STATUS_INTERNAL_ERROR;
124 return SAPI_STATUS_INTERNAL_ERROR;
129 return SAPI_STATUS_OK;
132static sapi_status_t backend_create(sapi_ipc_storage_t *storage,
const sapi_ipc_config_t *config,
133 sapi_ipc_handle_t *out_handle)
137 long requested_capacity;
139 if ((storage == NULL) || (config == NULL) || (out_handle == NULL) || (config->message_size == 0U)
140 || (config->queue_depth == 0U))
142 return SAPI_STATUS_INVALID_PARAM;
147 return SAPI_STATUS_INTERNAL_ERROR;
149 (void)fcntl(fds[0], F_SETFL, O_NONBLOCK);
150 (void)fcntl(fds[1], F_SETFL, O_NONBLOCK);
156 requested_capacity = (long)(config->message_size * config->queue_depth);
158 (void)fcntl(fds[1], F_SETPIPE_SZ, requested_capacity);
160 (void)requested_capacity;
164 state->read_fd = fds[0];
165 state->write_fd = fds[1];
166 state->message_size = config->message_size;
167 *out_handle = (sapi_ipc_handle_t)(
void *)storage;
168 return SAPI_STATUS_OK;
171static sapi_status_t backend_send(sapi_ipc_handle_t handle,
const void *message,
size_t message_size,
172 sapi_duration_ms_t timeout_ms)
176 if ((state == NULL) || (message == NULL) || (message_size == 0U))
178 return SAPI_STATUS_INVALID_PARAM;
180 return transfer_all(state->write_fd, message, NULL, message_size, timeout_ms,
false);
183static sapi_status_t backend_receive(sapi_ipc_handle_t handle,
void *out_message,
size_t buffer_size,
184 sapi_duration_ms_t timeout_ms)
188 if ((state == NULL) || (out_message == NULL) || (buffer_size == 0U))
190 return SAPI_STATUS_INVALID_PARAM;
192 return transfer_all(state->read_fd, NULL, out_message, buffer_size, timeout_ms,
true);
195static sapi_status_t backend_destroy(sapi_ipc_handle_t handle)
201 return SAPI_STATUS_INVALID_PARAM;
203 (void)close(state->read_fd);
204 (void)close(state->write_fd);
205 return SAPI_STATUS_OK;
208static const sapi_ipc_backend_t s_posix_ipc_backend = { backend_create, backend_send, backend_receive,
213 return &s_posix_ipc_backend;
Real POSIX/Linux backend for every OAL service (ADR-018).
const sapi_ipc_backend_t * sapi_posix_backend_ipc(void)
The POSIX sapi_ipc backend (pipe() per channel).
static sapi_status_t transfer_all(int fd, const void *write_src, void *read_dst, size_t size, sapi_duration_ms_t timeout_ms, bool read_not_write)
static int remaining_ms(const struct timespec *deadline)