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

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

kernel: add fbf_cma release, call it on task kill

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