Rev 97 | Rev 111 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 97 | Rev 107 | ||
---|---|---|---|
Line 48... | Line 48... | ||
48 | #include <config.h> |
48 | #include <config.h> |
49 | #include <arch/interrupt.h> |
49 | #include <arch/interrupt.h> |
50 | #include <smp/ipi.h> |
50 | #include <smp/ipi.h> |
51 | #include <arch/faddr.h> |
51 | #include <arch/faddr.h> |
52 | 52 | ||
53 | char *thread_states[] = {"Invalid", "Running", "Sleeping", "Ready", "Entering", "Exiting"}; |
53 | char *thread_states[] = {"Invalid", "Running", "Sleeping", "Ready", "Entering", "Exiting"}; /**< Thread states */ |
54 | 54 | ||
55 | spinlock_t threads_lock; |
55 | spinlock_t threads_lock; |
56 | link_t threads_head; |
56 | link_t threads_head; |
57 | 57 | ||
58 | static spinlock_t tidlock; |
58 | static spinlock_t tidlock; |
59 | __u32 last_tid = 0; |
59 | __u32 last_tid = 0; |
60 | 60 | ||
- | 61 | ||
- | 62 | /** Thread wrapper |
|
61 | /* |
63 | * |
62 | * cushion() is provided to ensure that every thread |
64 | * This wrapper is provided to ensure that every thread |
63 | * makes a call to thread_exit() when its implementing |
65 | * makes a call to thread_exit() when its implementing |
64 | * function returns. |
66 | * function returns. |
65 | * |
67 | * |
66 | * cpu_priority_high()'d |
68 | * cpu_priority_high() is assumed. |
- | 69 | * |
|
67 | */ |
70 | */ |
68 | void cushion(void) |
71 | void cushion(void) |
69 | { |
72 | { |
70 | void (*f)(void *) = THREAD->thread_code; |
73 | void (*f)(void *) = THREAD->thread_code; |
71 | void *arg = THREAD->thread_arg; |
74 | void *arg = THREAD->thread_arg; |
Line 79... | Line 82... | ||
79 | f(arg); |
82 | f(arg); |
80 | thread_exit(); |
83 | thread_exit(); |
81 | /* not reached */ |
84 | /* not reached */ |
82 | } |
85 | } |
83 | 86 | ||
- | 87 | ||
- | 88 | /** Initialize threads |
|
- | 89 | * |
|
- | 90 | * Initialize kernel threads support. |
|
- | 91 | * |
|
- | 92 | */ |
|
84 | void thread_init(void) |
93 | void thread_init(void) |
85 | { |
94 | { |
86 | THREAD = NULL; |
95 | THREAD = NULL; |
87 | nrdy = 0; |
96 | nrdy = 0; |
88 | spinlock_initialize(&threads_lock); |
97 | spinlock_initialize(&threads_lock); |
89 | list_initialize(&threads_head); |
98 | list_initialize(&threads_head); |
90 | } |
99 | } |
91 | 100 | ||
- | 101 | ||
- | 102 | /** Make thread ready |
|
- | 103 | * |
|
- | 104 | * Switch thread t to the ready state. |
|
- | 105 | * |
|
- | 106 | * @param t Thread to make ready. |
|
- | 107 | * |
|
- | 108 | */ |
|
92 | void thread_ready(thread_t *t) |
109 | void thread_ready(thread_t *t) |
93 | { |
110 | { |
94 | cpu_t *cpu; |
111 | cpu_t *cpu; |
95 | runq_t *r; |
112 | runq_t *r; |
96 | pri_t pri; |
113 | pri_t pri; |
Line 106... | Line 123... | ||
106 | if (t->flags & X_WIRED) { |
123 | if (t->flags & X_WIRED) { |
107 | cpu = t->cpu; |
124 | cpu = t->cpu; |
108 | } |
125 | } |
109 | spinlock_unlock(&t->lock); |
126 | spinlock_unlock(&t->lock); |
110 | 127 | ||
111 | /* |
128 | /* |
112 | * Append t to respective ready queue on respective processor. |
129 | * Append t to respective ready queue on respective processor. |
113 | */ |
130 | */ |
114 | r = &cpu->rq[i]; |
131 | r = &cpu->rq[i]; |
115 | spinlock_lock(&r->lock); |
132 | spinlock_lock(&r->lock); |
116 | list_append(&t->rq_link, &r->rq_head); |
133 | list_append(&t->rq_link, &r->rq_head); |
Line 131... | Line 148... | ||
131 | spinlock_unlock(&cpu->lock); |
148 | spinlock_unlock(&cpu->lock); |
132 | 149 | ||
133 | cpu_priority_restore(pri); |
150 | cpu_priority_restore(pri); |
134 | } |
151 | } |
135 | 152 | ||
- | 153 | ||
- | 154 | /** Create new thread |
|
- | 155 | * |
|
- | 156 | * Create a new thread. |
|
- | 157 | * |
|
- | 158 | * @param func Thread's implementing function. |
|
- | 159 | * @param arg Thread's implementing function argument. |
|
- | 160 | * @param task Task to which the thread belongs. |
|
- | 161 | * @param flags Thread flags. |
|
- | 162 | * |
|
- | 163 | * @return New thread's structure on success, NULL on failure. |
|
- | 164 | * |
|
- | 165 | */ |
|
136 | thread_t *thread_create(void (* func)(void *), void *arg, task_t *task, int flags) |
166 | thread_t *thread_create(void (* func)(void *), void *arg, task_t *task, int flags) |
137 | { |
167 | { |
138 | thread_t *t; |
168 | thread_t *t; |
139 | __address frame_ks, frame_us = NULL; |
169 | __address frame_ks, frame_us = NULL; |
140 | 170 | ||
Line 211... | Line 241... | ||
211 | } |
241 | } |
212 | 242 | ||
213 | return t; |
243 | return t; |
214 | } |
244 | } |
215 | 245 | ||
- | 246 | ||
- | 247 | /** Make thread exiting |
|
- | 248 | * |
|
- | 249 | * End current thread execution and switch it to the exiting |
|
- | 250 | * state. All pending timeouts are executed. |
|
- | 251 | * |
|
- | 252 | */ |
|
216 | void thread_exit(void) |
253 | void thread_exit(void) |
217 | { |
254 | { |
218 | pri_t pri; |
255 | pri_t pri; |
219 | 256 | ||
220 | restart: |
257 | restart: |
Line 228... | Line 265... | ||
228 | THREAD->state = Exiting; |
265 | THREAD->state = Exiting; |
229 | spinlock_unlock(&THREAD->lock); |
266 | spinlock_unlock(&THREAD->lock); |
230 | scheduler(); |
267 | scheduler(); |
231 | } |
268 | } |
232 | 269 | ||
- | 270 | ||
- | 271 | /** Thread sleep |
|
- | 272 | * |
|
- | 273 | * Suspend execution of the current thread. |
|
- | 274 | * |
|
- | 275 | * @param sec Number of seconds to sleep. |
|
- | 276 | * |
|
- | 277 | */ |
|
233 | void thread_sleep(__u32 sec) |
278 | void thread_sleep(__u32 sec) |
234 | { |
279 | { |
235 | thread_usleep(sec*1000000); |
280 | thread_usleep(sec*1000000); |
236 | } |
281 | } |
- | 282 | ||
237 | 283 | ||
- | 284 | /** Thread usleep |
|
238 | /* |
285 | * |
239 | * Suspend execution of current thread for usec microseconds. |
286 | * Suspend execution of the current thread. |
- | 287 | * |
|
- | 288 | * @param usec Number of microseconds to sleep. |
|
- | 289 | * |
|
240 | */ |
290 | */ |
241 | void thread_usleep(__u32 usec) |
291 | void thread_usleep(__u32 usec) |
242 | { |
292 | { |
243 | waitq_t wq; |
293 | waitq_t wq; |
244 | 294 | ||
245 | waitq_initialize(&wq); |
295 | waitq_initialize(&wq); |
246 | 296 | ||
247 | (void) waitq_sleep_timeout(&wq, usec, SYNCH_NON_BLOCKING); |
297 | (void) waitq_sleep_timeout(&wq, usec, SYNCH_NON_BLOCKING); |
248 | } |
298 | } |
249 | 299 | ||
- | 300 | ||
- | 301 | /** Register thread out-of-context invocation |
|
- | 302 | * |
|
- | 303 | * Register a function and its argument to be executed |
|
- | 304 | * on next context switch to the current thread. |
|
- | 305 | * |
|
- | 306 | * @param call_me Out-of-context function. |
|
- | 307 | * @param call_me_with Out-of-context function argument. |
|
- | 308 | * |
|
- | 309 | */ |
|
250 | void thread_register_call_me(void (* call_me)(void *), void *call_me_with) |
310 | void thread_register_call_me(void (* call_me)(void *), void *call_me_with) |
251 | { |
311 | { |
252 | pri_t pri; |
312 | pri_t pri; |
253 | 313 | ||
254 | pri = cpu_priority_high(); |
314 | pri = cpu_priority_high(); |