2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: The task Dispatcher for m68k; taken from i386-native version
9 #include <exec/execbase.h>
10 #include <aros/asmcall.h>
11 #include <exec/interrupts.h>
12 #include <proto/exec.h>
13 #include <exec_intern.h>
14 #include <exec/ptrace.h>
16 void SaveRegs(struct Task
*task
, struct pt_regs
*regs
)
18 /* Copy registers from struct pt_regs into the user stack */
19 struct pt_regs
* dest
= (struct pt_regs
*)task
->tc_UnionETask
.tc_ETask
->et_RegFrame
;
21 * Use this rather than memcpy! It does NOT work otherwise
24 dest
->usp
= regs
->usp
;
44 while (i
< sizeof(struct pt_regs
)) {
45 ((UBYTE
*)dest
)[i
] = ((UBYTE
*)regs
)[i
];
49 task
->tc_SPReg
= (APTR
)regs
->usp
;
52 void RestoreRegs(struct Task
*task
, struct pt_regs
*regs
)
54 /* Copy registers from the task's stack into struct pt_regs */
55 struct pt_regs
* src
= (struct pt_regs
*)task
->tc_UnionETask
.tc_ETask
->et_RegFrame
;
58 * Use this rather than memcpy! It does NOT work otherwise
81 while (i
< sizeof(struct pt_regs
)) {
82 ((UBYTE
*)regs
)[i
] = ((UBYTE
*)src
)[i
];
87 task
->tc_SPReg
= (APTR
)regs
->usp
;
90 #define SC_ENABLE(regs) (regs->sr &= 0xf8ff)
91 #define SC_DISABLE(regs) (regs->sr |= 0x0700)
93 void sys_Dispatch(struct pt_regs
* regs
)
95 struct ExecBase
* SysBase
= (struct ExecBase
*)*(ULONG
*)0x04;
97 /* Hmm, interrupts are nesting, not a good idea... */
98 if(!user_mode(regs
)) {
102 /* Check if a task switch is necessary */
103 /* 1. There has to be another task in the ready-list */
104 /* 2. The first task in the ready list hast to have the
105 same or higher priority than the currently active task */
107 if( SysBase
->TaskReady
.lh_Head
->ln_Succ
!= NULL
/* &&
108 ((BYTE)SysBase->ThisTask->tc_Node.ln_Pri <=
109 (BYTE)((struct Task *)SysBase->TaskReady.lh_Head)->tc_Node.ln_Pri )*/
112 /* Check if task switch is possible */
113 if( SysBase
->TDNestCnt
< 0 )
115 if( SysBase
->ThisTask
->tc_State
== TS_RUN
)
117 SysBase
->ThisTask
->tc_State
= TS_READY
;
118 Reschedule(SysBase
->ThisTask
);
119 SysBase
->AttnResched
|= 0x8000;
121 else if( SysBase
->ThisTask
->tc_State
== TS_REMOVED
)
122 SysBase
->AttnResched
|= 0x8000;
125 SysBase
->AttnResched
|= 0x80;
129 /* Has an interrupt told us to dispatch when leaving */
130 if (SysBase
->AttnResched
& 0x8000)
132 SysBase
->AttnResched
&= ~0x8000;
134 /* Save registers for this task (if there is one...) */
135 if (SysBase
->ThisTask
&& SysBase
->ThisTask
->tc_State
!= TS_REMOVED
)
136 SaveRegs(SysBase
->ThisTask
, regs
);
138 /* Tell exec that we have actually switched tasks... */
141 /* Get the registers of the old task */
142 RestoreRegs(SysBase
->ThisTask
, regs
);
143 /* Make sure that the state of the interrupts is what the task
146 if (SysBase
->IDNestCnt
< 0)
150 /* Ok, the next step is to either drop back to the new task, or
151 give it its Exception() if it wants one... */
153 if (SysBase
->ThisTask
->tc_Flags
& TF_EXCEPT
)
163 /* Leave the interrupt. */