1b411202f9ff33a587558e2e836626bc7eb9db183sewardj 2b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* FIXME: this is basically a bad test as it is scheduling- 3b411202f9ff33a587558e2e836626bc7eb9db183sewardj sensitive. Sometimes the output is: 4b411202f9ff33a587558e2e836626bc7eb9db183sewardj 5b411202f9ff33a587558e2e836626bc7eb9db183sewardj child: new value 6 6b411202f9ff33a587558e2e836626bc7eb9db183sewardj child: new value 10 7b411202f9ff33a587558e2e836626bc7eb9db183sewardj done, x = 10 8b411202f9ff33a587558e2e836626bc7eb9db183sewardj 9b411202f9ff33a587558e2e836626bc7eb9db183sewardj and sometimes 10b411202f9ff33a587558e2e836626bc7eb9db183sewardj 11b411202f9ff33a587558e2e836626bc7eb9db183sewardj child: new value 10 12b411202f9ff33a587558e2e836626bc7eb9db183sewardj done, x = 10 13b411202f9ff33a587558e2e836626bc7eb9db183sewardj*/ 14b411202f9ff33a587558e2e836626bc7eb9db183sewardj 15b411202f9ff33a587558e2e836626bc7eb9db183sewardj#include <pthread.h> 16b411202f9ff33a587558e2e836626bc7eb9db183sewardj#include <stdio.h> 17b411202f9ff33a587558e2e836626bc7eb9db183sewardj#include <stdlib.h> 18b411202f9ff33a587558e2e836626bc7eb9db183sewardj#include <unistd.h> 19b411202f9ff33a587558e2e836626bc7eb9db183sewardj 20b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* Simple test program, no race. Parent writes atomically to a counter 21b411202f9ff33a587558e2e836626bc7eb9db183sewardj whilst child reads it. When counter reaches a prearranged value, 22b411202f9ff33a587558e2e836626bc7eb9db183sewardj child joins back to parent. Parent (writer) uses hardware bus lock; 23b411202f9ff33a587558e2e836626bc7eb9db183sewardj child is only reading and so does not need to use a bus lock. */ 24b411202f9ff33a587558e2e836626bc7eb9db183sewardj 258777f7308785b4eb67898670e29ecdde42dec9dfsewardj#undef PLAT_x86_darwin 268777f7308785b4eb67898670e29ecdde42dec9dfsewardj#undef PLAT_amd64_darwin 27b411202f9ff33a587558e2e836626bc7eb9db183sewardj#undef PLAT_x86_linux 28b411202f9ff33a587558e2e836626bc7eb9db183sewardj#undef PLAT_amd64_linux 29b411202f9ff33a587558e2e836626bc7eb9db183sewardj#undef PLAT_ppc32_linux 30b411202f9ff33a587558e2e836626bc7eb9db183sewardj#undef PLAT_ppc64_linux 318777f7308785b4eb67898670e29ecdde42dec9dfsewardj#undef PLAT_arm_linux 3223ed6302e96eb905ef25d6c39db600e17e5f341fsewardj#undef PLAT_arm64_linux 33b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#undef PLAT_s390x_linux 345db15403e889d4db339b342bc2a824ef0bfaa654sewardj#undef PLAT_mips32_linux 35d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj#undef PLAT_mips64_linux 36112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#undef PLAT_tilegx_linux 378eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#undef PLAT_x86_solaris 388eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#undef PLAT_amd64_solaris 39b411202f9ff33a587558e2e836626bc7eb9db183sewardj 406e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#if defined(__APPLE__) && defined(__i386__) 418777f7308785b4eb67898670e29ecdde42dec9dfsewardj# define PLAT_x86_darwin 1 428777f7308785b4eb67898670e29ecdde42dec9dfsewardj#elif defined(__APPLE__) && defined(__x86_64__) 438777f7308785b4eb67898670e29ecdde42dec9dfsewardj# define PLAT_amd64_darwin 1 448777f7308785b4eb67898670e29ecdde42dec9dfsewardj#elif defined(__linux__) && defined(__i386__) 45b411202f9ff33a587558e2e836626bc7eb9db183sewardj# define PLAT_x86_linux 1 468777f7308785b4eb67898670e29ecdde42dec9dfsewardj#elif defined(__linux__) && defined(__x86_64__) 47b411202f9ff33a587558e2e836626bc7eb9db183sewardj# define PLAT_amd64_linux 1 488777f7308785b4eb67898670e29ecdde42dec9dfsewardj#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__) 49b411202f9ff33a587558e2e836626bc7eb9db183sewardj# define PLAT_ppc32_linux 1 508777f7308785b4eb67898670e29ecdde42dec9dfsewardj#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) 51b411202f9ff33a587558e2e836626bc7eb9db183sewardj# define PLAT_ppc64_linux 1 5223ed6302e96eb905ef25d6c39db600e17e5f341fsewardj#elif defined(__linux__) && defined(__arm__) && !defined(__aarch64__) 538777f7308785b4eb67898670e29ecdde42dec9dfsewardj# define PLAT_arm_linux 1 5423ed6302e96eb905ef25d6c39db600e17e5f341fsewardj#elif defined(__linux__) && defined(__aarch64__) && !defined(__arm__) 5523ed6302e96eb905ef25d6c39db600e17e5f341fsewardj# define PLAT_arm64_linux 1 56b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#elif defined(__linux__) && defined(__s390x__) 57b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj# define PLAT_s390x_linux 1 585db15403e889d4db339b342bc2a824ef0bfaa654sewardj#elif defined(__linux__) && defined(__mips__) 59d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj#if (__mips==64) 60d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj# define PLAT_mips64_linux 1 61d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj#else 625db15403e889d4db339b342bc2a824ef0bfaa654sewardj# define PLAT_mips32_linux 1 63b411202f9ff33a587558e2e836626bc7eb9db183sewardj#endif 64112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#elif defined(__linux__) && defined(__tilegx__) 65112711afefcfcd43680c7c4aa8d38ef180e8811esewardj# define PLAT_tilegx_linux 1 668eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#elif defined(__sun__) && defined(__i386__) 678eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# define PLAT_x86_solaris 1 688eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#elif defined(__sun__) && defined(__x86_64__) 698eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# define PLAT_amd64_solaris 1 70d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj#endif 71b411202f9ff33a587558e2e836626bc7eb9db183sewardj 728777f7308785b4eb67898670e29ecdde42dec9dfsewardj 73f5b5f84a476b54c239a5179de49728b6fa8f3b85sewardj#if defined(PLAT_amd64_linux) || defined(PLAT_x86_linux) \ 748eb8bab992e3998c33770b0cdb16059a8b918a06sewardj || defined(PLAT_amd64_darwin) || defined(PLAT_x86_darwin) \ 758eb8bab992e3998c33770b0cdb16059a8b918a06sewardj || defined(PLAT_amd64_solaris) || defined(PLAT_x86_solaris) 762ee33955b80812a8f31ec06a0430103b50aeca8csewardj# define INC(_lval,_lqual) \ 77b411202f9ff33a587558e2e836626bc7eb9db183sewardj __asm__ __volatile__ ( \ 78b411202f9ff33a587558e2e836626bc7eb9db183sewardj "lock ; incl (%0)" : /*out*/ : /*in*/"r"(&(_lval)) : "memory", "cc" ) 796e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#elif defined(PLAT_ppc32_linux) || defined(PLAT_ppc64_linux) 802ee33955b80812a8f31ec06a0430103b50aeca8csewardj# define INC(_lval,_lqual) \ 81b411202f9ff33a587558e2e836626bc7eb9db183sewardj __asm__ __volatile__( \ 82d12c4a53875f9280323784227b0af727c7991966sewardj "1:\n" \ 83b411202f9ff33a587558e2e836626bc7eb9db183sewardj " lwarx 15,0,%0\n" \ 84b411202f9ff33a587558e2e836626bc7eb9db183sewardj " addi 15,15,1\n" \ 85b411202f9ff33a587558e2e836626bc7eb9db183sewardj " stwcx. 15,0,%0\n" \ 86d12c4a53875f9280323784227b0af727c7991966sewardj " bne- 1b\n" \ 87b411202f9ff33a587558e2e836626bc7eb9db183sewardj : /*out*/ : /*in*/ "b"(&(_lval)) \ 88b411202f9ff33a587558e2e836626bc7eb9db183sewardj : /*trash*/ "r15", "cr0", "memory" \ 89b411202f9ff33a587558e2e836626bc7eb9db183sewardj ) 908777f7308785b4eb67898670e29ecdde42dec9dfsewardj#elif defined(PLAT_arm_linux) 918777f7308785b4eb67898670e29ecdde42dec9dfsewardj# define INC(_lval,_lqual) \ 928777f7308785b4eb67898670e29ecdde42dec9dfsewardj __asm__ __volatile__( \ 93d12c4a53875f9280323784227b0af727c7991966sewardj "1:\n" \ 948777f7308785b4eb67898670e29ecdde42dec9dfsewardj " ldrex r8, [%0, #0]\n" \ 958777f7308785b4eb67898670e29ecdde42dec9dfsewardj " add r8, r8, #1\n" \ 968777f7308785b4eb67898670e29ecdde42dec9dfsewardj " strex r9, r8, [%0, #0]\n" \ 978777f7308785b4eb67898670e29ecdde42dec9dfsewardj " cmp r9, #0\n" \ 98d12c4a53875f9280323784227b0af727c7991966sewardj " bne 1b\n" \ 998777f7308785b4eb67898670e29ecdde42dec9dfsewardj : /*out*/ : /*in*/ "r"(&(_lval)) \ 1008777f7308785b4eb67898670e29ecdde42dec9dfsewardj : /*trash*/ "r8", "r9", "cc", "memory" \ 1018777f7308785b4eb67898670e29ecdde42dec9dfsewardj ); 10223ed6302e96eb905ef25d6c39db600e17e5f341fsewardj#elif defined(PLAT_arm64_linux) 10323ed6302e96eb905ef25d6c39db600e17e5f341fsewardj# define INC(_lval,_lqual) \ 10423ed6302e96eb905ef25d6c39db600e17e5f341fsewardj __asm__ __volatile__( \ 10523ed6302e96eb905ef25d6c39db600e17e5f341fsewardj "1:\n" \ 10623ed6302e96eb905ef25d6c39db600e17e5f341fsewardj " ldxr w8, [%0, #0]\n" \ 10723ed6302e96eb905ef25d6c39db600e17e5f341fsewardj " add w8, w8, #1\n" \ 10823ed6302e96eb905ef25d6c39db600e17e5f341fsewardj " stxr w9, w8, [%0, #0]\n" \ 10923ed6302e96eb905ef25d6c39db600e17e5f341fsewardj " cmp w9, #0\n" \ 11023ed6302e96eb905ef25d6c39db600e17e5f341fsewardj " bne 1b\n" \ 11123ed6302e96eb905ef25d6c39db600e17e5f341fsewardj : /*out*/ : /*in*/ "r"(&(_lval)) \ 11223ed6302e96eb905ef25d6c39db600e17e5f341fsewardj : /*trash*/ "x8", "x9", "cc", "memory" \ 11323ed6302e96eb905ef25d6c39db600e17e5f341fsewardj ); 114b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#elif defined(PLAT_s390x_linux) 115b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj# define INC(_lval,_lqual) \ 116b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj __asm__ __volatile__( \ 117b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj "1: l 0,%0\n" \ 118b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj " lr 1,0\n" \ 119b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj " ahi 1,1\n" \ 120b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj " cs 0,1,%0\n" \ 121b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj " jl 1b\n" \ 122b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj : "+m" (_lval) :: "cc", "0","1" \ 123b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj ) 124d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj#elif defined(PLAT_mips32_linux) || defined(PLAT_mips64_linux) 1255db15403e889d4db339b342bc2a824ef0bfaa654sewardj# define INC(_lval,_lqual) \ 1265db15403e889d4db339b342bc2a824ef0bfaa654sewardj __asm__ __volatile__ ( \ 1275db15403e889d4db339b342bc2a824ef0bfaa654sewardj "L1xyzzy1" _lqual":\n" \ 128d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj " move $t0, %0\n" \ 129d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj " ll $t1, 0($t0)\n" \ 130d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj " addi $t1, $t1, 1\n" \ 131d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj " sc $t1, 0($t0)\n" \ 132d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj " beqz $t1, L1xyzzy1" _lqual \ 1335db15403e889d4db339b342bc2a824ef0bfaa654sewardj : /*out*/ : /*in*/ "r"(&(_lval)) \ 134d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj : /*trash*/ "t0", "t1", "memory" \ 1355db15403e889d4db339b342bc2a824ef0bfaa654sewardj ) 136112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#elif defined(PLAT_tilegx_linux) 137112711afefcfcd43680c7c4aa8d38ef180e8811esewardj# define INC(_lval,_lqual) \ 138112711afefcfcd43680c7c4aa8d38ef180e8811esewardj if (sizeof(_lval) == 4) \ 139112711afefcfcd43680c7c4aa8d38ef180e8811esewardj __insn_fetchadd(&(_lval), 1); \ 140112711afefcfcd43680c7c4aa8d38ef180e8811esewardj else if(sizeof(_lval) == 8) \ 141112711afefcfcd43680c7c4aa8d38ef180e8811esewardj __insn_fetchadd(&(_lval), 1) 142b411202f9ff33a587558e2e836626bc7eb9db183sewardj#else 143b411202f9ff33a587558e2e836626bc7eb9db183sewardj# error "Fix Me for this platform" 144b411202f9ff33a587558e2e836626bc7eb9db183sewardj#endif 145b411202f9ff33a587558e2e836626bc7eb9db183sewardj 146b411202f9ff33a587558e2e836626bc7eb9db183sewardj 147b411202f9ff33a587558e2e836626bc7eb9db183sewardj 148b411202f9ff33a587558e2e836626bc7eb9db183sewardj#define LIMIT 10 149b411202f9ff33a587558e2e836626bc7eb9db183sewardj 150b411202f9ff33a587558e2e836626bc7eb9db183sewardjvolatile int x = 0; 151b411202f9ff33a587558e2e836626bc7eb9db183sewardj 152b411202f9ff33a587558e2e836626bc7eb9db183sewardjvoid* child_fn ( void* arg ) 153b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 154b411202f9ff33a587558e2e836626bc7eb9db183sewardj int q = 0; 155b411202f9ff33a587558e2e836626bc7eb9db183sewardj int oldx = 0; 156f91fd73d264a38f0c742bd2eeb9895daa880aa5abart struct timespec ts = { 0, 1000 * 1000 }; 157f91fd73d264a38f0c742bd2eeb9895daa880aa5abart 158b411202f9ff33a587558e2e836626bc7eb9db183sewardj while (1) { 159b411202f9ff33a587558e2e836626bc7eb9db183sewardj q = (x >= LIMIT); 160b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (x != oldx) { 161b411202f9ff33a587558e2e836626bc7eb9db183sewardj oldx = x; 162b411202f9ff33a587558e2e836626bc7eb9db183sewardj printf("child: new value %d\n", oldx); 163b411202f9ff33a587558e2e836626bc7eb9db183sewardj fflush(stdout); 164b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 165b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (q) break; 166f91fd73d264a38f0c742bd2eeb9895daa880aa5abart nanosleep(&ts, 0); 167b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 168b411202f9ff33a587558e2e836626bc7eb9db183sewardj return NULL; 169b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 170b411202f9ff33a587558e2e836626bc7eb9db183sewardj 171b411202f9ff33a587558e2e836626bc7eb9db183sewardjint main ( void ) 172b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 173b411202f9ff33a587558e2e836626bc7eb9db183sewardj pthread_t child; 174b411202f9ff33a587558e2e836626bc7eb9db183sewardj int i; 175b411202f9ff33a587558e2e836626bc7eb9db183sewardj 176b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (pthread_create(&child, NULL, child_fn, NULL)) { 177b411202f9ff33a587558e2e836626bc7eb9db183sewardj perror("pthread_create"); 178b411202f9ff33a587558e2e836626bc7eb9db183sewardj exit(1); 179b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 180b411202f9ff33a587558e2e836626bc7eb9db183sewardj 181b411202f9ff33a587558e2e836626bc7eb9db183sewardj for (i = 0; i < LIMIT; i++) { 1822ee33955b80812a8f31ec06a0430103b50aeca8csewardj INC(x, "main"); 183b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (i == 5) sleep(1); /* make sure child doesn't starve */ 184b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 185b411202f9ff33a587558e2e836626bc7eb9db183sewardj 186b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (pthread_join(child, NULL)) { 187b411202f9ff33a587558e2e836626bc7eb9db183sewardj perror("pthread join"); 188b411202f9ff33a587558e2e836626bc7eb9db183sewardj exit(1); 189b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 190b411202f9ff33a587558e2e836626bc7eb9db183sewardj 191b411202f9ff33a587558e2e836626bc7eb9db183sewardj printf("done, x = %d\n", x); 192b411202f9ff33a587558e2e836626bc7eb9db183sewardj 193b411202f9ff33a587558e2e836626bc7eb9db183sewardj return 0; 194b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 195