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
RevLine 
[199]1/////////////////////////////////////////////////////////////////////////////////////////
[158]2// File     : ctx_handler.c
3// Date     : 01/04/2012
4// Authors  : alain greiner & joel porquet
5// Copyright (c) UPMC-LIP6
[199]6/////////////////////////////////////////////////////////////////////////////////////////
[189]7// The ctx_handler.h and ctx_handler.c files are part of the GIET-VM nano-kernel.
[158]8// This code is used to support context switch when several tasks are executing
9// in time multiplexing on a single processor.
[199]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/////////////////////////////////////////////////////////////////////////////////////////
[189]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
[199]24/////////////////////////////////////////////////////////////////////////////////////////
[158]25// A task context is an array of 64 words = 256 bytes.
[199]26// It contains copies of processor registers (when the task is preempted):
[238]27// - GPR[i], generally stored in slot (i). $0, $26 & $27 are not saved.
[199]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:
[238]32// - TTY    : TTY channel global index
[228]33// - NIC    : NIC channel global index
[238]34// - CMA    : CMA channel global index
35// - IOC    : IOC channel global index
36// - DMA    : DMA channel local index
37// - TIM    : TIM channel local index
[199]38// - PTAB   : page table virtual base address
[238]39// - LTID   : Task local index (in scheduler)
[199]40// - VSID   : Virtual space index
[228]41// - RUN    : Task state (0 => sleeping / 1 => runable )
[167]42//
[199]43// ctx[0]<- ***|ctx[8] <- $8 |ctx[16]<- $16|ctx[24]<- $24|ctx[32]<- EPC  |ctx[40]<- TTY
[218]44// ctx[1]<- $1 |ctx[9] <- $9 |ctx[17]<- $17|ctx[25]<- $25|ctx[33]<- CR   |ctx[41]<- DMA
[199]45// ctx[2]<- $2 |ctx[10]<- $10|ctx[18]<- $18|ctx[26]<- LO |ctx[34]<- SR   |ctx[42]<- NIC
[238]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
[199]50// ctx[7]<- $7 |ctx[15]<- $15|ctx[23]<- $23|ctx[31]<- RA |ctx[39]<- PTPR |ctx[47]<- RUN
51//////////////////////////////////////////////////////////////////////////////////////////
[158]52
[228]53extern void _task_switch(unsigned int *, unsigned int *);
[158]54
55/////////////////////////////////////////////////////////////////////////////////
[228]56//    _ctx_switch()
[158]57// This function performs a context switch between the running task
[199]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.
[189]63//
[238]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.
[158]68/////////////////////////////////////////////////////////////////////////////////
[238]69void _ctx_switch() 
70{
71    // get scheduler address
72    static_scheduler_t* psched = _get_sched();
[158]73
[189]74    // get number of tasks allocated to scheduler
[238]75    unsigned int tasks = psched->tasks;
[158]76
[199]77    // get current task index
[238]78    unsigned int curr_task_id = psched->current;
[199]79
80    // select the next task using a round-robin policy
[228]81    unsigned int next_task_id;
82    unsigned int tid;
83    unsigned int found = 0;
[199]84
[238]85    for (tid = curr_task_id + 1; tid < curr_task_id + 1 + tasks; tid++) 
86    {
[199]87        next_task_id = tid % tasks;
88        // test if the task is runable
[238]89        if ( psched->context[next_task_id][CTX_RUN_ID] ) 
90        {
[199]91            found = 1;
[228]92            break;
[199]93        }
94    }
95
96    // launch "idle" task if no runable task
[238]97    if (found == 0) 
98    {
[199]99        next_task_id = IDLE_TASK_INDEX;
100    }
101
102    // no switch if no change
[238]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]);
[199]107
[238]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
[228]113        // (the function is not yet present in drivers.c)
[189]114
[238]115        _task_switch(curr_ctx_vaddr, next_ctx_vaddr);
116
[158]117#if GIET_DEBUG_SWITCH
[238]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);
[158]134#endif
135
[199]136    }
137} //end _ctx_switch()
[165]138
[199]139/////////////////////////////////////////////////////////////////////////////////////
140// This function is executed as the"idle" task when no other task can be executed
141/////////////////////////////////////////////////////////////////////////////////////
[238]142void _ctx_idle() 
143{
[199]144    unsigned int delay = 1000000;
[189]145
[228]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" ); 
[189]156
[228]157        _get_lock(&_tty_put_lock);
158        _puts("\n[GIET WARNING] Processor ");
159        _putd(_procid());
160        _puts(" still idle at cycle ");
161        _putd(_proctime());
[199]162        _puts("\n");
[228]163        _release_lock(&_tty_put_lock);
164
[231]165        delay = 1000000;
[199]166    }
167} // end ctx_idle()
[189]168
[228]169
[199]170/////////////////////////////////////////////////////////////////////////////////
171// The address of this functionis used to initialise the return address
172// in the "idle" task context.
173/////////////////////////////////////////////////////////////////////////////////
[238]174void _ctx_eret() 
175{
[199]176    asm volatile("eret");
177}
[189]178
179
[228]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.