Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 10 Sep 2010 17:40:25 +0300
From:      Kostik Belousov <kostikbel@gmail.com>
To:        Dimitry Andric <dim@freebsd.org>
Cc:        "Thomas E. Spanjaard" <tgen@deepbone.net>, freebsd-current@freebsd.org
Subject:   Re: Eventtimers b0rking w/ math/atlas
Message-ID:  <20100910144025.GQ2465@deviant.kiev.zoral.com.ua>
In-Reply-To: <4C8A414C.6000603@FreeBSD.org>
References:  <4C8A379E.6080909@deepbone.net> <4C8A414C.6000603@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--v+Mbu5iuT/5Blw/K
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Fri, Sep 10, 2010 at 04:31:40PM +0200, Dimitry Andric wrote:
> On 2010-09-10 15:50, Thomas E. Spanjaard wrote:
> >While trying to build math/atlas on a FreeBSD/amd64 9.0-CURRENT r212411,
> >the kernel hangs at some point when math/atlas tries to run some tests
> >(presumably the ones to profile the code and optimise). The kernel
> >spouts messages about Starting event timers: LAPIC @ 1000Hz, HPET @
> >127Hz; then LAPIC @ 1000Hz, HPET @ 8128Hz (iirc), back, then back again.
>=20
> It's probably running profiled executables (e.g. compiled with -pg)?
> This can lead to the above messages, and apparently also to deadlocks.
>=20
> I am not sure what to do about it though, except confirm that this is
> very likely your problem...

Try this.

diff --git a/sys/kern/kern_clocksource.c b/sys/kern/kern_clocksource.c
index 6b005de..7f0c781 100644
--- a/sys/kern/kern_clocksource.c
+++ b/sys/kern/kern_clocksource.c
@@ -65,6 +65,7 @@ inline static int	doconfigtimer(int i);
 static void		configtimer(int i);
=20
 static struct eventtimer *timer[2] =3D { NULL, NULL };
+static int		blocked_timer[2];
 static int		timertest =3D 0;
 static int		timerticks[2] =3D { 0, 0 };
 static int		profiling_on =3D 0;
@@ -91,6 +92,22 @@ static DPCPU_DEFINE(tc, configtimer);
 	(((uint64_t)0x8000000000000000 + ((bt)->frac >> 2)) /		\
 	    ((bt)->frac >> 1))
=20
+static void
+block_timer(int i)
+{
+
+	critical_enter();
+	atomic_add_acq_int(&blocked_timer[i], 1);
+}
+
+static void
+unblock_timer(int i)
+{
+
+	atomic_add_rel_int(&blocked_timer[i], -1);
+	critical_exit();
+}
+
 /* Per-CPU timer1 handler. */
 static int
 hardclockhandler(struct trapframe *frame)
@@ -246,6 +263,8 @@ doconfigtimer(int i)
 		atomic_store_rel_int(*conf + i, 0);
 		return (1);
 	}
+	if (atomic_load_acq_int(&blocked_timer[i]) > 0)
+		return (1);
 	return (0);
 }
=20
@@ -366,9 +385,7 @@ cpu_initclocks_bsp(void)
 		profhz =3D round_freq(timer[1], stathz * 64);
 	}
 	tick =3D 1000000 / hz;
-	ET_LOCK();
 	cpu_restartclocks();
-	ET_UNLOCK();
 }
=20
 /* Start per-CPU event timers on APs. */
@@ -376,12 +393,10 @@ void
 cpu_initclocks_ap(void)
 {
=20
-	ET_LOCK();
 	if (timer[0]->et_flags & ET_FLAGS_PERCPU)
 		et_start(timer[0], NULL, &timerperiod[0]);
 	if (timer[1] && timer[1]->et_flags & ET_FLAGS_PERCPU)
 		et_start(timer[1], NULL, &timerperiod[1]);
-	ET_UNLOCK();
 }
=20
 /* Reconfigure and restart event timers after configuration changes. */
@@ -411,9 +426,11 @@ cpu_restartclocks(void)
 		timer2hz =3D round_freq(timer[1], timer2hz);
 	}
 	timer1hz =3D round_freq(timer[0], timer1hz);
+#ifdef notyet
 	printf("Starting kernel event timers: %s @ %dHz, %s @ %dHz\n",
 	    timer[0]->et_name, timer1hz,
 	    timer[1] ? timer[1]->et_name : "NONE", timer2hz);
+#endif
 	/* Restart event timers. */
 	FREQ2BT(timer1hz, &timerperiod[0]);
 	configtimer(0);
@@ -422,7 +439,9 @@ cpu_restartclocks(void)
 		timerticks[1] =3D 0;
 		FREQ2BT(timer2hz, &timerperiod[1]);
 		configtimer(1);
+#ifdef notyet
 		timertest =3D 1;
+#endif
 	}
 }
=20
@@ -433,7 +452,11 @@ cpu_startprofclock(void)
=20
 	ET_LOCK();
 	profiling_on =3D 1;
+	block_timer(0);
+	block_timer(1);
 	cpu_restartclocks();
+	unblock_timer(1);
+	unblock_timer(0);
 	ET_UNLOCK();
 }
=20
@@ -444,7 +467,11 @@ cpu_stopprofclock(void)
=20
 	ET_LOCK();
 	profiling_on =3D 0;
+	block_timer(0);
+	block_timer(1);
 	cpu_restartclocks();
+	unblock_timer(1);
+	unblock_timer(0);
 	ET_UNLOCK();
 }
=20
@@ -461,10 +488,11 @@ sysctl_kern_eventtimer_timer1(SYSCTL_HANDLER_ARGS)
 	snprintf(buf, sizeof(buf), "%s", et->et_name);
 	ET_UNLOCK();
 	error =3D sysctl_handle_string(oidp, buf, sizeof(buf), req);
+	if (error !=3D 0 || req->newptr =3D=3D NULL)
+		return (error);
 	ET_LOCK();
 	et =3D timer[0];
-	if (error !=3D 0 || req->newptr =3D=3D NULL ||
-	    strcmp(buf, et->et_name) =3D=3D 0) {
+	if (strcmp(buf, et->et_name) =3D=3D 0) {
 		ET_UNLOCK();
 		return (error);
 	}
@@ -473,12 +501,14 @@ sysctl_kern_eventtimer_timer1(SYSCTL_HANDLER_ARGS)
 		ET_UNLOCK();
 		return (ENOENT);
 	}
+	block_timer(0);
 	timer1hz =3D 0;
 	configtimer(0);
 	et_free(timer[0]);
 	timer[0] =3D et;
 	et_init(timer[0], timer1cb, NULL, NULL);
 	cpu_restartclocks();
+	unblock_timer(0);
 	ET_UNLOCK();
 	return (error);
 }
@@ -501,10 +531,11 @@ sysctl_kern_eventtimer_timer2(SYSCTL_HANDLER_ARGS)
 		snprintf(buf, sizeof(buf), "%s", et->et_name);
 	ET_UNLOCK();
 	error =3D sysctl_handle_string(oidp, buf, sizeof(buf), req);
+	if (error !=3D 0 || req->newptr =3D=3D NULL)
+		return (error);
 	ET_LOCK();
 	et =3D timer[1];
-	if (error !=3D 0 || req->newptr =3D=3D NULL ||
-	    strcmp(buf, et ? et->et_name : "NONE") =3D=3D 0) {
+	if (strcmp(buf, et ? et->et_name : "NONE") =3D=3D 0) {
 		ET_UNLOCK();
 		return (error);
 	}
@@ -513,6 +544,7 @@ sysctl_kern_eventtimer_timer2(SYSCTL_HANDLER_ARGS)
 		ET_UNLOCK();
 		return (ENOENT);
 	}
+	block_timer(1);
 	if (timer[1] !=3D NULL) {
 		timer2hz =3D 0;
 		configtimer(1);
@@ -522,6 +554,7 @@ sysctl_kern_eventtimer_timer2(SYSCTL_HANDLER_ARGS)
 	if (timer[1] !=3D NULL)
 		et_init(timer[1], timer2cb, NULL, NULL);
 	cpu_restartclocks();
+	unblock_timer(1);
 	ET_UNLOCK();
 	return (error);
 }
diff --git a/sys/kern/kern_et.c b/sys/kern/kern_et.c
index 6a56b1d..94e1466 100644
--- a/sys/kern/kern_et.c
+++ b/sys/kern/kern_et.c
@@ -38,7 +38,7 @@ SLIST_HEAD(et_eventtimers_list, eventtimer);
 static struct et_eventtimers_list eventtimers =3D SLIST_HEAD_INITIALIZER(e=
t_eventtimers);
=20
 struct mtx	et_eventtimers_mtx;
-MTX_SYSINIT(et_eventtimers_init, &et_eventtimers_mtx, "et_mtx", MTX_SPIN);
+MTX_SYSINIT(et_eventtimers_init, &et_eventtimers_mtx, "et_mtx", MTX_DEF);
=20
 SYSCTL_NODE(_kern, OID_AUTO, eventtimer, CTLFLAG_RW, 0, "Event timers");
 SYSCTL_NODE(_kern_eventtimer, OID_AUTO, et, CTLFLAG_RW, 0, "");
diff --git a/sys/sys/timeet.h b/sys/sys/timeet.h
index bc713d6..87392a2 100644
--- a/sys/sys/timeet.h
+++ b/sys/sys/timeet.h
@@ -83,8 +83,8 @@ struct eventtimer {
 };
=20
 extern struct mtx	et_eventtimers_mtx;
-#define	ET_LOCK()	mtx_lock_spin(&et_eventtimers_mtx)
-#define	ET_UNLOCK()	mtx_unlock_spin(&et_eventtimers_mtx)
+#define	ET_LOCK()	mtx_lock(&et_eventtimers_mtx)
+#define	ET_UNLOCK()	mtx_unlock(&et_eventtimers_mtx)
=20
 /* Driver API */
 int	et_register(struct eventtimer *et);
diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c
index f479bbe..7811441 100644
--- a/sys/x86/x86/local_apic.c
+++ b/sys/x86/x86/local_apic.c
@@ -500,9 +500,11 @@ lapic_et_start(struct eventtimer *et,
 		} while (lapic_timer_divisor <=3D 128);
 		if (lapic_timer_divisor > 128)
 			panic("lapic: Divisor too big");
+#ifdef notyet
 		if (bootverbose)
 			printf("lapic: Divisor %lu, Frequency %lu Hz\n",
 			    lapic_timer_divisor, value);
+#endif
 		et->et_frequency =3D value;
 		et->et_min_period.sec =3D 0;
 		et->et_min_period.frac =3D

--v+Mbu5iuT/5Blw/K
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (FreeBSD)

iEYEARECAAYFAkyKQ1kACgkQC3+MBN1Mb4hqiwCgof9TYCaBytdtm0dIOZaYmliT
u24AoI/Fg/27D5LKV1yPP5hlAO+4mZTE
=xEOU
-----END PGP SIGNATURE-----

--v+Mbu5iuT/5Blw/K--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20100910144025.GQ2465>