Removed excessive trace messages from threading code.
[marionette.git] / kernel / thread.c
bloba395acdb2849aad84ab836f1a0788be135bc37d8
1 /*
2 * Copyright (c) 2008 Joshua Phillips. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
15 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #define USE_TRACE
30 #include "thread.h"
31 #include "stdlib.h"
32 #include "string.h"
33 #include "console.h"
34 #include "interrupt.h"
35 #include "timer.h"
37 static struct thread *thread_first = NULL;
38 static struct thread *thread_last = NULL;
39 static struct thread *thread_current = NULL;
41 int preempt_on = 0;
42 tick_t next_preempt = 0;
44 // defined in thread-asm.S
45 void context_switch(struct pusha_struct *regs, uint32_t eip, uint32_t eflags);
46 void store_call(void (* func_ptr)(void));
48 void thread_save_call_state(uint32_t ebx, uint32_t esp, uint32_t ebp, uint32_t esi, uint32_t edi, uint32_t eip, uint32_t eflags)
50 if (!thread_current){
51 return;
53 thread_current->regs.eax = 0;
54 thread_current->regs.ecx = 0;
55 thread_current->regs.edx = 0;
56 thread_current->regs.ebx = ebx;
57 thread_current->regs.esp = esp;
58 thread_current->regs.ebp = ebp;
59 thread_current->regs.esi = esi;
60 thread_current->regs.edi = edi;
61 thread_current->eip = eip;
62 thread_current->eflags = eflags;
65 static struct thread *get_next_thread(void)
67 struct thread *t;
68 if (!thread_current){
69 t = thread_last;
70 } else {
71 t = thread_current;
73 if (!t){
74 return NULL;
76 for (;;){
77 if (t->next){
78 t = t->next;
79 } else {
80 t = thread_first;
82 if (t->suspend_count == 0){
83 return t;
88 static void switch_to_thread(struct thread *thread)
90 thread_current = thread;
91 preempt_on = 1;
92 next_preempt = get_tick() + 100;
93 if (thread->aspace){
94 addr_space_switch(thread->aspace);
96 context_switch(&thread->regs, thread->eip, thread->eflags);
99 // initialize the threading system
100 void thread_sys_init(void)
105 // start the threading system
106 void thread_sys_start(void)
108 struct thread *next_thread;
109 next_thread = get_next_thread();
110 if (next_thread){
111 switch_to_thread(next_thread);
112 } else {
113 trace("thread_sys_start: no threads\n");
117 struct thread *thread_new(void)
119 struct thread *new_thread;
120 new_thread = malloc(sizeof *new_thread);
121 if (!new_thread){
122 return NULL;
125 // set thread as suspended
126 new_thread->suspend_count = 1;
128 // linked-list insert
129 new_thread->prev = thread_last;
130 new_thread->next = NULL;
131 if (thread_last){
132 thread_last->next = new_thread;
133 } else {
134 thread_first = new_thread;
136 thread_last = new_thread;
138 memset(&new_thread->regs, 0, sizeof new_thread->regs);
139 new_thread->eip = 0;
140 new_thread->eflags = 0x0202;
141 new_thread->aspace = NULL;
143 return new_thread;
146 void thread_set_aspace(struct thread *t, struct addr_space *aspace)
148 t->aspace = aspace;
151 void thread_set_eip(struct thread *t, uint32_t eip)
153 t->eip = eip;
156 void thread_set_esp(struct thread *t, uint32_t esp)
158 t->regs.esp = esp;
161 void thread_resume(struct thread *t)
163 if (t->suspend_count > 0){
164 t->suspend_count--;
168 void thread_suspend(struct thread *t)
170 t->suspend_count++;
171 // TODO: if this is the current thread,
172 // need to switch away from it.
175 void thread_delete(struct thread *t)
177 // TODO: if this is the current thread,
178 // need to switch away from it
179 // TODO; more cleanup
180 if (t->prev){
181 t->prev->next = t->next;
182 } else {
183 thread_first = t->next;
185 if (t->next){
186 t->next->prev = t->prev;
187 } else {
188 thread_last = t->prev;
190 free(t);
193 void yield_internal(void)
195 struct thread *next_thread;
196 next_thread = get_next_thread();
197 if (next_thread){
198 switch_to_thread(next_thread);
199 } else {
200 trace("yield_internal: no threads\n");
204 void yield(void)
206 store_call(yield_internal);
209 void preempt(struct interrupt_stack *is)
211 struct thread *next_thread;
212 preempt_on = 0;
213 if (thread_current){
214 // store thread state
215 thread_current->regs = is->r;
216 thread_current->eip = is->eip;
217 thread_current->eflags = is->eflags;
219 next_thread = get_next_thread();
220 if (next_thread){
221 switch_to_thread(next_thread);
222 } else {
223 trace("preempt: no threads\n");