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

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

kernel: release WTI mailbox associated with TTY

We don't block on giet_tty_alloc() anymore when launching the same app
again and again.

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