source: soft/giet_vm/giet_kernel/ctx_handler.c

Last change on this file was 818, checked in by cfuguet, 9 years ago

Optimization: When doing a context switch between threads of the
same vspace and cluster, do not rewrite the PTPR register.

  • Property svn:executable set to *
File size: 7.0 KB
RevLine 
[294]1//////////////////////////////////////////////////////////////////////////////////
[258]2// File     : ctx_handler.c
3// Date     : 01/04/2012
4// Authors  : alain greiner & joel porquet
5// Copyright (c) UPMC-LIP6
[294]6//////////////////////////////////////////////////////////////////////////////////
[258]7
[440]8#include <ctx_handler.h>
[695]9#include <sys_handler.h>
[258]10#include <giet_config.h>
[709]11#include <fat32.h>
[528]12#include <hard_config.h>
[440]13#include <utils.h>
[459]14#include <tty0.h>
[258]15#include <xcu_driver.h>
[709]16#include <bdv_driver.h>
[258]17
[528]18/////////////////////////////////////////////////////////////////////////////////
19//     Extern variables and functions
20/////////////////////////////////////////////////////////////////////////////////
21
22// defined in giet_kernel/switch.s file
[709]23extern void _thread_switch( thread_context_t* , thread_context_t* );
[258]24
[528]25// allocated in boot.c or kernel_init.c files
26extern static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX];
27
[709]28// allocated in kernel_init.c file
29extern fat_desc_t  _fat;
[702]30
[725]31/////////////////////////////////////////////////////////////////////////////////
[709]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
[725]35// before the actual desactivation, that set the NORUN_MASK_THREAD
36// bit in the thread context.
37//////////////////////////////////////////////////////////////////////////////////
[709]38static void _ctx_kill_thread( unsigned int x,
39                              unsigned int y,
40                              unsigned int p,
41                              unsigned int ltid )
[695]42{
43    // get scheduler address
[709]44    static_scheduler_t* psched = _schedulers[x][y][p];
[695]45
[709]46    // pretend the thread to kill is the currently scheduled thread
47    // (required by the _sys_***_release() calls)
48    unsigned int cur_thread = psched->current;
[697]49    psched->current = ltid;
50
[709]51    // release BDV lock if taken and reset BDV peripheral
52    if ( psched->context[ltid].slot[CTX_LOCKS_ID] & LOCKS_MASK_BDV ) 
[695]53    {
[709]54        _bdv_set_register( BLOCK_DEVICE_STATUS , 0 );
55        _spin_lock_release( &_bdv_lock );
[695]56    }
57
[709]58    // release FAT lock if taken
59    if ( psched->context[ltid].slot[CTX_LOCKS_ID] & LOCKS_MASK_FAT ) 
60    {
[714]61       
[709]62        _spin_lock_release( &_fat.fat_lock );
63    }
64
[714]65    // release FBF lock if taken
66    if ( psched->context[ltid].slot[CTX_LOCKS_ID] & LOCKS_MASK_FBF ) 
67    {
68        _sys_fbf_release();
69    }
70
[709]71    // release private TTY terminal if required
72    if ( psched->context[ltid].slot[CTX_TTY_ID] < NB_TTY_CHANNELS ) 
73        _sys_tty_release(); 
74
[695]75    // release private TIM channel if required
[709]76
77    if ( psched->context[ltid].slot[CTX_TIM_ID] < NB_TIM_CHANNELS )
[695]78    {
79        _sys_tim_release();
80    }
81
[709]82    // release private NIC_RX and CMA_RX channels if required
83    if ( psched->context[ltid].slot[CTX_NIC_RX_ID] < NB_NIC_CHANNELS )
[695]84    {
85        _sys_nic_release( 1 );
86    }
87
[709]88    // release private NIC_TX and CMA_TX channels if required
89    if ( psched->context[ltid].slot[CTX_NIC_TX_ID] < NB_NIC_CHANNELS )
[695]90    {
91        _sys_nic_release( 0 );
92    }
93
[700]94    // release private FBF_CMA channel if required
[709]95    if ( psched->context[ltid].slot[CTX_CMA_FB_ID] < NB_CMA_CHANNELS )
[700]96    {
97        _sys_fbf_cma_release();
98    }
99
[709]100    // restore scheduled thread index
101    psched->current = cur_thread;
[697]102
[709]103    // set NORUN_MASK_THREAD bit to desactivate the target thread
104    psched->context[ltid].slot[CTX_NORUN_ID] = NORUN_MASK_THREAD;
[695]105
[709]106} // end _ctx_kill_thread()
[695]107
[702]108
[440]109//////////////////
[258]110void _ctx_switch() 
111{
[294]112    unsigned int gpid       = _get_procid();
[428]113    unsigned int cluster_xy = gpid >> P_WIDTH;
[709]114    unsigned int x          = cluster_xy >> Y_WIDTH;
115    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
116    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
[294]117
[709]118    unsigned int ltid;     // index for loops on threads in scheduler
119
120    // get calling thread scheduler address
[258]121    static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
122
[709]123    // get number of threads allocated to scheduler
124    unsigned int threads = psched->threads;
[258]125
[709]126    // get current thread ltid
127    unsigned int curr_thread_id = psched->current;
[258]128
[709]129    // first loop on threads: handle all pending KILL signals
130    for ( ltid = 0 ; ltid < threads ; ltid++ )
[258]131    {
[709]132        if ( psched->context[ltid].slot[CTX_SIGS_ID] & SIGS_MASK_KILL )
[695]133        {
[709]134            // acknowledge KILL signal
135            _atomic_and( &psched->context[ltid].slot[CTX_SIGS_ID], ~SIGS_MASK_KILL );
[706]136
[709]137            // desactivate the killed thread
138            _ctx_kill_thread( x , y , p , ltid );
[696]139        }
[709]140    }
[695]141
[709]142    // second loop: select next thread using a round-robin policy
143    unsigned int next_thread_id;
144    unsigned int found = 0;
145    for ( ltid = curr_thread_id + 1 ; ltid < (curr_thread_id + 1 + threads) ; ltid++ ) 
146    {
147        next_thread_id = ltid % threads;
148
149        // test if the thread is runable
150        if ( psched->context[next_thread_id].slot[CTX_NORUN_ID] == 0 )
[258]151        {
152            found = 1;
153            break;
154        }
155    }
156
[709]157    // launch idle_thread if no runable thread
158    if ( found == 0 ) next_thread_id = IDLE_THREAD_INDEX;
[258]159
[709]160    if ( curr_thread_id != next_thread_id )  // actual thread switch required
161    {
162
163#if GIET_DEBUG_SWITCH
[294]164unsigned int x = cluster_xy >> Y_WIDTH;
165unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
[709]166if ( (_get_proctime() > GIET_DEBUG_SWITCH) && (x == 0) && (y == 0) && (p == 0) )
[528]167_printf("\n[DEBUG SWITCH] (%d) -> (%d) on processor[%d,%d,%d] at cycle %d\n",
[709]168        curr_thread_id, next_thread_id, x, y , p, _get_proctime() );
[258]169#endif
170
[709]171        thread_context_t* curr_ctx_vaddr = &(psched->context[curr_thread_id]);
172        thread_context_t* next_ctx_vaddr = &(psched->context[next_thread_id]);
[275]173
[528]174        // reset TICK timer counter.
[709]175        _xcu_timer_reset_cpt( cluster_xy, p );
[275]176
[709]177        // set current thread index
178        psched->current = next_thread_id;
[275]179
180        // makes context switch
[709]181        _thread_switch( curr_ctx_vaddr , next_ctx_vaddr );
[818]182
183        // only modify the PTPR when necessary, in order to avoid unnecessary
184        // TLBs flush.
185        if (curr_ctx_vaddr->slot[CTX_PTPR_ID] !=
186            next_ctx_vaddr->slot[CTX_PTPR_ID])
187        {
188            _set_mmu_ptpr(next_ctx_vaddr->slot[CTX_PTPR_ID]);
189        }
[258]190    }
191} //end _ctx_switch()
192
[528]193
[709]194///////////////////
195void _idle_thread() 
[258]196{
[391]197    unsigned int gpid       = _get_procid();
[428]198    unsigned int cluster_xy = gpid >> P_WIDTH;
[391]199    unsigned int x          = cluster_xy >> Y_WIDTH;
200    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
[440]201    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
[391]202
[258]203    while(1)
204    {
[818]205        _sleep( GIET_IDLE_THREAD_PERIOD );
[275]206
[294]207        // warning message
[818]208        _printf("\n[GIET WARNING] Processor[%d,%d,%d] still idle at cycle %u",
[528]209                x , y , p , _get_proctime() );
[258]210    }
211} // end ctx_idle()
212
213
[440]214////////////////
[258]215void _ctx_eret() 
216{
217    asm volatile("eret");
218}
219
220
221// Local Variables:
222// tab-width: 4
223// c-basic-offset: 4
224// c-file-offsets:((innamespace . 0)(inline-open . 0))
225// indent-tabs-mode: nil
226// End:
227// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
228
Note: See TracBrowser for help on using the repository browser.