source: soft/giet_vm/giet_kernel/ctx_handler.c @ 696

Last change on this file since 696 was 696, checked in by guerin, 9 years ago

kernel: defer task exec to _ctx_switch()

  • Property svn:executable set to *
File size: 7.7 KB
Line 
1//////////////////////////////////////////////////////////////////////////////////
2// File     : ctx_handler.c
3// Date     : 01/04/2012
4// Authors  : alain greiner & joel porquet
5// Copyright (c) UPMC-LIP6
6//////////////////////////////////////////////////////////////////////////////////
7
8#include <ctx_handler.h>
9#include <sys_handler.h>
10#include <giet_config.h>
11#include <hard_config.h>
12#include <utils.h>
13#include <tty0.h>
14#include <xcu_driver.h>
15
16/////////////////////////////////////////////////////////////////////////////////
17//     Extern variables and functions
18/////////////////////////////////////////////////////////////////////////////////
19
20// defined in giet_kernel/switch.s file
21extern void _task_switch(unsigned int *, unsigned int *);
22
23// allocated in boot.c or kernel_init.c files
24extern static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX];
25
26//////////////////
27static void _ctx_kill_task( unsigned int ltid )
28{
29    // get scheduler address
30    static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
31
32    // release private TTY terminal if required
33    if ( psched->context[ltid][CTX_TTY_ID] < NB_TTY_CHANNELS )
34    {
35        psched->context[ltid][CTX_TTY_ID] = 0xFFFFFFFF;
36        _sys_tty_release();
37    }
38
39    // release private TIM channel if required
40    if ( psched->context[ltid][CTX_TIM_ID] < NB_TIM_CHANNELS )
41    {
42        psched->context[ltid][CTX_TIM_ID] = 0xFFFFFFFF;
43        _sys_tim_release();
44    }
45
46    // release private NIC_RX channel if required
47    if ( psched->context[ltid][CTX_NIC_RX_ID] < NB_NIC_CHANNELS )
48    {
49        psched->context[ltid][CTX_NIC_RX_ID] = 0xFFFFFFFF;
50        _sys_nic_release( 1 );
51    }
52
53    // release private NIC_TX channel if required
54    if ( psched->context[ltid][CTX_NIC_TX_ID] < NB_NIC_CHANNELS )
55    {
56        psched->context[ltid][CTX_NIC_TX_ID] = 0xFFFFFFFF;
57        _sys_nic_release( 0 );
58    }
59
60    // set NORUN_MASK_TASK bit
61    _atomic_or( &psched->context[ltid][CTX_NORUN_ID], NORUN_MASK_TASK );
62}
63
64
65//////////////////
66static void _ctx_exec_task( unsigned int ltid )
67{
68    // get scheduler address
69    static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
70
71    // TODO: reload .data segment
72
73    // find initial stack pointer
74    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
75    mapping_task_t   * task    = _get_task_base(header);
76    mapping_vseg_t   * vseg    = _get_vseg_base(header);
77    unsigned int task_id       = psched->context[ltid][CTX_GTID_ID];
78    unsigned int vseg_id       = task[task_id].stack_vseg_id;
79    unsigned int sp_value      = vseg[vseg_id].vbase + vseg[vseg_id].length;
80
81    // reset task context: RA / SR / SP / EPC / NORUN
82    psched->context[ltid][CTX_RA_ID]    = (unsigned int)&_ctx_eret;
83    psched->context[ltid][CTX_SR_ID]    = GIET_SR_INIT_VALUE;
84    psched->context[ltid][CTX_SP_ID]    = sp_value;
85    psched->context[ltid][CTX_EPC_ID]   = psched->context[ltid][CTX_ENTRY_ID];
86    psched->context[ltid][CTX_NORUN_ID] = 0;
87}
88
89
90//////////////////////////////////
91void _ctx_display( unsigned int x,
92                   unsigned int y,
93                   unsigned int p,
94                   unsigned int ltid,
95                   char*        string )
96{
97    static_scheduler_t* psched = _schedulers[x][y][p];
98    _printf("\n########## task[%d,%d,%d,%d] context\n"
99            " - CTX_EPC   = %x\n"
100            " - CTX_PTAB  = %x\n"
101            " - CTX_PTPR  = %x\n"
102            " - CTX_VSID  = %x\n"
103            " - CTX_SR    = %x\n"
104            " - CTX_RA    = %x\n"
105            " - CTX_SP    = %x\n"
106            " - CTX_NORUN = %x\n"
107            " - CTX_SIG   = %x\n"
108            "########## %s\n",
109            x , y , p , ltid ,
110            psched->context[ltid][CTX_EPC_ID], 
111            psched->context[ltid][CTX_PTAB_ID], 
112            psched->context[ltid][CTX_PTPR_ID], 
113            psched->context[ltid][CTX_VSID_ID], 
114            psched->context[ltid][CTX_SR_ID], 
115            psched->context[ltid][CTX_RA_ID], 
116            psched->context[ltid][CTX_SP_ID], 
117            psched->context[ltid][CTX_NORUN_ID],
118            psched->context[ltid][CTX_SIG_ID],
119            string );
120}  // _ctx_display()
121
122
123//////////////////
124void _ctx_switch() 
125{
126    unsigned int gpid       = _get_procid();
127    unsigned int cluster_xy = gpid >> P_WIDTH;
128    unsigned int lpid       = gpid & ((1<<P_WIDTH)-1);
129
130    // get scheduler address
131    static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
132
133    // get number of tasks allocated to scheduler
134    unsigned int tasks = psched->tasks;
135
136    // get current task index
137    unsigned int curr_task_id = psched->current;
138
139    // select the next task using a round-robin policy
140    unsigned int next_task_id;
141    unsigned int tid;
142    unsigned int found = 0;
143
144    for (tid = curr_task_id + 1; tid < curr_task_id + 1 + tasks; tid++) 
145    {
146        next_task_id = tid % tasks;
147
148        // this task needs to be killed
149        if ( psched->context[next_task_id][CTX_SIG_ID] & SIG_MASK_KILL )
150        {
151            _ctx_kill_task( next_task_id );
152
153            // acknowledge signal
154            _atomic_and( &psched->context[next_task_id][CTX_SIG_ID], ~SIG_MASK_KILL );
155        }
156
157        // this task needs to be executed
158        if ( psched->context[next_task_id][CTX_SIG_ID] & SIG_MASK_EXEC )
159        {
160            _ctx_exec_task( next_task_id );
161
162            // acknowledge signal
163            _atomic_and( &psched->context[next_task_id][CTX_SIG_ID], ~SIG_MASK_EXEC );
164        }
165
166        // test if the task is runable
167        if ( psched->context[next_task_id][CTX_NORUN_ID] == 0 ) 
168        {
169            found = 1;
170            // TODO: don't break to process all pending signals.
171            break;
172        }
173    }
174
175    // launch "idle" task if no runable task
176    if (found == 0) next_task_id = IDLE_TASK_INDEX;
177
178#if GIET_DEBUG_SWITCH
179unsigned int x = cluster_xy >> Y_WIDTH;
180unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
181_printf("\n[DEBUG SWITCH] (%d) -> (%d) on processor[%d,%d,%d] at cycle %d\n",
182        curr_task_id, next_task_id, x, y , lpid, _get_proctime() );
183#endif
184
185    if (curr_task_id != next_task_id)  // actual task switch required
186    {
187        unsigned int* curr_ctx_vaddr = &(psched->context[curr_task_id][0]);
188        unsigned int* next_ctx_vaddr = &(psched->context[next_task_id][0]);
189
190        // reset TICK timer counter.
191        _xcu_timer_reset_cpt( cluster_xy, lpid );
192
193        // set current task index
194        psched->current = next_task_id;
195
196        // makes context switch
197        _task_switch( curr_ctx_vaddr , next_ctx_vaddr );
198    }
199} //end _ctx_switch()
200
201
202/////////////////
203void _idle_task() 
204{
205    unsigned int gpid       = _get_procid();
206    unsigned int cluster_xy = gpid >> P_WIDTH;
207    unsigned int x          = cluster_xy >> Y_WIDTH;
208    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
209    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
210
211    while(1)
212    {
213        // initialize counter
214        unsigned int count = GIET_IDLE_TASK_PERIOD;
215
216        // decounting loop
217        asm volatile(
218                "move   $3,   %0              \n"
219                "_idle_task_loop:             \n"
220                "addi   $3,   $3,   -1        \n"
221                "bnez   $3,   _idle_task_loop \n"
222                "nop                          \n"
223                :
224                : "r"(count)
225                : "$3" ); 
226
227        // warning message
228        _printf("\n[GIET WARNING] Processor[%d,%d,%d] still idle at cycle %d",
229                x , y , p , _get_proctime() );
230    }
231} // end ctx_idle()
232
233
234////////////////
235void _ctx_eret() 
236{
237    asm volatile("eret");
238}
239
240
241// Local Variables:
242// tab-width: 4
243// c-basic-offset: 4
244// c-file-offsets:((innamespace . 0)(inline-open . 0))
245// indent-tabs-mode: nil
246// End:
247// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
248
Note: See TracBrowser for help on using the repository browser.