diff options
author | 2014-09-12 09:52:45 +0000 | |
---|---|---|
committer | 2014-09-12 09:52:45 +0000 | |
commit | f6650e177111d6e9855a0240261b4ae88b06466a (patch) | |
tree | 853886178692d16858f7463466eb8fd3427f841f | |
parent | dont leak a ccb in identify (diff) | |
download | wireguard-openbsd-f6650e177111d6e9855a0240261b4ae88b06466a.tar.xz wireguard-openbsd-f6650e177111d6e9855a0240261b4ae88b06466a.zip |
Remove the code that attempts to synchronize P-state transitions between CPUs.
Spinning inside an IPI handler is generally a bad idea as it is very hard to
avoid deadlocks. As far as I can tell the synchronization isn't necessary.
Multi-core CPUs have hardware mechanisms to do the appropropriate coordination
between cores and coordination between sockets isn't necessary either.
This seems to fix the various hangs and suspend/resume failures that people
have been seeing when running apmd -A or apmd -C.
Tested by many.
ok kspillner@, mpi@
-rw-r--r-- | sys/arch/amd64/amd64/mp_setperf.c | 99 | ||||
-rw-r--r-- | sys/arch/amd64/include/cpu.h | 8 | ||||
-rw-r--r-- | sys/arch/i386/i386/mp_setperf.c | 101 | ||||
-rw-r--r-- | sys/arch/i386/include/cpu.h | 8 |
4 files changed, 18 insertions, 198 deletions
diff --git a/sys/arch/amd64/amd64/mp_setperf.c b/sys/arch/amd64/amd64/mp_setperf.c index c860e88139a..9259e38be8c 100644 --- a/sys/arch/amd64/amd64/mp_setperf.c +++ b/sys/arch/amd64/amd64/mp_setperf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mp_setperf.c,v 1.4 2014/06/29 01:01:20 deraadt Exp $ */ +/* $OpenBSD: mp_setperf.c,v 1.5 2014/09/12 09:52:45 kettenis Exp $ */ /* * Copyright (c) 2007 Gordon Willem Klok <gwk@openbsd.org> * @@ -17,13 +17,10 @@ #include <sys/param.h> #include <sys/systm.h> -#include <sys/proc.h> #include <sys/sysctl.h> #include <sys/mutex.h> #include <machine/cpu.h> -#include <machine/cpufunc.h> - #include <machine/intr.h> struct mutex setperf_mp_mutex = MUTEX_INITIALIZER(IPL_HIGH); @@ -31,14 +28,7 @@ struct mutex setperf_mp_mutex = MUTEX_INITIALIZER(IPL_HIGH); /* underlying setperf mechanism e.g. k8_powernow_setperf() */ void (*ul_setperf)(int); -#define MP_SETPERF_STEADY 0 /* steady state - normal operation */ -#define MP_SETPERF_INTRANSIT 1 /* in transition */ -#define MP_SETPERF_PROCEED 2 /* proceed with transition */ -#define MP_SETPERF_FINISH 3 /* return from IPI */ - - /* protected by setperf_mp_mutex */ -volatile int mp_setperf_state = MP_SETPERF_STEADY; volatile int mp_perflevel; void mp_setperf(int); @@ -46,101 +36,28 @@ void mp_setperf(int); void mp_setperf(int level) { - CPU_INFO_ITERATOR cii; - struct cpu_info *ci; - int notready, s; - - if (mp_setperf_state == MP_SETPERF_STEADY) { - mtx_enter(&setperf_mp_mutex); - disable_intr(); - mp_perflevel = level; - - curcpu()->ci_setperf_state = CI_SETPERF_INTRANSIT; - /* ask all other processors to drop what they are doing */ - CPU_INFO_FOREACH(cii, ci) { - if (ci->ci_setperf_state != CI_SETPERF_INTRANSIT) { - ci->ci_setperf_state = - CI_SETPERF_SHOULDSTOP; - x86_send_ipi(ci, X86_IPI_SETPERF); - } - } - - - /* Loop until all processors report ready */ - do { - CPU_INFO_FOREACH(cii, ci) { - if ((notready = (ci->ci_setperf_state - != CI_SETPERF_INTRANSIT))) - break; - } - } while (notready); - - mp_setperf_state = MP_SETPERF_PROCEED; /* release the hounds */ - - s = splipi(); - - ul_setperf(mp_perflevel); - - splx(s); - - curcpu()->ci_setperf_state = CI_SETPERF_DONE; - /* Loop until all processors report done */ - do { - CPU_INFO_FOREACH(cii, ci) { - if ((notready = (ci->ci_setperf_state - != CI_SETPERF_DONE))) - break; - } - } while (notready); + mtx_enter(&setperf_mp_mutex); + mp_perflevel = level; - mp_setperf_state = MP_SETPERF_FINISH; - /* delay a little for potential straglers */ - DELAY(2); - curcpu()->ci_setperf_state = CI_SETPERF_READY; - mp_setperf_state = MP_SETPERF_STEADY; /* restore normallity */ - enable_intr(); - mtx_leave(&setperf_mp_mutex); - } + ul_setperf(mp_perflevel); + x86_broadcast_ipi(X86_IPI_SETPERF); + mtx_leave(&setperf_mp_mutex); } void x86_setperf_ipi(struct cpu_info *ci) { - - disable_intr(); - - if (ci->ci_setperf_state == CI_SETPERF_SHOULDSTOP) - ci->ci_setperf_state = CI_SETPERF_INTRANSIT; - - while (mp_setperf_state != MP_SETPERF_PROCEED) - ; - ul_setperf(mp_perflevel); - - ci->ci_setperf_state = CI_SETPERF_DONE; - - while (mp_setperf_state != MP_SETPERF_FINISH) - ; - ci->ci_setperf_state = CI_SETPERF_READY; - - enable_intr(); } void -mp_setperf_init() +mp_setperf_init(void) { - CPU_INFO_ITERATOR cii; - struct cpu_info *ci; - if (!cpu_setperf) return; - ul_setperf = cpu_setperf; + ul_setperf = cpu_setperf; cpu_setperf = mp_setperf; - - CPU_INFO_FOREACH(cii, ci) { - ci->ci_setperf_state = CI_SETPERF_READY; - } mtx_init(&setperf_mp_mutex, IPL_HIGH); } diff --git a/sys/arch/amd64/include/cpu.h b/sys/arch/amd64/include/cpu.h index f129aeb4330..06983dcbc75 100644 --- a/sys/arch/amd64/include/cpu.h +++ b/sys/arch/amd64/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.85 2014/07/11 10:53:07 uebayasi Exp $ */ +/* $OpenBSD: cpu.h,v 1.86 2014/09/12 09:52:45 kettenis Exp $ */ /* $NetBSD: cpu.h,v 1.1 2003/04/26 18:39:39 fvdl Exp $ */ /*- @@ -136,12 +136,6 @@ struct cpu_info { #define CI_DDB_ENTERDDB 3 #define CI_DDB_INDDB 4 - volatile int ci_setperf_state; -#define CI_SETPERF_READY 0 -#define CI_SETPERF_SHOULDSTOP 1 -#define CI_SETPERF_INTRANSIT 2 -#define CI_SETPERF_DONE 3 - struct ksensordev ci_sensordev; struct ksensor ci_sensor; #ifdef GPROF diff --git a/sys/arch/i386/i386/mp_setperf.c b/sys/arch/i386/i386/mp_setperf.c index cd530c1abbd..e050abf5925 100644 --- a/sys/arch/i386/i386/mp_setperf.c +++ b/sys/arch/i386/i386/mp_setperf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mp_setperf.c,v 1.5 2014/06/29 01:01:20 deraadt Exp $ */ +/* $OpenBSD: mp_setperf.c,v 1.6 2014/09/12 09:52:45 kettenis Exp $ */ /* * Copyright (c) 2007 Gordon Willem Klok <gwk@openbsd.org> * @@ -17,13 +17,10 @@ #include <sys/param.h> #include <sys/systm.h> -#include <sys/proc.h> #include <sys/sysctl.h> #include <sys/mutex.h> #include <machine/cpu.h> -#include <machine/cpufunc.h> - #include <machine/intr.h> struct mutex setperf_mp_mutex = MUTEX_INITIALIZER(IPL_HIGH); @@ -31,14 +28,7 @@ struct mutex setperf_mp_mutex = MUTEX_INITIALIZER(IPL_HIGH); /* underlying setperf mechanism e.g. k8_powernow_setperf() */ void (*ul_setperf)(int); -#define MP_SETPERF_STEADY 0 /* steady state - normal operation */ -#define MP_SETPERF_INTRANSIT 1 /* in transition */ -#define MP_SETPERF_PROCEED 2 /* proceed with transition */ -#define MP_SETPERF_FINISH 3 /* return from IPI */ - - /* protected by setperf_mp_mutex */ -volatile int mp_setperf_state = MP_SETPERF_STEADY; volatile int mp_perflevel; void mp_setperf(int); @@ -46,102 +36,27 @@ void mp_setperf(int); void mp_setperf(int level) { - CPU_INFO_ITERATOR cii; - struct cpu_info *ci; - int notready, s; - - if (mp_setperf_state == MP_SETPERF_STEADY) { - mtx_enter(&setperf_mp_mutex); - disable_intr(); - - mp_perflevel = level; - - curcpu()->ci_setperf_state = CI_SETPERF_INTRANSIT; - /* ask all other processors to drop what they are doing */ - CPU_INFO_FOREACH(cii, ci) { - if (ci->ci_setperf_state != CI_SETPERF_INTRANSIT) { - ci->ci_setperf_state = - CI_SETPERF_SHOULDSTOP; - i386_send_ipi(ci, I386_IPI_SETPERF); - } - } - - - /* Loop until all processors report ready */ - do { - CPU_INFO_FOREACH(cii, ci) { - if ((notready = (ci->ci_setperf_state - != CI_SETPERF_INTRANSIT))) - break; - } - } while (notready); - - mp_setperf_state = MP_SETPERF_PROCEED; /* release the hounds */ - - s = splipi(); - - ul_setperf(mp_perflevel); - - splx(s); - - curcpu()->ci_setperf_state = CI_SETPERF_DONE; - /* Loop until all processors report done */ - do { - CPU_INFO_FOREACH(cii, ci) { - if ((notready = (ci->ci_setperf_state - != CI_SETPERF_DONE))) - break; - } - } while (notready); - - mp_setperf_state = MP_SETPERF_FINISH; - /* delay a little for potential straglers */ - DELAY(2); - curcpu()->ci_setperf_state = CI_SETPERF_READY; - mp_setperf_state = MP_SETPERF_STEADY; /* restore normallity */ - enable_intr(); - mtx_leave(&setperf_mp_mutex); - } + mtx_enter(&setperf_mp_mutex); + mp_perflevel = level; + ul_setperf(mp_perflevel); + i386_broadcast_ipi(I386_IPI_SETPERF); + mtx_leave(&setperf_mp_mutex); } void i386_setperf_ipi(struct cpu_info *ci) { - - disable_intr(); - - if (ci->ci_setperf_state == CI_SETPERF_SHOULDSTOP) - ci->ci_setperf_state = CI_SETPERF_INTRANSIT; - - while (mp_setperf_state != MP_SETPERF_PROCEED) - ; - ul_setperf(mp_perflevel); - - ci->ci_setperf_state = CI_SETPERF_DONE; - - while (mp_setperf_state != MP_SETPERF_FINISH) - ; - ci->ci_setperf_state = CI_SETPERF_READY; - - enable_intr(); } void -mp_setperf_init() +mp_setperf_init(void) { - CPU_INFO_ITERATOR cii; - struct cpu_info *ci; - if (!cpu_setperf) return; - ul_setperf = cpu_setperf; + ul_setperf = cpu_setperf; cpu_setperf = mp_setperf; - - CPU_INFO_FOREACH(cii, ci) { - ci->ci_setperf_state = CI_SETPERF_READY; - } mtx_init(&setperf_mp_mutex, IPL_HIGH); } diff --git a/sys/arch/i386/include/cpu.h b/sys/arch/i386/include/cpu.h index 91b558a2934..791ebe2c954 100644 --- a/sys/arch/i386/include/cpu.h +++ b/sys/arch/i386/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.134 2014/07/11 10:53:07 uebayasi Exp $ */ +/* $OpenBSD: cpu.h,v 1.135 2014/09/12 09:52:45 kettenis Exp $ */ /* $NetBSD: cpu.h,v 1.35 1996/05/05 19:29:26 christos Exp $ */ /*- @@ -147,12 +147,6 @@ struct cpu_info { #define CI_DDB_ENTERDDB 3 #define CI_DDB_INDDB 4 - volatile int ci_setperf_state; -#define CI_SETPERF_READY 0 -#define CI_SETPERF_SHOULDSTOP 1 -#define CI_SETPERF_INTRANSIT 2 -#define CI_SETPERF_DONE 3 - struct ksensordev ci_sensordev; struct ksensor ci_sensor; #ifdef GPROF |