65 |
static struct queue_entry thread_list = queue_ctor (thread_list); |
static struct queue_entry thread_list = queue_ctor (thread_list); |
66 |
static spin_lock_t thread_list_lock; |
static spin_lock_t thread_list_lock; |
67 |
|
|
68 |
|
void thread_deallocate (struct thread *thread); |
69 |
|
|
70 |
|
|
71 |
|
|
72 |
/* Wait semantics. |
/* Wait semantics. |
73 |
|
|
103 |
if (! stack) |
if (! stack) |
104 |
panic ("no kernel stack for thread %p", thread); |
panic ("no kernel stack for thread %p", thread); |
105 |
|
|
106 |
|
trace_printf ("allocated stack %p for thread %p", |
107 |
|
stack, thread); |
108 |
|
|
109 |
trace_count (kernel_stacks++); |
trace_count (kernel_stacks++); |
110 |
STACK_ATTACH (thread, stack, continuation); |
STACK_ATTACH (thread, stack, continuation); |
111 |
} |
} |
116 |
void |
void |
117 |
reaper_continuation (void) |
reaper_continuation (void) |
118 |
{ |
{ |
119 |
/* ??? dead code right now. */ |
struct thread *thread; |
120 |
thread_sleep ((int) &reaper_list, 0, reaper_continuation); |
|
121 |
|
spin_lock (&reaper_lock); |
122 |
|
|
123 |
|
thread = (struct thread *) queue_first (&reaper_list); |
124 |
|
while (! queue_empty (&reaper_list)) |
125 |
|
{ |
126 |
|
queue_remove_first (&reaper_list, thread, struct thread *, runq); |
127 |
|
thread_deallocate (thread); |
128 |
|
} |
129 |
|
|
130 |
|
thread_sleep ((int) &reaper_list, &reaper_lock, reaper_continuation); |
131 |
} |
} |
132 |
|
|
133 |
/* Create a new thread in TASK. The thread is returned in THREADP. */ |
/* Create a new thread in TASK. The thread is returned in THREADP. */ |
192 |
return KERN_SUCCESS; |
return KERN_SUCCESS; |
193 |
} |
} |
194 |
|
|
195 |
|
/* Deallocate resources held by THREAD. */ |
196 |
|
|
197 |
|
void |
198 |
|
thread_deallocate (struct thread *thread) |
199 |
|
{ |
200 |
|
SPL_T spl; |
201 |
|
|
202 |
|
/* ??? check reference counter here? */ |
203 |
|
|
204 |
|
thread_lock (thread); |
205 |
|
|
206 |
|
if (--thread->ref_cnt != 0) |
207 |
|
{ |
208 |
|
thread_unlock (thread); |
209 |
|
return; |
210 |
|
} |
211 |
|
|
212 |
|
/* Since we held the last refernece to the thread we do not |
213 |
|
need to unlock it (no-one else should try to access it. */ |
214 |
|
|
215 |
|
/* ??? only be called from reaper? */ |
216 |
|
ASSERT (thread->sched_state & THREAD_STATE_ZOMBIE); |
217 |
|
|
218 |
|
if (thread->kernel_stack) |
219 |
|
kmem_cache_free (stack_cache, (void *) thread->kernel_stack); |
220 |
|
|
221 |
|
/* ??? release other resources. */ |
222 |
|
|
223 |
|
/* Remove thread from thread list. */ |
224 |
|
|
225 |
|
spl = SPLOFF (); |
226 |
|
spin_lock (&thread_list_lock); |
227 |
|
queue_remove (&thread_list, thread, struct thread *, allq); |
228 |
|
spin_unlock (&thread_list_lock); |
229 |
|
SPLON (spl); |
230 |
|
|
231 |
|
kmem_cache_free (thread_cache, thread); |
232 |
|
|
233 |
|
trace_count (n_threads--); |
234 |
|
} |
235 |
|
|
236 |
/* Terminate THREAD. */ |
/* Terminate THREAD. */ |
237 |
|
|
238 |
kern_return_t |
kern_return_t |
440 |
|
|
441 |
STACK_HANDOFF (old_thread, new_thread); |
STACK_HANDOFF (old_thread, new_thread); |
442 |
old_thread->sched_state |= THREAD_STATE_SWAPPED; |
old_thread->sched_state |= THREAD_STATE_SWAPPED; |
443 |
|
old_thread->swap_fn = continuation; |
444 |
|
|
445 |
if ((old_thread->sched_state & THREAD_SCHED_STATE) |
if ((old_thread->sched_state & THREAD_SCHED_STATE) |
446 |
== THREAD_STATE_RUN) |
== THREAD_STATE_RUN) |
935 |
|
|
936 |
assert ((thread->sched_state & THREAD_SCHED_STATE) == THREAD_STATE_RUN); |
assert ((thread->sched_state & THREAD_SCHED_STATE) == THREAD_STATE_RUN); |
937 |
|
|
938 |
|
/* Check if we can deallocate the kernel stack for THREAD. */ |
939 |
|
|
940 |
|
#if 0 |
941 |
|
if (thread->swap_fn) |
942 |
|
{ |
943 |
|
printf ("can dealloc stack (%p) for thread %p\n", thread->swap_fn, |
944 |
|
thread); |
945 |
|
|
946 |
|
/* kmem_cache_free (stack_cache, (void *) thread->kernel_stack); */ |
947 |
|
thread->kernel_stack = 0; |
948 |
|
thread->sched_state |= THREAD_STATE_SWAPPED; |
949 |
|
} |
950 |
|
#endif |
951 |
|
|
952 |
#if NCPUS > 1 |
#if NCPUS > 1 |
953 |
/* First check if we can continue to execute on processor that last |
/* First check if we can continue to execute on processor that last |
954 |
executed thread. */ |
executed thread. */ |