From 46969da5f8b7d09f4fb1368d6be669af63110127 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 2 Apr 2003 23:53:30 +0000 Subject: 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 --- sys/amd64/include/md_var.h | 16 ++++++++++++++++ sys/amd64/include/mptable.h | 9 ++++++++- sys/amd64/include/pmap.h | 2 +- sys/amd64/include/smp.h | 1 + 4 files changed, 26 insertions(+), 2 deletions(-) (limited to 'sys/amd64/include') diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h index 9143d19..6bcecff 100644 --- a/sys/amd64/include/md_var.h +++ b/sys/amd64/include/md_var.h @@ -65,6 +65,22 @@ extern int szfreebsd4_sigcode; #ifdef COMPAT_43 extern int szosigcode; #endif +#ifdef SWTCH_OPTIM_STATS +extern int stupid_switch; +extern int swtch_optim_stats; +extern int tlb_flush_count; +extern int lazy_flush_count; +extern int lazy_flush_fixup; +#ifdef SMP +extern int lazy_flush_smpfixup; +extern int lazy_flush_smpipi; +extern int lazy_flush_smpbadcr3; +extern int lazy_flush_smpmiss; +#endif +#endif +#ifdef LAZY_SWITCH +extern int lazy_flush_enable; +#endif typedef void alias_for_inthand_t(u_int cs, u_int ef, u_int esp, u_int ss); struct thread; diff --git a/sys/amd64/include/mptable.h b/sys/amd64/include/mptable.h index 954a7fd..4cc8bf5 100644 --- a/sys/amd64/include/mptable.h +++ b/sys/amd64/include/mptable.h @@ -27,6 +27,7 @@ #include "opt_cpu.h" #include "opt_kstack_pages.h" +#include "opt_swtch.h" #ifdef SMP #include @@ -634,6 +635,12 @@ mp_enable(u_int boot_addr) setidt(XSTATCLOCK_OFFSET, Xstatclock, SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); +#ifdef LAZY_SWITCH + /* install an inter-CPU IPI for lazy pmap release */ + setidt(XLAZYPMAP_OFFSET, Xlazypmap, + SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); +#endif + /* install an inter-CPU IPI for all-CPU rendezvous */ setidt(XRENDEZVOUS_OFFSET, Xrendezvous, SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); @@ -2598,7 +2605,7 @@ ap_init(void) binuptime(PCPU_PTR(switchtime)); PCPU_SET(switchticks, ticks); - cpu_throw(); /* doesn't return */ + cpu_throw(NULL, choosethread()); /* doesn't return */ panic("scheduler returned us to %s", __func__); } diff --git a/sys/amd64/include/pmap.h b/sys/amd64/include/pmap.h index 8fcf2cb..f044d45 100644 --- a/sys/amd64/include/pmap.h +++ b/sys/amd64/include/pmap.h @@ -247,7 +247,7 @@ struct pmap { pd_entry_t *pm_pdir; /* KVA of page directory */ vm_object_t pm_pteobj; /* Container for pte's */ TAILQ_HEAD(,pv_entry) pm_pvlist; /* list of mappings in pmap */ - int pm_active; /* active on cpus */ + u_int pm_active; /* active on cpus */ struct pmap_statistics pm_stats; /* pmap statistics */ LIST_ENTRY(pmap) pm_list; /* List of all pmaps */ #ifdef PAE diff --git a/sys/amd64/include/smp.h b/sys/amd64/include/smp.h index b503c2c..6467365 100644 --- a/sys/amd64/include/smp.h +++ b/sys/amd64/include/smp.h @@ -56,6 +56,7 @@ extern int current_postcode; /** XXX currently in mp_machdep.c */ #define IPI_INVLTLB XINVLTLB_OFFSET #define IPI_INVLPG XINVLPG_OFFSET #define IPI_INVLRNG XINVLRNG_OFFSET +#define IPI_LAZYPMAP XLAZYPMAP_OFFSET #define IPI_RENDEZVOUS XRENDEZVOUS_OFFSET #define IPI_AST XCPUAST_OFFSET #define IPI_STOP XCPUSTOP_OFFSET -- cgit v1.1