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

Last change on this file since 268 was 267, checked in by cfuguet, 10 years ago
  • Adding new task context information: THREAD INDEX.

This value can be accessed by USER applications to get the
thread index of the current task. This thread index
corresponds to the index in a vspace.

The value of this index can be forced in the vspace part
of the XML description file using the trdid field in the
task description. When this value is missing, for each
task, a value from 0 to N-1 will be assigned, where N is
the number of task in the vspace.

The user application access this value through the
giet_thread_id() function defined in the stdio library
which uses the SYSCALL_THREAD_ID to access the task
context information.

  • Supporting mono TTY platforms

When the GIET_MONO_TTY constant defined in the giet_config
file, contains a value different than 0, all tasks will
share the TTY[0]. If this is the case, in the stdio
library, the giet_tty_printf() function will take the TTY
hardware lock before writing

  • Property svn:executable set to *
File size: 7.1 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// The ctx_handler.h and ctx_handler.c files are part of the GIET-VM nano-kernel.
8// This code is used to support context switch when several tasks are executing
9// in time multiplexing on a single processor.
10// The tasks are statically allocated to a processor in the boot phase, and
11// there is one private scheduler per processor. Each sheduler occupies 4K bytes,
12// and contains up to 14 task contexts (task_id is from 0 to 13).
13// The task context [14] is reserved for the "idle" task that does nothing, and
14// is launched by the scheduler when there is no other runable task.
15/////////////////////////////////////////////////////////////////////////////////////////
16
17#include <giet_config.h>
18#include <tim_driver.h>
19#include <xcu_driver.h>
20#include <tty_driver.h>
21#include <utils.h>
22#include <ctx_handler.h>
23#include <mapping_info.h>
24#include <sys_handler.h>
25
26/////////////////////////////////////////////////////////////////////////////////////////
27// A task context is an array of 64 words = 256 bytes.
28// It contains copies of processor registers (when the task is preempted):
29// - GPR[i], generally stored in slot (i). $0, $26 & $27 are not saved.
30// - HI & LO registers
31// - CP0 registers: EPC, SR, CR, BVAR
32// - CP2 registers : PTPR
33// It contains some general informations associated to the task:
34// - TTY    : TTY channel global index
35// - NIC    : NIC channel global index
36// - CMA    : CMA channel global index
37// - HBA    : HBA channel global index
38// - DMA    : DMA channel local index
39// - TIM    : TIM channel local index
40// - PTAB   : page table virtual base address
41// - LTID   : Task local index (in scheduler)
42// - VSID   : Virtual space index
43// - RUN    : Task state (0 => sleeping / 1 => runnable )
44// - TRDID  : Thread ID index (in vspace)
45//
46// ctx[0]<- ***|ctx[8] <- $8 |ctx[16]<- $16|ctx[24]<- $24|ctx[32]<- EPC  |ctx[40]<- TTY
47// ctx[1]<- $1 |ctx[9] <- $9 |ctx[17]<- $17|ctx[25]<- $25|ctx[33]<- CR   |ctx[41]<- DMA
48// ctx[2]<- $2 |ctx[10]<- $10|ctx[18]<- $18|ctx[26]<- LO |ctx[34]<- SR   |ctx[42]<- NIC
49// ctx[3]<- $3 |ctx[11]<- $11|ctx[19]<- $19|ctx[27]<- HI |ctx[35]<- BVAR |ctx[43]<- TIM
50// ctx[4]<- $4 |ctx[12]<- $12|ctx[20]<- $20|ctx[28]<- $28|ctx[36]<- PTAB |ctx[44]<- HBA
51// ctx[5]<- $5 |ctx[13]<- $13|ctx[21]<- $21|ctx[29]<- SP |ctx[37]<- LTID |ctx[45]<- CMA
52// ctx[6]<- $6 |ctx[14]<- $14|ctx[22]<- $22|ctx[30]<- $30|ctx[38]<- VSID |ctx[46]<- GTID
53// ctx[7]<- $7 |ctx[15]<- $15|ctx[23]<- $23|ctx[31]<- RA |ctx[39]<- PTPR |ctx[47]<- RUN
54//
55// ctx[48]<- TRDID
56//////////////////////////////////////////////////////////////////////////////////////////
57
58extern void _task_switch(unsigned int *, unsigned int *);
59
60/////////////////////////////////////////////////////////////////////////////////
61//    _ctx_switch()
62// This function performs a context switch between the running task
63// and  another task, using a round-robin sheduling policy between all
64// tasks allocated to a given processor (static allocation).
65// It selects the next runable task to resume execution.
66// If the only runable task is the current task, return without context switch.
67// If there is no runable task, the scheduler switch to the default "idle" task.
68//
69// Implementation note
70// The return address contained in $31 is saved in the current task context
71// (in the ctx[31] slot), and the function actually returns to the address
72// contained in the ctx[31] slot of the next task context.
73/////////////////////////////////////////////////////////////////////////////////
74void _ctx_switch() 
75{
76    // get scheduler address
77    static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
78
79    // get number of tasks allocated to scheduler
80    unsigned int tasks = psched->tasks;
81
82    // get current task index
83    unsigned int curr_task_id = psched->current;
84
85    // select the next task using a round-robin policy
86    unsigned int next_task_id;
87    unsigned int tid;
88    unsigned int found = 0;
89
90    for (tid = curr_task_id + 1; tid < curr_task_id + 1 + tasks; tid++) 
91    {
92        next_task_id = tid % tasks;
93        // test if the task is runable
94        if ( psched->context[next_task_id][CTX_RUN_ID] ) 
95        {
96            found = 1;
97            break;
98        }
99    }
100
101    // launch "idle" task if no runable task
102    if (found == 0) 
103    {
104        next_task_id = IDLE_TASK_INDEX;
105    }
106
107    // no switch if no change
108    if (curr_task_id != next_task_id) 
109    {
110        unsigned int* curr_ctx_vaddr = &(psched->context[curr_task_id][0]);
111        unsigned int* next_ctx_vaddr = &(psched->context[next_task_id][0]);
112        unsigned int procid = _get_procid();
113        unsigned int local_id = procid % NB_PROCS_MAX;
114        unsigned int cluster_id = procid / NB_PROCS_MAX;
115
116        // set current task index
117        psched->current = next_task_id;
118
119        // reset timer counter
120#if USE_XICU
121        _xcu_timer_reset_cpt(cluster_id, local_id);
122#else
123        _timer_reset_cpt(cluster_id, local_id); 
124#endif
125
126        // makes context switch
127        _task_switch(curr_ctx_vaddr, next_ctx_vaddr);
128
129#if GIET_DEBUG_SWITCH
130_tty_get_lock( 0 );
131_puts("\n[GIET DEBUG] Context switch for processor ");
132_putd(_get_procid());
133_puts(" at cycle ");
134_putd(_get_proctime());
135_puts("\n");
136_puts(" - tasks        = ");
137_putd(tasks);
138_puts("\n");
139_puts(" - curr_task_id = ");
140_putd( curr_task_id );
141_puts("\n");
142_puts(" - next_task_id = ");
143_putd(next_task_id);
144_puts("\n");
145_tty_release_lock(  0 );
146#endif
147
148    }
149} //end _ctx_switch()
150
151/////////////////////////////////////////////////////////////////////////////////////
152// This function is executed as the"idle" task when no other task can be executed
153/////////////////////////////////////////////////////////////////////////////////////
154void _idle_task() 
155{
156    unsigned int count = GIET_IDLE_TASK_PERIOD;
157    while(1)
158    {
159        asm volatile(
160                "move   $3,   %0              \n"
161                "_idle_task_loop:             \n"
162                "addi   $3,   $3,   -1        \n"
163                "bnez   $3,   _idle_task_loop \n"
164                "nop                          \n"
165                :
166                : "r"(count)
167                : "$3" ); 
168
169#if GIET_IDLE_TASK_VERBOSITY == 1
170        _tty_get_lock( 0 );
171        _puts("\n[GIET WARNING] Processor ");
172        _putd(_get_procid());
173        _puts(" idle at cycle ");
174        _putd(_get_proctime());
175        _puts("\n");
176        _tty_release_lock( 0 );
177#endif
178
179         count = GIET_IDLE_TASK_PERIOD;
180    }
181} // end ctx_idle()
182
183
184/////////////////////////////////////////////////////////////////////////////////
185// The address of this functionis used to initialise the return address
186// in the "idle" task context.
187/////////////////////////////////////////////////////////////////////////////////
188void _ctx_eret() 
189{
190    asm volatile("eret");
191}
192
193
194// Local Variables:
195// tab-width: 4
196// c-basic-offset: 4
197// c-file-offsets:((innamespace . 0)(inline-open . 0))
198// indent-tabs-mode: nil
199// End:
200// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
201
Note: See TracBrowser for help on using the repository browser.