parent
fa9955dd7f
commit
5b933a82d3
@ -8,6 +8,7 @@
|
|||||||
#include "vga.h"
|
#include "vga.h"
|
||||||
|
|
||||||
static struct kthread *currentThread;
|
static struct kthread *currentThread;
|
||||||
|
static struct kthread *threadWithTimeout;
|
||||||
|
|
||||||
void kthreadExit()
|
void kthreadExit()
|
||||||
{
|
{
|
||||||
@ -36,6 +37,7 @@ int kthreadSetup(vaddr_t mainStack, size_t mainStackSize)
|
|||||||
current->state = RUNNING;
|
current->state = RUNNING;
|
||||||
|
|
||||||
list_singleton(currentThread, current);
|
list_singleton(currentThread, current);
|
||||||
|
list_init_named(threadWithTimeout, timePrev, timeNext);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -47,7 +49,9 @@ struct kthread *kthreadCreate(const char *name, cpu_kstate_function_arg1_t func,
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
thread->stackAddr = (vaddr_t)malloc(KTHREAD_DEFAULT_STACK_SIZE);
|
thread->stackAddr = (vaddr_t)malloc(KTHREAD_DEFAULT_STACK_SIZE);
|
||||||
|
#ifdef DEBUG
|
||||||
printf("Alloc stask at 0x%x struct at 0x%x\n", thread->stackAddr, thread);
|
printf("Alloc stask at 0x%x struct at 0x%x\n", thread->stackAddr, thread);
|
||||||
|
#endif
|
||||||
thread->stackSize = KTHREAD_DEFAULT_STACK_SIZE;
|
thread->stackSize = KTHREAD_DEFAULT_STACK_SIZE;
|
||||||
|
|
||||||
if (!thread->stackAddr)
|
if (!thread->stackAddr)
|
||||||
@ -102,13 +106,18 @@ struct kthread *kthreadSelectNext()
|
|||||||
struct cpu_state *kthreadSwitch(struct cpu_state *prevCpu)
|
struct cpu_state *kthreadSwitch(struct cpu_state *prevCpu)
|
||||||
{
|
{
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
|
struct kthread *nextThread;
|
||||||
|
|
||||||
disable_IRQs(flags);
|
disable_IRQs(flags);
|
||||||
currentThread->cpuState = prevCpu;
|
|
||||||
currentThread->state = READY;
|
nextThread = kthreadSelectNext();
|
||||||
struct kthread *nextThread = kthreadSelectNext();
|
currentThread->cpuState = prevCpu;
|
||||||
currentThread = nextThread;
|
currentThread->state = READY;
|
||||||
currentThread->state = RUNNING;
|
currentThread = nextThread;
|
||||||
|
currentThread->state = RUNNING;
|
||||||
|
|
||||||
restore_IRQs(flags);
|
restore_IRQs(flags);
|
||||||
|
|
||||||
return nextThread->cpuState;
|
return nextThread->cpuState;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,6 +136,17 @@ int kthreadOnJieffiesTick()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
list_foreach_named(threadWithTimeout, nextThread, idx, timePrev, timeNext)
|
||||||
|
{
|
||||||
|
if (nextThread->state == WAITING && nextThread->jiffiesSleeping) {
|
||||||
|
nextThread->jiffiesSleeping--;
|
||||||
|
if (!nextThread->jiffiesSleeping) {
|
||||||
|
nextThread->sleepHaveTimeouted = 1;
|
||||||
|
list_delete_named(threadWithTimeout, nextThread, timePrev, timeNext);
|
||||||
|
kthreadAddThread(nextThread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
restore_IRQs(flags);
|
restore_IRQs(flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -138,29 +158,27 @@ int kthreadUnsched(struct kthread *th)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kthreadSaveAndYield(struct kthread *current)
|
// Must be called with IRQ disabled
|
||||||
|
int kthreadWait(struct kthread *current, struct kthread *next, unsigned long msec)
|
||||||
{
|
{
|
||||||
uint32_t flags;
|
|
||||||
|
|
||||||
disable_IRQs(flags);
|
|
||||||
struct kthread *next = kthreadSelectNext();
|
|
||||||
|
|
||||||
if (current == next) {
|
if (current == next) {
|
||||||
restore_IRQs(flags);
|
assertmsg(0, "Cannot yield from %s to %s\n", current->name, next->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
assertmsg(next->state == READY, "thread %s is in state %d\n", next->name, next->state);
|
assertmsg(next->state == READY, "thread %s is in state %d\n", next->name, next->state);
|
||||||
|
|
||||||
if (current->state == RUNNING)
|
current->jiffiesSleeping = msecs_to_jiffies(msec);
|
||||||
current->state = READY;
|
current->sleepHaveTimeouted = 0;
|
||||||
|
|
||||||
|
if (current->jiffiesSleeping)
|
||||||
|
list_add_tail_named(threadWithTimeout, current, timePrev, timeNext);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
return 0;
|
return current->sleepHaveTimeouted;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kthreadYield()
|
int kthreadYield()
|
||||||
@ -201,9 +219,10 @@ int kthreadMsleep(unsigned long msec)
|
|||||||
assertmsg(current->state == RUNNING, "thread %s is in state %d for %d\n", current->name,
|
assertmsg(current->state == RUNNING, "thread %s is in state %d for %d\n", current->name,
|
||||||
current->state, msec);
|
current->state, msec);
|
||||||
|
|
||||||
current->state = SLEEPING;
|
current->state = SLEEPING;
|
||||||
current->jiffiesSleeping = msecs_to_jiffies(msec);
|
current->sleepHaveTimeouted = 0;
|
||||||
next = kthreadSelectNext();
|
current->jiffiesSleeping = msecs_to_jiffies(msec);
|
||||||
|
next = kthreadSelectNext();
|
||||||
|
|
||||||
assert(next != current);
|
assert(next != current);
|
||||||
assert(next->state == READY);
|
assert(next->state == READY);
|
||||||
@ -211,9 +230,8 @@ int kthreadMsleep(unsigned long msec)
|
|||||||
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;
|
return current->sleepHaveTimeouted == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct kthread *getCurrentThread()
|
struct kthread *getCurrentThread()
|
||||||
|
@ -22,8 +22,11 @@ struct kthread {
|
|||||||
vaddr_t stackAddr;
|
vaddr_t stackAddr;
|
||||||
size_t stackSize;
|
size_t stackSize;
|
||||||
unsigned long jiffiesSleeping;
|
unsigned long jiffiesSleeping;
|
||||||
|
int sleepHaveTimeouted;
|
||||||
struct kthread *next;
|
struct kthread *next;
|
||||||
struct kthread *prev;
|
struct kthread *prev;
|
||||||
|
struct kthread *timeNext;
|
||||||
|
struct kthread *timePrev;
|
||||||
};
|
};
|
||||||
|
|
||||||
int kthreadSetup(vaddr_t mainStack, size_t mainStackSize);
|
int kthreadSetup(vaddr_t mainStack, size_t mainStackSize);
|
||||||
@ -36,9 +39,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 kthreadWait(struct kthread *current, struct kthread *next, unsigned long msec);
|
||||||
|
int kthreadUnsched(struct kthread *th);
|
||||||
int kthreadMsleep(unsigned long msec);
|
int kthreadMsleep(unsigned long msec);
|
||||||
int kthreadOnJieffiesTick();
|
int kthreadOnJieffiesTick();
|
||||||
struct kthread *getCurrentThread();
|
struct kthread *getCurrentThread();
|
||||||
int kthreadAddThread(struct kthread *th);
|
int kthreadAddThread(struct kthread *th);
|
||||||
int kthreadUnsched(struct kthread *th);
|
|
||||||
|
20
core/wait.c
20
core/wait.c
@ -1,7 +1,7 @@
|
|||||||
#include "wait.h"
|
|
||||||
#include "irq.h"
|
#include "irq.h"
|
||||||
#include "kthread.h"
|
#include "kthread.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
#include "wait.h"
|
||||||
|
|
||||||
int wake_up(struct wait_queue *wq)
|
int wake_up(struct wait_queue *wq)
|
||||||
{
|
{
|
||||||
@ -21,17 +21,25 @@ int wake_up(struct wait_queue *wq)
|
|||||||
|
|
||||||
int wait(struct wait_queue *wq)
|
int wait(struct wait_queue *wq)
|
||||||
{
|
{
|
||||||
struct kthread *current;
|
return waitTimeout(wq, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int waitTimeout(struct wait_queue *wq, unsigned long msec)
|
||||||
|
{
|
||||||
|
struct kthread *current, *next;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
|
int ret;
|
||||||
|
|
||||||
disable_IRQs(flags);
|
disable_IRQs(flags);
|
||||||
|
|
||||||
current = getCurrentThread();
|
current = getCurrentThread();
|
||||||
kthreadUnsched(current);
|
|
||||||
list_add_tail(wq->thread, current);
|
|
||||||
current->state = WAITING;
|
current->state = WAITING;
|
||||||
kthreadSaveAndYield(current);
|
next = kthreadSelectNext();
|
||||||
|
kthreadUnsched(current);
|
||||||
|
|
||||||
|
list_add_tail(wq->thread, current);
|
||||||
|
ret = kthreadWait(current, next, msec);
|
||||||
|
|
||||||
restore_IRQs(flags);
|
restore_IRQs(flags);
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,16 @@ struct wait_queue {
|
|||||||
struct wait_queue *prev;
|
struct wait_queue *prev;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define __WAITQUEUE_INITIALIZER(name) \
|
||||||
|
{ \
|
||||||
|
.thread = NULL, .next = NULL, .prev = NULL \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DECLARE_WAITQUEUE(name) \
|
||||||
|
struct wait_queue name = __WAITQUEUE_INITIALIZER(name)
|
||||||
|
|
||||||
int wait(struct wait_queue *);
|
int wait(struct wait_queue *);
|
||||||
|
int waitTimeout(struct wait_queue *wq, unsigned long msec);
|
||||||
int wake_up(struct wait_queue *);
|
int wake_up(struct wait_queue *);
|
||||||
|
|
||||||
#define wait_event(wq, condition) \
|
#define wait_event(wq, condition) \
|
||||||
|
Loading…
Reference in New Issue
Block a user