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>
18 void SaveRegs(struct Task
*task
, struct pt_regs
*regs
)
20 /* Copy registers from struct pt_regs into the user stack */
21 struct pt_regs
* dest
= (struct pt_regs
*)task
->tc_UnionETask
.tc_ETask
->et_RegFrame
;
23 * Use this rather than memcpy! It does NOT work otherwise
26 dest
->usp
= regs
->usp
;
46 while (i
< sizeof(struct pt_regs
)) {
47 ((UBYTE
*)dest
)[i
] = ((UBYTE
*)regs
)[i
];
51 task
->tc_SPReg
= (APTR
)regs
->usp
;
54 void RestoreRegs(struct Task
*task
, struct pt_regs
*regs
)
56 /* Copy registers from the task's stack into struct pt_regs */
57 struct pt_regs
* src
= (struct pt_regs
*)task
->tc_UnionETask
.tc_ETask
->et_RegFrame
;
60 * Use this rather than memcpy! It does NOT work otherwise
83 while (i
< sizeof(struct pt_regs
)) {
84 ((UBYTE
*)regs
)[i
] = ((UBYTE
*)src
)[i
];
89 task
->tc_SPReg
= (APTR
)regs
->usp
;
92 #define SC_ENABLE(regs) (regs->sr &= 0xf8ff)
93 #define SC_DISABLE(regs) (regs->sr |= 0x0700)
95 void sys_Dispatch(struct pt_regs
* regs
)
97 struct ExecBase
* SysBase
= (struct ExecBase
*)*(ULONG
*)0x04;
99 /* Hmm, interrupts are nesting, not a good idea... */
100 if(!user_mode(regs
)) {
104 /* Check if a task switch is necessary */
105 /* 1. There has to be another task in the ready-list */
106 /* 2. The first task in the ready list hast to have the
107 same or higher priority than the currently active task */
109 if( SysBase
->TaskReady
.lh_Head
->ln_Succ
!= NULL
/* &&
110 ((BYTE)SysBase->ThisTask->tc_Node.ln_Pri <=
111 (BYTE)((struct Task *)SysBase->TaskReady.lh_Head)->tc_Node.ln_Pri )*/
114 /* Check if task switch is possible */
115 if( SysBase
->TDNestCnt
< 0 )
117 if( SysBase
->ThisTask
->tc_State
== TS_RUN
)
119 SysBase
->ThisTask
->tc_State
= TS_READY
;
120 Reschedule(SysBase
->ThisTask
);
121 SysBase
->AttnResched
|= 0x8000;
123 else if( SysBase
->ThisTask
->tc_State
== TS_REMOVED
)
124 SysBase
->AttnResched
|= 0x8000;
127 SysBase
->AttnResched
|= 0x80;
131 /* Has an interrupt told us to dispatch when leaving */
132 if (SysBase
->AttnResched
& 0x8000)
134 SysBase
->AttnResched
&= ~0x8000;
136 /* Save registers for this task (if there is one...) */
137 if (SysBase
->ThisTask
&& SysBase
->ThisTask
->tc_State
!= TS_REMOVED
)
138 SaveRegs(SysBase
->ThisTask
, regs
);
140 /* Tell exec that we have actually switched tasks... */
143 /* Get the registers of the old task */
144 RestoreRegs(SysBase
->ThisTask
, regs
);
145 /* Make sure that the state of the interrupts is what the task
148 if (SysBase
->IDNestCnt
< 0)
152 /* Ok, the next step is to either drop back to the new task, or
153 give it its Exception() if it wants one... */
155 if (SysBase
->ThisTask
->tc_Flags
& TF_EXCEPT
)
165 /* Leave the interrupt. */