Subversion Repositories HelenOS

Rev

Rev 1636 | 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
}