Subversion Repositories HelenOS

Rev

Rev 2898 | Rev 2903 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2898 Rev 2902
Line 410... Line 410...
410
        task_destroy(t->task);
410
        task_destroy(t->task);
411
   
411
   
412
    slab_free(thread_slab, t);
412
    slab_free(thread_slab, t);
413
}
413
}
414
 
414
 
415
/** Attach thread to the given task.
-
 
416
 *
-
 
417
 * The task's lock must already be held and interrupts must be disabled.
-
 
418
 *
-
 
419
 * @param t Thread to be attached to the task.
-
 
420
 * @param task  Task to which the thread is to be attached.
-
 
421
 */
-
 
422
static void _thread_attach_task(thread_t *t, task_t *task)
-
 
423
{
-
 
424
    atomic_inc(&task->refcount);
-
 
425
    atomic_inc(&task->lifecount);
-
 
426
 
-
 
427
    list_append(&t->th_link, &task->th_head);
-
 
428
 
-
 
429
    /*
-
 
430
     * Copy task debugging state to thread struct.
-
 
431
     * The thread needs to know it is being debugged,
-
 
432
     * otherwise it would neither stop nor respond to
-
 
433
     * debug ops.
-
 
434
     */
-
 
435
    if (t->flags & THREAD_FLAG_USPACE) {
-
 
436
        if (task->dt_state == UDEBUG_TS_BEGINNING ||
-
 
437
            task->dt_state == UDEBUG_TS_ACTIVE) {
-
 
438
            t->debug_active = true;
-
 
439
        }
-
 
440
    }
-
 
441
}
-
 
442
 
-
 
443
/** Add thread to the threads tree.
-
 
444
 *
-
 
445
 * Interrupts must be already disabled.
-
 
446
 *
-
 
447
 * @param t Thread to be attached to the task.
-
 
448
 * @param task  Task to which the thread is to be attached.
-
 
449
 */
-
 
450
static void _thread_attach_tree(thread_t *t)
-
 
451
{
-
 
452
    /*
-
 
453
     * Register this thread in the system-wide list.
-
 
454
     */
-
 
455
    spinlock_lock(&threads_lock);
-
 
456
    avltree_insert(&threads_tree, &t->threads_tree_node);
-
 
457
    spinlock_unlock(&threads_lock);
-
 
458
}
-
 
459
 
-
 
460
 
-
 
461
/** Make the thread visible to the system.
415
/** Make the thread visible to the system.
462
 *
416
 *
463
 * Attach the thread structure to the current task and make it visible in the
417
 * Attach the thread structure to the current task and make it visible in the
464
 * threads_tree.
418
 * threads_tree.
465
 *
419
 *
Line 468... Line 422...
468
 */
422
 */
469
void thread_attach(thread_t *t, task_t *task)
423
void thread_attach(thread_t *t, task_t *task)
470
{
424
{
471
    ipl_t ipl;
425
    ipl_t ipl;
472
 
426
 
473
    ipl = interrupts_disable();
-
 
474
 
-
 
475
    /*
-
 
476
     * Attach to the current task.
-
 
477
     */
-
 
478
    spinlock_lock(&task->lock);
-
 
479
    _thread_attach_task(t, task);
-
 
480
    spinlock_unlock(&task->lock);
-
 
481
 
-
 
482
    /*
427
    /*
483
     * Register this thread in the system-wide list.
428
     * Attach to the specified task.
484
     */
429
     */
485
    _thread_attach_tree(t);
-
 
486
   
-
 
487
    interrupts_restore(ipl);
-
 
488
}
-
 
489
 
-
 
490
/** Attach thread to a task given by its ID.
-
 
491
 *
-
 
492
 * Unlike thread_attach(), this function allows to attach a thread
-
 
493
 * to an arbitrary task.
-
 
494
 *
-
 
495
 * @param t     Thread to be attached to the task.
-
 
496
 * @param taskid    Task id to which the thread is to be attached.
-
 
497
 * @return      An error code from errno.h
-
 
498
 */
-
 
499
int thread_attach_by_id(thread_t *t, task_id_t taskid)
-
 
500
{
-
 
501
    ipl_t ipl;
-
 
502
    task_t *task;
-
 
503
 
-
 
504
    ipl = interrupts_disable();
430
    ipl = interrupts_disable();
505
 
-
 
506
    spinlock_lock(&tasks_lock);
-
 
507
    task = task_find_by_id(taskid);
-
 
508
    if (task == NULL) {
-
 
509
        spinlock_unlock(&tasks_lock);
-
 
510
        interrupts_restore(ipl);
-
 
511
        return ENOENT;
-
 
512
    }
-
 
513
 
-
 
514
    spinlock_lock(&task->lock);
431
    spinlock_lock(&task->lock);
515
    spinlock_unlock(&tasks_lock);
432
    atomic_inc(&task->refcount);
516
 
-
 
517
    /*
-
 
518
     * Attach to the current task.
433
    /* Must not count kbox thread into lifecount */
519
     */
434
    if (t->flags & THREAD_FLAG_USPACE)
-
 
435
        atomic_inc(&task->lifecount);
520
    _thread_attach_task(t, task);
436
    list_append(&t->th_link, &task->th_head);
521
 
-
 
522
    spinlock_unlock(&task->lock);
437
    spinlock_unlock(&task->lock);
523
 
438
 
524
    /*
439
    /*
525
     * Register this thread in the system-wide list.
440
     * Register this thread in the system-wide list.
526
     */
441
     */
-
 
442
    spinlock_lock(&threads_lock);
-
 
443
    avltree_insert(&threads_tree, &t->threads_tree_node);
527
    _thread_attach_tree(t);
444
    spinlock_unlock(&threads_lock);
528
   
445
   
529
    interrupts_restore(ipl);
446
    interrupts_restore(ipl);
530
 
-
 
531
    return EOK;
-
 
532
}
447
}
533
 
448
 
534
 
-
 
535
/** Terminate thread.
449
/** Terminate thread.
536
 *
450
 *
537
 * End current thread execution and switch it to the exiting state. All pending
451
 * End current thread execution and switch it to the exiting state. All pending
538
 * timeouts are executed.
452
 * timeouts are executed.
539
 */
453
 */
540
void thread_exit(void)
454
void thread_exit(void)
541
{
455
{
542
    ipl_t ipl;
456
    ipl_t ipl;
543
 
457
 
-
 
458
    if (THREAD->flags & THREAD_FLAG_USPACE) {
544
    if (atomic_predec(&TASK->lifecount) == 0) {
459
        if (atomic_predec(&TASK->lifecount) == 0) {
545
        /*
460
            /*
546
         * We are the last thread in the task that still has not exited.
461
             * We are the last userspace thread in the task that
-
 
462
             * still has not exited. With the exception of the
547
         * With the exception of the moment the task was created, new
463
             * moment the task was created, new userspace threads
548
         * threads can only be created by threads of the same task.
464
             * can only be created by threads of the same task.
549
         * We are safe to perform cleanup.
465
             * We are safe to perform cleanup.
550
         */
466
             */
551
        if (THREAD->flags & THREAD_FLAG_USPACE) {
-
 
552
            ipc_cleanup();
467
            ipc_cleanup();
553
                futex_cleanup();
468
                futex_cleanup();
554
            klog_printf("Cleanup of task %llu completed.",
469
            klog_printf("Cleanup of task %llu completed.",
555
                TASK->taskid);
470
                TASK->taskid);
556
        }
471
        }
557
    }
472
    }
558
 
473