1b411202f9ff33a587558e2e836626bc7eb9db183sewardj
2b411202f9ff33a587558e2e836626bc7eb9db183sewardj#include <pthread.h>
3b411202f9ff33a587558e2e836626bc7eb9db183sewardj#include <stdio.h>
4b411202f9ff33a587558e2e836626bc7eb9db183sewardj#include <stdlib.h>
5b411202f9ff33a587558e2e836626bc7eb9db183sewardj
6b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* Simple test program, no race.  Parent and child both modify x and
7b411202f9ff33a587558e2e836626bc7eb9db183sewardj   use the hardware bus lock. */
8b411202f9ff33a587558e2e836626bc7eb9db183sewardj
98777f7308785b4eb67898670e29ecdde42dec9dfsewardj#undef PLAT_x86_darwin
108777f7308785b4eb67898670e29ecdde42dec9dfsewardj#undef PLAT_amd64_darwin
11b411202f9ff33a587558e2e836626bc7eb9db183sewardj#undef PLAT_x86_linux
12b411202f9ff33a587558e2e836626bc7eb9db183sewardj#undef PLAT_amd64_linux
13b411202f9ff33a587558e2e836626bc7eb9db183sewardj#undef PLAT_ppc32_linux
14b411202f9ff33a587558e2e836626bc7eb9db183sewardj#undef PLAT_ppc64_linux
158777f7308785b4eb67898670e29ecdde42dec9dfsewardj#undef PLAT_arm_linux
1623ed6302e96eb905ef25d6c39db600e17e5f341fsewardj#undef PLAT_arm64_linux
17b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#undef PLAT_s390x_linux
185db15403e889d4db339b342bc2a824ef0bfaa654sewardj#undef PLAT_mips32_linux
19112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#undef PLAT_tilegx_linux
208eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#undef PLAT_x86_solaris
218eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#undef PLAT_amd64_solaris
22b411202f9ff33a587558e2e836626bc7eb9db183sewardj
236e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#if defined(__APPLE__) && defined(__i386__)
248777f7308785b4eb67898670e29ecdde42dec9dfsewardj#  define PLAT_x86_darwin 1
258777f7308785b4eb67898670e29ecdde42dec9dfsewardj#elif defined(__APPLE__) && defined(__x86_64__)
268777f7308785b4eb67898670e29ecdde42dec9dfsewardj#  define PLAT_amd64_darwin 1
278777f7308785b4eb67898670e29ecdde42dec9dfsewardj#elif defined(__linux__) && defined(__i386__)
28b411202f9ff33a587558e2e836626bc7eb9db183sewardj#  define PLAT_x86_linux 1
298777f7308785b4eb67898670e29ecdde42dec9dfsewardj#elif defined(__linux__) && defined(__x86_64__)
30b411202f9ff33a587558e2e836626bc7eb9db183sewardj#  define PLAT_amd64_linux 1
318777f7308785b4eb67898670e29ecdde42dec9dfsewardj#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
32b411202f9ff33a587558e2e836626bc7eb9db183sewardj#  define PLAT_ppc32_linux 1
338777f7308785b4eb67898670e29ecdde42dec9dfsewardj#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__)
34b411202f9ff33a587558e2e836626bc7eb9db183sewardj#  define PLAT_ppc64_linux 1
3523ed6302e96eb905ef25d6c39db600e17e5f341fsewardj#elif defined(__linux__) && defined(__arm__) && !defined(__aarch64__)
368777f7308785b4eb67898670e29ecdde42dec9dfsewardj#  define PLAT_arm_linux 1
3723ed6302e96eb905ef25d6c39db600e17e5f341fsewardj#elif defined(__linux__) && defined(__aarch64__) && !defined(__arm__)
3823ed6302e96eb905ef25d6c39db600e17e5f341fsewardj#  define PLAT_arm64_linux 1
39b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#elif defined(__linux__) && defined(__s390x__)
40b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  define PLAT_s390x_linux 1
415db15403e889d4db339b342bc2a824ef0bfaa654sewardj#elif defined(__linux__) && defined(__mips__)
425db15403e889d4db339b342bc2a824ef0bfaa654sewardj#  define PLAT_mips32_linux 1
43112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#elif defined(__linux__) && defined(__tilegx__)
44112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#  define PLAT_tilegx_linux 1
458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#elif defined(__sun__) && defined(__i386__)
468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  define PLAT_x86_solaris 1
478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#elif defined(__sun__) && defined(__x86_64__)
488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  define PLAT_amd64_solaris 1
49b411202f9ff33a587558e2e836626bc7eb9db183sewardj#endif
50b411202f9ff33a587558e2e836626bc7eb9db183sewardj
51f5b5f84a476b54c239a5179de49728b6fa8f3b85sewardj#if defined(PLAT_amd64_linux) || defined(PLAT_x86_linux) \
528eb8bab992e3998c33770b0cdb16059a8b918a06sewardj    || defined(PLAT_amd64_darwin) || defined(PLAT_x86_darwin) \
538eb8bab992e3998c33770b0cdb16059a8b918a06sewardj    || defined(PLAT_amd64_solaris) || defined(PLAT_x86_solaris)
542ee33955b80812a8f31ec06a0430103b50aeca8csewardj#  define INC(_lval,_lqual) \
55b411202f9ff33a587558e2e836626bc7eb9db183sewardj      __asm__ __volatile__ ( \
56b411202f9ff33a587558e2e836626bc7eb9db183sewardj      "lock ; incl (%0)" : /*out*/ : /*in*/"r"(&(_lval)) : "memory", "cc" )
576e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#elif defined(PLAT_ppc32_linux) || defined(PLAT_ppc64_linux)
582ee33955b80812a8f31ec06a0430103b50aeca8csewardj#  define INC(_lval,_lqual)               \
59b411202f9ff33a587558e2e836626bc7eb9db183sewardj   __asm__ __volatile__(                  \
60d12c4a53875f9280323784227b0af727c7991966sewardj      "1:\n"                              \
61b411202f9ff33a587558e2e836626bc7eb9db183sewardj      "        lwarx 15,0,%0\n"           \
62b411202f9ff33a587558e2e836626bc7eb9db183sewardj      "        addi 15,15,1\n"            \
63b411202f9ff33a587558e2e836626bc7eb9db183sewardj      "        stwcx. 15,0,%0\n"          \
64d12c4a53875f9280323784227b0af727c7991966sewardj      "        bne- 1b\n"                 \
65b411202f9ff33a587558e2e836626bc7eb9db183sewardj      : /*out*/ : /*in*/ "b"(&(_lval))    \
66b411202f9ff33a587558e2e836626bc7eb9db183sewardj      : /*trash*/ "r15", "cr0", "memory"  \
67b411202f9ff33a587558e2e836626bc7eb9db183sewardj   )
688777f7308785b4eb67898670e29ecdde42dec9dfsewardj#elif defined(PLAT_arm_linux)
698777f7308785b4eb67898670e29ecdde42dec9dfsewardj#  define INC(_lval,_lqual) \
708777f7308785b4eb67898670e29ecdde42dec9dfsewardj  __asm__ __volatile__( \
71d12c4a53875f9280323784227b0af727c7991966sewardj      "1:\n"                                 \
728777f7308785b4eb67898670e29ecdde42dec9dfsewardj      "        ldrex r8, [%0, #0]\n"         \
738777f7308785b4eb67898670e29ecdde42dec9dfsewardj      "        add   r8, r8, #1\n"           \
748777f7308785b4eb67898670e29ecdde42dec9dfsewardj      "        strex r9, r8, [%0, #0]\n"     \
758777f7308785b4eb67898670e29ecdde42dec9dfsewardj      "        cmp   r9, #0\n"               \
76d12c4a53875f9280323784227b0af727c7991966sewardj      "        bne   1b\n"                   \
778777f7308785b4eb67898670e29ecdde42dec9dfsewardj      : /*out*/ : /*in*/ "r"(&(_lval))       \
788777f7308785b4eb67898670e29ecdde42dec9dfsewardj      : /*trash*/ "r8", "r9", "cc", "memory" \
798777f7308785b4eb67898670e29ecdde42dec9dfsewardj  );
8023ed6302e96eb905ef25d6c39db600e17e5f341fsewardj#elif defined(PLAT_arm64_linux)
8123ed6302e96eb905ef25d6c39db600e17e5f341fsewardj#  define INC(_lval,_lqual) \
8223ed6302e96eb905ef25d6c39db600e17e5f341fsewardj  __asm__ __volatile__( \
8323ed6302e96eb905ef25d6c39db600e17e5f341fsewardj      "1:\n"                                 \
8423ed6302e96eb905ef25d6c39db600e17e5f341fsewardj      "        ldxr  w8, [%0, #0]\n"         \
8523ed6302e96eb905ef25d6c39db600e17e5f341fsewardj      "        add   w8, w8, #1\n"           \
8623ed6302e96eb905ef25d6c39db600e17e5f341fsewardj      "        stxr  w9, w8, [%0, #0]\n"     \
8723ed6302e96eb905ef25d6c39db600e17e5f341fsewardj      "        cmp   w9, #0\n"               \
8823ed6302e96eb905ef25d6c39db600e17e5f341fsewardj      "        bne   1b\n"                   \
8923ed6302e96eb905ef25d6c39db600e17e5f341fsewardj      : /*out*/ : /*in*/ "r"(&(_lval))       \
9023ed6302e96eb905ef25d6c39db600e17e5f341fsewardj      : /*trash*/ "x8", "x9", "cc", "memory" \
9123ed6302e96eb905ef25d6c39db600e17e5f341fsewardj  );
92b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#elif defined(PLAT_s390x_linux)
93b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  define INC(_lval,_lqual) \
94b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   __asm__ __volatile__( \
95b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      "1: l     0,%0\n"                            \
96b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      "   lr    1,0\n"                             \
97b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      "   ahi   1,1\n"                             \
98b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      "   cs    0,1,%0\n"                          \
99b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      "   jl    1b\n"                              \
100b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      : "+m" (_lval) :: "cc", "1","2" \
101b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   )
1025db15403e889d4db339b342bc2a824ef0bfaa654sewardj#elif defined(PLAT_mips32_linux)
1035db15403e889d4db339b342bc2a824ef0bfaa654sewardj#  define INC(_lval,_lqual)                         \
1045db15403e889d4db339b342bc2a824ef0bfaa654sewardj     __asm__ __volatile__ (                         \
1055db15403e889d4db339b342bc2a824ef0bfaa654sewardj      "1:\n"                                        \
1065db15403e889d4db339b342bc2a824ef0bfaa654sewardj      "        move $8, %0\n"                       \
1075db15403e889d4db339b342bc2a824ef0bfaa654sewardj      "        ll $9, 0($8)\n"                      \
1085db15403e889d4db339b342bc2a824ef0bfaa654sewardj      "        addiu $9, $9, 1\n"                   \
1095db15403e889d4db339b342bc2a824ef0bfaa654sewardj      "        sc $9, 0($8)\n"                      \
1105db15403e889d4db339b342bc2a824ef0bfaa654sewardj      "        li $10, 1\n"                         \
1115db15403e889d4db339b342bc2a824ef0bfaa654sewardj      "        bne $9, $10, 1b\n"                   \
1125db15403e889d4db339b342bc2a824ef0bfaa654sewardj      "        nop\n"                               \
1135db15403e889d4db339b342bc2a824ef0bfaa654sewardj      : /*out*/ : /*in*/ "r"(&(_lval))              \
1145db15403e889d4db339b342bc2a824ef0bfaa654sewardj      : /*trash*/ "$8", "$9", "$10", "cc", "memory" \
1155db15403e889d4db339b342bc2a824ef0bfaa654sewardj   )
116112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#elif defined(PLAT_tilegx_linux)
117112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#  define INC(_lval,_lqual)                        \
118112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   if (sizeof(_lval) == 4)                         \
119112711afefcfcd43680c7c4aa8d38ef180e8811esewardj      __insn_fetchadd(&(_lval), 1);                \
120112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   else if(sizeof(_lval) == 8)                     \
121112711afefcfcd43680c7c4aa8d38ef180e8811esewardj      __insn_fetchadd(&(_lval), 1)
122b411202f9ff33a587558e2e836626bc7eb9db183sewardj#else
123b411202f9ff33a587558e2e836626bc7eb9db183sewardj#  error "Fix Me for this platform"
124b411202f9ff33a587558e2e836626bc7eb9db183sewardj#endif
125b411202f9ff33a587558e2e836626bc7eb9db183sewardj
126b411202f9ff33a587558e2e836626bc7eb9db183sewardj
127b411202f9ff33a587558e2e836626bc7eb9db183sewardjint x = 0;
128b411202f9ff33a587558e2e836626bc7eb9db183sewardj
129b411202f9ff33a587558e2e836626bc7eb9db183sewardjvoid* child_fn ( void* arg )
130b411202f9ff33a587558e2e836626bc7eb9db183sewardj{
1312ee33955b80812a8f31ec06a0430103b50aeca8csewardj   INC(x, "childfn");
132b411202f9ff33a587558e2e836626bc7eb9db183sewardj   return NULL;
133b411202f9ff33a587558e2e836626bc7eb9db183sewardj}
134b411202f9ff33a587558e2e836626bc7eb9db183sewardj
135b411202f9ff33a587558e2e836626bc7eb9db183sewardjint main ( void )
136b411202f9ff33a587558e2e836626bc7eb9db183sewardj{
137b411202f9ff33a587558e2e836626bc7eb9db183sewardj   pthread_t child;
138b411202f9ff33a587558e2e836626bc7eb9db183sewardj
139b411202f9ff33a587558e2e836626bc7eb9db183sewardj   if (pthread_create(&child, NULL, child_fn, NULL)) {
140b411202f9ff33a587558e2e836626bc7eb9db183sewardj      perror("pthread_create");
141b411202f9ff33a587558e2e836626bc7eb9db183sewardj      exit(1);
142b411202f9ff33a587558e2e836626bc7eb9db183sewardj   }
143b411202f9ff33a587558e2e836626bc7eb9db183sewardj
1442ee33955b80812a8f31ec06a0430103b50aeca8csewardj   INC(x, "main");
145b411202f9ff33a587558e2e836626bc7eb9db183sewardj
146b411202f9ff33a587558e2e836626bc7eb9db183sewardj   if (pthread_join(child, NULL)) {
147b411202f9ff33a587558e2e836626bc7eb9db183sewardj      perror("pthread join");
148b411202f9ff33a587558e2e836626bc7eb9db183sewardj      exit(1);
149b411202f9ff33a587558e2e836626bc7eb9db183sewardj   }
150b411202f9ff33a587558e2e836626bc7eb9db183sewardj
151b411202f9ff33a587558e2e836626bc7eb9db183sewardj   printf("x = %d\n", x);
152b411202f9ff33a587558e2e836626bc7eb9db183sewardj   return 0;
153b411202f9ff33a587558e2e836626bc7eb9db183sewardj}
154