2 * Copyright (c) 2008 Joshua Phillips. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
34 #include "interrupt.h"
37 static struct thread
*thread_first
= NULL
;
38 static struct thread
*thread_last
= NULL
;
39 static struct thread
*thread_current
= NULL
;
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
)
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)
82 if (t
->suspend_count
== 0){
88 static void switch_to_thread(struct thread
*thread
)
90 thread_current
= thread
;
92 next_preempt
= get_tick() + 100;
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();
111 switch_to_thread(next_thread
);
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
);
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
;
132 thread_last
->next
= new_thread
;
134 thread_first
= new_thread
;
136 thread_last
= new_thread
;
138 memset(&new_thread
->regs
, 0, sizeof new_thread
->regs
);
140 new_thread
->eflags
= 0x0202;
141 new_thread
->aspace
= NULL
;
146 void thread_set_aspace(struct thread
*t
, struct addr_space
*aspace
)
151 void thread_set_eip(struct thread
*t
, uint32_t eip
)
156 void thread_set_esp(struct thread
*t
, uint32_t esp
)
161 void thread_resume(struct thread
*t
)
163 if (t
->suspend_count
> 0){
168 void thread_suspend(struct thread
*t
)
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
181 t
->prev
->next
= t
->next
;
183 thread_first
= t
->next
;
186 t
->next
->prev
= t
->prev
;
188 thread_last
= t
->prev
;
193 void yield_internal(void)
195 struct thread
*next_thread
;
196 next_thread
= get_next_thread();
198 switch_to_thread(next_thread
);
200 trace("yield_internal: no threads\n");
206 store_call(yield_internal
);
209 void preempt(struct interrupt_stack
*is
)
211 struct thread
*next_thread
;
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();
221 switch_to_thread(next_thread
);
223 trace("preempt: no threads\n");