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); }