svn commit: r283331 - head/sys/arm/arm

John Baldwin jhb at freebsd.org
Mon May 25 14:58:07 UTC 2015


On Monday, May 25, 2015 01:21:48 PM Andrew Turner wrote:
> On Mon, 25 May 2015 07:23:28 -0400
> John Baldwin <jhb at freebsd.org> wrote:
> 
> > On Saturday, May 23, 2015 10:28:59 PM Andrew Turner wrote:
> > > Author: andrew
> > > Date: Sat May 23 22:28:59 2015
> > > New Revision: 283331
> > > URL: https://svnweb.freebsd.org/changeset/base/283331
> > > 
> > > Log:
> > >   Use the wait-for-event instruction to put the core we have just
> > > enabled to sleep while it waits to start scheduling. The boot core
> > > can then use the send-event instruction to wake the cores when they
> > > should enter the scheduler.
> > >   
> > >   MFC after:	1 week
> > > 
> > > Modified:
> > >   head/sys/arm/arm/mp_machdep.c
> > > 
> > > Modified: head/sys/arm/arm/mp_machdep.c
> > > ==============================================================================
> > > --- head/sys/arm/arm/mp_machdep.c	Sat May 23 21:58:41
> > > 2015	(r283330) +++ head/sys/arm/arm/mp_machdep.c	Sat
> > > May 23 22:28:59 2015	(r283331) @@ -185,8 +185,11 @@
> > > init_secondary(int cpu) atomic_add_rel_32(&mp_naps, 1);
> > >  
> > >  	/* Spin until the BSP releases the APs */
> > > -	while (!aps_ready)
> > > -		;
> > > +	while (!atomic_load_acq_int(&aps_ready)) {
> > > +#if __ARM_ARCH >= 7
> > > +		__asm __volatile("wfe");
> > > +#endif
> > > +	}
> > 
> > I don't know that this atomic load acquire is really changing
> > anything here?  Since aps_ready is volatile reading it should
> > already be "atomic" on each check around the loop.
> 
> It's also adding acquire semantics to ensure we don't
> incorrectly reorder memory operations across the call.

I think the _rel barrier on the update to mp_naps above probably
already does that, but ok.
 
> > >  	/* Initialize curthread */
> > >  	KASSERT(PCPU_GET(idlethread) != NULL, ("no idle thread"));
> > > @@ -353,6 +356,10 @@ release_aps(void *dummy __unused)
> > >  		arm_unmask_irq(i);
> > >  	}
> > >  	atomic_store_rel_int(&aps_ready, 1);
> > > +	/* Wake the other threads up */
> > > +#if __ARM_ARCH >= 7
> > > +	armv7_sev();
> > > +#endif
> > 
> > So I'm not at all familiar with these instructions or what they do,
> > but are the events level triggered?  In particular, is there any
> > sort of race where the sev might arrive in between the check of
> > aps_ready and the wfe on an AP?  (For example, if wfe/sev were
> > similar to using mwait on x86 for wfe and a memory write for sev,
> > x86 would require a call to monitor before doing a check of
> > aps_ready to handle the race like so:
> > 
> > 	while (!aps_ready) {
> > 		monitor(&aps_ready);
> > 		if (!aps_ready)
> > 			mwait();
> > 	}
> > 
> 
> The armv7_sev function includes a barrier to ensure any previous memory
> operations have been flushed to cache before we send the event. The sev
> instruction then sets the event register in every processor.
> 
> The wfe instruction will check this event register and, if it is unset,
> it the processor can then enter a low power mode. From my reading of
> the documentation, if an event has been signalled before executing the
> wfe then the instruction is a nop so will exit the loop as the new
> value of aps_ready will be visible on all processors.

Mmmm, does that mean then that you can (conceivably) lose the race the other
way where it "sees" ap_ready's update before it calls wfe and never calls
wfe to "harvest" the event from sev?  (In practice I think this is not
possible during boot as AP's can't get preempted and there is typically
a "long" time between AP's being signalled to start and start_aps being
set.  However, this would be a concern for use of wfe/sev for other use
cases such as for the cpu_idle hook perhaps?)

-- 
John Baldwin


More information about the svn-src-all mailing list