Add mutex implementation
This commit is contained in:
parent
1230d738a6
commit
0f200d1911
@ -106,7 +106,6 @@ struct cpu_state *kthreadSwitch(struct cpu_state *prevCpu)
|
|||||||
currentThread->cpuState = prevCpu;
|
currentThread->cpuState = prevCpu;
|
||||||
currentThread->state = READY;
|
currentThread->state = READY;
|
||||||
struct kthread *nextThread = kthreadSelectNext();
|
struct kthread *nextThread = kthreadSelectNext();
|
||||||
printStringDetails(nextThread->name, RED, BLACK, 40, VGA_HEIGHT - 1);
|
|
||||||
currentThread = nextThread;
|
currentThread = nextThread;
|
||||||
currentThread->state = RUNNING;
|
currentThread->state = RUNNING;
|
||||||
restore_IRQs(flags);
|
restore_IRQs(flags);
|
||||||
@ -121,7 +120,7 @@ int kthreadOnJieffiesTick()
|
|||||||
disable_IRQs(flags);
|
disable_IRQs(flags);
|
||||||
list_foreach(currentThread, nextThread, idx)
|
list_foreach(currentThread, nextThread, idx)
|
||||||
{
|
{
|
||||||
if (nextThread->state == SLEEPING) {
|
if (nextThread->state == SLEEPING && nextThread->jiffiesSleeping) {
|
||||||
nextThread->jiffiesSleeping--;
|
nextThread->jiffiesSleeping--;
|
||||||
if (!nextThread->jiffiesSleeping) {
|
if (!nextThread->jiffiesSleeping) {
|
||||||
nextThread->state = READY;
|
nextThread->state = READY;
|
||||||
@ -132,23 +131,62 @@ int kthreadOnJieffiesTick()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kthreadYield()
|
int kthreadUnsched(struct kthread *th)
|
||||||
|
{
|
||||||
|
list_delete(currentThread, th);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int kthreadSaveAndYield(struct kthread *current)
|
||||||
{
|
{
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
|
|
||||||
disable_IRQs(flags);
|
disable_IRQs(flags);
|
||||||
struct kthread *next = kthreadSelectNext();
|
struct kthread *next = kthreadSelectNext();
|
||||||
struct kthread *current = currentThread;
|
|
||||||
if (current == next) {
|
if (current == next) {
|
||||||
restore_IRQs(flags);
|
restore_IRQs(flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
assert(current->state == RUNNING);
|
|
||||||
assert(next->state == READY);
|
assertmsg(next->state == READY, "thread %s is in state %d\n", next->name, next->state);
|
||||||
current->state = READY;
|
|
||||||
|
if (current->state == RUNNING)
|
||||||
|
current->state = READY;
|
||||||
|
|
||||||
currentThread = next;
|
currentThread = next;
|
||||||
currentThread->state = RUNNING;
|
currentThread->state = RUNNING;
|
||||||
cpu_context_switch(¤t->cpuState, next->cpuState);
|
cpu_context_switch(¤t->cpuState, next->cpuState);
|
||||||
restore_IRQs(flags);
|
restore_IRQs(flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int kthreadYield()
|
||||||
|
{
|
||||||
|
uint32_t flags;
|
||||||
|
|
||||||
|
disable_IRQs(flags);
|
||||||
|
struct kthread *next = kthreadSelectNext();
|
||||||
|
struct kthread *current = currentThread;
|
||||||
|
|
||||||
|
if (current == next) {
|
||||||
|
restore_IRQs(flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(current->state == RUNNING);
|
||||||
|
assertmsg(next->state == READY, "thread %s is in state %d\n", next->name, next->state);
|
||||||
|
|
||||||
|
if (current->state == RUNNING)
|
||||||
|
current->state = READY;
|
||||||
|
|
||||||
|
currentThread = next;
|
||||||
|
currentThread->state = RUNNING;
|
||||||
|
cpu_context_switch(¤t->cpuState, next->cpuState);
|
||||||
|
restore_IRQs(flags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +195,8 @@ int kthreadMsleep(unsigned long msec)
|
|||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
disable_IRQs(flags);
|
disable_IRQs(flags);
|
||||||
struct kthread *current = currentThread;
|
struct kthread *current = currentThread;
|
||||||
assert(current->state == RUNNING);
|
assertmsg(current->state == RUNNING, "thread %s is in state %d for %d\n", current->name,
|
||||||
|
current->state, msec);
|
||||||
current->state = SLEEPING;
|
current->state = SLEEPING;
|
||||||
struct kthread *next = kthreadSelectNext();
|
struct kthread *next = kthreadSelectNext();
|
||||||
assert(next != current);
|
assert(next != current);
|
||||||
@ -174,3 +213,14 @@ struct kthread *getCurrenThread()
|
|||||||
{
|
{
|
||||||
return currentThread;
|
return currentThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int kthreadAddThread(struct kthread *th)
|
||||||
|
{
|
||||||
|
if (th->state == READY)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
th->state = READY;
|
||||||
|
list_add_tail(currentThread, th);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -11,6 +11,7 @@ typedef enum {
|
|||||||
RUNNING,
|
RUNNING,
|
||||||
READY,
|
READY,
|
||||||
SLEEPING,
|
SLEEPING,
|
||||||
|
WAITING,
|
||||||
EXITING
|
EXITING
|
||||||
} kthread_state;
|
} kthread_state;
|
||||||
|
|
||||||
@ -35,6 +36,9 @@ struct kthread *kthreadSelectNext();
|
|||||||
struct cpu_state *kthreadSwitch(struct cpu_state *prevCpu);
|
struct cpu_state *kthreadSwitch(struct cpu_state *prevCpu);
|
||||||
|
|
||||||
int kthreadYield();
|
int kthreadYield();
|
||||||
|
int kthreadSaveAndYield(struct kthread *);
|
||||||
int kthreadMsleep(unsigned long msec);
|
int kthreadMsleep(unsigned long msec);
|
||||||
int kthreadOnJieffiesTick();
|
int kthreadOnJieffiesTick();
|
||||||
struct kthread *getCurrenThread();
|
struct kthread *getCurrenThread();
|
||||||
|
int kthreadAddThread(struct kthread *th);
|
||||||
|
int kthreadUnsched(struct kthread *th);
|
||||||
|
92
core/synchro.c
Normal file
92
core/synchro.c
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#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;
|
||||||
|
}
|
7
core/synchro.h
Normal file
7
core/synchro.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <wait.h>
|
||||||
|
|
||||||
|
int mutexInit(struct mutex *);
|
||||||
|
int mutexFree(struct mutex *);
|
||||||
|
int mutexLock(struct mutex *);
|
||||||
|
int mutexUnlock(struct mutex *);
|
19
core/wait.h
Normal file
19
core/wait.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "kthread.h"
|
||||||
|
|
||||||
|
struct wait_queue {
|
||||||
|
struct kthread *thread;
|
||||||
|
struct wait_queue *next;
|
||||||
|
struct wait_queue *prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct semaphore {
|
||||||
|
int count;
|
||||||
|
struct wait_queue *wait;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mutex {
|
||||||
|
struct kthread *owner;
|
||||||
|
struct wait_queue *wait;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user