source: soft/giet_vm/sys/ctx_handler.c @ 244

Last change on this file since 244 was 238, checked in by alain, 11 years ago

Major evolution to support physical addresses larger than 32 bits.
The map.xml format has been modified: the vsegs associated to schedulers
are now explicitely defined and mapped in the page tables.

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