diff --git a/low_level_platform/api/platform/lf_patmos_support.h b/low_level_platform/api/platform/lf_patmos_support.h index ccc4e46d0..91ccf975b 100644 --- a/low_level_platform/api/platform/lf_patmos_support.h +++ b/low_level_platform/api/platform/lf_patmos_support.h @@ -22,5 +22,14 @@ #define PRINTF_TIME "%" PRId64 #define PRINTF_MICROSTEP "%" PRIu32 #define PRINTF_TAG "(%" PRId64 ", %" PRIu32 ")" +#if !defined(LF_SINGLE_THREADED) +#include +typedef pthread_t lf_thread_t; +typedef pthread_mutex_t lf_mutex_t; +typedef struct { + lf_mutex_t* mutex; + pthread_cond_t condition; +} lf_cond_t; +#endif #endif // LF_PATMOS_SUPPORT_H diff --git a/low_level_platform/impl/src/lf_patmos_support.c b/low_level_platform/impl/src/lf_patmos_support.c index 4c3fc0fab..3e55c0408 100644 --- a/low_level_platform/impl/src/lf_patmos_support.c +++ b/low_level_platform/impl/src/lf_patmos_support.c @@ -16,6 +16,9 @@ #include #include +int lf_disable_interrupts_nested(void); +int lf_enable_interrupts_nested(void); + // Keep track of physical actions being entered into the system static volatile bool _lf_async_event = false; // Keep track of whether we are in a critical section or not @@ -112,6 +115,139 @@ int _lf_single_threaded_notify_of_event() { _lf_async_event = true; return 0; } -#endif // LF_SINGLE_THREADED +#else // LF_SINGLE_THREADED + +#define LF_PATMOS_MAX_CORES 64 +static volatile int _lf_num_nested_critical_sections_by_core[LF_PATMOS_MAX_CORES] = {0}; + +static inline volatile int* _lf_current_core_nested_counter() { + int cpuid = (int)get_cpuid(); + if (cpuid < 0 || cpuid >= LF_PATMOS_MAX_CORES) { + return &_lf_num_nested_critical_sections_by_core[0]; + } + return &_lf_num_nested_critical_sections_by_core[cpuid]; +} + +int lf_disable_interrupts_nested() { + volatile int* nested_counter = _lf_current_core_nested_counter(); + if ((*nested_counter)++ == 0) { + intr_disable(); + } + return 0; +} + +int lf_enable_interrupts_nested() { + volatile int* nested_counter = _lf_current_core_nested_counter(); + if (*nested_counter <= 0) { + return 1; + } + + if (--(*nested_counter) == 0) { + intr_enable(); + } + return 0; +} + +int lf_available_cores() { return (int)get_cpucnt(); } + +lf_thread_t lf_thread_self() { + lf_thread_t self = {0}; + self.cpuid = (int)get_cpuid(); + return self; +} + +int lf_thread_create(lf_thread_t* thread, void* (*lf_thread)(void*), void* arguments) { + assert(thread != NULL); + return pthread_create((pthread_t*)thread, NULL, lf_thread, arguments); +} + +int lf_thread_join(lf_thread_t thread, void** thread_return) { + return pthread_join((pthread_t)thread, thread_return); +} + +int lf_thread_id() { return (int)get_cpuid(); } + +void initialize_lf_thread_id() {} + +int lf_mutex_init(lf_mutex_t* mutex) { + int result; + pthread_mutexattr_t attr; + + assert(mutex != NULL); + + result = pthread_mutexattr_init(&attr); + if (result != 0) { + return result; + } + + result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + if (result != 0) { + pthread_mutexattr_destroy(&attr); + return result; + } + + result = pthread_mutex_init((pthread_mutex_t*)mutex, &attr); + pthread_mutexattr_destroy(&attr); + return result; +} + +int lf_mutex_lock(lf_mutex_t* mutex) { + assert(mutex != NULL); + return pthread_mutex_lock((pthread_mutex_t*)mutex); +} + +int lf_mutex_unlock(lf_mutex_t* mutex) { + assert(mutex != NULL); + return pthread_mutex_unlock((pthread_mutex_t*)mutex); +} + +int lf_cond_init(lf_cond_t* cond, lf_mutex_t* mutex) { + assert(cond != NULL); + assert(mutex != NULL); + cond->mutex = mutex; + return pthread_cond_init((pthread_cond_t*)&cond->condition, NULL); +} + +int lf_cond_signal(lf_cond_t* cond) { + assert(cond != NULL); + return pthread_cond_signal((pthread_cond_t*)&cond->condition); +} + +int lf_cond_broadcast(lf_cond_t* cond) { + assert(cond != NULL); + return pthread_cond_broadcast((pthread_cond_t*)&cond->condition); +} + +int lf_cond_wait(lf_cond_t* cond) { + assert(cond != NULL); + assert(cond->mutex != NULL); + return pthread_cond_wait((pthread_cond_t*)&cond->condition, (pthread_mutex_t*)cond->mutex); +} + +int _lf_cond_timedwait(lf_cond_t* cond, instant_t wakeup_time) { + struct timespec ts; + int rc; + + assert(cond != NULL); + assert(cond->mutex != NULL); + + instant_t now; + _lf_clock_gettime(&now); + + if (now >= wakeup_time) { + return LF_TIMEOUT; + } + + ts.tv_sec = wakeup_time / 1000000000LL; + ts.tv_nsec = wakeup_time % 1000000000LL; + + rc = pthread_cond_timedwait((pthread_cond_t*)&cond->condition, (pthread_mutex_t*)cond->mutex, &ts); + if (rc == ETIMEDOUT) { + return LF_TIMEOUT; + } + return rc; +} + +#endif #endif // PLATFORM_PATMOS diff --git a/low_level_platform/impl/src/lf_platform_util.c b/low_level_platform/impl/src/lf_platform_util.c index 212e6ea83..398f3335b 100644 --- a/low_level_platform/impl/src/lf_platform_util.c +++ b/low_level_platform/impl/src/lf_platform_util.c @@ -13,7 +13,7 @@ int map_priorities(int priority, int dest_min, int dest_max) { (LF_SCHED_MAX_PRIORITY - LF_SCHED_MIN_PRIORITY)); } -#ifndef PLATFORM_ZEPHYR // on Zephyr, this is handled separately +#if !defined(PLATFORM_ZEPHYR) && !defined(PLATFORM_PATMOS) // on Zephyr and PATMOS, this is handled separately #ifndef LF_SINGLE_THREADED static int _lf_worker_thread_count = 0;