summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2014-09-12 09:52:45 +0000
committerkettenis <kettenis@openbsd.org>2014-09-12 09:52:45 +0000
commitf6650e177111d6e9855a0240261b4ae88b06466a (patch)
tree853886178692d16858f7463466eb8fd3427f841f
parentdont leak a ccb in identify (diff)
downloadwireguard-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.c99
-rw-r--r--sys/arch/amd64/include/cpu.h8
-rw-r--r--sys/arch/i386/i386/mp_setperf.c101
-rw-r--r--sys/arch/i386/include/cpu.h8
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