Hey gang, although Intel's document seems to claim that they tested
proper operation of pause I'd like people with non-Intel processors
to verify that it actually works.  Please compile the attached test
program and run it.  The output should look like this:
> ./pt
Testing PAUSE instruction:
Register esp changed: 0xbfbff9fc -> 0xbfbff9c0

If you get a signal or any of the other registers change their value,
please let me know.  I've tested this on a Pentium III mobile, a K6-II,
and an Athlon.  The program cmopiles ok on both stable and current.

-----FW: <[EMAIL PROTECTED]>-----

Date: Tue, 21 May 2002 15:26:36 -0700 (PDT)
Sender: [EMAIL PROTECTED]
From: John Baldwin <[EMAIL PROTECTED]>
To: [EMAIL PROTECTED], [EMAIL PROTECTED]
Subject: cvs commit: src/sys/kern kern_mutex.c

jhb         2002/05/21 15:26:36 PDT

  Modified files:
    sys/kern             kern_mutex.c 
  Log:
  Add appropriate IA32 "pause" instructions to improve performanec on
  Pentium 4's and newer IA32 processors.  The "pause" instruction has been
  verified by Intel to be a NOP on all currently existing IA32 processors
  prior to the Pentium 4.
  
  Revision  Changes    Path
  1.95      +17 -1     src/sys/kern/kern_mutex.c

--------------End of forwarded message-------------------------

-- 

John Baldwin <[EMAIL PROTECTED]>  <><  http://www.FreeBSD.org/~jhb/
"Power Users Use the Power to Serve!"  -  http://www.FreeBSD.org/
/*
 * Simple program to see if the new IA32 PAUSE instruction works properly.
 * We test two different things: 1) that we don't get an illegal instruction
 * fault, and 2) that no registers change state.
 */

#include <sys/types.h>
#include <stdio.h>

#define NUM_SEGREGS     6
#define NUM_REGS        15

#define PUSH_REGS                       \
        "       pushf ;\n"              \
        "       pusha ;\n"              \
        "       push %cs ;\n"           \
        "       push %ds ;\n"           \
        "       push %es ;\n"           \
        "       push %fs ;\n"           \
        "       push %gs ;\n"           \
        "       push %ss ;\n"

const char *register_names[NUM_REGS] = {
        "ss", "gs", "fs", "es", "ds", "cs",
        "edi", "esi", "ebp", "esp", "ebx", "edx", "ecx", "eax",
        "eflags"
};

struct register_set {
        register_t      r_regs[NUM_REGS];
/*
        register_t      r_ss;
        register_t      r_gs;
        register_t      r_fs;
        register_t      r_es;
        register_t      r_ds;
        register_t      r_cs;
        register_t      r_edi;
        register_t      r_esi;
        register_t      r_ebp;
        register_t      r_isp;
        register_t      r_ebx;
        register_t      r_edx;
        register_t      r_ecx;
        register_t      r_eax;
        register_t      r_eflags;
 */
};

void
compare_registers(struct register_set after, struct register_set before)
{
        int i;

        for (i = 0; i < NUM_SEGREGS; i++) {
                before.r_regs[i] &= 0xffff;
                after.r_regs[i] &= 0xffff;
        }
        for (i = 0; i < NUM_REGS; i++)
                if (before.r_regs[i] != after.r_regs[i])
                        printf("Register %s changed: %#x -> %#x\n",
                            register_names[i], before.r_regs[i],
                            after.r_regs[i]);
}

void
test_pause(void)
{
        __asm __volatile(
        "       mov $10,%ecx ;\n"
        PUSH_REGS
        "       pause ;\n"
        PUSH_REGS
        "       call compare_registers ;\n"
        "       addl $0x78,%esp ;\n");
}

int
main(int ac, char **av)
{

        printf("Testing PAUSE instruction:\n");
        test_pause();
        return (0);
}

Reply via email to