Mercurial > sdl-ios-xcode
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 } |