summaryrefslogtreecommitdiffstats
path: root/sys/i386/include/pcpu.h
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>2007-02-06 16:21:09 +0000
committerbde <bde@FreeBSD.org>2007-02-06 16:21:09 +0000
commita1801d3dbe17947c0d798bc06538505638334150 (patch)
tree0df8af938166f2119109eb564d15a22d970cbc43 /sys/i386/include/pcpu.h
parenta7eaaf4149d85508b0c5cfb739ffae169cdb3a5b (diff)
downloadFreeBSD-src-a1801d3dbe17947c0d798bc06538505638334150.zip
FreeBSD-src-a1801d3dbe17947c0d798bc06538505638334150.tar.gz
Simplified PCPU_GET() and PCPU_SET(). We must copy through a temporary
variable to avoid invalid constraints in dead code. Use an array of u_char's (inside a struct) instead of a char/short/int/long variable so that the variable and its accesses can be spelled in the same way in all cases and code doesn't need to be cloned just to hold the spelling differences. Fixed strict-aliasing errors in PCPU_SET() and in the amd64 PCPU_GET(). Cast to (void *) as in rev.1.37 of the i386 version where the errors were fixed for the i386 PCPU_GET() only. It would be more correct to copy to and from the temp. variable using memcpy(), but then an ifdef tangle would be required to ensure using the builtin memcpy(). We depend on fairly aggressive optimization to put the temp. variable only in a register despite it being copied using *(type *)(void *)&anothertype and could depend on this when using memcpy() too. This seems to work right even for -O0, but the -O0 case has not been completely tested. This change gives identical object code for all object files in LINT on amd64 (except for one file with a __TIME__ stamp). For LINT on i386 it gives unimportant differences in instruction order and padding in a few object files. This was only tested for -O. This change (actually a previous version of it) gives the following reductions in the number of object files in LINT that fail to compile with -O2 but without the -fno-strict-aliasing kludge: - amd64: 29 (down from 211) - i386: 36 (down from 47) gcc-3.4.6 actually allows the invalid constraints that result from not using the temp. variable, at least with -O[1-2], but gcc-3.3.3 crashes on them and I don't want to depend on compiler bugs.
Diffstat (limited to 'sys/i386/include/pcpu.h')
-rw-r--r--sys/i386/include/pcpu.h54
1 files changed, 18 insertions, 36 deletions
diff --git a/sys/i386/include/pcpu.h b/sys/i386/include/pcpu.h
index 1427495..e624df6 100644
--- a/sys/i386/include/pcpu.h
+++ b/sys/i386/include/pcpu.h
@@ -100,24 +100,15 @@ extern struct pcpu *pcpup;
#define __PCPU_GET(name) __extension__ ({ \
__pcpu_type(name) __result; \
\
- if (sizeof(__result) == 1) { \
- u_char __b; \
- __asm __volatile("movb %%fs:%1,%0" \
- : "=r" (__b) \
- : "m" (*(u_char *)(__pcpu_offset(name)))); \
- __result = *(__pcpu_type(name) *)(void *)&__b; \
- } else if (sizeof(__result) == 2) { \
- u_short __w; \
- __asm __volatile("movw %%fs:%1,%0" \
- : "=r" (__w) \
- : "m" (*(u_short *)(__pcpu_offset(name)))); \
- __result = *(__pcpu_type(name) *)(void *)&__w; \
- } else if (sizeof(__result) == 4) { \
- u_int __i; \
- __asm __volatile("movl %%fs:%1,%0" \
- : "=r" (__i) \
- : "m" (*(u_int *)(__pcpu_offset(name)))); \
- __result = *(__pcpu_type(name) *)(void *)&__i; \
+ if (sizeof(__result) == 1 || sizeof(__result) == 2 || \
+ sizeof(__result) == 4) { \
+ struct __s { \
+ u_char __b[MIN(sizeof(__pcpu_type(name)), 4)]; \
+ } __s; \
+ __asm __volatile("mov %%fs:%1,%0" \
+ : "=r" (__s) \
+ : "m" (*(struct __s *)(__pcpu_offset(name)))); \
+ *(struct __s *)(void *)&__result = __s; \
} else { \
__result = *__PCPU_PTR(name); \
} \
@@ -131,24 +122,15 @@ extern struct pcpu *pcpup;
#define __PCPU_SET(name, val) { \
__pcpu_type(name) __val = (val); \
\
- if (sizeof(__val) == 1) { \
- u_char __b; \
- __b = *(u_char *)&__val; \
- __asm __volatile("movb %1,%%fs:%0" \
- : "=m" (*(u_char *)(__pcpu_offset(name))) \
- : "r" (__b)); \
- } else if (sizeof(__val) == 2) { \
- u_short __w; \
- __w = *(u_short *)&__val; \
- __asm __volatile("movw %1,%%fs:%0" \
- : "=m" (*(u_short *)(__pcpu_offset(name))) \
- : "r" (__w)); \
- } else if (sizeof(__val) == 4) { \
- u_int __i; \
- __i = *(u_int *)&__val; \
- __asm __volatile("movl %1,%%fs:%0" \
- : "=m" (*(u_int *)(__pcpu_offset(name))) \
- : "r" (__i)); \
+ if (sizeof(__val) == 1 || sizeof(__val) == 2 || \
+ sizeof(__val) == 4) { \
+ struct __s { \
+ u_char __b[MIN(sizeof(__pcpu_type(name)), 4)]; \
+ } __s; \
+ __s = *(struct __s *)(void *)&__val; \
+ __asm __volatile("mov %1,%%fs:%0" \
+ : "=m" (*(struct __s *)(__pcpu_offset(name))) \
+ : "r" (__s)); \
} else { \
*__PCPU_PTR(name) = __val; \
} \
OpenPOWER on IntegriCloud