1#define _POSIX_C_SOURCE 200809L
125#include "rte/oal/memory/rte_mem_util.h"
133#ifndef RTE_POSIX_TIMER_STACK_SIZE
134#define RTE_POSIX_TIMER_STACK_SIZE ((size_t)8388608U)
141 rte_timer_config_t config;
143 volatile sig_atomic_t should_stop;
144 rte_timer_handle_t self_handle;
150typedef char posix_timer_storage_fits_[(
sizeof(
posix_timer_state_t) <=
sizeof(rte_timer_storage_t)) ? 1 : -1];
161static rte_status_t
osadapter_create(rte_timer_storage_t *storage,
const rte_timer_config_t *config,
162 rte_timer_handle_t *out_handle);
163static rte_status_t osadapter_stop(rte_timer_handle_t handle);
164static rte_status_t osadapter_start(rte_timer_handle_t handle);
165static rte_status_t osadapter_destroy(rte_timer_handle_t handle);
166static rte_status_t osadapter_now(rte_timestamp_ms_t *out_now_ms);
170 osadapter_destroy, osadapter_now };
175static pthread_key_t s_timer_key;
176static bool s_timer_key_ready =
false;
194 s_timer_key_ready = (pthread_key_create(&s_timer_key, NULL) == 0);
201 static pthread_once_t key_once = PTHREAD_ONCE_INIT;
206 ready = s_timer_key_ready;
217 if (pthread_setspecific(s_timer_key, state) == 0)
225 POSIX_OSA_REPORT_RT_ATTRIBUTE(
"timer thread-specific data not set - timer not run");
235 struct timespec deadline;
237 bool clock_failed = !running;
247 else if (state->should_stop != 0)
253 state->config.callback(state->self_handle, state->config.user_ctx);
257 if ((state->config.mode != RTE_TIMER_MODE_PERIODIC) || (state->should_stop != 0))
268 POSIX_OSA_REPORT_RT_ATTRIBUTE(
"timer monotonic clock failed - timer stopped");
276 return (pthread_getspecific(s_timer_key) == (
const void *)state);
284 rte_status_t status = RTE_STATUS_OK;
289 if (pthread_join(state->thread, NULL) == 0)
291 state->joinable =
false;
295 status = RTE_STATUS_INTERNAL_ERROR;
307 bool applied =
false;
308 struct sched_param sched;
311 rte_mem_set(&sched, 0,
sizeof(sched));
312 if (pthread_getschedparam(pthread_self(), &policy, &sched) == 0)
314 if (pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED) == 0)
316 if (pthread_attr_setschedpolicy(attr, policy) == 0)
318 if (pthread_attr_setschedparam(attr, &sched) == 0)
333 rte_status_t status = RTE_STATUS_INTERNAL_ERROR;
336 if (pthread_attr_init(&attr) == 0)
338 bool inherit_fallback =
false;
342#if defined(PTHREAD_STACK_MIN)
343 if (stack_size < (
size_t)PTHREAD_STACK_MIN)
345 stack_size = (size_t)PTHREAD_STACK_MIN;
348 if (pthread_attr_setstacksize(&attr, stack_size) != 0)
351 POSIX_OSA_REPORT_RT_ATTRIBUTE(
"timer stack size not applied");
360 inherit_fallback =
true;
365 inherit_fallback =
true;
368 if (inherit_fallback)
372 POSIX_OSA_REPORT_RT_ATTRIBUTE(
"timer scheduling not applied");
374 if (pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED) == 0)
382 status = RTE_STATUS_OK;
384 (void)pthread_attr_destroy(&attr);
389static rte_status_t
osadapter_create(rte_timer_storage_t *storage,
const rte_timer_config_t *config,
390 rte_timer_handle_t *out_handle)
395 if ((storage == NULL) || (config == NULL) || (out_handle == NULL) || (config->callback == NULL)
396 || (config->period_ms == 0U))
398 return RTE_STATUS_INVALID_PARAM;
409 return RTE_STATUS_INTERNAL_ERROR;
413 rte_mem_set(state, 0,
sizeof(*state));
414 state->config = *config;
415 state->self_handle = (rte_timer_handle_t)(
void *)storage;
416 *out_handle = state->self_handle;
417 return RTE_STATUS_OK;
420static rte_status_t osadapter_stop(rte_timer_handle_t handle)
427 return RTE_STATUS_INVALID_PARAM;
436 status = RTE_STATUS_OK;
445static rte_status_t osadapter_start(rte_timer_handle_t handle)
452 return RTE_STATUS_INVALID_PARAM;
459 status = RTE_STATUS_NOT_SUPPORTED;
466 if (status == RTE_STATUS_OK)
468 state->should_stop = 0;
470 if (status == RTE_STATUS_OK)
472 state->joinable =
true;
479static rte_status_t osadapter_destroy(rte_timer_handle_t handle)
481 return osadapter_stop(handle);
484static rte_status_t osadapter_now(rte_timestamp_ms_t *out_now_ms)
488 if (out_now_ms == NULL)
490 return RTE_STATUS_INVALID_PARAM;
492 if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
495 return RTE_STATUS_INTERNAL_ERROR;
497 *out_now_ms = (rte_timestamp_ms_t)(((uint64_t)ts.tv_sec * 1000ULL) + ((uint64_t)ts.tv_nsec / 1000000ULL));
498 return RTE_STATUS_OK;
Real POSIX/Linux OSAdapter for every OAL service (ADR-018).
const rte_osadapter_timer_t * rte_posix_osadapter_timer(void)
The POSIX rte_timer OSAdapter (one pthread per timer).
static rte_status_t osadapter_create(rte_ipc_storage_t *storage, const rte_ipc_config_t *config, rte_ipc_handle_t *out_handle)
rte_status_t posix_period_init(struct timespec *out_deadline)
Starts a period: reads CLOCK_MONOTONIC into the deadline.
void posix_period_wake_all(volatile sig_atomic_t *should_stop)
Requests a stop of a periodic thread and wakes it from its wait.
bool posix_period_wake_ready(void)
Creates the process-wide wake object on the first call; true once it exists.
rte_status_t posix_period_sleep_until(const struct timespec *deadline, const volatile sig_atomic_t *should_stop)
Waits until the absolute CLOCK_MONOTONIC deadline, or until a stop is requested.
void posix_period_advance(struct timespec *deadline, rte_duration_ms_t period_ms)
Moves the deadline one period later, keeping tv_nsec in [0, 1 s).
Private helper: pacing of a periodic thread by an absolute CLOCK_MONOTONIC deadline (OSA rule R3),...
Private helper: reports a real-time attribute this OSAdapter could not apply (OSA rules R1/R2/R6).
static bool is_timer_thread(const posix_timer_state_t *state)
static void * timer_thread_main(void *arg)
#define RTE_POSIX_TIMER_STACK_SIZE
static bool set_creator_sched_attributes(pthread_attr_t *attr)
static void create_timer_key(void)
static const rte_osadapter_timer_t s_posix_timer_osadapter
static void run_timer_loop(posix_timer_state_t *state)
static bool timer_key_ready(void)
static rte_status_t create_timer_thread(posix_timer_state_t *state)
static rte_status_t join_timer_thread(posix_timer_state_t *state)