Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 5 Oct 2003 10:38:54 -0700 (PDT)
From:      Matthew Dillon <dillon@apollo.backplane.com>
To:        Don Bowman <don@sandvine.com>
Cc:        Kris Kennaway <kris@obsecurity.org>
Subject:   RE: Hyperthreading slowdown
Message-ID:  <200310051738.h95Hcslx052023@apollo.backplane.com>
References:  <FE045D4D9F7AED4CBFF1B3B813C85337035E39E5@mail.sandvine.com>

next in thread | previous in thread | raw e-mail | index | archive | help
:FWIW, if you set the machdep.cpu_idle_hlt=1, your power will
:go down considerably (our AC inlet power dropped 0.94A @ 110V).
:The performance will also go up considerably.
:
:HTT seems to get a lot of bad press on this list, and its due
:to this sysctl having the wrong default.

    Sheesh, nobody has fixed HLT's (minor) performance issues yet?  All
    it takes is something like this:

    i386/i386/machdep.c, cpu_idle():

    ...
    if (cpu_idle_hlt) {
	    disable_intr();
	    PCPU_SET(amhalted, 1);
	    if (sched_runnable()) {
		    enable_intr();
	    } else {
		    /*
		     * we must absolutely guarentee that hlt is the
		     * absolute next instruction after sti or we 
		     * introduce a timing window.
		     */
		    __asm __volatile("sti; hlt");
	    }
	    PCPU_SET(amhalted, 0);
    }

    And then somewhere in the scheduler's wakeup code:

    ...
    targetcpu = td->td_lastcpu;
    if (targetcpu >= 0 && PCPUFORCPUID(targetcpu)->amhalted) {
	PCPUFORCPUID(targetcpu)->amhalted = 0; /* ignore cache coherency race*/
	... queue async IPI to wakeup targetcpu ...
    }

    So if the target thread wants to be woken up on a particular cpu
    (cpu affinity), then we IPI that cpu.  If the target thread doesn't
    care we let the clock interrupt deal with it.

    I'll leave it others to figure out how to get the per-cpu structure
    pointer for a particular cpu and where to put the code, but basically
    that is all you have to do and then you can make cpu_idle_hlt the
    default, saving all the headaches.

    One could even send the IPI passively.. that is, if the APIC is already
    busy you just give up.   If the APIC isn't busy you queue the IPI and
    return.  And if you are worried about sleep/wakeup ping-ponging between
    two processes becoming non-optimal, just have the idle loop loop for a 
    few microseconds before it actually HLT's.  It's a no-brainer.

						-Matt



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