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.
35 static struct thread
*thread_first
= NULL
;
36 static struct thread
*thread_last
= NULL
;
37 static struct thread
*thread_current
= NULL
;
39 // defined in thread-asm.S
40 void context_switch(struct pusha_struct
*regs
, uint32_t eip
, uint32_t eflags
);
41 void store_call(void (* func_ptr
)(void));
43 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
)
48 thread_current
->regs
.eax
= 0;
49 thread_current
->regs
.ecx
= 0;
50 thread_current
->regs
.edx
= 0;
51 thread_current
->regs
.ebx
= ebx
;
52 thread_current
->regs
.esp
= esp
;
53 thread_current
->regs
.ebp
= ebp
;
54 thread_current
->regs
.esi
= esi
;
55 thread_current
->regs
.edi
= edi
;
56 thread_current
->eip
= eip
;
57 thread_current
->eflags
= eflags
;
60 static struct thread
*get_next_thread(void)
77 if (t
->suspend_count
== 0){
83 static void switch_to_thread(struct thread
*thread
)
85 thread_current
= thread
;
87 addr_space_switch(thread
->aspace
);
89 trace("eip=0x%.8X, eflags=0x%.8X\n", thread
->eip
, thread
->eflags
);
90 trace("esp=0x%.8x\n", thread
->regs
.esp
);
91 context_switch(&thread
->regs
, thread
->eip
, thread
->eflags
);
94 // initialize the threading system
95 void thread_sys_init(void)
100 // start the threading system
101 void thread_sys_start(void)
103 struct thread
*next_thread
;
104 next_thread
= get_next_thread();
106 switch_to_thread(next_thread
);
108 trace("thread_sys_start: no threads\n");
112 struct thread
*thread_new(void)
114 struct thread
*new_thread
;
115 new_thread
= malloc(sizeof *new_thread
);
120 // set thread as suspended
121 new_thread
->suspend_count
= 1;
123 // linked-list insert
124 new_thread
->prev
= thread_last
;
126 thread_last
->next
= new_thread
;
128 thread_first
= new_thread
;
130 new_thread
->next
= NULL
;
131 thread_last
= new_thread
;
133 memset(&new_thread
->regs
, 0, sizeof new_thread
->regs
);
135 new_thread
->eflags
= 0x0202;
136 new_thread
->aspace
= NULL
;
141 void thread_set_aspace(struct thread
*t
, struct addr_space
*aspace
)
146 void thread_set_eip(struct thread
*t
, uint32_t eip
)
151 void thread_set_esp(struct thread
*t
, uint32_t esp
)
156 void thread_resume(struct thread
*t
)
158 if (t
->suspend_count
> 0){
163 void thread_suspend(struct thread
*t
)
166 // TODO: if this is the current thread,
167 // need to switch away from it.
170 void thread_delete(struct thread
*t
)
172 // TODO: if this is the current thread,
173 // need to switch away from it
174 // TODO; more cleanup
176 t
->prev
->next
= t
->next
;
178 thread_first
= t
->next
;
181 t
->next
->prev
= t
->prev
;
183 thread_last
= t
->prev
;
188 void yield_internal(void)
190 struct thread
*next_thread
;
191 next_thread
= get_next_thread();
193 switch_to_thread(next_thread
);
195 trace("yield_internal: no threads\n");
201 store_call(yield_internal
);