1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
14:
15: 16: 17: 18:
19:
20: #include "kernel.h"
21: #include "task.h"
22: #include "wait.h"
23: #include "ready_queue.h"
24: #include "cpu_task.h"
25: #include "tkdev_timer.h"
26: #include "check.h"
27: #include <sys/rominfo.h>
28:
29: 30: 31:
32: EXPORT INT dispatch_disabled;
33:
34: 35: 36:
37: EXPORT TCB *ctxtsk;
38: EXPORT TCB *schedtsk;
39: EXPORT RDYQUE ready_queue;
40:
41: 42: 43:
44: EXPORT TCB *tcb_table;
45: EXPORT QUEUE free_tcb;
46: EXPORT ID max_tskid;
47:
48: EXPORT INT default_sstksz;
49: EXPORT INT svc_call_limit;
50:
51: 52: 53:
54: EXPORT ER task_initialize( void )
55: {
56: INT i;
57: TCB *tcb;
58: ID tskid;
59:
60:
61: i = _tk_get_cfn(SCTAG_TMAXTSKID, &max_tskid, 1);
62: if ( i < 1 || NUM_TSKID < 1 ) {
63: return E_SYS;
64: }
65: i = _tk_get_cfn(SCTAG_TSYSSTKSZ, &default_sstksz, 1);
66: if ( i < 1 || default_sstksz < MIN_SYS_STACK_SIZE ) {
67: return E_SYS;
68: }
69: i = _tk_get_cfn(SCTAG_TSVCLIMIT, &svc_call_limit, 1);
70: if ( i < 1 || svc_call_limit < 0 || svc_call_limit > 3 ) {
71: return E_SYS;
72: }
73:
74:
75: tcb_table = Imalloc((UINT)NUM_TSKID * sizeof(TCB));
76: if ( tcb_table == NULL ) {
77: return E_NOMEM;
78: }
79:
80:
81: ctxtsk = schedtsk = NULL;
82: ready_queue_initialize(&ready_queue);
83: dispatch_disabled = DDS_ENABLE;
84:
85:
86: QueInit(&free_tcb);
87: for ( tcb = tcb_table, i = 0; i < NUM_TSKID; tcb++, i++ ) {
88: tskid = ID_TSK(i);
89: tcb->tskid = tskid;
90: tcb->state = TS_NONEXIST;
91: #ifdef NUM_PORID
92: tcb->wrdvno = tskid;
93: #endif
94: InitSVCLOCK(&tcb->svclock);
95: tcb->svclocked = NULL;
96:
97: QueInsert(&tcb->tskque, &free_tcb);
98: }
99:
100: return E_OK;
101: }
102:
103: 104: 105:
106: EXPORT void make_dormant( TCB *tcb )
107: {
108:
109: tcb->state = TS_DORMANT;
110: tcb->priority = tcb->bpriority = tcb->ipriority;
111: tcb->sysmode = tcb->isysmode;
112: tcb->wupcnt = 0;
113: tcb->suscnt = 0;
114: tcb->waitmask = 0;
115:
116: tcb->nodiswai = FALSE;
117: tcb->klockwait = FALSE;
118: tcb->klocked = FALSE;
119:
120: tcb->slicetime = 0;
121: tcb->stime = 0;
122: tcb->utime = 0;
123:
124: #ifdef NUM_MTXID
125: tcb->mtxlist = NULL;
126: #endif
127: tcb->tskevt = 0;
128:
129: tcb->reqdct = 0;
130:
131: tcb->texhdr = NULL;
132: tcb->texmask = 0;
133: tcb->pendtex = 0;
134: tcb->exectex = 0;
135: tcb->texflg = 0;
136: tcb->execssid = 0;
137:
138:
139: setup_context(tcb);
140: }
141:
142:
143:
144: 145: 146: 147: 148: 149:
150: EXPORT TCB* time_slice_schedule( TCB *tcb )
151: {
152: if ( tcb != NULL && tcb->slicetime > 0 ) {
153:
154: tcb->slicecnt += TIMER_PERIOD;
155: if ( tcb->slicecnt > tcb->slicetime ) {
156: tcb = ready_queue_move_last(&ready_queue, tcb);
157: }
158: }
159:
160: return tcb;
161: }
162:
163: 164: 165: 166:
167: Inline void reschedule( void )
168: {
169: TCB *toptsk;
170:
171: toptsk = ready_queue_top(&ready_queue);
172: if ( schedtsk != toptsk ) {
173: 174: 175: 176:
177: if ( schedtsk == ctxtsk ) {
178: time_slice_schedule(schedtsk);
179: }
180:
181: schedtsk = toptsk;
182: dispatch_request();
183: }
184: }
185:
186: 187: 188: 189: 190:
191: EXPORT void make_ready( TCB *tcb )
192: {
193: tcb->state = TS_READY;
194: if ( ready_queue_insert(&ready_queue, tcb) ) {
195: 196: 197: 198:
199: if ( schedtsk == ctxtsk ) {
200: time_slice_schedule(schedtsk);
201: }
202:
203: schedtsk = tcb;
204: dispatch_request();
205: }
206: }
207:
208: 209: 210: 211: 212: 213: 214:
215: EXPORT void make_non_ready( TCB *tcb )
216: {
217: ready_queue_delete(&ready_queue, tcb);
218: if ( schedtsk == tcb ) {
219: schedtsk = ready_queue_top(&ready_queue);
220: dispatch_request();
221: }
222: }
223:
224: 225: 226:
227: EXPORT void change_task_priority( TCB *tcb, INT priority )
228: {
229: INT oldpri;
230:
231: if ( tcb->state == TS_READY ) {
232: 233: 234: 235: 236: 237:
238: ready_queue_delete(&ready_queue, tcb);
239: tcb->priority = (UB)priority;
240: ready_queue_insert(&ready_queue, tcb);
241: reschedule();
242: } else {
243: oldpri = tcb->priority;
244: tcb->priority = (UB)priority;
245:
246: 247:
248: if ( (tcb->state & TS_WAIT) != 0 && tcb->wspec->chg_pri_hook) {
249: (*tcb->wspec->chg_pri_hook)(tcb, oldpri);
250: }
251: }
252: }
253:
254: 255: 256:
257: EXPORT void rotate_ready_queue( INT priority )
258: {
259: ready_queue_rotate(&ready_queue, priority);
260: reschedule();
261: }
262:
263: 264: 265:
266: EXPORT void rotate_ready_queue_run( void )
267: {
268: if ( schedtsk != NULL ) {
269: ready_queue_rotate(&ready_queue,
270: ready_queue_top_priority(&ready_queue));
271: reschedule();
272: }
273: }
274:
275:
276: 277: 278:
279: #if USE_DBGSPT
280:
281: 282: 283:
284: SYSCALL INT _td_rdy_que( PRI pri, ID list[], INT nent )
285: {
286: QUEUE *q, *tskque;
287: INT n = 0;
288:
289: CHECK_PRI(pri);
290:
291: BEGIN_DISABLE_INTERRUPT;
292: tskque = &ready_queue.tskque[int_priority(pri)];
293: for ( q = tskque->next; q != tskque; q = q->next ) {
294: if ( n++ < nent ) {
295: *(list++) = ((TCB*)q)->tskid;
296: }
297: }
298: END_DISABLE_INTERRUPT;
299:
300: return n;
301: }
302:
303: #endif