* evl. event and mutex
@ 2026-02-17 20:28 Giulio Moro
2026-02-18 8:50 ` Philippe Gerum
0 siblings, 1 reply; 3+ messages in thread
From: Giulio Moro @ 2026-02-17 20:28 UTC (permalink / raw)
To: Xenomai
Hi everyone,
I am trying to use evl_event and evl_mutex so that two threads can signal each other when either needs work from the other, so they each need to call evl_signal_event() and evl_wait_event(). The first thread to call evl_wait_event() seems to correctly drop the mutex, thus unlocking the second thread. When the second thread signals the condition variable (while holding the mutex) and then calls evl_wait_event(), thus implicitly dropping the mutex, the first thread is, unexpectedly, not restarted. I noticed that if a third thread acquires and then releases the lock (without touching the condition variable), then the first thread is restarted. This sounds like a bug?
I am running this on ARM64 (PocketBeagle 2)
evl.0.55 -- #98a8b88 (2025-10-08 22:41:39 +0000) [requires ABI 42]
Linux bela 6.12.49-arm64-ti-evl #4 SMP EVL Sun Nov 2 19:24:32 UTC 2025 aarch64 GNU/Linux
Below is a demo program to reproduce the issue.
If I run the program it prints the following when executed:
main: evl_lock_mutex
main: evl mutex locked
main: evl_signal_event cond
main: evl_wait_event cond, should drop mutex
thread: evl_lock_mutex
thread: evl mutex locked
thread: evl_signal_event cond
thread: evl_wait_event cond, should drop mutex
[HANGS]
If I #define AUXTHREAD (thus enabling the auxiliary thread that periodically locks and unlocks the mutex without touching the condition variable), I get:
main: evl_lock_mutex
main: evl mutex locked
main: evl_signal_event cond
main: evl_wait_event cond, should drop mutex
thread: evl_lock_mutex
thread: evl mutex locked
thread: evl_signal_event cond
thread: evl_wait_event cond, should drop mutex
[wait]
auxthread: evl_lock_mutex()
auxthread: evl locked mutex
auxthread: evl_unlock_mutex()
auxthread: evl mutex unlocked()
main: sleeps
main: evl_lock_mutex
main: evl mutex locked
main: evl_signal_event cond
main: evl_wait_event cond, should drop mutex
[wait]
auxthread: evl_lock_mutex()
auxthread: evl locked mutex
auxthread: evl_unlock_mutex()
auxthread: evl mutex unlocked()
thread: sleeps
thread: evl_lock_mutex
thread: evl mutex locked
thread: evl_signal_event cond
thread: evl_wait_event cond, should drop mutex
[wait]
auxthread: evl_lock_mutex()
auxthread: evl locked mutex
auxthread: evl_unlock_mutex()
main: sleeps
auxthread: evl mutex unlocked()
main: evl_lock_mutex
main: evl mutex locked
main: evl_signal_event cond
main: evl_wait_event cond, should drop mutex
Demo program:
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <evl/evl.h>
// #define AUXTHREAD
struct evl_event cond;
struct evl_mutex mtx;
void allCores() {
cpu_set_t set;
CPU_ZERO(&set);
for(unsigned int n = 0; n < 64; ++n)
CPU_SET(n, &set);
if(sched_setaffinity(gettid(), sizeof(set), &set) == -1) {
fprintf(stderr, "sched_setaffinity error\n");
abort();
}
}
void loop(const char* id) {
while(1) {
printf("%s: evl_lock_mutex\n", id);
int ret = evl_lock_mutex(&mtx);
if(ret) {
fprintf(stderr, "%s: evl_signal_event returned %d %s\n", id, ret, strerrorname_np(-ret));
abort();
}
printf("%s: evl mutex locked\n", id);
printf("%s: evl_signal_event cond\n", id);
ret = evl_signal_event(&cond);
if(ret) {
fprintf(stderr, "thread: evl_signal_event returned %d %s\n", ret, strerrorname_np(-ret));
abort();
}
printf("%s: evl_wait_event cond, should drop mutex\n", id);
ret = evl_wait_event(&cond, &mtx);
if(ret) {
fprintf(stderr, "%s: evl_wait_event returned %d %s\n", id, ret, strerrorname_np(-ret));
abort();
}
evl_unlock_mutex(&mtx);
printf("%s: sleeps\n", id);
usleep(10000);
}
}
void* thread(void* arg) {
int ret = evl_attach_thread(EVL_CLONE_PRIVATE, "thread:%d:%u", getpid(), pthread_self());
if(ret <= 0) {
fprintf(stderr, "evl_attach_thread returned %d %s\n", ret, strerrorname_np(-ret));
abort();
}
allCores();
loop("thread");
}
void* auxthread(void*) {
int ret = evl_attach_thread(EVL_CLONE_PRIVATE, "auxthread:%d:%u", getpid(), pthread_self());
if(ret <= 0) {
fprintf(stderr, "evl_attach_thread returned %d %s\n", ret, strerrorname_np(-ret));
abort();
}
while(1) {
usleep(1000000); // long wait
printf("auxthread: evl_lock_mutex()\n");
ret = evl_lock_mutex(&mtx);
if(ret) {
fprintf(stderr, "auxthread: evl_mutex_lock returned %d %s\n", ret, strerrorname_np(ret));
abort();
}
printf("auxthread: evl locked mutex\n");
printf("auxthread: evl_unlock_mutex()\n");
ret = evl_unlock_mutex(&mtx);
if(ret) {
fprintf(stderr, "auxthread: evl_mutex_unlock returned %d %s\n", ret, strerrorname_np(ret));
abort();
}
printf("auxthread: evl mutex unlocked()\n");
}
return NULL;
}
int main()
{
int ret = 0;
ret = evl_init();
if(ret) {
fprintf(stderr, "evl_init() returned %d\n", ret);
abort();
}
ret = evl_attach_self("%s:%d:%u", "main", gettid(), rand());
if(ret < 0) {
fprintf(stderr, "evl_attach_self() returned %d\n", ret);
abort();
}
allCores();
ret = evl_create_mutex(&mtx, EVL_CLOCK_MONOTONIC, 0, EVL_MUTEX_NORMAL, "mutex:%d:%p", getpid(), &mtx) < 0;
ret |= evl_create_event(&cond, EVL_CLOCK_MONOTONIC, EVL_CLONE_PRIVATE, "cond:%d:%p", getpid(), &cond) < 0;
pthread_t t;
ret |= pthread_create(&t, 0, thread, 0);
#ifdef AUXTHREAD
pthread_t at;
ret |= pthread_create(&at, 0, auxthread, 0);
#endif // AUXTHREAD
if(ret) {
fprintf(stderr, "Initialisation error\n");
return ret;
}
loop("main");
return 0;
}
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: evl. event and mutex
2026-02-17 20:28 evl. event and mutex Giulio Moro
@ 2026-02-18 8:50 ` Philippe Gerum
2026-02-19 13:28 ` Giulio Moro
0 siblings, 1 reply; 3+ messages in thread
From: Philippe Gerum @ 2026-02-18 8:50 UTC (permalink / raw)
To: Giulio Moro; +Cc: Xenomai
Giulio Moro <giulio@bela.io> writes:
> Hi everyone,
> I am trying to use evl_event and evl_mutex so that two threads can signal each other when either needs work from the other, so they each need to call evl_signal_event() and evl_wait_event(). The first thread to call evl_wait_event() seems to correctly drop the mutex, thus unlocking the second thread. When the second thread signals the condition variable (while holding the mutex) and then calls evl_wait_event(), thus implicitly dropping the mutex, the first thread is, unexpectedly, not restarted. I noticed that if a third thread acquires and then releases the lock (without touching the condition variable), then the first thread is restarted. This sounds like a bug?
>
It is, please pick this commit (on v6.18.y, backported to v6.1.y-cip and v6.12.y):
https://gitlab.com/Xenomai/xenomai4/linux-evl/-/commit/c02e718dda07cfa1db079450d352f62b32702c55
--
Philippe.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-02-19 13:28 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-17 20:28 evl. event and mutex Giulio Moro
2026-02-18 8:50 ` Philippe Gerum
2026-02-19 13:28 ` Giulio Moro
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.