matos/core/kthread.c

177 lines
4.6 KiB
C
Raw Normal View History

2020-04-23 00:49:09 +02:00
#include "kthread.h"
#include "alloc.h"
2020-04-24 23:34:34 +02:00
#include "assert.h"
#include "irq.h"
2020-04-23 00:49:09 +02:00
#include "klibc.h"
2020-04-24 23:34:34 +02:00
#include "list.h"
2020-04-27 23:08:36 +02:00
#include "time.h"
2020-04-23 23:40:16 +02:00
#include "vga.h"
2020-04-23 00:49:09 +02:00
static struct kthread *currentThread;
2020-04-24 23:34:34 +02:00
void kthreadExit()
{
uint32_t flags;
disable_IRQs(flags);
struct kthread *current = currentThread;
struct kthread *next = kthreadSelectNext();
if (next == current)
assert("cannot exit thread");
2020-05-03 14:45:26 +02:00
currentThread->state = EXITING;
currentThread = next;
currentThread->state = RUNNING;
cpu_context_exit_to(next->cpuState, (cpu_kstate_function_arg1_t *)kthreadDelete,
(uint32_t)current);
restore_IRQs(flags);
return;
2020-04-23 00:49:09 +02:00
}
2020-04-24 23:40:19 +02:00
int kthreadSetup(vaddr_t mainStack, size_t mainStackSize)
{
struct kthread *current = (struct kthread *)malloc(sizeof(struct kthread));
strzcpy(current->name, "[KINIT]", KTHREAD_NAME_MAX_LENGTH);
current->stackAddr = mainStack;
current->stackSize = mainStackSize;
2020-04-23 00:49:09 +02:00
2020-05-03 23:11:45 +02:00
current->state = RUNNING;
list_singleton(currentThread, current);
2020-04-23 00:49:09 +02:00
return 0;
2020-04-23 00:49:09 +02:00
}
2020-04-24 23:40:19 +02:00
struct kthread *kthreadCreate(const char *name, cpu_kstate_function_arg1_t func, void *args)
2020-04-23 00:49:09 +02:00
{
struct kthread *thread = (struct kthread *)malloc(sizeof(struct kthread));
if (!thread)
return NULL;
2020-04-23 00:49:09 +02:00
thread->stackAddr = (vaddr_t)malloc(KTHREAD_DEFAULT_STACK_SIZE);
2020-05-03 14:45:26 +02:00
printf("Alloc stask at 0x%x struct at 0x%x\n", thread->stackAddr, thread);
thread->stackSize = KTHREAD_DEFAULT_STACK_SIZE;
2020-04-23 00:49:09 +02:00
if (!thread->stackAddr)
goto free_mem;
2020-04-23 00:49:09 +02:00
if (name)
strzcpy(thread->name, name, KTHREAD_NAME_MAX_LENGTH);
else
strzcpy(thread->name, "[UNKNOW]", KTHREAD_NAME_MAX_LENGTH);
2020-04-23 00:49:09 +02:00
if (cpu_kstate_init(&thread->cpuState, (cpu_kstate_function_arg1_t *)func, (vaddr_t)args,
thread->stackAddr, thread->stackSize,
(cpu_kstate_function_arg1_t *)kthreadExit, 0))
goto free_mem;
2020-04-23 00:49:09 +02:00
2020-05-03 14:45:26 +02:00
thread->state = READY;
uint32_t flags;
disable_IRQs(flags);
list_add_tail(currentThread, thread);
2020-05-03 14:45:26 +02:00
restore_IRQs(flags);
return thread;
2020-04-23 00:49:09 +02:00
free_mem:
free((void *)thread->stackAddr);
free((void *)thread);
return NULL;
2020-04-23 00:49:09 +02:00
}
2020-04-24 23:40:19 +02:00
void kthreadDelete(struct kthread *thread)
{
2020-05-03 23:13:17 +02:00
uint32_t flags;
disable_IRQs(flags);
list_delete(currentThread, thread);
2020-04-23 00:49:09 +02:00
free((void *)thread->stackAddr);
free((void *)thread);
2020-05-03 23:13:17 +02:00
restore_IRQs(flags);
2020-04-23 00:49:09 +02:00
}
2020-04-24 23:40:19 +02:00
struct kthread *kthreadSelectNext()
{
2020-05-03 14:45:26 +02:00
struct kthread *nextThread;
int idx;
list_foreach(currentThread->next, nextThread, idx)
{
if (nextThread->state == READY) {
return nextThread;
}
}
2020-05-03 23:13:17 +02:00
return currentThread;
2020-04-23 23:40:16 +02:00
}
2020-04-27 23:08:36 +02:00
struct cpu_state *kthreadSwitch(struct cpu_state *prevCpu)
2020-04-24 23:34:34 +02:00
{
uint32_t flags;
disable_IRQs(flags);
currentThread->cpuState = prevCpu;
2020-05-03 14:45:26 +02:00
currentThread->state = READY;
struct kthread *nextThread = kthreadSelectNext();
printStringDetails(nextThread->name, RED, BLACK, 40, VGA_HEIGHT - 1);
2020-05-03 14:45:26 +02:00
currentThread = nextThread;
currentThread->state = RUNNING;
restore_IRQs(flags);
return nextThread->cpuState;
2020-04-23 00:49:09 +02:00
}
2020-04-24 23:34:34 +02:00
2020-05-03 14:45:26 +02:00
int kthreadOnJieffiesTick()
{
struct kthread *nextThread;
int idx;
uint32_t flags;
disable_IRQs(flags);
list_foreach(currentThread, nextThread, idx)
{
if (nextThread->state == SLEEPING) {
nextThread->jiffiesSleeping--;
if (!nextThread->jiffiesSleeping) {
nextThread->state = READY;
}
}
}
restore_IRQs(flags);
return 0;
}
2020-04-24 23:34:34 +02:00
int kthreadYield()
{
uint32_t flags;
disable_IRQs(flags);
struct kthread *next = kthreadSelectNext();
struct kthread *current = currentThread;
2020-05-03 14:45:26 +02:00
if (current == next) {
restore_IRQs(flags);
return 0;
}
2020-05-03 23:13:17 +02:00
assert(current->state == RUNNING);
assert(next->state == READY);
current->state = READY;
2020-05-03 14:45:26 +02:00
currentThread = next;
currentThread->state = RUNNING;
cpu_context_switch(&current->cpuState, next->cpuState);
restore_IRQs(flags);
return 0;
2020-04-24 23:34:34 +02:00
}
2020-05-03 14:45:26 +02:00
int kthreadMsleep(unsigned long msec)
{
uint32_t flags;
disable_IRQs(flags);
struct kthread *current = currentThread;
2020-05-03 23:13:17 +02:00
assert(current->state == RUNNING);
current->state = SLEEPING;
struct kthread *next = kthreadSelectNext();
2020-05-03 14:45:26 +02:00
assert(next != current);
current->jiffiesSleeping = msecs_to_jiffies(msec);
assert(next->state == READY);
currentThread = next;
currentThread->state = RUNNING;
cpu_context_switch(&current->cpuState, next->cpuState);
restore_IRQs(flags);
return 0;
}
struct kthread *getCurrenThread()
{
return currentThread;
}