summaryrefslogtreecommitdiff
path: root/src/kernel/task
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/task')
-rw-r--r--src/kernel/task/task.c22
-rw-r--r--src/kernel/task/task.h2
-rw-r--r--src/kernel/task/timer.c86
-rw-r--r--src/kernel/task/timer.h2
4 files changed, 72 insertions, 40 deletions
diff --git a/src/kernel/task/task.c b/src/kernel/task/task.c
index d8670a0..68cb249 100644
--- a/src/kernel/task/task.c
+++ b/src/kernel/task/task.c
@@ -17,8 +17,6 @@ static void thread_exit2(uint32_t reason);
static void thread_delete(struct thread *th);
static void process_delete(struct process *pr);
-static uint32_t thread_runnable(struct thread *th);
-
//From task_.asm
extern uint32_t read_eip();
extern void task_idle(void*);
@@ -65,7 +63,7 @@ static struct thread *thread_next() {
while (1) {
ret = ret->next;
if (ret == 0) ret = threads;
- if (thread_runnable(ret)) {
+ if (ret->state == TS_RUNNING) {
return ret;
}
if (ret == current_thread) {
@@ -141,14 +139,6 @@ uint32_t tasking_handleException(struct registers *regs) {
return 0;
}
-/* Makes the current thread sleep. */
-void thread_sleep(uint32_t msecs) {
- if (current_thread == 0) return;
- current_thread->state = TS_SLEEPING;
- current_thread->timeWait = timer_time() + msecs;
- tasking_switch();
-}
-
/* Puts the current thread in an inactive state. */
void thread_goInactive() {
current_thread->state = TS_WAKEWAIT;
@@ -215,16 +205,6 @@ void process_exit(uint32_t retval) {
thread_exit_stackJmp(retval);
}
-/* Nonzero if given thread is not in a waiting state. */
-static uint32_t thread_runnable(struct thread *t) {
- if (t->state == TS_RUNNING) return 1;
- if (t->state == TS_SLEEPING && timer_time() >= t->timeWait) {
- t->state = TS_RUNNING;
- return 1;
- }
- return 0;
-}
-
/* For internal use only. This is called when a newly created thread first runs
(its address is the value given for EIP).
It switches to user mode if necessary and calls the entry point. */
diff --git a/src/kernel/task/task.h b/src/kernel/task/task.h
index ef93c9f..3b7d9af 100644
--- a/src/kernel/task/task.h
+++ b/src/kernel/task/task.h
@@ -6,7 +6,6 @@
#include "idt.h"
#define TS_RUNNING 0
-#define TS_SLEEPING 1 //Sleeping for a defined amount of time
#define TS_WAKEWAIT 2 //Waiting to be waked up by something precise (thread currently blocked)
#define PL_UNKNOWN 4
@@ -56,7 +55,6 @@ void tasking_switch();
void tasking_updateKernelPagetable(uint32_t idx, struct page_table *table, uint32_t tablePhysical);
uint32_t tasking_handleException(struct registers *regs);
-void thread_sleep(uint32_t msecs);
void thread_goInactive(); //Blocks the current thread. it is then waked up by another thread or a system event.
void thread_wakeUp(struct thread *t);
int proc_priv(); //Returns current privilege level
diff --git a/src/kernel/task/timer.c b/src/kernel/task/timer.c
index 1ec1523..643ca54 100644
--- a/src/kernel/task/timer.c
+++ b/src/kernel/task/timer.c
@@ -1,27 +1,13 @@
#include "timer.h"
+#include "task.h"
#include "idt.h"
#include <core/sys.h>
#include <core/monitor.h>
static uint32_t tick = 0, frequency = 0, uptime = 0;
-/* Called when IRQ0 fires. Updates the uptime variable.
- DOES NOT provoke a task switch. The task switch is called in idt.c (IRQ handler). */
-void timer_callback(struct registers *regs) {
- tick++;
- if (tick == frequency) {
- uptime++;
- tick = 0;
- }
-}
-
-/* Accessor function to get machine uptime. */
-uint32_t timer_uptime() { return uptime; }
-
-/* Accessor function, gets uptime in miliseconds. */
-uint32_t timer_time() {
- return (uptime * 1000) + (tick * 1000 / frequency);
-}
+static void timer_callback(struct registers *regs);
+static void timer_wakeUpSleepingThreads();
/* Called by kmain. Sets up the PIT and the IRQ0 handler. */
void timer_init(uint32_t freq) {
@@ -39,3 +25,69 @@ void timer_init(uint32_t freq) {
monitor_write("[PIT] ");
}
+
+/* Accessor function to get machine uptime. */
+uint32_t timer_uptime() { return uptime; }
+
+/* Accessor function, gets uptime in miliseconds. */
+uint32_t timer_time() {
+ return (uptime * 1000) + (tick * 1000 / frequency);
+}
+
+/* Called when IRQ0 fires. Updates the uptime variable.
+ DOES NOT provoke a task switch. The task switch is called in idt.c (IRQ handler). */
+void timer_callback(struct registers *regs) {
+ tick++;
+ if (tick == frequency) {
+ uptime++;
+ tick = 0;
+ }
+ timer_wakeUpSleepingThreads();
+}
+
+//************************************************ SLEEP FUNCTIONS *****************
+
+static struct sleeping_thread {
+ uint32_t wakeup_time;
+ struct thread *thread;
+ struct sleeping_thread *next;
+} *sleeping_threads = 0;
+
+/* Makes the current thread sleep. */
+void thread_sleep(uint32_t msecs) {
+ if (current_thread == 0) return;
+ // Create the sleeping_thread structure
+ struct sleeping_thread *sf = kmalloc(sizeof(struct sleeping_thread)), *tmp;
+ sf->wakeup_time = timer_time() + msecs;
+ sf->thread = current_thread;
+ //Insert it at the right place
+ if (sleeping_threads == 0) {
+ sleeping_threads = sf;
+ sf->next = 0;
+ } else if (sleeping_threads->wakeup_time >= sf->wakeup_time) {
+ sf->next = sleeping_threads;
+ sleeping_threads = sf;
+ } else {
+ tmp = sleeping_threads;
+ while (1) {
+ if (tmp->next == 0 || tmp->next->wakeup_time >= sf->wakeup_time) {
+ sf->next = tmp->next;
+ tmp->next = sf;
+ break;
+ }
+ tmp = tmp->next;
+ }
+ }
+
+ thread_goInactive();
+}
+
+void timer_wakeUpSleepingThreads() {
+ uint32_t time = timer_time();
+ while (sleeping_threads != 0 && sleeping_threads->wakeup_time <= time) {
+ struct sleeping_thread *tmp = sleeping_threads;
+ thread_wakeUp(tmp->thread);
+ sleeping_threads = tmp->next;
+ kfree(tmp);
+ }
+}
diff --git a/src/kernel/task/timer.h b/src/kernel/task/timer.h
index 4909245..cf6a2d2 100644
--- a/src/kernel/task/timer.h
+++ b/src/kernel/task/timer.h
@@ -7,4 +7,6 @@ void timer_init(uint32_t frequency);
uint32_t timer_time(); //Returns miliseconds (approximate) since computer started
uint32_t timer_uptime(); //Same thing in seconds
+void thread_sleep(uint32_t msecs);
+
#endif