Diff markup
001 001
002 002
003 003
004 004
005 005
006 006
007 007
008 008
009 009
010 010
011 011
012 012
013 013
014 014
015 015
016 016
017 017
018 018
019 #include <sos/physmem.h> 019 #include <sos/physmem.h>
020 #include <sos/kmem_slab.h> 020 #include <sos/kmem_slab.h>
021 #include <sos/kmalloc.h> 021 #include <sos/kmalloc.h>
022 #include <sos/klibc.h> 022 #include <sos/klibc.h>
023 #include <sos/list.h> 023 #include <sos/list.h>
024 #include <sos/assert.h> 024 #include <sos/assert.h>
025 #include <hwcore/mm_context.h> 025 #include <hwcore/mm_context.h>
026 #include <sos/process.h> 026 #include <sos/process.h>
027 027
028 #include <drivers/bochs.h> 028 #include <drivers/bochs.h>
029 #include <drivers/x86_videomem.h> 029 #include <drivers/x86_videomem.h>
030 030
031 #include <hwcore/irq.h> 031 #include <hwcore/irq.h>
032 032
033 #include "thread.h" 033 #include "thread.h"
034 034
035 035
036 036
037 037
038 038
039 #define SOS_THREAD_KERNEL_STACK_SIZE (1*SOS_PA 039 #define SOS_THREAD_KERNEL_STACK_SIZE (1*SOS_PAGE_SIZE)
040 040
041 041
042 042
043 043
044 044
045 045
046 046
047 047
048 048
049 049
050 050
051 051
052 052
053 053
054 054
055 055
056 static volatile struct sos_thread *current_thr 056 static volatile struct sos_thread *current_thread = NULL;
057 057
058 058
059 059
060 060
061 061
062 062
063 063
064 static struct sos_thread *thread_list = NULL; 064 static struct sos_thread *thread_list = NULL;
065 065
066 066
067 067
068 068
069 069
070 static struct sos_kslab_cache *cache_thread; 070 static struct sos_kslab_cache *cache_thread;
071 071
072 072
073 <<
074 <<
075 <<
076 <<
077 <<
078 static sos_ret_t change_current_mm_context(str <<
079 <<
080 <<
081 struct sos_thread *sos_thread_get_current() 073 struct sos_thread *sos_thread_get_current()
082 { 074 {
083 SOS_ASSERT_FATAL(current_thread->state == SO 075 SOS_ASSERT_FATAL(current_thread->state == SOS_THR_RUNNING);
084 return (struct sos_thread*)current_thread; 076 return (struct sos_thread*)current_thread;
085 } 077 }
086 078
087 079
088 inline static sos_ret_t _set_current(struct so 080 inline static sos_ret_t _set_current(struct sos_thread *thr)
089 { 081 {
090 SOS_ASSERT_FATAL(thr->state == SOS_THR_READY 082 SOS_ASSERT_FATAL(thr->state == SOS_THR_READY);
091 current_thread = thr; 083 current_thread = thr;
092 current_thread->state = SOS_THR_RUNNING; 084 current_thread->state = SOS_THR_RUNNING;
093 return SOS_OK; 085 return SOS_OK;
094 } 086 }
095 087
096 088
097 sos_ret_t sos_thread_subsystem_setup(sos_vaddr 089 sos_ret_t sos_thread_subsystem_setup(sos_vaddr_t init_thread_stack_base_addr,
098 sos_size_ 090 sos_size_t init_thread_stack_size)
099 { 091 {
100 struct sos_thread *myself; 092 struct sos_thread *myself;
101 093
102 094
103 cache_thread = sos_kmem_cache_create("thread 095 cache_thread = sos_kmem_cache_create("thread",
104 sizeof( 096 sizeof(struct sos_thread),
105 2, 097 2,
106 0, 098 0,
107 SOS_KSL 099 SOS_KSLAB_CREATE_MAP
108 | SOS_K 100 | SOS_KSLAB_CREATE_ZERO);
109 if (! cache_thread) 101 if (! cache_thread)
110 return -SOS_ENOMEM; 102 return -SOS_ENOMEM;
111 103
112 104
113 myself = (struct sos_thread*) sos_kmem_cache 105 myself = (struct sos_thread*) sos_kmem_cache_alloc(cache_thread,
114 106 SOS_KSLAB_ALLOC_ATOMIC);
115 if (! myself) 107 if (! myself)
116 return -SOS_ENOMEM; 108 return -SOS_ENOMEM;
117 109
118 110
119 strzcpy(myself->name, "[kinit]", SOS_THR_MAX 111 strzcpy(myself->name, "[kinit]", SOS_THR_MAX_NAMELEN);
120 myself->state = SOS_THR_CREATED; 112 myself->state = SOS_THR_CREATED;
121 myself->priority = SOS_SCHED_PRIO_LOW 113 myself->priority = SOS_SCHED_PRIO_LOWEST;
122 myself->kernel_stack_base_addr = init_thread 114 myself->kernel_stack_base_addr = init_thread_stack_base_addr;
123 myself->kernel_stack_size = init_thread 115 myself->kernel_stack_size = init_thread_stack_size;
124 116
125 117
126 sos_cpu_state_prepare_detect_kernel_stack_ov 118 sos_cpu_state_prepare_detect_kernel_stack_overflow(myself->cpu_state,
127 119 myself->kernel_stack_base_addr,
128 120 myself->kernel_stack_size);
129 121
130 122
131 list_singleton_named(thread_list, myself, gb 123 list_singleton_named(thread_list, myself, gbl_prev, gbl_next);
132 124
133 125
134 myself->state = SOS_THR_READY; 126 myself->state = SOS_THR_READY;
135 _set_current(myself); 127 _set_current(myself);
136 128
137 return SOS_OK; 129 return SOS_OK;
138 } 130 }
139 131
140 132
141 struct sos_thread * 133 struct sos_thread *
142 sos_create_kernel_thread(const char *name, 134 sos_create_kernel_thread(const char *name,
143 sos_kernel_thread_sta 135 sos_kernel_thread_start_routine_t start_func,
144 void *start_arg, 136 void *start_arg,
145 sos_sched_priority_t 137 sos_sched_priority_t priority)
146 { 138 {
147 __label__ undo_creation; 139 __label__ undo_creation;
148 sos_ui32_t flags; 140 sos_ui32_t flags;
149 struct sos_thread *new_thread; 141 struct sos_thread *new_thread;
150 142
151 if (! start_func) 143 if (! start_func)
152 return NULL; 144 return NULL;
153 if (! SOS_SCHED_PRIO_IS_VALID(priority)) 145 if (! SOS_SCHED_PRIO_IS_VALID(priority))
154 return NULL; 146 return NULL;
155 147
156 148
157 new_thread 149 new_thread
158 = (struct sos_thread*) sos_kmem_cache_allo 150 = (struct sos_thread*) sos_kmem_cache_alloc(cache_thread,
159 151 SOS_KSLAB_ALLOC_ATOMIC);
160 if (! new_thread) 152 if (! new_thread)
161 return NULL; 153 return NULL;
162 154
163 155
164 strzcpy(new_thread->name, ((name)?name:"[NON 156 strzcpy(new_thread->name, ((name)?name:"[NONAME]"), SOS_THR_MAX_NAMELEN);
165 new_thread->state = SOS_THR_CREATED; 157 new_thread->state = SOS_THR_CREATED;
166 new_thread->priority = priority; 158 new_thread->priority = priority;
167 159
168 160
169 new_thread->kernel_stack_base_addr = sos_kma 161 new_thread->kernel_stack_base_addr = sos_kmalloc(SOS_THREAD_KERNEL_STACK_SIZE, 0);
170 new_thread->kernel_stack_size = SOS_THR 162 new_thread->kernel_stack_size = SOS_THREAD_KERNEL_STACK_SIZE;
171 if (! new_thread->kernel_stack_base_addr) 163 if (! new_thread->kernel_stack_base_addr)
172 goto undo_creation; 164 goto undo_creation;
173 165
174 166
175 if (SOS_OK 167 if (SOS_OK
176 != sos_cpu_kstate_init(& new_thread->cpu 168 != sos_cpu_kstate_init(& new_thread->cpu_state,
177 (sos_cpu_kstate_f 169 (sos_cpu_kstate_function_arg1_t*) start_func,
178 (sos_ui32_t) star 170 (sos_ui32_t) start_arg,
179 new_thread->kerne 171 new_thread->kernel_stack_base_addr,
180 new_thread->kerne 172 new_thread->kernel_stack_size,
181 (sos_cpu_kstate_f 173 (sos_cpu_kstate_function_arg1_t*) sos_thread_exit,
182 (sos_ui32_t) NULL 174 (sos_ui32_t) NULL))
183 goto undo_creation; 175 goto undo_creation;
184 176
185 177
186 sos_disable_IRQs(flags); 178 sos_disable_IRQs(flags);
187 list_add_tail_named(thread_list, new_thread, 179 list_add_tail_named(thread_list, new_thread, gbl_prev, gbl_next);
188 sos_restore_IRQs(flags); 180 sos_restore_IRQs(flags);
189 181
190 182
191 if (SOS_OK != sos_sched_set_ready(new_thread 183 if (SOS_OK != sos_sched_set_ready(new_thread))
192 goto undo_creation; 184 goto undo_creation;
193 185
194 186
195 return new_thread; 187 return new_thread;
196 188
197 undo_creation: 189 undo_creation:
198 if (new_thread->kernel_stack_base_addr) 190 if (new_thread->kernel_stack_base_addr)
199 sos_kfree((sos_vaddr_t) new_thread->kernel 191 sos_kfree((sos_vaddr_t) new_thread->kernel_stack_base_addr);
200 sos_kmem_cache_free((sos_vaddr_t) new_thread 192 sos_kmem_cache_free((sos_vaddr_t) new_thread);
201 return NULL; 193 return NULL;
202 } 194 }
203 195
204 196
205 !! 197 struct sos_thread *
206 !! 198 sos_create_user_thread(const char *name,
207 !! 199 struct sos_process *process,
208 !! 200 sos_uaddr_t user_initial_PC,
209 !! 201 sos_ui32_t user_start_arg1,
210 !! 202 sos_ui32_t user_start_arg2,
211 static struct sos_thread * !! 203 sos_uaddr_t user_initial_SP,
212 create_user_thread(const char *name, !! 204 sos_sched_priority_t priority)
213 struct sos_process *process <<
214 const struct sos_thread * m <<
215 const struct sos_cpu_state <<
216 sos_uaddr_t user_initial_PC <<
217 sos_ui32_t user_start_arg1 <<
218 sos_ui32_t user_start_arg2 <<
219 sos_uaddr_t user_initial_SP <<
220 sos_sched_priority_t priori <<
221 { 205 {
222 __label__ undo_creation; 206 __label__ undo_creation;
223 sos_ui32_t flags; 207 sos_ui32_t flags;
224 struct sos_thread *new_thread; 208 struct sos_thread *new_thread;
225 209
226 if (model_thread) !! 210 if (! SOS_SCHED_PRIO_IS_VALID(priority))
227 { !! 211 return NULL;
228 SOS_ASSERT_FATAL(model_uctxt); <<
229 } <<
230 else <<
231 { <<
232 if (! SOS_SCHED_PRIO_IS_VALID(priority)) <<
233 return NULL; <<
234 } <<
235 212
236 213
237 if (! process) 214 if (! process)
238 return NULL; 215 return NULL;
239 216
240 217
241 new_thread 218 new_thread
242 = (struct sos_thread*) sos_kmem_cache_allo 219 = (struct sos_thread*) sos_kmem_cache_alloc(cache_thread,
243 220 SOS_KSLAB_ALLOC_ATOMIC);
244 if (! new_thread) 221 if (! new_thread)
245 return NULL; 222 return NULL;
246 223
247 224
248 strzcpy(new_thread->name, ((name)?name:"[NON 225 strzcpy(new_thread->name, ((name)?name:"[NONAME]"), SOS_THR_MAX_NAMELEN);
249 new_thread->state = SOS_THR_CREATED; 226 new_thread->state = SOS_THR_CREATED;
250 if (model_thread) !! 227 new_thread->priority = priority;
251 new_thread->priority = model_thread->prior <<
252 else <<
253 new_thread->priority = priority; <<
254 228
255 229
256 new_thread->kernel_stack_base_addr = sos_kma 230 new_thread->kernel_stack_base_addr = sos_kmalloc(SOS_THREAD_KERNEL_STACK_SIZE, 0);
257 new_thread->kernel_stack_size = SOS_THR 231 new_thread->kernel_stack_size = SOS_THREAD_KERNEL_STACK_SIZE;
258 if (! new_thread->kernel_stack_base_addr) 232 if (! new_thread->kernel_stack_base_addr)
259 goto undo_creation; 233 goto undo_creation;
260 234
261 !! 235 if (SOS_OK
262 if (model_thread) !! 236 != sos_cpu_ustate_init(& new_thread->cpu_state,
263 { !! 237 user_initial_PC,
264 if (SOS_OK !! 238 user_start_arg1,
265 != sos_cpu_ustate_duplicate(& new_th !! 239 user_start_arg2,
266 model_uc !! 240 user_initial_SP,
267 user_sta !! 241 new_thread->kernel_stack_base_addr,
268 new_thre !! 242 new_thread->kernel_stack_size))
269 new_thre !! 243 goto undo_creation;
270 goto undo_creation; <<
271 } <<
272 else <<
273 { <<
274 if (SOS_OK <<
275 != sos_cpu_ustate_init(& new_thread- <<
276 user_initial_ <<
277 user_start_ar <<
278 user_start_ar <<
279 user_initial_ <<
280 new_thread->k <<
281 new_thread->k <<
282 goto undo_creation; <<
283 } <<
284 244
285 245
286 if (SOS_OK != sos_process_register_thread(pr 246 if (SOS_OK != sos_process_register_thread(process, new_thread))
287 goto undo_creation; 247 goto undo_creation;
288 248
289 249
290 sos_disable_IRQs(flags); 250 sos_disable_IRQs(flags);
291 list_add_tail_named(thread_list, new_thread, 251 list_add_tail_named(thread_list, new_thread, gbl_prev, gbl_next);
292 sos_restore_IRQs(flags); 252 sos_restore_IRQs(flags);
293 253
294 254
295 if (SOS_OK != sos_sched_set_ready(new_thread 255 if (SOS_OK != sos_sched_set_ready(new_thread))
296 goto undo_creation; 256 goto undo_creation;
297 257
298 258
299 return new_thread; 259 return new_thread;
300 260
301 undo_creation: 261 undo_creation:
302 if (new_thread->kernel_stack_base_addr) 262 if (new_thread->kernel_stack_base_addr)
303 sos_kfree((sos_vaddr_t) new_thread->kernel 263 sos_kfree((sos_vaddr_t) new_thread->kernel_stack_base_addr);
304 sos_kmem_cache_free((sos_vaddr_t) new_thread 264 sos_kmem_cache_free((sos_vaddr_t) new_thread);
305 return NULL; 265 return NULL;
306 } 266 }
307 267
308 268
309 struct sos_thread * <<
310 sos_create_user_thread(const char *name, <<
311 struct sos_process *pro <<
312 sos_uaddr_t user_initia <<
313 sos_ui32_t user_start_ <<
314 sos_ui32_t user_start_ <<
315 sos_uaddr_t user_initia <<
316 sos_sched_priority_t pr <<
317 { <<
318 return create_user_thread(name, process, NUL <<
319 user_initial_PC, <<
320 user_start_arg1, <<
321 user_start_arg2, <<
322 user_initial_SP, <<
323 priority); <<
324 } <<
325 <<
326 <<
327 <<
328 <<
329 <<
330 <<
331 struct sos_thread * <<
332 sos_duplicate_user_thread(const char *name, <<
333 struct sos_process * <<
334 const struct sos_thr <<
335 const struct sos_cpu <<
336 sos_ui32_t retval) <<
337 { <<
338 return create_user_thread(name, process, mod <<
339 0, retval, 0, 0, 0 <<
340 } <<
341 <<
342 <<
343 269
344 270
345 271
346 272
347 273
348 274
349 275
350 276
351 static void _prepare_mm_context(struct sos_thr 277 static void _prepare_mm_context(struct sos_thread *the_thread)
352 { 278 {
353 279
354 if (sos_cpu_context_is_in_user_mode(the_thre 280 if (sos_cpu_context_is_in_user_mode(the_thread->cpu_state)
355 == TRUE) 281 == TRUE)
356 { 282 {
357 283
358 284
359 285
360 286
361 SOS_ASSERT_FATAL(the_thread->process != 287 SOS_ASSERT_FATAL(the_thread->process != NULL);
362 288
363 289
364 SOS_ASSERT_FATAL(the_thread->squatted_mm 290 SOS_ASSERT_FATAL(the_thread->squatted_mm_context == NULL);
365 291
366 292
367 sos_mm_context_switch_to(sos_process_get 293 sos_mm_context_switch_to(sos_process_get_mm_context(the_thread->process));
368 } 294 }
369 295
370 296
371 297
372 else if (the_thread->squatted_mm_context != 298 else if (the_thread->squatted_mm_context != NULL)
373 sos_mm_context_switch_to(the_thread->squat 299 sos_mm_context_switch_to(the_thread->squatted_mm_context);
374 } 300 }
375 301
376 302
377 303
378 304
379 static void delete_thread(struct sos_thread *t 305 static void delete_thread(struct sos_thread *thr)
380 { 306 {
381 sos_ui32_t flags; 307 sos_ui32_t flags;
382 308
383 sos_disable_IRQs(flags); 309 sos_disable_IRQs(flags);
384 list_delete_named(thread_list, thr, gbl_prev 310 list_delete_named(thread_list, thr, gbl_prev, gbl_next);
385 sos_restore_IRQs(flags); 311 sos_restore_IRQs(flags);
386 312
387 sos_kfree((sos_vaddr_t) thr->kernel_stack_ba 313 sos_kfree((sos_vaddr_t) thr->kernel_stack_base_addr);
388 314
389 315
390 if (thr->squatted_mm_context) 316 if (thr->squatted_mm_context)
391 SOS_ASSERT_FATAL(SOS_OK == change_current_ !! 317 SOS_ASSERT_FATAL(SOS_OK == sos_thread_change_current_mm_context(NULL));
392 318
393 319
394 if (thr->process) 320 if (thr->process)
395 SOS_ASSERT_FATAL(SOS_OK == sos_process_unr 321 SOS_ASSERT_FATAL(SOS_OK == sos_process_unregister_thread(thr));
396 322
397 memset(thr, 0x0, sizeof(struct sos_thread)); 323 memset(thr, 0x0, sizeof(struct sos_thread));
398 sos_kmem_cache_free((sos_vaddr_t) thr); 324 sos_kmem_cache_free((sos_vaddr_t) thr);
399 } 325 }
400 326
401 327
402 void sos_thread_exit() 328 void sos_thread_exit()
403 { 329 {
404 sos_ui32_t flags; 330 sos_ui32_t flags;
405 struct sos_thread *myself, *next_thread; 331 struct sos_thread *myself, *next_thread;
406 332
407 333
408 SOS_ASSERT_FATAL(! sos_servicing_irq()); 334 SOS_ASSERT_FATAL(! sos_servicing_irq());
409 335
410 myself = sos_thread_get_current(); 336 myself = sos_thread_get_current();
411 337
412 338
413 339
414 SOS_ASSERT_FATAL(list_is_empty_named(myself- 340 SOS_ASSERT_FATAL(list_is_empty_named(myself->kwaitq_list,
415 prev_en 341 prev_entry_for_thread,
416 next_en 342 next_entry_for_thread));
417 343
418 344
419 sos_disable_IRQs(flags); 345 sos_disable_IRQs(flags);
420 myself->state = SOS_THR_ZOMBIE; 346 myself->state = SOS_THR_ZOMBIE;
421 next_thread = sos_reschedule(myself, FALSE); 347 next_thread = sos_reschedule(myself, FALSE);
422 348
423 349
424 sos_cpu_state_detect_kernel_stack_overflow(n 350 sos_cpu_state_detect_kernel_stack_overflow(next_thread->cpu_state,
425 n 351 next_thread->kernel_stack_base_addr,
426 n 352 next_thread->kernel_stack_size);
427 353
428 354
429 355
430 356
431 _prepare_mm_context(next_thread); 357 _prepare_mm_context(next_thread);
432 358
433 359
434 360
435 361
436 362
437 _set_current(next_thread); 363 _set_current(next_thread);
438 sos_cpu_context_exit_to(next_thread->cpu_sta 364 sos_cpu_context_exit_to(next_thread->cpu_state,
439 (sos_cpu_kstate_func 365 (sos_cpu_kstate_function_arg1_t*) delete_thread,
440 (sos_ui32_t) myself) 366 (sos_ui32_t) myself);
441 } 367 }
442 368
443 369
444 sos_sched_priority_t sos_thread_get_priority(s 370 sos_sched_priority_t sos_thread_get_priority(struct sos_thread *thr)
445 { 371 {
446 if (! thr) 372 if (! thr)
447 thr = (struct sos_thread*)current_thread; 373 thr = (struct sos_thread*)current_thread;
448 374
449 return thr->priority; 375 return thr->priority;
450 } 376 }
451 377
452 378
453 sos_thread_state_t sos_thread_get_state(struct 379 sos_thread_state_t sos_thread_get_state(struct sos_thread *thr)
454 { 380 {
455 if (! thr) 381 if (! thr)
456 thr = (struct sos_thread*)current_thread; 382 thr = (struct sos_thread*)current_thread;
457 383
458 return thr->state; 384 return thr->state;
459 } 385 }
460 386
461 387
462 typedef enum { YIELD_MYSELF, BLOCK_MYSELF } sw 388 typedef enum { YIELD_MYSELF, BLOCK_MYSELF } switch_type_t;
463 389
464 390
465 391
466 392
467 static sos_ret_t _switch_to_next_thread(switch 393 static sos_ret_t _switch_to_next_thread(switch_type_t operation)
468 { 394 {
469 struct sos_thread *myself, *next_thread; 395 struct sos_thread *myself, *next_thread;
470 396
471 SOS_ASSERT_FATAL(current_thread->state == SO 397 SOS_ASSERT_FATAL(current_thread->state == SOS_THR_RUNNING);
472 398
473 399
474 SOS_ASSERT_FATAL(! sos_servicing_irq()); 400 SOS_ASSERT_FATAL(! sos_servicing_irq());
475 401
476 myself = (struct sos_thread*)current_thread; 402 myself = (struct sos_thread*)current_thread;
477 403
478 404
479 405
480 if (BLOCK_MYSELF == operation) 406 if (BLOCK_MYSELF == operation)
481 { 407 {
482 myself->state = SOS_THR_BLOCKED; 408 myself->state = SOS_THR_BLOCKED;
483 } 409 }
484 410
485 411
486 next_thread = sos_reschedule(myself, YIELD_M 412 next_thread = sos_reschedule(myself, YIELD_MYSELF == operation);
487 413
488 414
489 if (myself != next_thread) 415 if (myself != next_thread)
490 { 416 {
491 417
492 sos_cpu_state_detect_kernel_stack_overfl 418 sos_cpu_state_detect_kernel_stack_overflow(next_thread->cpu_state,
493 419 next_thread->kernel_stack_base_addr,
494 420 next_thread->kernel_stack_size);
495 421
496 422
497 423
498 424
499 _prepare_mm_context(next_thread); 425 _prepare_mm_context(next_thread);
500 426
501 427
502 428
503 429
504 _set_current(next_thread); 430 _set_current(next_thread);
505 sos_cpu_context_switch(& myself->cpu_sta 431 sos_cpu_context_switch(& myself->cpu_state, next_thread->cpu_state);
506 432
507 433
508 SOS_ASSERT_FATAL(current_thread == mysel 434 SOS_ASSERT_FATAL(current_thread == myself);
509 SOS_ASSERT_FATAL(current_thread->state = 435 SOS_ASSERT_FATAL(current_thread->state == SOS_THR_RUNNING);
510 } 436 }
511 else 437 else
512 { 438 {
513 439
514 _set_current(next_thread); 440 _set_current(next_thread);
515 } 441 }
516 442
517 return SOS_OK; 443 return SOS_OK;
518 } 444 }
519 445
520 446
521 447
522 448
523 449
524 450
525 static sos_ret_t _change_waitq_priorities(stru 451 static sos_ret_t _change_waitq_priorities(struct sos_thread *thr,
526 sos_ 452 sos_sched_priority_t priority)
527 { 453 {
528 struct sos_kwaitq_entry *kwq_entry; 454 struct sos_kwaitq_entry *kwq_entry;
529 int nb_waitqs; 455 int nb_waitqs;
530 456
531 list_foreach_forward_named(thr->kwaitq_list, 457 list_foreach_forward_named(thr->kwaitq_list, kwq_entry, nb_waitqs,
532 prev_entry_for_th 458 prev_entry_for_thread, next_entry_for_thread)
533 { 459 {
534 SOS_ASSERT_FATAL(SOS_OK == sos_kwaitq_ch 460 SOS_ASSERT_FATAL(SOS_OK == sos_kwaitq_change_priority(kwq_entry->kwaitq,
535 461 kwq_entry,
536 462 priority));
537 } 463 }
538 464
539 return SOS_OK; 465 return SOS_OK;
540 } 466 }
541 467
542 468
543 sos_ret_t sos_thread_set_priority(struct sos_t 469 sos_ret_t sos_thread_set_priority(struct sos_thread *thr,
544 sos_sched_p 470 sos_sched_priority_t priority)
545 { 471 {
546 __label__ exit_set_prio; 472 __label__ exit_set_prio;
547 sos_ui32_t flags; 473 sos_ui32_t flags;
548 sos_ret_t retval; 474 sos_ret_t retval;
549 475
550 476
551 if (! SOS_SCHED_PRIO_IS_VALID(priority)) 477 if (! SOS_SCHED_PRIO_IS_VALID(priority))
552 return -SOS_EINVAL; 478 return -SOS_EINVAL;
553 479
554 if (! thr) 480 if (! thr)
555 thr = (struct sos_thread*)current_thread; 481 thr = (struct sos_thread*)current_thread;
556 482
557 sos_disable_IRQs(flags); 483 sos_disable_IRQs(flags);
558 484
559 485
560 486
561 retval = _change_waitq_priorities(thr, prior 487 retval = _change_waitq_priorities(thr, priority);
562 if (SOS_OK != retval) 488 if (SOS_OK != retval)
563 goto exit_set_prio; 489 goto exit_set_prio;
564 490
565 491
566 492
567 if (SOS_THR_READY == thr->state) 493 if (SOS_THR_READY == thr->state)
568 retval = sos_sched_change_priority(thr, pr 494 retval = sos_sched_change_priority(thr, priority);
569 495
570 496
571 thr->priority = priority; 497 thr->priority = priority;
572 498
573 exit_set_prio: 499 exit_set_prio:
574 sos_restore_IRQs(flags); 500 sos_restore_IRQs(flags);
575 return retval; 501 return retval;
576 } 502 }
577 503
578 504
579 sos_ret_t sos_thread_yield() 505 sos_ret_t sos_thread_yield()
580 { 506 {
581 sos_ui32_t flags; 507 sos_ui32_t flags;
582 sos_ret_t retval; 508 sos_ret_t retval;
583 509
584 sos_disable_IRQs(flags); 510 sos_disable_IRQs(flags);
585 511
586 retval = _switch_to_next_thread(YIELD_MYSELF 512 retval = _switch_to_next_thread(YIELD_MYSELF);
587 513
588 sos_restore_IRQs(flags); 514 sos_restore_IRQs(flags);
589 return retval; 515 return retval;
590 } 516 }
591 517
592 518
593 519
594 520
595 521
596 struct sleep_timeout_params 522 struct sleep_timeout_params
597 { 523 {
598 struct sos_thread *thread_to_wakeup; 524 struct sos_thread *thread_to_wakeup;
599 sos_bool_t timeout_triggered; 525 sos_bool_t timeout_triggered;
600 }; 526 };
601 527
602 528
603 529
604 530
605 531
606 static void sleep_timeout(struct sos_timeout_a 532 static void sleep_timeout(struct sos_timeout_action *act)
607 { 533 {
608 struct sleep_timeout_params *sleep_timeout_p 534 struct sleep_timeout_params *sleep_timeout_params
609 = (struct sleep_timeout_params*) act->rout 535 = (struct sleep_timeout_params*) act->routine_data;
610 536
611 537
612 sleep_timeout_params->timeout_triggered = TR 538 sleep_timeout_params->timeout_triggered = TRUE;
613 539
614 540
615 SOS_ASSERT_FATAL(SOS_OK == 541 SOS_ASSERT_FATAL(SOS_OK ==
616 sos_thread_force_unblock(sl 542 sos_thread_force_unblock(sleep_timeout_params
617 - 543 ->thread_to_wakeup));
618 } 544 }
619 545
620 546
621 sos_ret_t sos_thread_sleep(struct sos_time *ti 547 sos_ret_t sos_thread_sleep(struct sos_time *timeout)
622 { 548 {
623 sos_ui32_t flags; 549 sos_ui32_t flags;
624 struct sleep_timeout_params sleep_timeout_pa 550 struct sleep_timeout_params sleep_timeout_params;
625 struct sos_timeout_action timeout_action; 551 struct sos_timeout_action timeout_action;
626 sos_ret_t retval; 552 sos_ret_t retval;
627 553
628 554
629 if (NULL == timeout) 555 if (NULL == timeout)
630 { 556 {
631 sos_disable_IRQs(flags); 557 sos_disable_IRQs(flags);
632 retval = _switch_to_next_thread(BLOCK_MY 558 retval = _switch_to_next_thread(BLOCK_MYSELF);
633 sos_restore_IRQs(flags); 559 sos_restore_IRQs(flags);
634 560
635 return retval; 561 return retval;
636 } 562 }
637 563
638 564
639 sos_time_init_action(& timeout_action); 565 sos_time_init_action(& timeout_action);
640 566
641 567
642 sleep_timeout_params.thread_to_wakeup 568 sleep_timeout_params.thread_to_wakeup
643 = (struct sos_thread*)current_thread; 569 = (struct sos_thread*)current_thread;
644 sleep_timeout_params.timeout_triggered = FAL 570 sleep_timeout_params.timeout_triggered = FALSE;
645 571
646 sos_disable_IRQs(flags); 572 sos_disable_IRQs(flags);
647 573
648 574
649 SOS_ASSERT_FATAL(SOS_OK == 575 SOS_ASSERT_FATAL(SOS_OK ==
650 sos_time_register_action_re 576 sos_time_register_action_relative(& timeout_action,
651 577 timeout,
652 578 sleep_timeout,
653 579 & sleep_timeout_params));
654 580
655 581
656 582
657 583
658 retval = _switch_to_next_thread(BLOCK_MYSELF 584 retval = _switch_to_next_thread(BLOCK_MYSELF);
659 585
660 586
661 587
662 if (sleep_timeout_params.timeout_triggered) 588 if (sleep_timeout_params.timeout_triggered)
663 { 589 {
664 590
665 SOS_ASSERT_FATAL(sos_time_is_zero(& time 591 SOS_ASSERT_FATAL(sos_time_is_zero(& timeout_action.timeout));
666 retval = SOS_OK; 592 retval = SOS_OK;
667 } 593 }
668 else 594 else
669 { 595 {
670 596
671 597
672 SOS_ASSERT_FATAL(SOS_OK == sos_time_unre 598 SOS_ASSERT_FATAL(SOS_OK == sos_time_unregister_action(& timeout_action));
673 retval = -SOS_EINTR; 599 retval = -SOS_EINTR;
674 } 600 }
675 601
676 sos_restore_IRQs(flags); 602 sos_restore_IRQs(flags);
677 603
678 604
679 memcpy(timeout, & timeout_action.timeout, si 605 memcpy(timeout, & timeout_action.timeout, sizeof(struct sos_time));
680 606
681 return retval; 607 return retval;
682 } 608 }
683 609
684 610
685 sos_ret_t sos_thread_force_unblock(struct sos_ 611 sos_ret_t sos_thread_force_unblock(struct sos_thread *thread)
686 { 612 {
687 sos_ret_t retval; 613 sos_ret_t retval;
688 sos_ui32_t flags; 614 sos_ui32_t flags;
689 615
690 if (! thread) 616 if (! thread)
691 return -SOS_EINVAL; 617 return -SOS_EINVAL;
692 618
693 sos_disable_IRQs(flags); 619 sos_disable_IRQs(flags);
694 620
695 621
696 retval = SOS_OK; 622 retval = SOS_OK;
697 switch(sos_thread_get_state(thread)) 623 switch(sos_thread_get_state(thread))
698 { 624 {
699 case SOS_THR_RUNNING: 625 case SOS_THR_RUNNING:
700 case SOS_THR_READY: 626 case SOS_THR_READY:
701 627
702 break; 628 break;
703 629
704 case SOS_THR_ZOMBIE: 630 case SOS_THR_ZOMBIE:
705 retval = -SOS_EFATAL; 631 retval = -SOS_EFATAL;
706 break; 632 break;
707 633
708 default: 634 default:
709 retval = sos_sched_set_ready(thread); 635 retval = sos_sched_set_ready(thread);
710 break; 636 break;
711 } 637 }
712 638
713 sos_restore_IRQs(flags); 639 sos_restore_IRQs(flags);
714 640
715 return retval; 641 return retval;
716 } 642 }
717 643
718 644
719 void sos_thread_dump_backtrace(sos_bool_t on_c 645 void sos_thread_dump_backtrace(sos_bool_t on_console,
720 sos_bool_t on_b 646 sos_bool_t on_bochs)
721 { 647 {
722 sos_vaddr_t stack_bottom = current_thread->k 648 sos_vaddr_t stack_bottom = current_thread->kernel_stack_base_addr;
723 sos_size_t stack_size = current_thread->k 649 sos_size_t stack_size = current_thread->kernel_stack_size;
724 650
725 static void backtracer(sos_vaddr_t PC, 651 static void backtracer(sos_vaddr_t PC,
726 sos_vaddr_t params, 652 sos_vaddr_t params,
727 sos_ui32_t depth, 653 sos_ui32_t depth,
728 void *custom_arg) 654 void *custom_arg)
729 { 655 {
730 sos_ui32_t invalid = 0xffffffff, *arg1, 656 sos_ui32_t invalid = 0xffffffff, *arg1, *arg2, *arg3, *arg4;
731 657
732 658
733 659
734 660
735 661
736 arg1 = (sos_ui32_t*)params; 662 arg1 = (sos_ui32_t*)params;
737 arg2 = (sos_ui32_t*)(params+4); 663 arg2 = (sos_ui32_t*)(params+4);
738 arg3 = (sos_ui32_t*)(params+8); 664 arg3 = (sos_ui32_t*)(params+8);
739 arg4 = (sos_ui32_t*)(params+12); 665 arg4 = (sos_ui32_t*)(params+12);
740 666
741 667
742 668
743 #define INTERVAL_OK(b,v,u) ( ((b) <= (sos_vadd 669 #define INTERVAL_OK(b,v,u) ( ((b) <= (sos_vaddr_t)(v)) \
744 && ((sos_vaddr_t) 670 && ((sos_vaddr_t)(v) < (u)) )
745 if (!INTERVAL_OK(stack_bottom, arg1, sta 671 if (!INTERVAL_OK(stack_bottom, arg1, stack_bottom + stack_size))
746 arg1 = &invalid; 672 arg1 = &invalid;
747 if (!INTERVAL_OK(stack_bottom, arg2, sta 673 if (!INTERVAL_OK(stack_bottom, arg2, stack_bottom + stack_size))
748 arg2 = &invalid; 674 arg2 = &invalid;
749 if (!INTERVAL_OK(stack_bottom, arg3, sta 675 if (!INTERVAL_OK(stack_bottom, arg3, stack_bottom + stack_size))
750 arg3 = &invalid; 676 arg3 = &invalid;
751 if (!INTERVAL_OK(stack_bottom, arg4, sta 677 if (!INTERVAL_OK(stack_bottom, arg4, stack_bottom + stack_size))
752 arg4 = &invalid; 678 arg4 = &invalid;
753 679
754 680
755 if (on_bochs) 681 if (on_bochs)
756 sos_bochs_printf("[%d] PC=0x%x arg1=0x 682 sos_bochs_printf("[%d] PC=0x%x arg1=0x%x arg2=0x%x arg3=0x%x\n",
757 (unsigned)depth, (uns 683 (unsigned)depth, (unsigned)PC,
758 (unsigned)*arg1, (uns 684 (unsigned)*arg1, (unsigned)*arg2,
759 (unsigned)*arg3); 685 (unsigned)*arg3);
760 686
761 if (on_console) 687 if (on_console)
762 sos_x86_videomem_printf(23-depth, 3, 688 sos_x86_videomem_printf(23-depth, 3,
763 SOS_X86_VIDEO_ 689 SOS_X86_VIDEO_BG_BLUE
764 | SOS_X86_VI 690 | SOS_X86_VIDEO_FG_LTGREEN,
765 "[%d] PC=0x%x 691 "[%d] PC=0x%x arg1=0x%x arg2=0x%x arg3=0x%x arg4=0x%x",
766 (unsigned)dept 692 (unsigned)depth, PC,
767 (unsigned)*arg 693 (unsigned)*arg1, (unsigned)*arg2,
768 (unsigned)*arg 694 (unsigned)*arg3, (unsigned)*arg4);
769 695
770 } 696 }
771 697
772 sos_backtrace(NULL, 15, stack_bottom, stack_ 698 sos_backtrace(NULL, 15, stack_bottom, stack_size,
773 backtracer, NULL); 699 backtracer, NULL);
774 } 700 }
775 701
776 702
777 703
778 704
779 705
780 706
781 707
782 708
783 static sos_ret_t !! 709 sos_ret_t
784 change_current_mm_context(struct sos_mm_contex !! 710 sos_thread_change_current_mm_context(struct sos_mm_context *mm_ctxt)
785 { 711 {
>> 712 sos_ui32_t flags;
>> 713
786 714
787 struct sos_mm_context * prev_mm_ctxt 715 struct sos_mm_context * prev_mm_ctxt
788 = current_thread->squatted_mm_context; 716 = current_thread->squatted_mm_context;
789 717
>> 718
>> 719
>> 720 if (mm_ctxt != NULL)
>> 721 SOS_ASSERT_FATAL(prev_mm_ctxt == NULL);
>> 722 else
>> 723 SOS_ASSERT_FATAL(prev_mm_ctxt != NULL);
>> 724
>> 725 sos_disable_IRQs(flags);
>> 726
790 727
791 current_thread->squatted_mm_context = mm_ctx 728 current_thread->squatted_mm_context = mm_ctxt;
792 729
793 730
794 731
795 if (mm_ctxt != NULL) 732 if (mm_ctxt != NULL)
796 { 733 {
797 sos_mm_context_ref(mm_ctxt); 734 sos_mm_context_ref(mm_ctxt);
798 735
799 736
800 sos_mm_context_switch_to(mm_ctxt); 737 sos_mm_context_switch_to(mm_ctxt);
801 } 738 }
802 else 739 else
803 sos_mm_context_unref(prev_mm_ctxt); 740 sos_mm_context_unref(prev_mm_ctxt);
804 741
805 742
806 743
807 return SOS_OK; <<
808 } <<
809 <<
810 <<
811 sos_ret_t <<
812 sos_thread_prepare_user_space_access(struct so <<
813 sos_vaddr <<
814 { <<
815 sos_ret_t retval; <<
816 sos_ui32_t flags; <<
817 <<
818 if (! dest_as) <<
819 { <<
820 <<
821 if (! current_thread->process) <<
822 return -SOS_EINVAL; <<
823 <<
824 dest_as = sos_process_get_address_space( <<
825 } <<
826 else <<
827 <<
828 <<
829 SOS_ASSERT_FATAL(! fixup_retvaddr); <<
830 <<
831 sos_disable_IRQs(flags); <<
832 SOS_ASSERT_FATAL(NULL == current_thread->squ <<
833 SOS_ASSERT_FATAL(0 == current_thread->fixup_ <<
834 <<
835 <<
836 retval = change_current_mm_context(sos_umem_ <<
837 if (SOS_OK == retval) <<
838 { <<
839 current_thread->fixup_uaccess.return_vad <<
840 current_thread->fixup_uaccess.faulted_ua <<
841 } <<
842 <<
843 sos_restore_IRQs(flags); 744 sos_restore_IRQs(flags);
844 return retval; <<
845 } <<
846 745
847 !! 746 return SOS_OK;
848 sos_ret_t <<
849 sos_thread_end_user_space_access(void) <<
850 { <<
851 sos_ret_t retval; <<
852 sos_ui32_t flags; <<
853 <<
854 sos_disable_IRQs(flags); <<
855 SOS_ASSERT_FATAL(NULL != current_thread->squ <<
856 <<
857 <<
858 retval = change_current_mm_context(NULL); <<
859 current_thread->fixup_uaccess.return_vaddr <<
860 current_thread->fixup_uaccess.faulted_uaddr <<
861 <<
862 sos_restore_IRQs(flags); <<
863 return retval; <<
864 } 747 }
865 748
866 749
867 void sos_thread_prepare_syscall_switch_back(st 750 void sos_thread_prepare_syscall_switch_back(struct sos_cpu_state *cpu_state)
868 { 751 {
869 752
870 753
871 754
872 755
873 756
874 757
875 758
876 759
877 current_thread->cpu_state = cpu_state; 760 current_thread->cpu_state = cpu_state;
878 761
879 762
880 _prepare_mm_context((struct sos_thread*) cur 763 _prepare_mm_context((struct sos_thread*) current_thread);
881 } 764 }
882 765
883 766
884 void sos_thread_prepare_exception_switch_back( 767 void sos_thread_prepare_exception_switch_back(struct sos_cpu_state *cpu_state)
885 { 768 {
886 769
887 770
888 771
889 772
890 773
891 774
892 775
893 776
894 current_thread->cpu_state = cpu_state; 777 current_thread->cpu_state = cpu_state;
895 778
896 779
897 _prepare_mm_context((struct sos_thread*) cur 780 _prepare_mm_context((struct sos_thread*) current_thread);
898 } 781 }
899 782
900 783
901 void 784 void
902 sos_thread_prepare_irq_servicing(struct sos_cp 785 sos_thread_prepare_irq_servicing(struct sos_cpu_state *interrupted_state)
903 { 786 {
904 current_thread->cpu_state = interrupted_stat 787 current_thread->cpu_state = interrupted_state;
905 } 788 }
906 789
907 790
908 struct sos_cpu_state * 791 struct sos_cpu_state *
909 sos_thread_prepare_irq_switch_back(void) 792 sos_thread_prepare_irq_switch_back(void)
910 { 793 {
911 struct sos_thread *myself, *next_thread; 794 struct sos_thread *myself, *next_thread;
912 795
913 796
914 797
915 if (! sos_cpu_context_is_in_user_mode(curren 798 if (! sos_cpu_context_is_in_user_mode(current_thread->cpu_state))
916 return current_thread->cpu_state; 799 return current_thread->cpu_state;
917 800
918 801
919 802
920 803
921 804
922 805
923 806
924 SOS_ASSERT_FATAL(current_thread->process != 807 SOS_ASSERT_FATAL(current_thread->process != NULL);
925 808
926 809
927 myself = (struct sos_thread*)current_thread; 810 myself = (struct sos_thread*)current_thread;
928 811
929 812
930 next_thread = sos_reschedule(myself, FALSE); 813 next_thread = sos_reschedule(myself, FALSE);
931 814
932 815
933 _prepare_mm_context(next_thread); 816 _prepare_mm_context(next_thread);
934 817
935 818
936 _set_current(next_thread); 819 _set_current(next_thread);
937 return next_thread->cpu_state; 820 return next_thread->cpu_state;
938 } 821 }