blob: 5362faae41195aa1271d2125625f5d23fe451ca1 [file] [log] [blame]
sewardjb4112022007-11-09 22:49:28 +00001
2/* FIXME: this is basically a bad test as it is scheduling-
3 sensitive. Sometimes the output is:
4
5 child: new value 6
6 child: new value 10
7 done, x = 10
8
9 and sometimes
10
11 child: new value 10
12 done, x = 10
13*/
14
15#include <pthread.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <unistd.h>
19
20/* Simple test program, no race. Parent writes atomically to a counter
21 whilst child reads it. When counter reaches a prearranged value,
22 child joins back to parent. Parent (writer) uses hardware bus lock;
23 child is only reading and so does not need to use a bus lock. */
24
25
26#undef PLAT_x86_linux
27#undef PLAT_amd64_linux
28#undef PLAT_ppc32_linux
29#undef PLAT_ppc64_linux
30#undef PLAT_ppc32_aix5
31#undef PLAT_ppc64_aix5
32
33#if !defined(_AIX) && defined(__i386__)
34# define PLAT_x86_linux 1
35#elif !defined(_AIX) && defined(__x86_64__)
36# define PLAT_amd64_linux 1
37#elif !defined(_AIX) && defined(__powerpc__) && !defined(__powerpc64__)
38# define PLAT_ppc32_linux 1
39#elif !defined(_AIX) && defined(__powerpc__) && defined(__powerpc64__)
40# define PLAT_ppc64_linux 1
41#elif defined(_AIX) && defined(__64BIT__)
42# define PLAT_ppc64_aix5 1
43#elif defined(_AIX) && !defined(__64BIT__)
44# define PLAT_ppc32_aix5 1
45#endif
46
47
48#if defined(PLAT_amd64_linux) || defined(PLAT_x86_linux)
49# define INC(_lval) \
50 __asm__ __volatile__ ( \
51 "lock ; incl (%0)" : /*out*/ : /*in*/"r"(&(_lval)) : "memory", "cc" )
52#elif defined(PLAT_ppc32_linux) || defined(PLAT_ppc64_linux)
53# define INC(_lval) \
54 __asm__ __volatile__( \
55 "1:\n" \
56 " lwarx 15,0,%0\n" \
57 " addi 15,15,1\n" \
58 " stwcx. 15,0,%0\n" \
59 " bne- 1b" \
60 : /*out*/ : /*in*/ "b"(&(_lval)) \
61 : /*trash*/ "r15", "cr0", "memory" \
62 )
63#else
64# error "Fix Me for this platform"
65#endif
66
67
68
69#define LIMIT 10
70
71volatile int x = 0;
72
73void* child_fn ( void* arg )
74{
75 int q = 0;
76 int oldx = 0;
77 int ctr = 0;
78 while (1) {
79 q = (x >= LIMIT);
80 if (x != oldx) {
81 oldx = x;
82 printf("child: new value %d\n", oldx);
83 fflush(stdout);
84 }
85 if (q) break;
86 /* Make sure the parent doesn't starve. Seems to be a problem
87 on very slow machines. */
88 ctr++;
89 if (ctr == 2000000) sleep(1);
90 }
91 return NULL;
92}
93
94int main ( void )
95{
96 pthread_t child;
97 int i;
98
99 if (pthread_create(&child, NULL, child_fn, NULL)) {
100 perror("pthread_create");
101 exit(1);
102 }
103
104 for (i = 0; i < LIMIT; i++) {
105 INC(x);
106 if (i == 5) sleep(1); /* make sure child doesn't starve */
107 }
108
109 if (pthread_join(child, NULL)) {
110 perror("pthread join");
111 exit(1);
112 }
113
114 printf("done, x = %d\n", x);
115
116 return 0;
117}