summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2012-12-09 23:59:47 +0100
committerRichard Braun <rbraun@sceen.net>2012-12-09 23:59:47 +0100
commit43efe2324da8d7644cccc2ec1b354fe6bd6c4028 (patch)
treee37f076429e17857f8b50065f5ba31dd83ca53f9
parent2ea00731678790ed5712b19ad2fb84988682aaf5 (diff)
kern/thread: add preemption control functions
-rw-r--r--kern/thread.c17
-rw-r--r--kern/thread.h71
2 files changed, 72 insertions, 16 deletions
diff --git a/kern/thread.c b/kern/thread.c
index 61a2d5b0..959208ab 100644
--- a/kern/thread.c
+++ b/kern/thread.c
@@ -28,15 +28,7 @@
#include <machine/cpu.h>
#include <machine/tcb.h>
-/*
- * Per processor run queue.
- */
-struct thread_runq {
- struct thread *current;
- struct list threads;
-} __aligned(CPU_L1_SIZE);
-
-static struct thread_runq thread_runqs[MAX_CPUS];
+struct thread_runq thread_runqs[MAX_CPUS];
/*
* Caches for allocated threads and their stacks.
@@ -72,12 +64,6 @@ thread_runq_dequeue(struct thread_runq *runq)
return thread;
}
-static inline struct thread_runq *
-thread_runq_local(void)
-{
- return &thread_runqs[cpu_id()];
-}
-
void __init
thread_setup(void)
{
@@ -138,6 +124,7 @@ thread_create(struct thread **threadp, const char *name, struct task *task,
name = task->name;
thread->flags = 0;
+ thread->preempt = 0;
thread->task = task;
thread->stack = stack;
strlcpy(thread->name, name, sizeof(thread->name));
diff --git a/kern/thread.h b/kern/thread.h
index 52c0f813..3c6395c8 100644
--- a/kern/thread.h
+++ b/kern/thread.h
@@ -18,9 +18,12 @@
#ifndef _KERN_THREAD_H
#define _KERN_THREAD_H
+#include <kern/assert.h>
#include <kern/list.h>
#include <kern/macros.h>
+#include <kern/param.h>
#include <kern/task.h>
+#include <machine/cpu.h>
#include <machine/tcb.h>
/*
@@ -38,7 +41,8 @@
*/
struct thread {
struct tcb tcb;
- int flags;
+ short flags;
+ unsigned short preempt;
struct list runq_node;
struct list task_node;
struct task *task;
@@ -49,6 +53,16 @@ struct thread {
};
/*
+ * Per processor run queue.
+ */
+struct thread_runq {
+ struct thread *current;
+ struct list threads;
+} __aligned(CPU_L1_SIZE);
+
+extern struct thread_runq thread_runqs[MAX_CPUS];
+
+/*
* Initialize the thread module.
*/
void thread_setup(void);
@@ -88,4 +102,59 @@ void thread_reschedule(void);
*/
void thread_tick(void);
+static inline struct thread_runq *
+thread_runq_local(void)
+{
+ return &thread_runqs[cpu_id()];
+}
+
+static inline struct thread *
+thread_current(void)
+{
+ return thread_runq_local()->current;
+}
+
+/*
+ * Preemption control functions.
+ */
+
+static inline int
+thread_preempt_enabled(void)
+{
+ return (thread_current()->preempt == 0);
+}
+
+static inline void
+thread_preempt_enable_no_resched(void)
+{
+ struct thread *thread;
+
+ thread = thread_current();
+ assert(thread->preempt != 0);
+ thread->preempt--;
+}
+
+static inline void
+thread_preempt_enable(void)
+{
+ struct thread *thread;
+
+ thread = thread_current();
+ assert(thread->preempt != 0);
+ thread->preempt--;
+
+ if ((thread->preempt == 0) && (thread->flags & THREAD_RESCHEDULE))
+ thread_schedule();
+}
+
+static inline void
+thread_preempt_disable(void)
+{
+ struct thread *thread;
+
+ thread = thread_current();
+ thread->preempt++;
+ assert(thread->preempt != 0);
+}
+
#endif /* _KERN_THREAD_H */