feat: add deadlock verification

This commit is contained in:
Martin Eyben 2025-03-25 10:35:02 +01:00
parent ea5017321b
commit f6a78b3516

View File

@ -9,6 +9,7 @@
#include <sys/queue.h> #include <sys/queue.h>
#include <ucontext.h> #include <ucontext.h>
#include <valgrind/valgrind.h> #include <valgrind/valgrind.h>
#include <errno.h>
#define FINISHED 0x1 #define FINISHED 0x1
#define IS_FINISHED(entry) (entry->status & FINISHED) #define IS_FINISHED(entry) (entry->status & FINISHED)
@ -49,7 +50,7 @@ static struct context_entry* running = NULL;
int thread_yield(void) int thread_yield(void)
{ {
TRACE("thread_yield"); //TRACE("thread_yield");
if (TAILQ_EMPTY(&head)) { if (TAILQ_EMPTY(&head)) {
return 0; return 0;
} }
@ -140,10 +141,20 @@ int thread_join(thread_t thread, void** retval)
TRACE("Join thread %p", thread); TRACE("Join thread %p", thread);
struct context_entry* entry = thread; struct context_entry* entry = thread;
// Check if the target is not already waited by another // Check if the target is not already waited by another
if (IS_WAITED(entry) || IS_WAITING(entry) && GET_WAITED_THREAD(entry) == running) { if (IS_WAITED(entry)) {
return -1; return -1;
} }
// Check if there is a deadlock
struct context_entry* parent = thread;
while (IS_WAITING(parent)) {
if (GET_WAITED_THREAD(parent) == running) {
TRACE("Deadlock detected");
return EDEADLK;
}
parent = GET_WAITED_THREAD(parent);
}
if (!IS_FINISHED(entry)) { if (!IS_FINISHED(entry)) {
// Use status to be in waiting state // Use status to be in waiting state
running->status |= WAITING; running->status |= WAITING;
@ -152,6 +163,8 @@ int thread_join(thread_t thread, void** retval)
entry->status |= WAITED; entry->status |= WAITED;
// Use retvalue to share which thread is currently waiting for this thread // Use retvalue to share which thread is currently waiting for this thread
entry->retvalue = running; entry->retvalue = running;
DBG("%p is waiting for %p", running, entry);
do { do {
thread_yield(); thread_yield();
} while (!IS_FINISHED(entry)); } while (!IS_FINISHED(entry));