Rev 1636 | Rev 1676 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1636 | Rev 1661 | ||
---|---|---|---|
Line 69... | Line 69... | ||
69 | btree_t tasks_btree; |
69 | btree_t tasks_btree; |
70 | 70 | ||
71 | static task_id_t task_counter = 0; |
71 | static task_id_t task_counter = 0; |
72 | 72 | ||
73 | static void ktaskclnp(void *arg); |
73 | static void ktaskclnp(void *arg); |
74 | static void ktaskkill(void *arg); |
74 | static void ktaskgc(void *arg); |
75 | 75 | ||
76 | /** Initialize tasks |
76 | /** Initialize tasks |
77 | * |
77 | * |
78 | * Initialize kernel tasks support. |
78 | * Initialize kernel tasks support. |
79 | * |
79 | * |
Line 219... | Line 219... | ||
219 | ASSERT(t1); |
219 | ASSERT(t1); |
220 | 220 | ||
221 | /* |
221 | /* |
222 | * Create killer thread for the new task. |
222 | * Create killer thread for the new task. |
223 | */ |
223 | */ |
224 | t2 = thread_create(ktaskkill, t1, task, 0, "ktaskkill"); |
224 | t2 = thread_create(ktaskgc, t1, task, 0, "ktaskgc"); |
225 | ASSERT(t2); |
225 | ASSERT(t2); |
226 | thread_ready(t2); |
226 | thread_ready(t2); |
227 | 227 | ||
228 | thread_ready(t1); |
228 | thread_ready(t1); |
229 | 229 | ||
Line 370... | Line 370... | ||
370 | void ktaskclnp(void *arg) |
370 | void ktaskclnp(void *arg) |
371 | { |
371 | { |
372 | ipl_t ipl; |
372 | ipl_t ipl; |
373 | thread_t *t = NULL, *main_thread; |
373 | thread_t *t = NULL, *main_thread; |
374 | link_t *cur; |
374 | link_t *cur; |
- | 375 | bool again; |
|
375 | 376 | ||
376 | thread_detach(THREAD); |
377 | thread_detach(THREAD); |
377 | 378 | ||
378 | loop: |
379 | loop: |
379 | ipl = interrupts_disable(); |
380 | ipl = interrupts_disable(); |
Line 382... | Line 383... | ||
382 | main_thread = TASK->main_thread; |
383 | main_thread = TASK->main_thread; |
383 | 384 | ||
384 | /* |
385 | /* |
385 | * Find a thread to join. |
386 | * Find a thread to join. |
386 | */ |
387 | */ |
- | 388 | again = false; |
|
387 | for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) { |
389 | for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) { |
388 | t = list_get_instance(cur, thread_t, th_link); |
390 | t = list_get_instance(cur, thread_t, th_link); |
- | 391 | ||
- | 392 | spinlock_lock(&t->lock); |
|
389 | if (t == THREAD) |
393 | if (t == THREAD) { |
- | 394 | spinlock_unlock(&t->lock); |
|
- | 395 | continue; |
|
- | 396 | } else if (t == main_thread) { |
|
- | 397 | spinlock_unlock(&t->lock); |
|
390 | continue; |
398 | continue; |
391 | else if (t == main_thread) |
399 | } else if (t->join_type != None) { |
- | 400 | spinlock_unlock(&t->lock); |
|
- | 401 | again = true; |
|
392 | continue; |
402 | continue; |
393 | else |
403 | } else { |
- | 404 | t->join_type = TaskClnp; |
|
- | 405 | spinlock_unlock(&t->lock); |
|
- | 406 | again = false; |
|
394 | break; |
407 | break; |
- | 408 | } |
|
395 | } |
409 | } |
396 | 410 | ||
397 | spinlock_unlock(&TASK->lock); |
411 | spinlock_unlock(&TASK->lock); |
398 | interrupts_restore(ipl); |
412 | interrupts_restore(ipl); |
399 | 413 | ||
- | 414 | if (again) { |
|
- | 415 | /* |
|
- | 416 | * Other cleanup (e.g. ktaskgc) is in progress. |
|
- | 417 | */ |
|
- | 418 | scheduler(); |
|
- | 419 | goto loop; |
|
- | 420 | } |
|
- | 421 | ||
400 | if (t != THREAD) { |
422 | if (t != THREAD) { |
401 | ASSERT(t != main_thread); /* uninit is joined and detached in ktaskkill */ |
423 | ASSERT(t != main_thread); /* uninit is joined and detached in ktaskgc */ |
402 | thread_join(t); |
424 | thread_join(t); |
403 | thread_detach(t); |
425 | thread_detach(t); |
404 | goto loop; /* go for another thread */ |
426 | goto loop; /* go for another thread */ |
405 | } |
427 | } |
406 | 428 | ||
Line 415... | Line 437... | ||
415 | } |
437 | } |
416 | 438 | ||
417 | /** Kernel task used to kill a userspace task when its main thread exits. |
439 | /** Kernel task used to kill a userspace task when its main thread exits. |
418 | * |
440 | * |
419 | * This thread waits until the main userspace thread (i.e. uninit) exits. |
441 | * This thread waits until the main userspace thread (i.e. uninit) exits. |
420 | * When this happens, the task is killed. |
442 | * When this happens, the task is killed. In the meantime, exited threads |
- | 443 | * are garbage collected. |
|
421 | * |
444 | * |
422 | * @param arg Pointer to the thread structure of the task's main thread. |
445 | * @param arg Pointer to the thread structure of the task's main thread. |
423 | */ |
446 | */ |
424 | void ktaskkill(void *arg) |
447 | void ktaskgc(void *arg) |
425 | { |
448 | { |
426 | thread_t *t = (thread_t *) arg; |
449 | thread_t *t = (thread_t *) arg; |
427 | 450 | loop: |
|
428 | /* |
451 | /* |
429 | * Userspace threads cannot detach themselves, |
452 | * Userspace threads cannot detach themselves, |
430 | * therefore the thread pointer is guaranteed to be valid. |
453 | * therefore the thread pointer is guaranteed to be valid. |
431 | */ |
454 | */ |
432 | thread_join(t); /* sleep uninterruptibly here! */ |
455 | if (thread_join_timeout(t, 1000000, SYNCH_FLAGS_NONE) == ESYNCH_TIMEOUT) { /* sleep uninterruptibly here! */ |
- | 456 | ipl_t ipl; |
|
- | 457 | link_t *cur; |
|
- | 458 | thread_t *thr = NULL; |
|
- | 459 | ||
- | 460 | /* |
|
- | 461 | * The join timed out. Try to do some garbage collection of Undead threads. |
|
- | 462 | */ |
|
- | 463 | more_gc: |
|
- | 464 | ipl = interrupts_disable(); |
|
- | 465 | spinlock_lock(&TASK->lock); |
|
- | 466 | ||
- | 467 | for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) { |
|
- | 468 | thr = list_get_instance(cur, thread_t, th_link); |
|
- | 469 | spinlock_lock(&thr->lock); |
|
- | 470 | if (thr->state == Undead && thr->join_type == None) { |
|
- | 471 | thr->join_type = TaskGC; |
|
- | 472 | spinlock_unlock(&thr->lock); |
|
- | 473 | break; |
|
- | 474 | } |
|
- | 475 | spinlock_unlock(&thr->lock); |
|
- | 476 | thr = NULL; |
|
- | 477 | } |
|
- | 478 | spinlock_unlock(&TASK->lock); |
|
- | 479 | ||
- | 480 | if (thr) { |
|
- | 481 | thread_join(thr); |
|
- | 482 | thread_detach(thr); |
|
- | 483 | scheduler(); |
|
- | 484 | goto more_gc; |
|
- | 485 | } |
|
- | 486 | ||
- | 487 | goto loop; |
|
- | 488 | } |
|
433 | thread_detach(t); |
489 | thread_detach(t); |
434 | task_kill(TASK->taskid); |
490 | task_kill(TASK->taskid); |
435 | } |
491 | } |