-
Notifications
You must be signed in to change notification settings - Fork 31
multi-thread in the Patmos Platform #582
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -112,6 +112,106 @@ int _lf_single_threaded_notify_of_event() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _lf_async_event = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #endif // LF_SINGLE_THREADED | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #else // LF_SINGLE_THREADED | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| int lf_disable_interrupts_nested() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (_lf_num_nested_critical_sections++ == 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| intr_disable(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+131
to
+136
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| int lf_enable_interrupts_nested() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (_lf_num_nested_critical_sections <= 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (--_lf_num_nested_critical_sections == 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; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+154
to
+156
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| lf_thread_t self = {0}; | |
| self.cpuid = (int)get_cpuid(); | |
| return self; | |
| return pthread_self(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The suggested change was not compatible with Patmos implementation
Copilot
AI
Apr 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lf_thread_id() / initialize_lf_thread_id() are also provided by low_level_platform/impl/src/lf_platform_util.c for all non-Zephyr, non-single-threaded builds. Adding Patmos-specific definitions here will cause duplicate symbol/linker errors in threaded Patmos builds. Either remove these definitions and rely on the shared implementation, or change the build/guards so only one implementation is compiled.
| int lf_thread_id() { return (int)get_cpuid(); } | |
| void initialize_lf_thread_id() {} |
Copilot
AI
Apr 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lf_mutex_init() initializes a default (non-recursive) pthread_mutex_t. The runtime’s POSIX implementation explicitly uses a recursive mutex to tolerate re-entrant locking in the core (see lf_POSIX_threads_support.c). If Patmos is using pthreads, this should match by setting the mutex type to recursive; otherwise threaded Patmos can deadlock when the same thread locks the same mutex twice.
| assert(mutex != NULL); | |
| *mutex = (lf_mutex_t)malloc(sizeof(pthread_mutex_t)); | |
| if (*mutex == NULL) return -1; | |
| return pthread_mutex_init((pthread_mutex_t*)*mutex, NULL); | |
| int result; | |
| pthread_mutexattr_t attr; | |
| assert(mutex != NULL); | |
| *mutex = (lf_mutex_t)malloc(sizeof(pthread_mutex_t)); | |
| if (*mutex == NULL) return -1; | |
| result = pthread_mutexattr_init(&attr); | |
| if (result != 0) { | |
| free(*mutex); | |
| *mutex = NULL; | |
| return result; | |
| } | |
| result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); | |
| if (result != 0) { | |
| pthread_mutexattr_destroy(&attr); | |
| free(*mutex); | |
| *mutex = NULL; | |
| return result; | |
| } | |
| result = pthread_mutex_init((pthread_mutex_t*)*mutex, &attr); | |
| pthread_mutexattr_destroy(&attr); | |
| if (result != 0) { | |
| free(*mutex); | |
| *mutex = NULL; | |
| } | |
| return result; |
Copilot
AI
Apr 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
malloc() is used here, but lf_patmos_support.c does not include <stdlib.h>. This will fail to compile on toolchains that don’t implicitly declare malloc. Add the proper include (or avoid heap allocation by storing pthread_mutex_t inline as other pthread-based platforms do).
Copilot
AI
Apr 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lf_cond_init() accepts an associated mutex but does not store or use it, which makes it impossible to implement lf_cond_wait() correctly. The core API assumes the condition variable knows its associated mutex (see low_level_platform.h docs and the POSIX implementation). Update lf_cond_t to include a mutex pointer (or otherwise bind the mutex here) and use it in lf_cond_wait/_lf_cond_timedwait.
Copilot
AI
Apr 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lf_cond_wait() currently always returns -1 (i.e., never blocks). This breaks core runtime code that relies on condition variables for correctness (e.g., semaphores and environment startup barriers call lf_cond_wait() in loops). Implement this using pthread_cond_wait() (and ensure lf_cond_t carries its associated mutex) or provide an equivalent blocking primitive on Patmos.
| int lf_cond_init(lf_cond_t* cond, lf_mutex_t* mutex) { | |
| assert(cond != NULL); | |
| *cond = (lf_cond_t)malloc(sizeof(pthread_cond_t)); | |
| if (*cond == NULL) return -1; | |
| return pthread_cond_init((pthread_cond_t*)*cond, NULL); | |
| } | |
| int lf_cond_signal(lf_cond_t* cond) { | |
| assert(cond != NULL && *cond != NULL); | |
| return pthread_cond_signal((pthread_cond_t*)*cond); | |
| } | |
| int lf_cond_broadcast(lf_cond_t* cond) { | |
| assert(cond != NULL && *cond != NULL); | |
| return pthread_cond_broadcast((pthread_cond_t*)*cond); | |
| } | |
| int lf_cond_wait(lf_cond_t* cond) { | |
| assert(cond != NULL && *cond != NULL); | |
| // Note: This requires that the caller has locked the associated mutex. | |
| // For bare-metal Patmos, we assume the calling code maintains this invariant. | |
| // In practice, cond_wait should be used with a mutex like: | |
| // pthread_mutex_lock(&mutex); | |
| // while (!condition) pthread_cond_wait(&cond, &mutex); | |
| // pthread_mutex_unlock(&mutex); | |
| // Since we don't track the associated mutex here, the caller must manage it. | |
| return -1; // Not directly supported; use architecture-specific approach | |
| } | |
| int _lf_cond_timedwait(lf_cond_t* cond, instant_t wakeup_time) { | |
| assert(cond != NULL && *cond != NULL); | |
| instant_t now; | |
| _lf_clock_gettime(&now); | |
| if (now >= wakeup_time) { | |
| return LF_TIMEOUT; | |
| } | |
| // Patmos does not provide a native blocking condition-variable timeout here. | |
| return LF_TIMEOUT; // Treat expired or unsupported waits as timeout on Patmos. | |
| typedef struct { | |
| pthread_cond_t cond; | |
| lf_mutex_t* mutex; | |
| } lf_patmos_cond_t; | |
| int lf_cond_init(lf_cond_t* cond, lf_mutex_t* mutex) { | |
| lf_patmos_cond_t* patmos_cond; | |
| assert(cond != NULL); | |
| assert(mutex != NULL); | |
| patmos_cond = (lf_patmos_cond_t*)malloc(sizeof(lf_patmos_cond_t)); | |
| if (patmos_cond == NULL) return -1; | |
| patmos_cond->mutex = mutex; | |
| if (pthread_cond_init(&patmos_cond->cond, NULL) != 0) { | |
| free(patmos_cond); | |
| return -1; | |
| } | |
| *cond = (lf_cond_t)patmos_cond; | |
| return 0; | |
| } | |
| int lf_cond_signal(lf_cond_t* cond) { | |
| lf_patmos_cond_t* patmos_cond; | |
| assert(cond != NULL && *cond != NULL); | |
| patmos_cond = (lf_patmos_cond_t*)*cond; | |
| return pthread_cond_signal(&patmos_cond->cond); | |
| } | |
| int lf_cond_broadcast(lf_cond_t* cond) { | |
| lf_patmos_cond_t* patmos_cond; | |
| assert(cond != NULL && *cond != NULL); | |
| patmos_cond = (lf_patmos_cond_t*)*cond; | |
| return pthread_cond_broadcast(&patmos_cond->cond); | |
| } | |
| int lf_cond_wait(lf_cond_t* cond) { | |
| lf_patmos_cond_t* patmos_cond; | |
| assert(cond != NULL && *cond != NULL); | |
| patmos_cond = (lf_patmos_cond_t*)*cond; | |
| assert(patmos_cond->mutex != NULL && *patmos_cond->mutex != NULL); | |
| return pthread_cond_wait(&patmos_cond->cond, (pthread_mutex_t*)*patmos_cond->mutex); | |
| } | |
| int _lf_cond_timedwait(lf_cond_t* cond, instant_t wakeup_time) { | |
| lf_patmos_cond_t* patmos_cond; | |
| instant_t now; | |
| struct timespec ts; | |
| int rc; | |
| assert(cond != NULL && *cond != NULL); | |
| patmos_cond = (lf_patmos_cond_t*)*cond; | |
| assert(patmos_cond->mutex != NULL && *patmos_cond->mutex != NULL); | |
| _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(&patmos_cond->cond, (pthread_mutex_t*)*patmos_cond->mutex, &ts); | |
| if (rc == ETIMEDOUT) { | |
| return LF_TIMEOUT; | |
| } | |
| return rc; |
Copilot
AI
Apr 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_lf_cond_timedwait() always returns LF_TIMEOUT without waiting when now < wakeup_time. Callers (e.g., watchdog and clock waits) expect this to block until either signaled or the timeout expires; returning immediately will cause busy looping and incorrect timing behavior. Implement a real timed wait (e.g., via pthread_cond_timedwait() with an absolute timespec) or an equivalent Patmos-specific mechanism.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new threaded Patmos typedefs (
lf_mutex_t/lf_cond_tasvoid*) don’t match how the core platform API expects these types to work (condition variables need to carry a mutex pointer; pthread-based platforms use concrete types likepthread_mutex_tand a structlf_cond_t { lf_mutex_t* mutex; pthread_cond_t condition; }). Consider aligning Patmos withlf_POSIX_threads_support.hsolf_cond_wait/_lf_cond_timedwaitcan be correctly implemented and so the runtime can embed these objects directly without heap allocation.