Ignore:
Timestamp:
Jul 27, 2017, 12:23:29 AM (7 years ago)
Author:
alain
Message:

1) Introduce independant command fields for the various devices in the thread descriptor.
2) Introduce a new dev_pic_enable_ipi() function in the generic PIC device
3) Fix two bugs identified by Maxime in the scheduler initialisation, and in the sched_select().
4) fix several bugs in the TSAR hal_kentry.S.
5) Introduce a third kgiet segment (besides kdata and kcode) in the TSAR bootloader.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kernel/kern/scheduler.c

    r278 r279  
    4141    sched->k_threads_nr   = 0;
    4242
    43     sched->current        = NULL;
    44     sched->idle           = NULL;
    45     sched->u_last         = NULL;
    46     sched->k_last         = NULL;
     43    sched->current        = CURRENT_THREAD;
     44    sched->idle           = NULL;             // initialized in kernel_init()
     45    sched->u_last         = NULL;             // initialized in sched_register_thread()
     46    sched->k_last         = NULL;             // initialized in sched_register_thread()
    4747
    4848    // initialise threads lists
     
    6262    spinlock_lock( &sched->lock );
    6363
    64     // register thread
    6564    if( type == THREAD_USER )
    6665    {
     66        // register thread in scheduler user list
    6767        list_add_last( &sched->u_root , &thread->sched_list );
    6868        sched->u_threads_nr++;
     69
     70        // initialize u_last field if first user thread
     71        if( sched->u_last == NULL ) sched->u_last = &thread->sched_list;
    6972    }
    7073    else // kernel thread
    7174    {
     75        // register thread in scheduler kernel list
    7276        list_add_last( &sched->k_root , &thread->sched_list );
    7377        sched->k_threads_nr++;
     78
     79        // initialize k_last field if first kernel thread
     80        if( sched->k_last == NULL ) sched->k_last = &thread->sched_list;
    7481    }
    7582
     
    8996    spinlock_lock( &sched->lock );
    9097
    91     // remove thread
    9298    if( type == THREAD_USER )
    9399    {
     100        // remove thread from user list
    94101        list_unlink( &thread->sched_list );
    95102        sched->u_threads_nr--;
     103
     104        // reset the u_last field if list empty
     105        if( sched->u_threads_nr == 0 ) sched->u_last = NULL;
    96106    }
    97107    else // kernel thread
    98108    {
     109        // remove thread from kernel list
    99110        list_unlink( &thread->sched_list );
    100111        sched->k_threads_nr--;
     112
     113        // reset the k_last field if list empty
     114        if( sched->k_threads_nr == 0 ) sched->k_last = NULL;
    101115    }
    102116
     
    140154    list_entry_t * last;
    141155
    142     // first scan the kernel threads
    143     last    = sched->k_last;
    144     current = sched->k_last;
    145     do
    146     {
    147         // get next entry in kernel list
    148         current = list_next( &sched->k_root , current );
    149 
    150         // skip the list root that does not contain a thread
    151         if( current == NULL ) continue;
    152 
    153         // get thread pointer
    154         thread = LIST_ELEMENT( current , thread_t , sched_list );
    155 
    156         // return thread if not blocked
    157         if( thread->blocked == 0 )
     156    // first : scan the kernel threads list,
     157    // only if this list is not empty
     158    if( list_is_empty( &sched->k_root ) == false )
     159    {
     160        last    = sched->k_last;
     161        current = sched->k_last;
     162        do
    158163        {
    159             // release lock
    160             spinlock_unlock( &sched->lock );
    161             return thread;
     164            // get next entry in kernel list
     165            current = list_next( &sched->k_root , current );
     166
     167            // skip the root that does not contain a thread
     168            if( current == NULL ) current = sched->k_root.next;
     169
     170            // get thread pointer for this entry
     171            thread = LIST_ELEMENT( current , thread_t , sched_list );
     172
     173            // return thread if runnable
     174            if( thread->blocked == 0 )
     175            {
     176                // release lock
     177                spinlock_unlock( &sched->lock );
     178                return thread;
     179            }
    162180        }
    163     }
    164     while( current != last );
    165 
    166     // second scan the user threads
    167     last    = sched->u_last;
    168     current = sched->u_last;
    169     do
    170     {
    171         // get next entry in user list
    172         current = list_next( &sched->u_root , current );
    173 
    174         // skip the list root that does not contain a thread
    175         if( current == NULL ) continue;
    176 
    177         // get thread pointer
    178         thread = LIST_ELEMENT( current , thread_t , sched_list );
    179 
    180         // return thread if not blocked
    181         if( thread->blocked == 0 )
     181        while( current != last );
     182    }
     183
     184    // second : scan the user threads list,
     185    // only if this list is not empty
     186    if( list_is_empty( &sched->u_root ) == false )
     187    {
     188        last    = sched->u_last;
     189        current = sched->u_last;
     190        do
    182191        {
    183             // release lock
    184             spinlock_unlock( &sched->lock );
    185             return thread;
     192            // get next entry in user list
     193            current = list_next( &sched->u_root , current );
     194
     195            // skip the root that does not contain a thread
     196            if( current == NULL ) current = sched->u_root.next;
     197
     198            // get thread pointer for this entry
     199            thread = LIST_ELEMENT( current , thread_t , sched_list );
     200
     201            // return thread if runnable
     202            if( thread->blocked == 0 )
     203            {
     204                // release lock
     205                spinlock_unlock( &sched->lock );
     206                return thread;
     207            }
    186208        }
    187     }
    188     while( current != last );
     209        while( current != last );
     210    }
    189211
    190212    // release lock
    191213    spinlock_unlock( &sched->lock );
    192214
    193     // third, return idle thread if no runnable thread
     215    // third : return idle thread if no runnable thread
    194216    return sched->idle;
    195217
     
    234256    thread_t    * current = CURRENT_THREAD;
    235257    core_t      * core    = current->core;
     258    scheduler_t * sched   = &core->scheduler;
    236259
    237260    if( thread_can_yield() == false )
     
    265288               __FUNCTION__, core->lid, local_cxy, current->trdid, next->trdid );
    266289
    267     // switch contexts if new thread
     290    // switch contexts and update scheduler state if new thread
    268291        if( next != current ) 
    269292        {
    270293        hal_cpu_context_save( current );
    271294        hal_cpu_context_restore( next );
     295
     296        if( current->type == THREAD_USER ) sched->u_last = &current->sched_list;
     297        else                               sched->k_last = &current->sched_list;
     298
     299        sched->current = next;
    272300        }
    273301
Note: See TracChangeset for help on using the changeset viewer.