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