comparison test/testatomic.c @ 5004:0c72ae7b7cb2

Added native atomic operations for Windows, Mac OS X, and gcc compiler intrinsics. Changed the CAS return value to bool, so it's efficient with OSAtomicCompareAndSwap32Barrier() Added an atomic test adapted from code by Michael Davidsaver
author Sam Lantinga <slouken@libsdl.org>
date Sun, 16 Jan 2011 15:16:39 -0800
parents 3a95a2b93eb3
children 8e8876e4aec6
comparison
equal deleted inserted replaced
5003:3a95a2b93eb3 5004:0c72ae7b7cb2
1 #include <stdio.h> 1 #include <stdio.h>
2 #include "SDL.h" 2 #include "SDL.h"
3 #include "SDL_assert.h"
3 4
4 /* 5 /*
5 Absolutely basic tests just to see if we get the expected value 6 Absolutely basic tests just to see if we get the expected value
6 after calling each function. 7 after calling each function.
7 */ 8 */
8 9
10 static
9 char * 11 char *
10 tf(SDL_bool tf) 12 tf(SDL_bool tf)
11 { 13 {
12 static char *t = "TRUE"; 14 static char *t = "TRUE";
13 static char *f = "FALSE"; 15 static char *f = "FALSE";
18 } 20 }
19 21
20 return f; 22 return f;
21 } 23 }
22 24
23 int 25 static
24 main(int argc, char *argv[]) 26 void RunBasicTest()
25 { 27 {
26 int value; 28 int value;
27 SDL_SpinLock lock = 0; 29 SDL_SpinLock lock = 0;
28 30
29 SDL_bool tfret = SDL_FALSE; 31 SDL_bool tfret = SDL_FALSE;
56 printf("AtomicDecRef() tfret=%s val=%"PRIu32"\n", tf(tfret), SDL_AtomicGet(&v)); 58 printf("AtomicDecRef() tfret=%s val=%"PRIu32"\n", tf(tfret), SDL_AtomicGet(&v));
57 tfret = (SDL_AtomicDecRef(&v) == SDL_TRUE); 59 tfret = (SDL_AtomicDecRef(&v) == SDL_TRUE);
58 printf("AtomicDecRef() tfret=%s val=%"PRIu32"\n", tf(tfret), SDL_AtomicGet(&v)); 60 printf("AtomicDecRef() tfret=%s val=%"PRIu32"\n", tf(tfret), SDL_AtomicGet(&v));
59 61
60 SDL_AtomicSet(&v, 10); 62 SDL_AtomicSet(&v, 10);
61 tfret = (SDL_AtomicCAS(&v, 0, 20) != 0); 63 tfret = (SDL_AtomicCAS(&v, 0, 20) == SDL_FALSE);
62 printf("AtomicCAS() tfret=%s val=%"PRIu32"\n", tf(tfret), SDL_AtomicGet(&v)); 64 printf("AtomicCAS() tfret=%s val=%"PRIu32"\n", tf(tfret), SDL_AtomicGet(&v));
63 value = SDL_AtomicGet(&v); 65 value = SDL_AtomicGet(&v);
64 tfret = (SDL_AtomicCAS(&v, value, 20) == value); 66 tfret = (SDL_AtomicCAS(&v, value, 20) == SDL_TRUE);
65 printf("AtomicCAS() tfret=%s val=%"PRIu32"\n", tf(tfret), SDL_AtomicGet(&v)); 67 printf("AtomicCAS() tfret=%s val=%"PRIu32"\n", tf(tfret), SDL_AtomicGet(&v));
66 68 }
69
70 /* Atomic operation test, adapted from code by Michael Davidsaver at:
71 http://bazaar.launchpad.net/~mdavidsaver/epics-base/atomic/revision/12105#src/libCom/test/epicsAtomicTest.c
72 */
73
74 /* Tests semantics of atomic operations. Also a stress test
75 * to see if they are really atomic.
76 *
77 * Serveral threads adding to the same variable.
78 * at the end the value is compared with the expected
79 * and with a non-atomic counter.
80 */
81
82 /* Number of concurrent incrementers */
83 #define NThreads 2
84 #define CountInc 100
85 #define VALBITS (sizeof(atomicValue)*8)
86
87 #define atomicValue int
88 #define CountTo ((atomicValue)((unsigned int)(1<<(VALBITS-1))-1))
89 #define NInter (CountTo/CountInc/NThreads)
90 #define Expect (CountTo-NInter*CountInc*NThreads)
91
92 SDL_COMPILE_TIME_ASSERT(size, CountTo>0); /* check for rollover */
93
94 static SDL_atomic_t good = { 42 };
95
96 static atomicValue bad = 42;
97
98 static SDL_atomic_t threadsRunning;
99
100 static SDL_sem *threadDone;
101
102 static
103 int adder(void* junk)
104 {
105 unsigned long N=NInter;
106 printf("Thread subtracting %d %lu times\n",CountInc,N);
107 while (N--) {
108 SDL_AtomicAdd(&good, -CountInc);
109 bad-=CountInc;
110 }
111 SDL_AtomicAdd(&threadsRunning, -1);
112 SDL_SemPost(threadDone);
67 return 0; 113 return 0;
68 } 114 }
115
116 static
117 void runAdder(void)
118 {
119 Uint32 start, end;
120 int T=NThreads;
121
122 start = SDL_GetTicks();
123
124 threadDone = SDL_CreateSemaphore(0);
125
126 SDL_AtomicSet(&threadsRunning, NThreads);
127
128 while (T--)
129 SDL_CreateThread(adder, NULL);
130
131 while (SDL_AtomicGet(&threadsRunning) > 0)
132 SDL_SemWait(threadDone);
133
134 SDL_DestroySemaphore(threadDone);
135
136 end = SDL_GetTicks();
137
138 printf("Finished in %f sec\n", (end - start) / 1000.f);
139 }
140
141 static
142 void RunEpicTest()
143 {
144 int b;
145 atomicValue v;
146
147 printf("\nepic test---------------------------------------\n\n");
148
149 printf("Size asserted to be >= 32-bit\n");
150 SDL_assert(sizeof(atomicValue)>=4);
151
152 printf("Check static initializer\n");
153 v=SDL_AtomicGet(&good);
154 SDL_assert(v==42);
155
156 SDL_assert(bad==42);
157
158 printf("Test negative values\n");
159 SDL_AtomicSet(&good, -5);
160 v=SDL_AtomicGet(&good);
161 SDL_assert(v==-5);
162
163 printf("Verify maximum value\n");
164 SDL_AtomicSet(&good, CountTo);
165 v=SDL_AtomicGet(&good);
166 SDL_assert(v==CountTo);
167
168 printf("Test compare and exchange\n");
169
170 b=SDL_AtomicCAS(&good, 500, 43);
171 SDL_assert(!b); /* no swap since CountTo!=500 */
172 v=SDL_AtomicGet(&good);
173 SDL_assert(v==CountTo); /* ensure no swap */
174
175 b=SDL_AtomicCAS(&good, CountTo, 44);
176 SDL_assert(!!b); /* will swap */
177 v=SDL_AtomicGet(&good);
178 SDL_assert(v==44);
179
180 printf("Test Add\n");
181
182 v=SDL_AtomicAdd(&good, 1);
183 SDL_assert(v==44);
184 v=SDL_AtomicGet(&good);
185 SDL_assert(v==45);
186
187 v=SDL_AtomicAdd(&good, 10);
188 SDL_assert(v==45);
189 v=SDL_AtomicGet(&good);
190 SDL_assert(v==55);
191
192 printf("Test Add (Negative values)\n");
193
194 v=SDL_AtomicAdd(&good, -20);
195 SDL_assert(v==55);
196 v=SDL_AtomicGet(&good);
197 SDL_assert(v==35);
198
199 v=SDL_AtomicAdd(&good, -50); /* crossing zero down */
200 SDL_assert(v==35);
201 v=SDL_AtomicGet(&good);
202 SDL_assert(v==-15);
203
204 v=SDL_AtomicAdd(&good, 30); /* crossing zero up */
205 SDL_assert(v==-15);
206 v=SDL_AtomicGet(&good);
207 SDL_assert(v==15);
208
209 printf("Reset before count down test\n");
210 SDL_AtomicSet(&good, CountTo);
211 v=SDL_AtomicGet(&good);
212 SDL_assert(v==CountTo);
213
214 bad=CountTo;
215 SDL_assert(bad==CountTo);
216
217 printf("Counting down from %d, Expect %d remaining\n",CountTo,Expect);
218 runAdder();
219
220 v=SDL_AtomicGet(&good);
221 printf("Atomic %d Non-Atomic %d\n",v,bad);
222 SDL_assert(v==Expect);
223 SDL_assert(bad!=Expect);
224 }
225
226 int
227 main(int argc, char *argv[])
228 {
229 RunBasicTest();
230 RunEpicTest();
231 return 0;
232 }