matos/core/synchro.c
2023-11-09 23:44:04 +01:00

134 lines
2.3 KiB
C

#include "synchro.h"
#include "alloc.h"
#include "assert.h"
#include "irq.h"
#include "klibc.h"
#include "list.h"
#include "time.h"
int mutexInit(struct mutex *m)
{
m->owner = NULL;
m->wait = (struct wait_queue *)malloc(sizeof(struct wait_queue));
if (!m->wait)
return ENOMEM;
waitQueueInit(m->wait);
return 0;
}
int mutexFree(struct mutex *m)
{
int ret = 0;
if (m) {
uint32_t flags;
disable_IRQs(flags);
if (list_is_empty(m->wait)) {
#ifdef DEBUG
if (m->owner) {
printf("Warning: freeing a owned mutex 0x%p. owned by 0x%p 0x%p\n", m, m->owner,
getCurrentThread());
}
#endif
waitQueueFree(m->wait);
free(m->wait);
} else {
ret = EBUSY;
}
restore_IRQs(flags);
}
return ret;
}
int mutexLock(struct mutex *m)
{
uint32_t flags;
struct thread *current;
disable_IRQs(flags);
current = getCurrentThread();
assert(m->owner != current);
wait_event(m->wait, m->owner == NULL);
m->owner = current;
restore_IRQs(flags);
return 0;
}
int mutexUnlock(struct mutex *m)
{
uint32_t flags;
disable_IRQs(flags);
assert(m->owner == getCurrentThread());
m->owner = NULL;
waitUp(m->wait);
restore_IRQs(flags);
return 0;
}
int semInit(struct semaphore *sem, int initVal)
{
sem->count = initVal;
waitQueueInit(&sem->wait);
return 0;
}
int semFree(struct semaphore *sem)
{
return waitQueueFree(&sem->wait);
}
int semDown(struct semaphore *sem, unsigned long timeout)
{
uint32_t flags;
int ret = 0;
disable_IRQs(flags);
sem->count--;
if (sem->count < 0) {
ret = waitTimeout(&sem->wait, timeout);
if (ret) {
sem->count++;
}
}
restore_IRQs(flags);
return ret;
}
int semTryDown(struct semaphore *sem)
{
uint32_t flags;
int ret = -EBUSY;
disable_IRQs(flags);
if (sem->count > 1) {
ret = 0;
sem->count--;
}
restore_IRQs(flags);
return ret;
}
int semUp(struct semaphore *sem)
{
uint32_t flags;
int ret = 0;
disable_IRQs(flags);
sem->count++;
ret = waitUpNb(&sem->wait, 1);
restore_IRQs(flags);
return ret;
}