2020-07-08 23:08:50 +02:00
|
|
|
#include "synchro.h"
|
|
|
|
#include "alloc.h"
|
2020-08-15 23:31:35 +02:00
|
|
|
#include "assert.h"
|
2020-07-08 23:08:50 +02:00
|
|
|
#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;
|
2020-08-19 14:31:16 +02:00
|
|
|
|
|
|
|
waitQueueInit(m->wait);
|
2020-07-08 23:08:50 +02:00
|
|
|
|
|
|
|
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) {
|
2023-11-09 20:30:09 +01:00
|
|
|
printf("Warning: freeing a owned mutex 0x%p. owned by 0x%p 0x%p\n", m, m->owner,
|
2020-08-16 00:24:59 +02:00
|
|
|
getCurrentThread());
|
2020-07-08 23:08:50 +02:00
|
|
|
}
|
|
|
|
#endif
|
2020-08-19 14:31:16 +02:00
|
|
|
waitQueueFree(m->wait);
|
2020-07-08 23:08:50 +02:00
|
|
|
free(m->wait);
|
|
|
|
} else {
|
|
|
|
ret = EBUSY;
|
|
|
|
}
|
|
|
|
restore_IRQs(flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int mutexLock(struct mutex *m)
|
|
|
|
{
|
|
|
|
uint32_t flags;
|
2021-10-30 14:08:12 +02:00
|
|
|
struct thread *current;
|
2020-07-08 23:08:50 +02:00
|
|
|
|
|
|
|
disable_IRQs(flags);
|
2020-08-16 00:24:59 +02:00
|
|
|
current = getCurrentThread();
|
2020-07-08 23:08:50 +02:00
|
|
|
assert(m->owner != current);
|
2020-08-15 23:31:35 +02:00
|
|
|
wait_event(m->wait, m->owner == NULL);
|
2020-07-08 23:08:50 +02:00
|
|
|
m->owner = current;
|
|
|
|
|
|
|
|
restore_IRQs(flags);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int mutexUnlock(struct mutex *m)
|
|
|
|
{
|
|
|
|
uint32_t flags;
|
|
|
|
|
|
|
|
disable_IRQs(flags);
|
2020-08-16 00:24:59 +02:00
|
|
|
assert(m->owner == getCurrentThread());
|
2020-07-08 23:08:50 +02:00
|
|
|
|
|
|
|
m->owner = NULL;
|
2020-08-15 23:31:35 +02:00
|
|
|
|
2021-11-09 20:13:40 +01:00
|
|
|
waitUp(m->wait);
|
2020-07-08 23:08:50 +02:00
|
|
|
|
|
|
|
restore_IRQs(flags);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2021-11-09 20:13:40 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|