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