Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 481d4751 in mainline


Ignore:
Timestamp:
2010-05-02T18:52:45Z (11 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master
Children:
1624aae
Parents:
663bb537
Message:

Fix a race condition between the scheduler and as_destroy().

It was possible for the scheduler to use page tables of an address space which
was already destroyed. Prevent this from happening by holding extra references
to the current task and the current address space in
scheduler_separated_stack().

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/proc/scheduler.c

    r663bb537 r481d4751  
    11/*
    2  * Copyright (c) 2001-2007 Jakub Jermar
     2 * Copyright (c) 2010 Jakub Jermar
    33 * All rights reserved.
    44 *
     
    382382        int priority;
    383383        DEADLOCK_PROBE_INIT(p_joinwq);
     384        task_t *old_task = TASK;
     385        as_t *old_as = AS;
    384386
    385387        ASSERT(CPU != NULL);
    386388       
     389        /*
     390         * Hold the current task and the address space to prevent their
     391         * possible destruction should thread_destroy() be called on this or any
     392         * other processor while the scheduler is still using them.
     393         */
     394        if (old_task)
     395                task_hold(old_task);
     396        if (old_as)
     397                as_hold(old_as);
     398
    387399        if (THREAD) {
    388400                /* must be run after the switch to scheduler stack */
     
    476488         */
    477489        if (TASK != THREAD->task) {
    478                 as_t *as1 = NULL;
    479                 as_t *as2;
    480 
    481                 if (TASK) {
    482                         spinlock_lock(&TASK->lock);
    483                         as1 = TASK->as;
    484                         spinlock_unlock(&TASK->lock);
    485                 }
    486 
    487                 spinlock_lock(&THREAD->task->lock);
    488                 as2 = THREAD->task->as;
    489                 spinlock_unlock(&THREAD->task->lock);
     490                as_t *new_as = THREAD->task->as;
    490491               
    491492                /*
     
    493494                 * space.
    494495                 */
    495                 if (as1 != as2) {
     496                if (old_as != new_as) {
    496497                        /*
    497498                         * Both tasks and address spaces are different.
    498499                         * Replace the old one with the new one.
    499500                         */
    500                         as_switch(as1, as2);
     501                        as_switch(old_as, new_as);
    501502                }
     503
    502504                TASK = THREAD->task;
    503505                before_task_runs();
    504506        }
    505507
     508        if (old_task)
     509                task_release(old_task);
     510        if (old_as)
     511                as_release(old_as);
     512       
    506513        spinlock_lock(&THREAD->lock);   
    507514        THREAD->state = Running;
Note: See TracChangeset for help on using the changeset viewer.