patch-2.1.109 linux/include/asm-i386/system.h
Next file: linux/include/asm-i386/vga.h
Previous file: linux/include/asm-i386/processor.h
Back to the patch index
Back to the overall index
- Lines: 116
- Date:
Fri Jul 10 16:19:06 1998
- Orig file:
v2.1.108/linux/include/asm-i386/system.h
- Orig date:
Sat Apr 25 18:13:12 1998
diff -u --recursive --new-file v2.1.108/linux/include/asm-i386/system.h linux/include/asm-i386/system.h
@@ -1,6 +1,7 @@
#ifndef __ASM_SYSTEM_H
#define __ASM_SYSTEM_H
+#include <linux/kernel.h>
#include <asm/segment.h>
/*
@@ -35,83 +36,34 @@
:"=a" (n) \
:"0" (0),"i" (FIRST_TSS_ENTRY<<3))
-/* This special macro can be used to load a debugging register */
-
-#define loaddebug(tsk,register) \
- __asm__("movl %0,%%db" #register \
- : /* no output */ \
- :"r" (tsk->debugreg[register]))
-
+struct task_struct; /* one of the stranger aspects of C forward declarations.. */
+extern void FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next));
/*
- * switch_to(n) should switch tasks to task nr n, first
- * checking that n isn't the current task, in which case it does nothing.
- * This also clears the TS-flag if the task we switched to has used
- * the math co-processor latest.
- *
- * It also reloads the debug regs if necessary..
+ * We do most of the task switching in C, but we need
+ * to do the EIP/ESP switch in assembly..
*/
-
-
-#ifdef __SMP__
- /*
- * Keep the lock depth straight. If we switch on an interrupt from
- * kernel->user task we need to lose a depth, and if we switch the
- * other way we need to gain a depth. Same layer switches come out
- * the same.
- *
- * We spot a switch in user mode because the kernel counter is the
- * same as the interrupt counter depth. (We never switch during the
- * message/invalidate IPI).
- *
- * We fsave/fwait so that an exception goes off at the right time
- * (as a call from the fsave or fwait in effect) rather than to
- * the wrong process.
- */
-
-#define switch_to(prev,next) do { \
- if(prev->flags&PF_USEDFPU) \
- { \
- __asm__ __volatile__("fnsave %0":"=m" (prev->tss.i387.hard)); \
- __asm__ __volatile__("fwait"); \
- prev->flags&=~PF_USEDFPU; \
- } \
-__asm__("ljmp %0\n\t" \
- : /* no output */ \
- :"m" (*(((char *)&next->tss.tr)-4)), \
- "c" (next)); \
- /* Now maybe reload the debug registers */ \
- if(prev->debugreg[7]){ \
- loaddebug(prev,0); \
- loaddebug(prev,1); \
- loaddebug(prev,2); \
- loaddebug(prev,3); \
- loaddebug(prev,6); \
- loaddebug(prev,7); \
- } \
-} while (0)
-
-#else
-#define switch_to(prev,next) do { \
-__asm__("ljmp %0\n\t" \
- "cmpl %1,"SYMBOL_NAME_STR(last_task_used_math)"\n\t" \
- "jne 1f\n\t" \
- "clts\n" \
- "1:" \
- : /* no outputs */ \
- :"m" (*(((char *)&next->tss.tr)-4)), \
- "r" (prev), "r" (next)); \
- /* Now maybe reload the debug registers */ \
- if(prev->debugreg[7]){ \
- loaddebug(prev,0); \
- loaddebug(prev,1); \
- loaddebug(prev,2); \
- loaddebug(prev,3); \
- loaddebug(prev,6); \
- loaddebug(prev,7); \
- } \
+#define switch_to(prev,next) do { \
+ unsigned long eax, edx, ecx; \
+ asm volatile("pushl %%ebx\n\t" \
+ "pushl %%esi\n\t" \
+ "pushl %%edi\n\t" \
+ "pushl %%ebp\n\t" \
+ "movl %%esp,%0\n\t" /* save ESP */ \
+ "movl %5,%%esp\n\t" /* restore ESP */ \
+ "movl $1f,%1\n\t" /* save EIP */ \
+ "pushl %6\n\t" /* restore EIP */ \
+ "jmp __switch_to\n" \
+ "1:\t" \
+ "popl %%ebp\n\t" \
+ "popl %%edi\n\t" \
+ "popl %%esi\n\t" \
+ "popl %%ebx" \
+ :"=m" (prev->tss.esp),"=m" (prev->tss.eip), \
+ "=a" (eax), "=d" (edx), "=c" (ecx) \
+ :"m" (next->tss.esp),"m" (next->tss.eip), \
+ "a" (prev), "d" (next)); \
} while (0)
-#endif
#define _set_base(addr,base) \
__asm__("movw %%dx,%0\n\t" \
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov