blob: 5b46c7ed809bff94a2a732148139d2c59c689065 [file] [log] [blame]
sewardjb4112022007-11-09 22:49:28 +00001
2#include <pthread.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <assert.h>
6
7/* Simple test program, no race. Parent and child both modify x and
8 use the hardware bus lock (implicitly, since XCHG r,m on x86/amd64
9 does not require an explicit LOCK prefix.). */
10
11#undef PLAT_x86_linux
12#undef PLAT_amd64_linux
13#undef PLAT_ppc32_linux
14#undef PLAT_ppc64_linux
15#undef PLAT_ppc32_aix5
16#undef PLAT_ppc64_aix5
17
18#if !defined(_AIX) && defined(__i386__)
19# define PLAT_x86_linux 1
20#elif !defined(_AIX) && defined(__x86_64__)
21# define PLAT_amd64_linux 1
22#elif !defined(_AIX) && defined(__powerpc__) && !defined(__powerpc64__)
23# define PLAT_ppc32_linux 1
24#elif !defined(_AIX) && defined(__powerpc__) && defined(__powerpc64__)
25# define PLAT_ppc64_linux 1
26#elif defined(_AIX) && defined(__64BIT__)
27# define PLAT_ppc64_aix5 1
28#elif defined(_AIX) && !defined(__64BIT__)
29# define PLAT_ppc32_aix5 1
30#endif
31
32
33#if defined(PLAT_amd64_linux) || defined(PLAT_x86_linux)
34# define XCHG_M_R(_addr,_lval) \
35 __asm__ __volatile__( \
36 "xchgl %0, %1" \
37 : /*out*/ "+r"(_lval) \
38 : /*in*/ "m"(_addr) \
39 : "memory", "cc" \
40 )
41# define XCHG_M_R_with_redundant_LOCK(_addr,_lval) \
42 __asm__ __volatile__( \
43 "lock xchgl %0, %1" \
44 : /*out*/ "+r"(_lval) \
45 : /*in*/ "m"(_addr) \
46 : "memory", "cc" \
47 )
48#else
49# define XCHG_M_R(_addr,_lval) \
50 do { int tmp = *(int*)(& _addr); \
51 *(int*)(& _addr) = (_lval); \
52 _lval = tmp; \
53 } while (0)
54# define XCHG_M_R_with_redundant_LOCK(_addr,_lval) \
55 XCHG_M_R(_addr,_lval)
56#endif
57
58int x = 0;
59
60void* child_fn ( void* arg )
61{
62 int v = 12345;
63 XCHG_M_R_with_redundant_LOCK(x, v);
64 assert(v == 0 || v == 6789);
65 return NULL;
66}
67
68int main ( void )
69{
70 int v = 6789;
71 pthread_t child;
72
73 if (pthread_create(&child, NULL, child_fn, NULL)) {
74 perror("pthread_create");
75 exit(1);
76 }
77
78 XCHG_M_R(x, v);
79 assert(v == 0 || v == 12345);
80
81 if (pthread_join(child, NULL)) {
82 perror("pthread join");
83 exit(1);
84 }
85
86 if (v == 0 || v == 12345)
87 printf("success\n");
88 else
89 printf("failure\n");
90
91 return v;
92}