Files
SOEM/osal/linux/osal.c
Hans-Erik Floryd 7c2da72988 Add OSAL functions for monotonic time
This commit adds osal_get_monotonic_time() and
osal_monotonic_sleep(). These functions are designed to facilitate
synchronization with DC time, which can achieve nanosecond precision.

To support this functionality, the ec_timet structure has been
refactored to hold time values in nanoseconds, eliminating the need to
maintain separate time representations.

Change-Id: I039a006ccdb21ba35c437ab76e44e5153c711998
2025-07-10 10:23:07 +02:00

155 lines
3.5 KiB
C

/*
* This software is dual-licensed under GPLv3 and a commercial
* license. See the file LICENSE.md distributed with this software for
* full license information.
*/
#include <osal.h>
#include <stdlib.h>
#include <string.h>
/* Returns time from some unspecified moment in past,
* strictly increasing, used for time intervals measurement. */
void osal_get_monotonic_time(ec_timet *ts)
{
/* Use clock_gettime to prevent possible live-lock.
* Gettimeofday uses CLOCK_REALTIME that can get NTP timeadjust.
* If this function preempts timeadjust and it uses vpage it live-locks.
* Also when using XENOMAI, only clock_gettime is RT safe */
clock_gettime(CLOCK_MONOTONIC, ts);
}
ec_timet osal_current_time(void)
{
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
return ts;
}
void osal_time_diff(ec_timet *start, ec_timet *end, ec_timet *diff)
{
osal_timespecsub(end, start, diff);
}
void osal_timer_start(osal_timert *self, uint32 timeout_usec)
{
struct timespec start_time;
struct timespec timeout;
osal_get_monotonic_time(&start_time);
osal_timespec_from_usec(timeout_usec, &timeout);
osal_timespecadd(&start_time, &timeout, &self->stop_time);
}
boolean osal_timer_is_expired(osal_timert *self)
{
struct timespec current_time;
int is_not_yet_expired;
osal_get_monotonic_time(&current_time);
is_not_yet_expired = osal_timespeccmp(&current_time, &self->stop_time, <);
return is_not_yet_expired == FALSE;
}
int osal_usleep(uint32 usec)
{
struct timespec ts;
int result;
osal_timespec_from_usec(usec, &ts);
result = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
return result == 0 ? 0 : -1;
}
int osal_monotonic_sleep(ec_timet *ts)
{
int result;
result = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, ts, NULL);
return result == 0 ? 0 : -1;
}
void *osal_malloc(size_t size)
{
return malloc(size);
}
void osal_free(void *ptr)
{
free(ptr);
}
int osal_thread_create(void *thandle, int stacksize, void *func, void *param)
{
int ret;
pthread_attr_t attr;
pthread_t *threadp;
threadp = thandle;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, stacksize);
ret = pthread_create(threadp, &attr, func, param);
if (ret < 0)
{
return 0;
}
return 1;
}
int osal_thread_create_rt(void *thandle, int stacksize, void *func, void *param)
{
int ret;
pthread_attr_t attr;
struct sched_param schparam;
pthread_t *threadp;
threadp = thandle;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, stacksize);
ret = pthread_create(threadp, &attr, func, param);
pthread_attr_destroy(&attr);
if (ret < 0)
{
return 0;
}
memset(&schparam, 0, sizeof(schparam));
schparam.sched_priority = 40;
ret = pthread_setschedparam(*threadp, SCHED_FIFO, &schparam);
if (ret < 0)
{
return 0;
}
return 1;
}
void *osal_mutex_create(void)
{
pthread_mutexattr_t mutexattr;
osal_mutext *mutex;
mutex = (osal_mutext *)osal_malloc(sizeof(osal_mutext));
if (mutex)
{
pthread_mutexattr_init(&mutexattr);
pthread_mutexattr_setprotocol(&mutexattr, PTHREAD_PRIO_INHERIT);
pthread_mutex_init(mutex, &mutexattr);
}
return (void *)mutex;
}
void osal_mutex_destroy(void *mutex)
{
pthread_mutex_destroy((osal_mutext *)mutex);
osal_free(mutex);
}
void osal_mutex_lock(void *mutex)
{
pthread_mutex_lock((osal_mutext *)mutex);
}
void osal_mutex_unlock(void *mutex)
{
pthread_mutex_unlock((osal_mutext *)mutex);
}