tc08_hbl2.c revision 112711afefcfcd43680c7c4aa8d38ef180e8811e
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
37b411202f9ff33a587558e2e836626bc7eb9db183sewardj
386e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#if defined(__APPLE__) && defined(__i386__)
398777f7308785b4eb67898670e29ecdde42dec9dfsewardj#  define PLAT_x86_darwin 1
408777f7308785b4eb67898670e29ecdde42dec9dfsewardj#elif defined(__APPLE__) && defined(__x86_64__)
418777f7308785b4eb67898670e29ecdde42dec9dfsewardj#  define PLAT_amd64_darwin 1
428777f7308785b4eb67898670e29ecdde42dec9dfsewardj#elif defined(__linux__) && defined(__i386__)
43b411202f9ff33a587558e2e836626bc7eb9db183sewardj#  define PLAT_x86_linux 1
448777f7308785b4eb67898670e29ecdde42dec9dfsewardj#elif defined(__linux__) && defined(__x86_64__)
45b411202f9ff33a587558e2e836626bc7eb9db183sewardj#  define PLAT_amd64_linux 1
468777f7308785b4eb67898670e29ecdde42dec9dfsewardj#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
47b411202f9ff33a587558e2e836626bc7eb9db183sewardj#  define PLAT_ppc32_linux 1
488777f7308785b4eb67898670e29ecdde42dec9dfsewardj#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__)
49b411202f9ff33a587558e2e836626bc7eb9db183sewardj#  define PLAT_ppc64_linux 1
5023ed6302e96eb905ef25d6c39db600e17e5f341fsewardj#elif defined(__linux__) && defined(__arm__) && !defined(__aarch64__)
518777f7308785b4eb67898670e29ecdde42dec9dfsewardj#  define PLAT_arm_linux 1
5223ed6302e96eb905ef25d6c39db600e17e5f341fsewardj#elif defined(__linux__) && defined(__aarch64__) && !defined(__arm__)
5323ed6302e96eb905ef25d6c39db600e17e5f341fsewardj#  define PLAT_arm64_linux 1
54b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#elif defined(__linux__) && defined(__s390x__)
55b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  define PLAT_s390x_linux 1
565db15403e889d4db339b342bc2a824ef0bfaa654sewardj#elif defined(__linux__) && defined(__mips__)
57d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj#if (__mips==64)
58d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj#  define PLAT_mips64_linux 1
59d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj#else
605db15403e889d4db339b342bc2a824ef0bfaa654sewardj#  define PLAT_mips32_linux 1
61b411202f9ff33a587558e2e836626bc7eb9db183sewardj#endif
62112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#elif defined(__linux__) && defined(__tilegx__)
63112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#  define PLAT_tilegx_linux 1
64d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj#endif
65b411202f9ff33a587558e2e836626bc7eb9db183sewardj
668777f7308785b4eb67898670e29ecdde42dec9dfsewardj
67f5b5f84a476b54c239a5179de49728b6fa8f3b85sewardj#if defined(PLAT_amd64_linux) || defined(PLAT_x86_linux) \
68f5b5f84a476b54c239a5179de49728b6fa8f3b85sewardj    || defined(PLAT_amd64_darwin) || defined(PLAT_x86_darwin)
692ee33955b80812a8f31ec06a0430103b50aeca8csewardj#  define INC(_lval,_lqual)	     \
70b411202f9ff33a587558e2e836626bc7eb9db183sewardj      __asm__ __volatile__ ( \
71b411202f9ff33a587558e2e836626bc7eb9db183sewardj      "lock ; incl (%0)" : /*out*/ : /*in*/"r"(&(_lval)) : "memory", "cc" )
726e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#elif defined(PLAT_ppc32_linux) || defined(PLAT_ppc64_linux)
732ee33955b80812a8f31ec06a0430103b50aeca8csewardj#  define INC(_lval,_lqual)		  \
74b411202f9ff33a587558e2e836626bc7eb9db183sewardj   __asm__ __volatile__(                  \
75d12c4a53875f9280323784227b0af727c7991966sewardj      "1:\n"                              \
76b411202f9ff33a587558e2e836626bc7eb9db183sewardj      "        lwarx 15,0,%0\n"           \
77b411202f9ff33a587558e2e836626bc7eb9db183sewardj      "        addi 15,15,1\n"            \
78b411202f9ff33a587558e2e836626bc7eb9db183sewardj      "        stwcx. 15,0,%0\n"          \
79d12c4a53875f9280323784227b0af727c7991966sewardj      "        bne- 1b\n"                 \
80b411202f9ff33a587558e2e836626bc7eb9db183sewardj      : /*out*/ : /*in*/ "b"(&(_lval))    \
81b411202f9ff33a587558e2e836626bc7eb9db183sewardj      : /*trash*/ "r15", "cr0", "memory"  \
82b411202f9ff33a587558e2e836626bc7eb9db183sewardj   )
838777f7308785b4eb67898670e29ecdde42dec9dfsewardj#elif defined(PLAT_arm_linux)
848777f7308785b4eb67898670e29ecdde42dec9dfsewardj#  define INC(_lval,_lqual) \
858777f7308785b4eb67898670e29ecdde42dec9dfsewardj  __asm__ __volatile__( \
86d12c4a53875f9280323784227b0af727c7991966sewardj      "1:\n"                                 \
878777f7308785b4eb67898670e29ecdde42dec9dfsewardj      "        ldrex r8, [%0, #0]\n"         \
888777f7308785b4eb67898670e29ecdde42dec9dfsewardj      "        add   r8, r8, #1\n"           \
898777f7308785b4eb67898670e29ecdde42dec9dfsewardj      "        strex r9, r8, [%0, #0]\n"     \
908777f7308785b4eb67898670e29ecdde42dec9dfsewardj      "        cmp   r9, #0\n"               \
91d12c4a53875f9280323784227b0af727c7991966sewardj      "        bne   1b\n"                   \
928777f7308785b4eb67898670e29ecdde42dec9dfsewardj      : /*out*/ : /*in*/ "r"(&(_lval))       \
938777f7308785b4eb67898670e29ecdde42dec9dfsewardj      : /*trash*/ "r8", "r9", "cc", "memory" \
948777f7308785b4eb67898670e29ecdde42dec9dfsewardj  );
9523ed6302e96eb905ef25d6c39db600e17e5f341fsewardj#elif defined(PLAT_arm64_linux)
9623ed6302e96eb905ef25d6c39db600e17e5f341fsewardj#  define INC(_lval,_lqual) \
9723ed6302e96eb905ef25d6c39db600e17e5f341fsewardj  __asm__ __volatile__( \
9823ed6302e96eb905ef25d6c39db600e17e5f341fsewardj      "1:\n"                                 \
9923ed6302e96eb905ef25d6c39db600e17e5f341fsewardj      "        ldxr  w8, [%0, #0]\n"         \
10023ed6302e96eb905ef25d6c39db600e17e5f341fsewardj      "        add   w8, w8, #1\n"           \
10123ed6302e96eb905ef25d6c39db600e17e5f341fsewardj      "        stxr  w9, w8, [%0, #0]\n"     \
10223ed6302e96eb905ef25d6c39db600e17e5f341fsewardj      "        cmp   w9, #0\n"               \
10323ed6302e96eb905ef25d6c39db600e17e5f341fsewardj      "        bne   1b\n"                   \
10423ed6302e96eb905ef25d6c39db600e17e5f341fsewardj      : /*out*/ : /*in*/ "r"(&(_lval))       \
10523ed6302e96eb905ef25d6c39db600e17e5f341fsewardj      : /*trash*/ "x8", "x9", "cc", "memory" \
10623ed6302e96eb905ef25d6c39db600e17e5f341fsewardj  );
107b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#elif defined(PLAT_s390x_linux)
108b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  define INC(_lval,_lqual) \
109b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   __asm__ __volatile__( \
110b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      "1: l     0,%0\n"                            \
111b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      "   lr    1,0\n"                             \
112b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      "   ahi   1,1\n"                             \
113b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      "   cs    0,1,%0\n"                          \
114b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      "   jl    1b\n"                              \
115b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      : "+m" (_lval) :: "cc", "0","1" \
116b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   )
117d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj#elif defined(PLAT_mips32_linux) || defined(PLAT_mips64_linux)
1185db15403e889d4db339b342bc2a824ef0bfaa654sewardj#  define INC(_lval,_lqual)                         \
1195db15403e889d4db339b342bc2a824ef0bfaa654sewardj     __asm__ __volatile__ (                         \
1205db15403e889d4db339b342bc2a824ef0bfaa654sewardj      "L1xyzzy1" _lqual":\n"                        \
121d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj      "        move $t0, %0\n"                      \
122d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj      "        ll   $t1, 0($t0)\n"                  \
123d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj      "        addi $t1, $t1, 1\n"                  \
124d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj      "        sc   $t1, 0($t0)\n"                  \
125d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj      "        beqz $t1, L1xyzzy1" _lqual           \
1265db15403e889d4db339b342bc2a824ef0bfaa654sewardj      : /*out*/ : /*in*/ "r"(&(_lval))              \
127d5f0d1e2ae84afae0ef5c1db0fa1089280f0e3c9petarj      : /*trash*/ "t0", "t1", "memory"              \
1285db15403e889d4db339b342bc2a824ef0bfaa654sewardj        )
129112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#elif defined(PLAT_tilegx_linux)
130112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#  define INC(_lval,_lqual)                     \
131112711afefcfcd43680c7c4aa8d38ef180e8811esewardj  if (sizeof(_lval) == 4)                       \
132112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    __insn_fetchadd(&(_lval), 1);               \
133112711afefcfcd43680c7c4aa8d38ef180e8811esewardj  else if(sizeof(_lval) == 8)                   \
134112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    __insn_fetchadd(&(_lval), 1)
135b411202f9ff33a587558e2e836626bc7eb9db183sewardj#else
136b411202f9ff33a587558e2e836626bc7eb9db183sewardj#  error "Fix Me for this platform"
137b411202f9ff33a587558e2e836626bc7eb9db183sewardj#endif
138b411202f9ff33a587558e2e836626bc7eb9db183sewardj
139b411202f9ff33a587558e2e836626bc7eb9db183sewardj
140b411202f9ff33a587558e2e836626bc7eb9db183sewardj
141b411202f9ff33a587558e2e836626bc7eb9db183sewardj#define LIMIT 10
142b411202f9ff33a587558e2e836626bc7eb9db183sewardj
143b411202f9ff33a587558e2e836626bc7eb9db183sewardjvolatile int x = 0;
144b411202f9ff33a587558e2e836626bc7eb9db183sewardj
145b411202f9ff33a587558e2e836626bc7eb9db183sewardjvoid* child_fn ( void* arg )
146b411202f9ff33a587558e2e836626bc7eb9db183sewardj{
147b411202f9ff33a587558e2e836626bc7eb9db183sewardj   int q = 0;
148b411202f9ff33a587558e2e836626bc7eb9db183sewardj   int oldx = 0;
149f91fd73d264a38f0c742bd2eeb9895daa880aa5abart   struct timespec ts = { 0, 1000 * 1000 };
150f91fd73d264a38f0c742bd2eeb9895daa880aa5abart
151b411202f9ff33a587558e2e836626bc7eb9db183sewardj   while (1) {
152b411202f9ff33a587558e2e836626bc7eb9db183sewardj      q = (x >= LIMIT);
153b411202f9ff33a587558e2e836626bc7eb9db183sewardj      if (x != oldx) {
154b411202f9ff33a587558e2e836626bc7eb9db183sewardj         oldx = x;
155b411202f9ff33a587558e2e836626bc7eb9db183sewardj         printf("child: new value %d\n", oldx);
156b411202f9ff33a587558e2e836626bc7eb9db183sewardj         fflush(stdout);
157b411202f9ff33a587558e2e836626bc7eb9db183sewardj      }
158b411202f9ff33a587558e2e836626bc7eb9db183sewardj      if (q) break;
159f91fd73d264a38f0c742bd2eeb9895daa880aa5abart      nanosleep(&ts, 0);
160b411202f9ff33a587558e2e836626bc7eb9db183sewardj   }
161b411202f9ff33a587558e2e836626bc7eb9db183sewardj   return NULL;
162b411202f9ff33a587558e2e836626bc7eb9db183sewardj}
163b411202f9ff33a587558e2e836626bc7eb9db183sewardj
164b411202f9ff33a587558e2e836626bc7eb9db183sewardjint main ( void )
165b411202f9ff33a587558e2e836626bc7eb9db183sewardj{
166b411202f9ff33a587558e2e836626bc7eb9db183sewardj   pthread_t child;
167b411202f9ff33a587558e2e836626bc7eb9db183sewardj   int i;
168b411202f9ff33a587558e2e836626bc7eb9db183sewardj
169b411202f9ff33a587558e2e836626bc7eb9db183sewardj   if (pthread_create(&child, NULL, child_fn, NULL)) {
170b411202f9ff33a587558e2e836626bc7eb9db183sewardj      perror("pthread_create");
171b411202f9ff33a587558e2e836626bc7eb9db183sewardj      exit(1);
172b411202f9ff33a587558e2e836626bc7eb9db183sewardj   }
173b411202f9ff33a587558e2e836626bc7eb9db183sewardj
174b411202f9ff33a587558e2e836626bc7eb9db183sewardj   for (i = 0; i < LIMIT; i++) {
1752ee33955b80812a8f31ec06a0430103b50aeca8csewardj      INC(x, "main");
176b411202f9ff33a587558e2e836626bc7eb9db183sewardj      if (i == 5) sleep(1); /* make sure child doesn't starve */
177b411202f9ff33a587558e2e836626bc7eb9db183sewardj   }
178b411202f9ff33a587558e2e836626bc7eb9db183sewardj
179b411202f9ff33a587558e2e836626bc7eb9db183sewardj   if (pthread_join(child, NULL)) {
180b411202f9ff33a587558e2e836626bc7eb9db183sewardj      perror("pthread join");
181b411202f9ff33a587558e2e836626bc7eb9db183sewardj      exit(1);
182b411202f9ff33a587558e2e836626bc7eb9db183sewardj   }
183b411202f9ff33a587558e2e836626bc7eb9db183sewardj
184b411202f9ff33a587558e2e836626bc7eb9db183sewardj   printf("done, x = %d\n", x);
185b411202f9ff33a587558e2e836626bc7eb9db183sewardj
186b411202f9ff33a587558e2e836626bc7eb9db183sewardj   return 0;
187b411202f9ff33a587558e2e836626bc7eb9db183sewardj}
188