diff --git a/src/include/kernel/event.h b/src/include/kernel/event.h new file mode 100644 index 00000000..bda649c4 --- /dev/null +++ b/src/include/kernel/event.h @@ -0,0 +1,21 @@ +#ifndef _EVENT_H_INCLUDE +#define _EVENT_H_INCLUDE + +#include +#include + +#define EVENT_MAX_THREADS 100 + +typedef struct _thread_t thread_t; + +typedef struct _event_t{ + int lock; + thread_t* threads[EVENT_MAX_THREADS]; +} event_t; + +#include + +int event_signal(event_t* event, bool interruptson); +int event_wait(event_t* event, bool interruptible); + +#endif diff --git a/src/include/kernel/sched.h b/src/include/kernel/sched.h index da10fa17..3491d912 100644 --- a/src/include/kernel/sched.h +++ b/src/include/kernel/sched.h @@ -1,6 +1,8 @@ #ifndef _SCHED_H_INCLUDE #define _SCHED_H_INCLUDE + +#include #include #include #include @@ -14,6 +16,7 @@ #define THREAD_STATE_WAITING 0 #define THREAD_STATE_RUNNING 1 #define THREAD_STATE_BLOCKED 2 +#define THREAD_STATE_BLOCKED_INTR 3 typedef unsigned long state_t; @@ -26,6 +29,8 @@ typedef struct _thread_t{ arch_regs* regs; arch_extraregs extraregs; state_t state; + event_t sigevent; + event_t* awokenby; void* kernelstack; void* kernelstackbase; size_t stacksize; @@ -59,5 +64,8 @@ typedef struct{ } sched_queue; void sched_init(); - +void sched_runinit(); +void sched_eventsignal(event_t* event, thread_t* thread); +void sched_block(bool interruptible); +void sched_yield(); #endif diff --git a/src/sys/event.c b/src/sys/event.c new file mode 100644 index 00000000..47a912d3 --- /dev/null +++ b/src/sys/event.c @@ -0,0 +1,101 @@ +#include +#include +#include +#include + +static bool addtoevent(thread_t* thread, event_t* event){ + + spinlock_acquire(&event->lock); + + uintmax_t i = 0; + + for(; i < EVENT_MAX_THREADS; ++i){ + if(!event->threads[i]){ + event->threads[i] = arch_getcls()->thread; + break; + } + } + + spinlock_release(&event->lock); + + return true; + +} + +void removefromevent(thread_t* thread, event_t* event){ + spinlock_acquire(&event->lock); + + for(size_t i = 0; i < EVENT_MAX_THREADS; ++i){ + if(event->threads[i] == thread){ + event->threads[i] = NULL; + break; + } + } + + spinlock_release(&event->lock); +} + +int event_wait(event_t* event, bool interruptible){ + + + arch_interrupt_disable(); + + thread_t* thread = arch_getcls()->thread; + + if(interruptible){ + addtoevent(thread, &thread->sigevent); + } + + addtoevent(thread, event); + + + // ... + + + int ret = 0; + + event_t* awokenby = thread->awokenby; + + if(awokenby == &thread->sigevent){ + ret = EINTR; + removefromevent(thread, awokenby); + awokenby = event; + } + + removefromevent(thread, awokenby); + + spinlock_release(&event->lock); + + arch_interrupt_enable(); + + return ret; + +} + +int event_signal(event_t* event, bool interruptson){ + + if(interruptson) + arch_interrupt_disable(); + + spinlock_acquire(&event->lock); + + + for(uintmax_t i = 0; i < EVENT_MAX_THREADS; ++i){ + + thread_t* thread = event->threads[i]; + + if(!thread) + continue; + + // ... + + + } + + + spinlock_release(&event->lock); + + if(interruptson) + arch_interrupt_enable(); + +} diff --git a/src/sys/sched/scheduler.c b/src/sys/sched/scheduler.c index ee444730..e328c21d 100644 --- a/src/sys/sched/scheduler.c +++ b/src/sys/sched/scheduler.c @@ -262,12 +262,35 @@ thread_t* sched_newkthread(void* ip, size_t stacksize, bool run, int prio){ return thread; } +void sched_eventsignal(event_t* event, thread_t* thread){ + if((thread->state == THREAD_STATE_BLOCKED_INTR || (thread->state == THREAD_STATE_BLOCKED && event != &thread->sigevent))) + return; + + thread->state = THREAD_STATE_WAITING; + thread->awokenby = event; + queue_remove(&blocked, thread); + queue_add(&queues[thread->priority], thread); + +} + +void sched_block(bool interruptible){ + + thread_t* thread = arch_getcls()->thread; + + queue_remove(&queues[thread->priority], thread); + queue_add(&blocked, thread); + thread->state = interruptible ? THREAD_STATE_BLOCKED_INTR : THREAD_STATE_BLOCKED; + + sched_yield(); + +} + void sched_init(){ arch_getcls()->thread = allocthread(NULL, THREAD_STATE_RUNNING, 0, 0); arch_getcls()->thread->priority = THREAD_PRIORITY_KERNEL; timer_req* req = &arch_getcls()->schedreq; - + req->func = sched_timerhook; } @@ -327,14 +350,20 @@ void sched_runinit(){ char* argv[] = {"/usr/bin/bash", NULL}; char* env[] = {NULL}; + + void *entry, *stack; - ret = elf_load(thread, node, argv, env); + ret = elf_load(thread, node, argv, env, &stack, &entry); if(ret){ printf("ELF load error: %s\n", strerror(ret)); _panic("Could not load init", 0); } + arch_regs_setupuser(thread->regs, entry, stack, true); + + timer_add(&arch_getcls()->schedreq, THREAD_QUANTUM, true); + switch_thread(thread); }