source: soft/giet_vm/sys/ctx_handler_new.c @ 158

Last change on this file since 158 was 158, checked in by alain, 12 years ago

Introducing the giet_vm and some example applications

File size: 9.9 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 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 must be statically allocated to a processor in the boot phase, and
11// there is one private scheduler per processor:  NB_CLUSTERS * NB_PROCS
12// Each sheduler contains up to NB_TASKS_MAX contexts.
13////////////////////////////////////////////////////////////////////////////////////
14// A task context is an array of 64 words = 256 bytes.
15// It contains copies of processor registers, when the task is not running,
16// and some general informations associated to the task.
17// - It contains GPR[i], generally stored in slot (i). $0, *26 & $27 are not saved.
18// - It contains HI & LO registers.
19// - It contains CP0 registers: EPC, SR, CR.
20// - It contains CP2 registers : PTPR and MODE.
21// - It contains the TTY index for the terminal allocated to the task.
22// ctx[0] <- SR   ctx[8] <- $8    ctx[16]<- $16   ctx[24]<- $24   ctx[32]<- EPC
23// ctx[1] <- $1   ctx[9] <- $9    ctx[17]<- $17   ctx[25]<- $25   ctx[33]<- CR
24// ctx[2] <- $2   ctx[10]<- $10   ctx[18]<- $18   ctx[26]<- LO    ctx[34]<- TTY
25// ctx[3] <- $3   ctx[11]<- $11   ctx[19]<- $19   ctx[27]<- HI    ctx[35]<- PTPR
26// ctx[4] <- $4   ctx[12]<- $12   ctx[20]<- $20   ctx[28]<- $28   ctx[36]<- MODE
27// ctx[5] <- $5   ctx[13]<- $13   ctx[21]<- $21   ctx[29]<- $29   ctx[37]<- reserved
28// ctx[6] <- $6   ctx[14]<- $14   ctx[22]<- $22   ctx[30]<- $30   ctx[38]<- reserved
29// ctx[7] <- $7   ctx[15]<- $15   ctx[23]<- $23   ctx[31]<- $31   ctx[39]<- reserved
30/////////////////////////////////////////////////////////////////////////////////////
31
32#include <giet_config.h>
33#include <ctx_handler.h>
34#include <drivers.h>
35#include <common.h>
36
37extern void _task_switch(unsigned int *, unsigned int *);
38
39/////////////////////////////////////////////////////////////////////////////////
40//      Global variables
41/////////////////////////////////////////////////////////////////////////////////
42
43static_scheduler_t _scheduler[NB_CLUSTERS * NB_PROCS];
44
45/////////////////////////////////////////////////////////////////////////////////
46//  _ctx_select()
47// The scheduling policy is round-robin : for each processor, the task index is
48// incremented, modulo the number of tasks allocated to the processor.
49/////////////////////////////////////////////////////////////////////////////////
50unsigned int _ctx_select( unsigned int curr_task_id,
51                          unsigned int proc_id )
52{
53    unsigned int tasks = _scheduler[proc_id].tasks; 
54    return (curr_task_id + 1) % tasks;
55} 
56
57////////////////////////////////////////////////////////////////////////////////////
58// _ctx_switch()
59// This function performs a context switch between the running task
60// and  another task, selected by the _ctx_select() function.
61// It use the global variable scheduler[] : array indexed by the procid,
62// that has NB_CLUSTERS * NB_PROCS entries.
63// The return address contained in $31 is saved in the _current task context
64// (in the ctx[31] slot), and the function actually returns to the address
65// contained in the ctx[31] slot of the new task context.
66////////////////////////////////////////////////////////////////////////////////////
67void _ctx_switch()
68{
69    unsigned int*       curr_context;   // pointer on the current task context
70    unsigned int*       next_context;   // pointer on the next task context
71
72    unsigned int        curr_task_id;
73    unsigned int        next_task_id;
74    unsigned int        tasks;
75    unsigned int        proc_id;
76
77    proc_id      = _procid();
78    curr_task_id = _scheduler[proc_id].current;
79    tasks        = _scheduler[proc_id].tasks;
80
81    // if no more than one task, return
82    if ( tasks <= 1 ) return;
83
84    /* save _current task context */
85
86    curr_context = &_scheduler[proc_id].context[curr_task_id][0];
87
88    asm volatile(
89    "add     $27,    %0,  $0       \n"  /* $27<= &context[curr_task_id] */
90    "mfc0    $26,    $12           \n"  /* $26 <= SR */
91    "sw      $26,    0*4($27)      \n"  /* ctx[0] <= SR */
92    ".set noat                     \n"
93    "sw      $1,     1*4($27)      \n"  /* ctx[1] <= $1 */
94    ".set at                       \n"
95    "sw      $2,     2*4($27)      \n"  /* ctx[2] <= $2 */
96    "sw      $3,     3*4($27)      \n"  /* ctx[3] <= $3 */
97    "sw      $4,     4*4($27)      \n"  /* ctx[4] <= $4 */
98    "sw      $5,     5*4($27)      \n"  /* ctx[5] <= $5 */
99    "sw      $6,     6*4($27)      \n"  /* ctx[6] <= $6 */
100    "sw      $7,     7*4($27)      \n"  /* ctx[7] <= $7 */
101    "sw      $8,     8*4($27)      \n"  /* ctx[8] <= $8 */
102    "sw      $9,     9*4($27)      \n"  /* ctx[9] <= $9 */
103    "sw      $10,    10*4($27)     \n"  /* ctx[10] <= $10 */
104    "sw      $11,    11*4($27)     \n"  /* ctx[11] <= $11 */
105    "sw      $12,    12*4($27)     \n"  /* ctx[12] <= $12 */
106    "sw      $13,    13*4($27)     \n"  /* ctx[13] <= $13 */
107    "sw      $14,    14*4($27)     \n"  /* ctx[14] <= $14 */
108    "sw      $15,    15*4($27)     \n"  /* ctx[15] <= $15 */
109    "sw      $16,    16*4($27)     \n"  /* ctx[16] <= $16 */
110    "sw      $17,    17*4($27)     \n"  /* ctx[17] <= $17 */
111    "sw      $18,    18*4($27)     \n"  /* ctx[18] <= $18 */
112    "sw      $19,    19*4($27)     \n"  /* ctx[19] <= $19 */
113    "sw      $20,    20*4($27)     \n"  /* ctx[20] <= $20 */
114    "sw      $21,    21*4($27)     \n"  /* ctx[21] <= $21 */
115    "sw      $22,    22*4($27)     \n"  /* ctx[22] <= $22 */
116    "sw      $23,    23*4($27)     \n"  /* ctx[23] <= $23 */
117    "sw      $24,    24*4($27)     \n"  /* ctx[24] <= $24 */
118    "sw      $25,    25*4($27)     \n"  /* ctx[25] <= $25 */
119    "mflo    $26                   \n"
120    "sw      $26,    26*4($27)     \n"  /* ctx[26] <= LO */
121    "mfhi    $26                   \n"
122    "sw      $26,    27*4($27)     \n"  /* ctx[27] <= H1 */
123    "sw      $28,    28*4($27)     \n"  /* ctx[28] <= $28 */
124    "sw      $29,    29*4($27)     \n"  /* ctx[29] <= $29 */
125    "sw      $30,    30*4($27)     \n"  /* ctx[30] <= $30 */
126    "sw      $31,    31*4($27)     \n"  /* ctx[31] <= $31 */
127    "mfc0    $26,    $14           \n"
128    "sw      $26,    32*4($27)     \n"  /* ctx[32] <= EPC */
129    "mfc0    $26,    $13           \n"
130    "sw      $26,    33*4($27)     \n"  /* ctx[33] <= CR */
131    "mfc2    $26,    $0            \n"
132    "sw      $26,    35*4($27)     \n"  /* ctx[35] <= PTPR */
133    "mfc2    $26,    $1            \n"
134    "sw      $26,    36*4($27)     \n"  /* ctx[36] <= MODE */
135    :
136    : "r" (curr_context)
137    );
138
139    // select next task and update scheduler state
140
141    next_task_id = _ctx_select( curr_task_id, proc_id );
142    _scheduler[proc_id].current = next_task_id;
143
144#if GIET_DEBUG_SWITCH
145unsigned int time = _proctime();
146_tty_puts( "\n[GIET] Context switch for processor ");
147_tty_putw( proc_id );
148_tty_puts( " at cycle ");
149_tty_putw( time );
150_tty_puts("\n");
151_tty_puts( " - tasks        = ");
152_tty_putw( tasks );
153_tty_puts("\n");
154_tty_puts( " - curr_task_id = ");
155_tty_putw( curr_task_id );
156_tty_puts("\n");
157_tty_puts( " - next_task_id = ");
158_tty_putw( next_task_id );
159_tty_puts("\n");
160#endif
161
162    /* restore next task context */
163
164    next_context = &_scheduler[proc_id].context[next_task_id][0];
165
166    asm volatile(
167    "add     $27,    %0,  $0       \n"  /* $27<= &context[next] */
168    "lw      $26,    35*4($27)     \n"
169    "mtc2    $26,    $0            \n"  /* restore PTPR */
170    "lw      $26,    36*4($27)     \n"
171    "mtc2    $26,    $1            \n"  /* restore MODE */
172    "lw      $26,    0*4($27)      \n"
173    "mtc0    $26,    $12           \n"  /* restore SR */
174    ".set noat                     \n"
175    "lw      $1,     1*4($27)      \n"  /* restore $1 */
176    ".set at                       \n"
177    "lw      $2,     2*4($27)      \n"  /* restore $2 */
178    "lw      $3,     3*4($27)      \n"  /* restore $3 */
179    "lw      $4,     4*4($27)      \n"  /* restore $4 */
180    "lw      $5,     5*4($27)      \n"  /* restore $5 */
181    "lw      $6,     6*4($27)      \n"  /* restore $6 */
182    "lw      $7,     7*4($27)      \n"  /* restore $7 */
183    "lw      $8,     8*4($27)      \n"  /* restore $8 */
184    "lw      $9,     9*4($27)      \n"  /* restore $9 */
185    "lw      $10,    10*4($27)     \n"  /* restore $10 */
186    "lw      $11,    11*4($27)     \n"  /* restore $11 */
187    "lw      $12,    12*4($27)     \n"  /* restore $12 */
188    "lw      $13,    13*4($27)     \n"  /* restore $13 */
189    "lw      $14,    14*4($27)     \n"  /* restore $14 */
190    "lw      $15,    15*4($27)     \n"  /* restore $15 */
191    "lw      $16,    16*4($27)     \n"  /* restore $16 */
192    "lw      $17,    17*4($27)     \n"  /* restore $17 */
193    "lw      $18,    18*4($27)     \n"  /* restore $18 */
194    "lw      $19,    19*4($27)     \n"  /* restore $19 */
195    "lw      $20,    20*4($27)     \n"  /* restore $20 */
196    "lw      $21,    21*4($27)     \n"  /* restore $21 */
197    "lw      $22,    22*4($27)     \n"  /* restore $22 */
198    "lw      $23,    23*4($27)     \n"  /* restore $23 */
199    "lw      $24,    24*4($27)     \n"  /* restore $24 */
200    "lw      $25,    25*4($27)     \n"  /* restore $25 */
201    "lw      $26,    26*4($27)     \n"
202    "mtlo    $26                   \n"  /* restore LO */
203    "lw      $26,    27*4($27)     \n"
204    "mthi    $26                   \n"  /* restore HI */
205    "lw      $28,    28*4($27)     \n"  /* restore $28 */
206    "lw      $29,    29*4($27)     \n"  /* restore $29 */
207    "lw      $30,    30*4($27)     \n"  /* restore $30 */
208    "lw      $31,    31*4($27)     \n"  /* restore $31 */
209    "lw      $26,    32*4($27)     \n"
210    "mtc0    $26,    $14           \n"  /* restore EPC */
211    "lw      $26,    33*4($27)     \n"
212    "mtc0    $26,    $13           \n"  /* restore CR */
213    "eret                          \n"  /* returns to user code */
214    :
215    : "r" (next_context)
216    );
217} // end task_switch()
218
Note: See TracBrowser for help on using the repository browser.