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