Ignore:
Timestamp:
Oct 1, 2015, 4:20:46 PM (9 years ago)
Author:
alain
Message:

Major release: Change the task model to implement the POSIX threads API.

  • The shell "exec" and "kill" commands can be used to activate/de-activate the applications.
  • The "pause", "resume", and "context" commands can be used to stop, restart, a single thtead or to display the thread context.

This version has been tested on the following multi-threaded applications,
that have been modified to use the POSIX threads:

  • classif
  • convol
  • transpose
  • gameoflife
  • raycast
File:
1 edited

Legend:

Unmodified
Added
Removed
  • soft/giet_vm/giet_kernel/ctx_handler.c

    r707 r709  
    99#include <sys_handler.h>
    1010#include <giet_config.h>
     11#include <fat32.h>
    1112#include <hard_config.h>
    1213#include <utils.h>
    1314#include <tty0.h>
    1415#include <xcu_driver.h>
     16#include <bdv_driver.h>
    1517
    1618/////////////////////////////////////////////////////////////////////////////////
     
    1921
    2022// defined in giet_kernel/switch.s file
    21 extern void _task_switch(unsigned int *, unsigned int *);
     23extern void _thread_switch( thread_context_t* , thread_context_t* );
    2224
    2325// allocated in boot.c or kernel_init.c files
    2426extern static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX];
    2527
    26 
    27 ///////////////////////////////////////////////
    28 static void _ctx_kill_task( unsigned int ltid )
     28// allocated in kernel_init.c file
     29extern fat_desc_t  _fat;
     30
     31//////////////////////////////////////////////////////////////////
     32// This function is called by the _ctx_switch() function.
     33// It desactivates a thread that received a KILL signal.
     34// We must release all ressources allocated to the thread
     35// before the actual desactivation, that uses NORUN_MASK_THREAD.
     36//////////////////////////////////////////////////////////////////
     37static void _ctx_kill_thread( unsigned int x,
     38                              unsigned int y,
     39                              unsigned int p,
     40                              unsigned int ltid )
    2941{
    3042    // get scheduler address
    31     static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
    32 
    33     // pretend the task to kill is scheduled (required for sys_handler calls)
    34     unsigned int cur_task = psched->current;
     43    static_scheduler_t* psched = _schedulers[x][y][p];
     44
     45    // pretend the thread to kill is the currently scheduled thread
     46    // (required by the _sys_***_release() calls)
     47    unsigned int cur_thread = psched->current;
    3548    psched->current = ltid;
    3649
     50    // release BDV lock if taken and reset BDV peripheral
     51    if ( psched->context[ltid].slot[CTX_LOCKS_ID] & LOCKS_MASK_BDV )
     52    {
     53        _bdv_set_register( BLOCK_DEVICE_STATUS , 0 );
     54        _spin_lock_release( &_bdv_lock );
     55    }
     56
     57    // release FAT lock if taken
     58    if ( psched->context[ltid].slot[CTX_LOCKS_ID] & LOCKS_MASK_FAT )
     59    {
     60        _spin_lock_release( &_fat.fat_lock );
     61    }
     62
    3763    // release private TTY terminal if required
    38     if ( psched->context[ltid][CTX_TTY_ID] < NB_TTY_CHANNELS )
    39     {
    40         _sys_tty_release();
    41         psched->context[ltid][CTX_TTY_ID] = -1;
    42     }
     64    if ( psched->context[ltid].slot[CTX_TTY_ID] < NB_TTY_CHANNELS )
     65        _sys_tty_release();
    4366
    4467    // release private TIM channel if required
    45     if ( psched->context[ltid][CTX_TIM_ID] < NB_TIM_CHANNELS )
     68
     69    if ( psched->context[ltid].slot[CTX_TIM_ID] < NB_TIM_CHANNELS )
    4670    {
    4771        _sys_tim_release();
    48         psched->context[ltid][CTX_TIM_ID] = -1;
    49     }
    50 
    51     // release private NIC_RX channel if required
    52     if ( psched->context[ltid][CTX_NIC_RX_ID] < NB_NIC_CHANNELS )
     72    }
     73
     74    // release private NIC_RX and CMA_RX channels if required
     75    if ( psched->context[ltid].slot[CTX_NIC_RX_ID] < NB_NIC_CHANNELS )
    5376    {
    5477        _sys_nic_release( 1 );
    55         psched->context[ltid][CTX_NIC_RX_ID] = -1;
    56     }
    57 
    58     // release private NIC_TX channel if required
    59     if ( psched->context[ltid][CTX_NIC_TX_ID] < NB_NIC_CHANNELS )
     78    }
     79
     80    // release private NIC_TX and CMA_TX channels if required
     81    if ( psched->context[ltid].slot[CTX_NIC_TX_ID] < NB_NIC_CHANNELS )
    6082    {
    6183        _sys_nic_release( 0 );
    62         psched->context[ltid][CTX_NIC_TX_ID] = -1;
    6384    }
    6485
    6586    // release private FBF_CMA channel if required
    66     if ( psched->context[ltid][CTX_CMA_FB_ID] < NB_CMA_CHANNELS )
     87    if ( psched->context[ltid].slot[CTX_CMA_FB_ID] < NB_CMA_CHANNELS )
    6788    {
    6889        _sys_fbf_cma_release();
    69         psched->context[ltid][CTX_CMA_FB_ID] = -1;
    70     }
    71 
    72     // restore scheduled task
    73     psched->current = cur_task;
    74 
    75     // set NORUN_MASK_TASK bit
    76     _atomic_or( &psched->context[ltid][CTX_NORUN_ID], NORUN_MASK_TASK );
    77 
    78 } // end _ctx_kill_task()
    79 
    80 
    81 //////////////////////////////////
    82 void _ctx_display( unsigned int x,
    83                    unsigned int y,
    84                    unsigned int p,
    85                    unsigned int ltid,
    86                    char*        string )
    87 {
    88     static_scheduler_t* psched = _schedulers[x][y][p];
    89     _printf("\n########## task[%d,%d,%d,%d] context\n"
    90             " - CTX_EPC   = %x\n"
    91             " - CTX_PTAB  = %x\n"
    92             " - CTX_PTPR  = %x\n"
    93             " - CTX_VSID  = %x\n"
    94             " - CTX_SR    = %x\n"
    95             " - CTX_RA    = %x\n"
    96             " - CTX_SP    = %x\n"
    97             " - CTX_NORUN = %x\n"
    98             " - CTX_SIG   = %x\n"
    99             "########## %s\n",
    100             x , y , p , ltid ,
    101             psched->context[ltid][CTX_EPC_ID],
    102             psched->context[ltid][CTX_PTAB_ID],
    103             psched->context[ltid][CTX_PTPR_ID],
    104             psched->context[ltid][CTX_VSID_ID],
    105             psched->context[ltid][CTX_SR_ID],
    106             psched->context[ltid][CTX_RA_ID],
    107             psched->context[ltid][CTX_SP_ID],
    108             psched->context[ltid][CTX_NORUN_ID],
    109             psched->context[ltid][CTX_SIG_ID],
    110             string );
    111 }  // _ctx_display()
     90    }
     91
     92    // restore scheduled thread index
     93    psched->current = cur_thread;
     94
     95    // set NORUN_MASK_THREAD bit to desactivate the target thread
     96    psched->context[ltid].slot[CTX_NORUN_ID] = NORUN_MASK_THREAD;
     97
     98} // end _ctx_kill_thread()
    11299
    113100
    114101//////////////////
    115102void _ctx_switch()
    116 {
    117     unsigned int gpid       = _get_procid();
    118     unsigned int cluster_xy = gpid >> P_WIDTH;
    119     unsigned int lpid       = gpid & ((1<<P_WIDTH)-1);
    120 
    121     // get scheduler address
    122     static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
    123 
    124     // get number of tasks allocated to scheduler
    125     unsigned int tasks = psched->tasks;
    126 
    127     // get current task index
    128     unsigned int curr_task_id = psched->current;
    129 
    130     // select the next task using a round-robin policy
    131     unsigned int next_task_id;
    132     unsigned int tid;
    133     unsigned int found = 0;
    134 
    135     for (tid = curr_task_id + 1; tid < curr_task_id + 1 + tasks; tid++)
    136     {
    137         next_task_id = tid % tasks;
    138 
    139         // this task needs to be killed
    140         if ( psched->context[next_task_id][CTX_SIG_ID] & SIG_MASK_KILL )
    141         {
    142             // acknowledge signal
    143             _atomic_and( &psched->context[next_task_id][CTX_SIG_ID], ~SIG_MASK_KILL );
    144 
    145             _ctx_kill_task( next_task_id );
    146         }
    147 
    148         // test if the task is runable
    149         if ( psched->context[next_task_id][CTX_NORUN_ID] == 0 )
    150         {
    151             found = 1;
    152             // TODO: don't break to process all pending signals.
    153             break;
    154         }
    155     }
    156 
    157     // launch "idle" task if no runable task
    158     if (found == 0) next_task_id = IDLE_TASK_INDEX;
    159 
    160 #if ( GIET_DEBUG_SWITCH & 0x1 )
    161 unsigned int x = cluster_xy >> Y_WIDTH;
    162 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
    163 if ( _get_proctime() > GIET_DEBUG_SWITCH )
    164 _printf("\n[DEBUG SWITCH] (%d) -> (%d) on processor[%d,%d,%d] at cycle %d\n",
    165         curr_task_id, next_task_id, x, y , lpid, _get_proctime() );
    166 #endif
    167 
    168     if (curr_task_id != next_task_id)  // actual task switch required
    169     {
    170         unsigned int* curr_ctx_vaddr = &(psched->context[curr_task_id][0]);
    171         unsigned int* next_ctx_vaddr = &(psched->context[next_task_id][0]);
    172 
    173         // reset TICK timer counter.
    174         _xcu_timer_reset_cpt( cluster_xy, lpid );
    175 
    176         // set current task index
    177         psched->current = next_task_id;
    178 
    179         // makes context switch
    180         _task_switch( curr_ctx_vaddr , next_ctx_vaddr );
    181     }
    182 } //end _ctx_switch()
    183 
    184 
    185 /////////////////
    186 void _idle_task()
    187103{
    188104    unsigned int gpid       = _get_procid();
     
    192108    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
    193109
     110    unsigned int ltid;     // index for loops on threads in scheduler
     111
     112    // get calling thread scheduler address
     113    static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
     114
     115    // get number of threads allocated to scheduler
     116    unsigned int threads = psched->threads;
     117
     118    // get current thread ltid
     119    unsigned int curr_thread_id = psched->current;
     120
     121    // first loop on threads: handle all pending KILL signals
     122    for ( ltid = 0 ; ltid < threads ; ltid++ )
     123    {
     124        if ( psched->context[ltid].slot[CTX_SIGS_ID] & SIGS_MASK_KILL )
     125        {
     126            // acknowledge KILL signal
     127            _atomic_and( &psched->context[ltid].slot[CTX_SIGS_ID], ~SIGS_MASK_KILL );
     128
     129            // desactivate the killed thread
     130            _ctx_kill_thread( x , y , p , ltid );
     131        }
     132    }
     133
     134    // second loop: select next thread using a round-robin policy
     135    unsigned int next_thread_id;
     136    unsigned int found = 0;
     137    for ( ltid = curr_thread_id + 1 ; ltid < (curr_thread_id + 1 + threads) ; ltid++ )
     138    {
     139        next_thread_id = ltid % threads;
     140
     141        // test if the thread is runable
     142        if ( psched->context[next_thread_id].slot[CTX_NORUN_ID] == 0 )
     143        {
     144            found = 1;
     145            break;
     146        }
     147    }
     148
     149    // launch idle_thread if no runable thread
     150    if ( found == 0 ) next_thread_id = IDLE_THREAD_INDEX;
     151
     152    if ( curr_thread_id != next_thread_id )  // actual thread switch required
     153    {
     154
     155#if GIET_DEBUG_SWITCH
     156unsigned int x = cluster_xy >> Y_WIDTH;
     157unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
     158if ( (_get_proctime() > GIET_DEBUG_SWITCH) && (x == 0) && (y == 0) && (p == 0) )
     159_printf("\n[DEBUG SWITCH] (%d) -> (%d) on processor[%d,%d,%d] at cycle %d\n",
     160        curr_thread_id, next_thread_id, x, y , p, _get_proctime() );
     161#endif
     162
     163        thread_context_t* curr_ctx_vaddr = &(psched->context[curr_thread_id]);
     164        thread_context_t* next_ctx_vaddr = &(psched->context[next_thread_id]);
     165
     166        // reset TICK timer counter.
     167        _xcu_timer_reset_cpt( cluster_xy, p );
     168
     169        // set current thread index
     170        psched->current = next_thread_id;
     171
     172        // makes context switch
     173        _thread_switch( curr_ctx_vaddr , next_ctx_vaddr );
     174    }
     175} //end _ctx_switch()
     176
     177
     178///////////////////
     179void _idle_thread()
     180{
     181    unsigned int gpid       = _get_procid();
     182    unsigned int cluster_xy = gpid >> P_WIDTH;
     183    unsigned int x          = cluster_xy >> Y_WIDTH;
     184    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
     185    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
     186
    194187    while(1)
    195188    {
    196189        // initialize counter
    197         unsigned int count = GIET_IDLE_TASK_PERIOD;
     190        unsigned int count = GIET_IDLE_THREAD_PERIOD;
    198191
    199192        // decounting loop
    200193        asm volatile(
    201194                "move   $3,   %0              \n"
    202                 "_idle_task_loop:             \n"
     195                "_idle_thread_loop:             \n"
    203196                "addi   $3,   $3,   -1        \n"
    204                 "bnez   $3,   _idle_task_loop \n"
     197                "bnez   $3,   _idle_thread_loop \n"
    205198                "nop                          \n"
    206199                :
Note: See TracChangeset for help on using the changeset viewer.