diff options
author | peter <peter@FreeBSD.org> | 2003-04-02 23:53:30 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2003-04-02 23:53:30 +0000 |
commit | 46969da5f8b7d09f4fb1368d6be669af63110127 (patch) | |
tree | 4ec7883ecb294f0c60d2aa5a5a0b58973fafc545 /sys/i386/isa | |
parent | de8dcf74da6f877502c92f233c1c8020975a826f (diff) | |
download | FreeBSD-src-46969da5f8b7d09f4fb1368d6be669af63110127.zip FreeBSD-src-46969da5f8b7d09f4fb1368d6be669af63110127.tar.gz |
Commit a partial lazy thread switch mechanism for i386. it isn't as lazy
as it could be and can do with some more cleanup. Currently its under
options LAZY_SWITCH. What this does is avoid %cr3 reloads for short
context switches that do not involve another user process. ie: we can
take an interrupt, switch to a kthread and return to the user without
explicitly flushing the tlb. However, this isn't as exciting as it could
be, the interrupt overhead is still high and too much blocks on Giant
still. There are some debug sysctls, for stats and for an on/off switch.
The main problem with doing this has been "what if the process that you're
running on exits while we're borrowing its address space?" - in this case
we use an IPI to give it a kick when we're about to reclaim the pmap.
Its not compiled in unless you add the LAZY_SWITCH option. I want to fix a
few more things and get some more feedback before turning it on by default.
This is NOT a replacement for Bosko's lazy interrupt stuff. This was more
meant for the kthread case, while his was for interrupts. Mine helps a
little for interrupts, but his helps a lot more.
The stats are enabled with options SWTCH_OPTIM_STATS - this has been a
pseudo-option for years, I just added a bunch of stuff to it.
One non-trivial change was to select a new thread before calling
cpu_switch() in the first place. This allows us to catch the silly
case of doing a cpu_switch() to the current process. This happens
uncomfortably often. This simplifies a bit of the asm code in cpu_switch
(no longer have to call choosethread() in the middle). This has been
implemented on i386 and (thanks to jake) sparc64. The others will come
soon. This is actually seperate to the lazy switch stuff.
Glanced at by: jake, jhb
Diffstat (limited to 'sys/i386/isa')
-rw-r--r-- | sys/i386/isa/apic_vector.s | 22 | ||||
-rw-r--r-- | sys/i386/isa/intr_machdep.h | 6 |
2 files changed, 27 insertions, 1 deletions
diff --git a/sys/i386/isa/apic_vector.s b/sys/i386/isa/apic_vector.s index e4b6ea5..d91ff1c 100644 --- a/sys/i386/isa/apic_vector.s +++ b/sys/i386/isa/apic_vector.s @@ -3,6 +3,7 @@ * $FreeBSD$ */ +#include "opt_swtch.h" #include <machine/apic.h> #include <machine/smp.h> @@ -648,7 +649,28 @@ Xrendezvous: POP_FRAME iret +#ifdef LAZY_SWITCH +/* + * Clean up when we lose out on the lazy context switch optimization. + * ie: when we are about to release a PTD but a cpu is still borrowing it. + */ + SUPERALIGN_TEXT + .globl Xlazypmap +Xlazypmap: + PUSH_FRAME + movl $KDSEL, %eax + mov %ax, %ds /* use KERNEL data segment */ + mov %ax, %es + movl $KPSEL, %eax + mov %ax, %fs + + call pmap_lazyfix_action + movl $0, lapic+LA_EOI /* End Of Interrupt to APIC */ + POP_FRAME + iret +#endif + .data .globl apic_pin_trigger diff --git a/sys/i386/isa/intr_machdep.h b/sys/i386/isa/intr_machdep.h index 7179268..4cfecb5 100644 --- a/sys/i386/isa/intr_machdep.h +++ b/sys/i386/isa/intr_machdep.h @@ -116,6 +116,9 @@ /* inter-CPU rendezvous */ #define XRENDEZVOUS_OFFSET (ICU_OFFSET + 122) /* 0x9A */ +/* lazy pmap release */ +#define XLAZYPMAP_OFFSET (ICU_OFFSET + 123) /* 0x9B */ + /* IPI to generate an additional software trap at the target CPU */ /* XXX in the middle of the interrupt range, overlapping IRQ48 */ #define XCPUAST_OFFSET (ICU_OFFSET + 48) /* 0x50 */ @@ -206,7 +209,8 @@ inthand_t Xcpuast, /* Additional software trap on other cpu */ Xcpustop, /* CPU stops & waits for another CPU to restart it */ Xspuriousint, /* handle APIC "spurious INTs" */ - Xrendezvous; /* handle CPU rendezvous */ + Xrendezvous, /* handle CPU rendezvous */ + Xlazypmap; /* handle lazy pmap release */ #ifdef TEST_TEST1 inthand_t |