93 lines
1.7 KiB
C
93 lines
1.7 KiB
C
#include "assert.h"
|
|
#include "synchro.h"
|
|
#include "alloc.h"
|
|
#include "irq.h"
|
|
#include "klibc.h"
|
|
#include "list.h"
|
|
#include "time.h"
|
|
|
|
struct wait_queue *waitQueues = NULL;
|
|
|
|
int mutexInit(struct mutex *m)
|
|
{
|
|
uint32_t flags;
|
|
|
|
m->owner = NULL;
|
|
m->wait = (struct wait_queue *)malloc(sizeof(struct wait_queue));
|
|
if (!m->wait)
|
|
return ENOMEM;
|
|
list_init(m->wait->thread);
|
|
|
|
disable_IRQs(flags);
|
|
list_add_tail(waitQueues, m->wait);
|
|
restore_IRQs(flags);
|
|
|
|
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%. owned by 0x%p 0x%p\n", m, m->owner,
|
|
getCurrenThread());
|
|
}
|
|
#endif
|
|
list_delete(waitQueues, m->wait);
|
|
free(m->wait);
|
|
} else {
|
|
ret = EBUSY;
|
|
}
|
|
restore_IRQs(flags);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int mutexLock(struct mutex *m)
|
|
{
|
|
uint32_t flags;
|
|
struct kthread *current;
|
|
|
|
disable_IRQs(flags);
|
|
current = getCurrenThread();
|
|
assert(m->owner != current);
|
|
while (m->owner) {
|
|
kthreadUnsched(current);
|
|
list_add_tail(m->wait->thread, current);
|
|
current->state = WAITING;
|
|
kthreadSaveAndYield(current);
|
|
}
|
|
m->owner = current;
|
|
|
|
restore_IRQs(flags);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int mutexUnlock(struct mutex *m)
|
|
{
|
|
struct kthread *th;
|
|
uint32_t flags;
|
|
|
|
disable_IRQs(flags);
|
|
assert(m->owner == getCurrenThread());
|
|
|
|
m->owner = NULL;
|
|
|
|
list_collapse(m->wait->thread, th){
|
|
kthreadAddThread(th);
|
|
}
|
|
|
|
restore_IRQs(flags);
|
|
|
|
return 0;
|
|
}
|