Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 26 Feb 2019 12:25:00 -0800
From:      Mark Millard <marklmi@yahoo.com>
To:        Justin Hibbits <chmeeedalf@gmail.com>, FreeBSD PowerPC ML <freebsd-ppc@freebsd.org>, freebsd-hackers Hackers <freebsd-hackers@freebsd.org>
Subject:   Re: The FreeBSD code structure that sometimes break powerpc64's pmac_thermal, buf*daemon* threads, etc. (stuck sleeping)
Message-ID:  <4DFDC776-BE0E-4952-8414-6B7ACFEC815B@yahoo.com>
In-Reply-To: <1C8071BF-5B3B-416D-8CE4-437D4555EEB5@yahoo.com>
References:  <1C8071BF-5B3B-416D-8CE4-437D4555EEB5@yahoo.com>

next in thread | previous in thread | raw e-mail | index | archive | help
[In one aspect of my comments I seem to have misapplied
some generic background information: cross CPU sbinuptime()
values are not involved for timercb vs. sleepq_timeout
in the call chain. It sometimes goes backwards on the
same CPU during the call chain.]

On 2019-Feb-26, at 04:29, Mark Millard <marklmi at  yahoo.com> wrote:

> [head -r334018 based. I temporarily changed what messaging
> happens for KTR_PROC in order to gather information. As stands
> it was reporting on pmac_thermal because I can listen for the
> fans to know the stuck-sleeping has happened recently.]
>=20
> A powerpc64 sleepq_timeout callout usage has the structure:
>=20
> 0xe00000009af7c730: at sleepq_timeout+0x148
> 0xe00000009af7c7d0: at softclock_call_cc+0x234
> 0xe00000009af7c910: at callout_process+0x2e0
> 0xe00000009af7c9f0: at handleevents+0x22c
> 0xe00000009af7caa0: at timercb+0x340
> 0xe00000009af7cba0: at decr_intr+0x140
> 0xe00000009af7cbd0: at powerpc_interrupt+0x268
>=20
> timercb does:
>=20
>        now =3D sbinuptime();
> . . .
>        handleevents(now, 0);
>=20
> That in turn leads to:
>=20
>        if (now >=3D state->nextcallopt || now >=3D state->nextcall) {
>                state->nextcall =3D state->nextcallopt =3D SBT_MAX;
>                callout_process(now);
>       }
>=20
> Which leads to:
>=20
>                        if (tmp->c_time <=3D now) {
> . . .
>                                if (tmp->c_iflags & CALLOUT_DIRECT) {
> . . .
>                                        softclock_call_cc(tmp, cc,
> #ifdef CALLOUT_PROFILING
>                                            &mpcalls_dir, =
&lockcalls_dir, NULL,
> #endif
>                                            1);
>=20
> So softclock_call_cc and sleepq_timeout do not get a copy
> of timercb 's now value. (I will refer to this now value
> in contexts for which it is not accessible.)
>=20
> sleepq_timeout uses:
>=20
> td->td_sleeptimo > sbinuptime()
>=20
> to indicate to not do something like:
>=20
> sleepq_resume_thread(. . .)
>=20
> but also does not use sleepq_set_timeout_sbt to
> set up another sleepq_timeout callout or do some
> other such under this condition. (So a what is
> effectively a no-op ends up the last activity
> before the thread is stuck asleep.)
>=20
> (I will continue to write sbinuptime() to reference
> the value used in that test.)
>=20
> With multiple processors, it is observed that,
> despite sbinuptime() being physically later:
>=20
> sbinuptime() < now
>=20
> does sometimes happen for the code involved,
> for example:
>=20
> sbinuptime(): 0x11abf13bd142
> now         : 0x11accb5df419
>=20
> This is even though:
>=20
> tmp->c_time =3D=3D td->td_sleeptimo
>=20
> is observed. sbinuptime() < now sometimes leads
> to:
>=20
> sbinuptime() < tmp->c_time =3D=3D td->td_sleeptimo <=3D now
>=20
> for example the following happened:
>=20
> sbinuptime(): 0x11abf13bd142
> tmp->c_time : 0x11ac2096af71 [=3D=3D td->td_sleeptimo]
> now         : 0x11accb5df419
>=20
> As I understand, keeping the various
> powerpc64 CPUs' sbinuptime() values fully
> synchronized is unlikely so the problem would
> still exist even if "closer but not identical"
> across CPUs was achieved.

The comments about various CPUs having somewhat
mismatched sbinuptime() values does not seem to
apply to timercb vs. softclock_call_cc in:

0xe00000009af7c7d0: at softclock_call_cc+0x234
0xe00000009af7c910: at callout_process+0x2e0
0xe00000009af7c9f0: at handleevents+0x22c
0xe00000009af7caa0: at timercb+0x340

But that means that sbinuptime() values are
going backwards on the same CPU during that
call chain's activity! Ouch.

> [The testing context here is an old PowerMac G5
> 4-core (system total), which actually involves
> 2 sockets, 2 cores per socket.]
>=20
> Overall this structure does not seemed to be
> designed to handle variations in sbinuptime()
> values across CPUs.
>=20
>=20
> The sleepq_timeout source code (before my
> limited modifications for reporting more):
>=20
> static void
> sleepq_timeout(void *arg)
> {
>        struct sleepqueue_chain *sc __unused;
>        struct sleepqueue *sq;
>        struct thread *td;
>        void *wchan;
>        int wakeup_swapper;
>=20
>        td =3D arg;
>        wakeup_swapper =3D 0;
>        CTR3(KTR_PROC, "sleepq_timeout: thread %p (pid %ld, %s)",
>            (void *)td, (long)td->td_proc->p_pid, (void *)td->td_name);
>=20
>        thread_lock(td);
>=20
>        if (td->td_sleeptimo > sbinuptime() || td->td_sleeptimo =3D=3D =
0) {
>                /*
>                 * The thread does not want a timeout (yet).
>                 */
>        } else if (TD_IS_SLEEPING(td) && TD_ON_SLEEPQ(td)) {
>                /*
>                 * See if the thread is asleep and get the wait
>                 * channel if it is.
>                 */
>                wchan =3D td->td_wchan;
>                sc =3D SC_LOOKUP(wchan);
>                THREAD_LOCKPTR_ASSERT(td, &sc->sc_lock);
>                sq =3D sleepq_lookup(wchan);
>                MPASS(sq !=3D NULL);
>                td->td_flags |=3D TDF_TIMEOUT;
>                wakeup_swapper =3D sleepq_resume_thread(sq, td, 0);
>        } else if (TD_ON_SLEEPQ(td)) {
>                /*
>                 * If the thread is on the SLEEPQ but isn't sleeping
>                 * yet, it can either be on another CPU in between
>                 * sleepq_add() and one of the sleepq_*wait*()
>                 * routines or it can be in sleepq_catch_signals().
>                 */
>                td->td_flags |=3D TDF_TIMEOUT;
>        }
>=20
>        thread_unlock(td);
>        if (wakeup_swapper)
>                kick_proc0();
> }
>=20
>=20
> I wonder if just not having:
>=20
> td->td_sleeptimo > sbinuptime() ||
>=20
> in the if (. . .) is appropriate for the powerpc64 context in
> use: presume callout_process 's tmp->c_time <=3D now is
> sufficient? (Vs: race issues?)
>=20
>=20
>=20
> Adjusted KTR_PROC output example ("show ktr /v" in ddb
> captured, so newest to oldest order, flags and such are
> in hex despite my not providing 0x prefixes):
>=20
> 922 (0xc00000000d12f000:cpu3) 151713214399 =
/usr/src/sys/kern/subr_sleepqueue.c.1027: sleepq_timeout thread not want =
timeout yet: thread 0xc00000000a8315a0 (pid 26, pmac_thermal) =
td_sleeptimo=3D11ac2096af71 sbinuptime=3D11abf13bd142
> 921 (0xc00000000d12f000:cpu3) 151713214374 =
/usr/src/sys/kern/subr_sleepqueue.c.1016: sleepq_timeout: thread =
0xc00000000a8315a0 (pid 26, pmac_thermal)
> 920 (0xc00000000d12f000:cpu3) 151713214337 =
/usr/src/sys/kern/kern_timeout.c.503: callout_process to call =
softclock_clock_cc: thread 0xc00000000a8315a0 c_time=3D11ac2096af71 =
now=3D11accb5df419
> 919 (0xc00000000a8315a0:cpu3) 151686051357 =
/usr/src/sys/kern/kern_synch.c.435: mi_switch: old thread 100078 =
(td_sched 0xc00000000a831ad8, pid 26, pmac_thermal)
> 918 (0xc00000000a8315a0:cpu3) 151686051310 =
/usr/src/sys/kern/subr_sleepqueue.c.409: sleepq_set_timeout_sbt: =
sbt=3Dfffffed8 pr=3D0 flags=3D100 td_sleeptimo=3D11ac2096af71 =
prec=3Dfffffed flags=3D501
> 917 (0xc00000000a8315a0:cpu3) 151686051306 =
/usr/src/sys/kern/subr_sleepqueue.c.407: sleepq_set_timeout_sbt =
installing sleepq_timeout: thread 0xc00000000a8315a0 (pid 26, =
pmac_thermal)
> 916 (0xc00000000a8315a0:cpu3) 151686051267 =
/usr/src/sys/kern/kern_synch.c.180: sleep: thread 100078 (pid 26, =
pmac_thermal) on pmac_therm (0xc0000000015082c3)
> 915 (0xc00000000a8315a0:cpu3) 151686051162 =
/usr/src/sys/kern/subr_sleepqueue.c.631: sleepq resume: thread =
0xc00000000a8315a0 (pid 26, pmac_thermal)
> 914 (0xc00000000a8315a0:cpu3) 151686051144 =
/usr/src/sys/kern/kern_synch.c.445: mi_switch: new thread 100078 =
(td_sched 0xc00000000a831ad8, pid 26, pmac_thermal)
> 913 (0xc000000001f6e000:cpu0) 151686050654 =
/usr/src/sys/kern/subr_sleepqueue.c.837: sleepq_wakeup: thread =
0xc00000000a8315a0 (pid 26, pmac_thermal)
> 912 (0xc000000001f6e000:cpu0) 151686050634 =
/usr/src/sys/kern/subr_sleepqueue.c.989: sleepq_remove_matching calling =
sleepq_resume_thread: thread 0xc00000000a8315a0 (pid 26, pmac_thermal)
> 911 (0xc00000000a8315a0:cpu3) 151684339557 =
/usr/src/sys/kern/kern_synch.c.435: mi_switch: old thread 100078 =
(td_sched 0xc00000000a831ad8, pid 26, pmac_thermal)
> 910 (0xc00000000a8315a0:cpu3) 151684339525 =
/usr/src/sys/kern/subr_sleepqueue.c.409: sleepq_set_timeout_sbt: =
sbt=3Dcccccbe0 pr=3D0 flags=3D100 td_sleeptimo=3D11abe0139d4d =
prec=3Dcccccbe flags=3D501
> 909 (0xc00000000a8315a0:cpu3) 151684339517 =
/usr/src/sys/kern/subr_sleepqueue.c.407: sleepq_set_timeout_sbt =
installing sleepq_timeout: thread 0xc00000000a8315a0 (pid 26, =
pmac_thermal)
> 908 (0xc00000000a8315a0:cpu3) 151684339498 =
/usr/src/sys/kern/kern_synch.c.180: sleep: thread 100078 (pid 26, =
pmac_thermal) on smu (0xe000000087fd1670)
> 907 (0xc00000000a8315a0:cpu3) 151684339326 =
/usr/src/sys/kern/subr_sleepqueue.c.631: sleepq resume: thread =
0xc00000000a8315a0 (pid 26, pmac_thermal)
> 906 (0xc00000000a8315a0:cpu3) 151684339313 =
/usr/src/sys/kern/kern_synch.c.445: mi_switch: new thread 100078 =
(td_sched 0xc00000000a831ad8, pid 26, pmac_thermal)
> 905 (0xc000000001f6e000:cpu3) 151684338924 =
/usr/src/sys/kern/subr_sleepqueue.c.837: sleepq_wakeup: thread =
0xc00000000a8315a0 (pid 26, pmac_thermal)
> 904 (0xc000000001f6e000:cpu3) 151684338918 =
/usr/src/sys/kern/subr_sleepqueue.c.989: sleepq_remove_matching calling =
sleepq_resume_thread: thread 0xc00000000a8315a0 (pid 26, pmac_thermal)
> 903 (0xc00000000a8315a0:cpu3) 151682628069 =
/usr/src/sys/kern/kern_synch.c.435: mi_switch: old thread 100078 =
(td_sched 0xc00000000a831ad8, pid 26, pmac_thermal)
> 902 (0xc00000000a8315a0:cpu3) 151682628004 =
/usr/src/sys/kern/subr_sleepqueue.c.409: sleepq_set_timeout_sbt: =
sbt=3Dcccccbe0 pr=3D0 flags=3D100 td_sleeptimo=3D11abd3054758 =
prec=3Dcccccbe flags=3D501
> 901 (0xc00000000a8315a0:cpu3) 151682628000 =
/usr/src/sys/kern/subr_sleepqueue.c.407: sleepq_set_timeout_sbt =
installing sleepq_timeout: thread 0xc00000000a8315a0 (pid 26, =
pmac_thermal)
> 900 (0xc00000000a8315a0:cpu3) 151682627960 =
/usr/src/sys/kern/kern_synch.c.180: sleep: thread 100078 (pid 26, =
pmac_thermal) on smu (0xe000000087fd1670)
> 899 (0xc00000000a8315a0:cpu3) 151682627706 =
/usr/src/sys/kern/subr_sleepqueue.c.631: sleepq resume: thread =
0xc00000000a8315a0 (pid 26, pmac_thermal)
> 898 (0xc00000000a8315a0:cpu3) 151682627683 =
/usr/src/sys/kern/kern_synch.c.445: mi_switch: new thread 100078 =
(td_sched 0xc00000000a831ad8, pid 26, pmac_thermal)
> 897 (0xc000000001f6e000:cpu0) 151682627254 =
/usr/src/sys/kern/subr_sleepqueue.c.837: sleepq_wakeup: thread =
0xc00000000a8315a0 (pid 26, pmac_thermal)
> 896 (0xc000000001f6e000:cpu0) 151682627242 =
/usr/src/sys/kern/subr_sleepqueue.c.989: sleepq_remove_matching calling =
sleepq_resume_thread: thread 0xc00000000a8315a0 (pid 26, pmac_thermal)
> 895 (0xc00000000a8315a0:cpu0) 151680915222 =
/usr/src/sys/kern/kern_synch.c.435: mi_switch: old thread 100078 =
(td_sched 0xc00000000a831ad8, pid 26, pmac_thermal)
> 894 (0xc00000000a8315a0:cpu0) 151680915139 =
/usr/src/sys/kern/subr_sleepqueue.c.409: sleepq_set_timeout_sbt: =
sbt=3Dcccccbe0 pr=3D0 flags=3D100 td_sleeptimo=3D11abc5f6f163 =
prec=3Dcccccbe flags=3D501
> 893 (0xc00000000a8315a0:cpu0) 151680915133 =
/usr/src/sys/kern/subr_sleepqueue.c.407: sleepq_set_timeout_sbt =
installing sleepq_timeout: thread 0xc00000000a8315a0 (pid 26, =
pmac_thermal)
> 892 (0xc00000000a8315a0:cpu0) 151680915085 =
/usr/src/sys/kern/kern_synch.c.180: sleep: thread 100078 (pid 26, =
pmac_thermal) on smu (0xe000000087fd1670)
> 891 (0xc00000000a8315a0:cpu0) 151680914811 =
/usr/src/sys/kern/subr_sleepqueue.c.631: sleepq resume: thread =
0xc00000000a8315a0 (pid 26, pmac_thermal)
> 890 (0xc00000000a8315a0:cpu0) 151680914784 =
/usr/src/sys/kern/kern_synch.c.445: mi_switch: new thread 100078 =
(td_sched 0xc00000000a831ad8, pid 26, pmac_thermal)
> 889 (0xc000000001f6e000:cpu2) 151680914304 =
/usr/src/sys/kern/subr_sleepqueue.c.837: sleepq_wakeup: thread =
0xc00000000a8315a0 (pid 26, pmac_thermal)
> 888 (0xc000000001f6e000:cpu2) 151680914284 =
/usr/src/sys/kern/subr_sleepqueue.c.989: sleepq_remove_matching calling =
sleepq_resume_thread: thread 0xc00000000a8315a0 (pid 26, pmac_thermal)
> . . .




=3D=3D=3D
Mark Millard
marklmi at yahoo.com
( dsl-only.net went
away in early 2018-Mar)




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4DFDC776-BE0E-4952-8414-6B7ACFEC815B>