00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef __ZAtomic__
00026 #define __ZAtomic__ 1
00027 #include "zconfig.h"
00028
00029 #include "ZDebug.h"
00030
00031
00032
00033
00034
00035
00036 struct ZAtomic_t
00037 {
00038 volatile int fValue;
00039 };
00040
00041
00042 ZAssertCompile(sizeof(ZAtomic_t) == sizeof(int));
00043
00044 #if 0
00045 int ZAtomic_Get(const ZAtomic_t* iAtomic);
00046 void ZAtomic_Set(ZAtomic_t* iAtomic, int iParam);
00047
00048 int ZAtomic_Swap(ZAtomic_t* iAtomic, int iParam);
00049 bool ZAtomic_CompareAndSwap(ZAtomic_t* iAtomic, int iOldValue, int iNewValue);
00050
00051 int ZAtomic_Add(ZAtomic_t* iAtomic, int iParam);
00052 int ZAtomic_And(ZAtomic_t* iAtomic, int iParam);
00053 int ZAtomic_Or(ZAtomic_t* iAtomic, int iParam);
00054 int ZAtomic_Xor(ZAtomic_t* iAtomic, int iParam);
00055
00056 bool ZAtomic_DecAndTest(ZAtomic_t* iAtomic);
00057 void ZAtomic_Inc(ZAtomic_t* iAtomic);
00058 void ZAtomic_Dec(ZAtomic_t* iAtomic);
00059 #endif
00060
00061
00062
00063
00064
00065
00066 #ifndef ZCONFIG_Atomic_SMP
00067 # define ZCONFIG_Atomic_SMP 1
00068 #endif
00069
00070
00071
00072
00073
00074
00075
00076
00077 #if 1
00078 # define ZAtomic_PPC405_ERR77(rA,rB)
00079 #else
00080 # if ZCONFIG(Compiler, GCC)
00081 # define ZAtomic_PPC405_ERR77(rA,rB) "dcbt " #ra "," #rb "\n"
00082 # elif ZCONFIG(Compiler, CodeWarrior)
00083 # define ZAtomic_PPC405_ERR77(rA,rB) dcbt rA , rB;
00084 # else
00085 # error Unsupported
00086 # endif
00087 #endif
00088
00089
00090 #if ZCONFIG(Compiler, CodeWarrior) && ZCONFIG(Processor, 68K)
00091 #pragma mark -
00092 #pragma mark * CodeWarrior/68K
00093
00094 inline int ZAtomic_Get(const ZAtomic_t* iAtomic)
00095 { return iAtomic->fValue; }
00096
00097 inline void ZAtomic_Set(ZAtomic_t* iAtomic, int iParam)
00098 { iAtomic->fValue = iParam; }
00099
00100 asm inline int ZAtomic_Swap(ZAtomic_t* iAtomic : __A0, int iParam : __D1)
00101 {
00102 tryagain:
00103 move.l (a0), d0
00104 dc.l 0x0ED00040
00105 bne.s tryagain
00106 }
00107
00108 asm inline bool ZAtomic_CompareAndSwap(ZAtomic_t* iAtomic : __A0,
00109 int iOldValue : __D0, int iNewValue : __D1)
00110 {
00111 dc.l 0x0ED00040
00112 seq d0
00113 moveq #1, d1
00114 and.l d1, d0
00115 }
00116
00117
00118
00119 #define ZAtomic_Op_Macro(theOp) \
00120 tryagain: \
00121 move.l (a0), d0; \
00122 move.l d0, d2; \
00123 theOp d1, d2; \
00124 dc.l 0x0ED00080; \
00125 bne tryagain
00126
00127 asm inline int ZAtomic_Add(ZAtomic_t* iAtomic : __A0, int iParam : __D1)
00128 {
00129 ZAtomic_Op_Macro(add.l);
00130 }
00131
00132 asm inline int ZAtomic_And(ZAtomic_t* iAtomic : __A0, int iParam : __D1)
00133 {
00134 ZAtomic_Op_Macro(and.l);
00135 }
00136
00137 asm inline int ZAtomic_Or(ZAtomic_t* iAtomic : __A0, int iParam : __D1)
00138 {
00139 ZAtomic_Op_Macro(or.l);
00140 }
00141
00142 asm inline int ZAtomic_Xor(ZAtomic_t* iAtomic : __A0, int iParam : __D1)
00143 {
00144 ZAtomic_Op_Macro(eor.l);
00145 }
00146
00147 #undef ZAtomic_Op_Macro
00148
00149 asm inline bool ZAtomic_DecAndTest(ZAtomic_t* : __A0)
00150 {
00151 subq.l #1, (a0)
00152 seq d0
00153 moveq #1, d1
00154 and.l d1, d0
00155 }
00156
00157 asm inline void ZAtomic_Inc(ZAtomic_t* : __A0)
00158 {
00159 add.l #1, (a0)
00160 }
00161
00162 asm inline void ZAtomic_Dec(ZAtomic_t* : __A0)
00163 {
00164 sub.l #1, (a0)
00165 }
00166
00167
00168 #elif ZCONFIG(Compiler, CodeWarrior) && ZCONFIG(Processor, PPC) && !ZCONFIG(OS, Be)
00169 #pragma mark -
00170 #pragma mark * CodeWarrior/PPC/Not BeOS
00171
00172
00173
00174
00175
00176
00177 inline int ZAtomic_Get(const ZAtomic_t* iAtomic)
00178 { return iAtomic->fValue; }
00179
00180 inline void ZAtomic_Set(ZAtomic_t* iAtomic, int iParam)
00181 { iAtomic->fValue = iParam; }
00182
00183 int ZAtomic_Swap(ZAtomic_t* iAtomic, int iParam);
00184 bool ZAtomic_CompareAndSwap(ZAtomic_t* iAtomic, int iOldValue, int iNewValue);
00185
00186 int ZAtomic_Add(ZAtomic_t* iAtomic, int iParam);
00187 int ZAtomic_And(ZAtomic_t* iAtomic, int iParam);
00188 int ZAtomic_Or(ZAtomic_t* iAtomic, int iParam);
00189 int ZAtomic_Xor(ZAtomic_t* iAtomic, int iParam);
00190
00191 bool ZAtomic_DecAndTest(ZAtomic_t* iAtomic);
00192 void ZAtomic_Inc(ZAtomic_t* iAtomic);
00193 void ZAtomic_Dec(ZAtomic_t* iAtomic);
00194
00195
00196 #elif ZCONFIG(Compiler, CodeWarrior) && ZCONFIG(Processor, PPC) && ZCONFIG(OS, Be)
00197 #pragma mark -
00198 #pragma mark * CodeWarrior/PPC/BeOS
00199
00200 #include <support/SupportDefs.h>
00201
00202
00203
00204
00205 inline int ZAtomic_Get(const ZAtomic_t* iAtomic)
00206 { return iAtomic->fValue; }
00207
00208 inline void ZAtomic_Set(ZAtomic_t* iAtomic, int iParam)
00209 { iAtomic->fValue = iParam; }
00210
00211 inline int ZAtomic_Swap(ZAtomic_t* iAtomic, int iParam)
00212 { return int(atomic_add(reinterpret_cast<int32*>(iAtomic), 0)); }
00213
00214 inline bool ZAtomic_CompareAndSwap(ZAtomic_t* iAtomic, int iOldValue, int iNewValue)
00215 { ZUnimplemented(); }
00216
00217 inline int ZAtomic_Add(ZAtomic_t* iAtomic, int iParam)
00218 { return int(atomic_add(reinterpret_cast<int32*>(iAtomic), int32(iParam))); }
00219
00220 int ZAtomic_And(ZAtomic_t* iAtomic, int iParam)
00221 { return int(atomic_and(reinterpret_cast<int32*>(iAtomic), int32(iParam))); }
00222
00223 int ZAtomic_Or(ZAtomic_t* iAtomic, int iParam)
00224 { return int(atomic_or(reinterpret_cast<int32*>(iAtomic), int32(iParam))); }
00225
00226 int ZAtomic_Xor(ZAtomic_t* iAtomic, int iParam)
00227 { ZUnimplemented(); }
00228
00229 bool ZAtomic_DecAndTest(ZAtomic_t* iAtomic)
00230 { return 1 == atomic_add(reinterpret_cast<int32*>(iAtomic), -1); }
00231
00232 void ZAtomic_Inc(ZAtomic_t* iAtomic)
00233 { atomic_add(reinterpret_cast<int32*>(iAtomic), 1); }
00234
00235 void ZAtomic_Dec(ZAtomic_t* iAtomic)
00236 { atomic_add(reinterpret_cast<int32*>(iAtomic), -1); }
00237
00238
00239 #elif ZCONFIG(Compiler, CodeWarrior) && ZCONFIG(Processor, x86)
00240 #pragma mark -
00241 #pragma mark * CodeWarrior/Intel x86
00242
00243
00244
00245
00246
00247
00248
00249 inline int ZAtomic_Get(const ZAtomic_t* iAtomic)
00250 { return iAtomic->fValue; }
00251
00252 inline void ZAtomic_Set(ZAtomic_t* iAtomic, int iParam)
00253 { iAtomic->fValue = iParam; }
00254
00255 int ZAtomic_Swap(register ZAtomic_t* iAtomic, int iParam);
00256 bool ZAtomic_CompareAndSwap(ZAtomic_t* iAtomic, int iOldValue, int iNewValue);
00257
00258 int ZAtomic_Add(ZAtomic_t* iAtomic, int iParam);
00259 int ZAtomic_And(ZAtomic_t* iAtomic, int iParam);
00260 int ZAtomic_Or(ZAtomic_t* iAtomic, int iParam);
00261 int ZAtomic_Xor(ZAtomic_t* iAtomic, int iParam);
00262
00263 bool ZAtomic_DecAndTest(ZAtomic_t* iAtomic);
00264 void ZAtomic_Inc(ZAtomic_t* iAtomic);
00265 void ZAtomic_Dec(ZAtomic_t* iAtomic);
00266
00267
00268 #elif ZCONFIG(Compiler, GCC) && ZCONFIG(Processor, PPC)
00269 #pragma mark -
00270 #pragma mark * GCC/PPC
00271
00272 inline int ZAtomic_Get(const ZAtomic_t* iAtomic)
00273 { return iAtomic->fValue; }
00274
00275 inline void ZAtomic_Set(ZAtomic_t* iAtomic, int iParam)
00276 { iAtomic->fValue = iParam; }
00277
00278 inline int ZAtomic_Swap(ZAtomic_t* iAtomic, int iParam)
00279 {
00280 int oldValue;
00281 asm volatile
00282 (
00283 "1: lwarx %1, 0, %2\n"
00284 ZAtomic_PPC405_ERR77(0, %2)
00285 "stwcx. %3, 0, %2\n"
00286 "bne- 1b\n"
00287 "isync\n"
00288 : "=m" (iAtomic->fValue), "=&r" (oldValue)
00289 : "r" (iAtomic), "r" (iParam)
00290 : "cc"
00291 );
00292 return oldValue;
00293 }
00294
00295 inline bool ZAtomic_CompareAndSwap(ZAtomic_t* iAtomic, int iOldValue, int iNewValue)
00296 {
00297 int oldValue;
00298 asm volatile
00299 (
00300 "1: lwarx %1, 0, %2\n"
00301 "cmpw %1, %3\n"
00302 "beq 2f\n"
00303 "mr %4, %1\n"
00304 "2: stwcx. %4, 0, %2\n"
00305 "bne- 1b\n"
00306 "isync\n"
00307 : "=m" (iAtomic->fValue), "=&r" (oldValue)
00308 : "r" (iAtomic), "r" (iOldValue), "r" (iNewValue)
00309 : "cc"
00310 );
00311 return oldValue == iOldValue;
00312 }
00313
00314 #define ZAtomic_Op_Macro(theOp) \
00315 int oldValue, temp; \
00316 asm volatile \
00317 ( \
00318 "1: lwarx %1, 0, %3\n" \
00319 #theOp" %2, %1, %4\n" \
00320 ZAtomic_PPC405_ERR77(0, %3) \
00321 "stwcx. %2, 0, %3\n" \
00322 "bne- 1b\n" \
00323 "isync\n" \
00324 : "=m" (iAtomic->fValue), "=&r" (oldValue), "=&r" (temp) \
00325 : "r" (iAtomic), "r" (iParam) \
00326 : "cc" \
00327 ); \
00328 return oldValue
00329
00330 inline int ZAtomic_Add(ZAtomic_t* iAtomic, int iParam)
00331 {
00332 ZAtomic_Op_Macro(add);
00333 }
00334
00335 inline int ZAtomic_And(ZAtomic_t* iAtomic,int iParam)
00336 {
00337 ZAtomic_Op_Macro(and);
00338 }
00339
00340 inline int ZAtomic_Or(ZAtomic_t* iAtomic, int iParam)
00341 {
00342 ZAtomic_Op_Macro(or);
00343 }
00344
00345 inline int ZAtomic_Xor(ZAtomic_t* iAtomic, int iParam)
00346 {
00347 ZAtomic_Op_Macro(xor);
00348 }
00349
00350 #undef ZAtomic_Op_Macro
00351
00352 inline bool ZAtomic_DecAndTest(ZAtomic_t* iAtomic)
00353 {
00354 return ZAtomic_Add(iAtomic, -1) == 1;
00355 }
00356
00357 inline void ZAtomic_Inc(ZAtomic_t* iAtomic)
00358 {
00359 int temp;
00360 asm volatile
00361 (
00362 "1: lwarx %1, 0, %2\n"
00363 "addic %1, %1, 1\n"
00364 ZAtomic_PPC405_ERR77(0, %2)
00365 "stwcx. %1, 0, %2\n"
00366 "bne- 1b"
00367 : "=m" (iAtomic->fValue), "=&r" (temp)
00368 : "r" (iAtomic)
00369 : "cc"
00370 );
00371 }
00372
00373 inline void ZAtomic_Dec(ZAtomic_t* iAtomic)
00374 {
00375 int temp;
00376 asm volatile
00377 (
00378 "1: lwarx %1, 0, %2\n"
00379 "addic %1, %1, -1\n"
00380 ZAtomic_PPC405_ERR77(0, %2)
00381 "stwcx. %1, 0, %2\n"
00382 "bne- 1b"
00383 : "=m" (iAtomic->fValue), "=&r" (temp)
00384 : "r" (iAtomic)
00385 : "cc"
00386 );
00387 }
00388
00389
00390 #elif ZCONFIG(Compiler, GCC) && ZCONFIG(Processor, x86)
00391 #pragma mark -
00392 #pragma mark * GCC/Intel x86
00393
00394 #if ZCONFIG_Atomic_SMP
00395 # define ZooLib_SMPLockPrefix "lock; "
00396 #else
00397 # define ZooLib_SMPLockPrefix
00398 #endif
00399
00400 inline int ZAtomic_Get(const ZAtomic_t* iAtomic)
00401 { return iAtomic->fValue; }
00402
00403 inline void ZAtomic_Set(ZAtomic_t* iAtomic, int iParam)
00404 { iAtomic->fValue = iParam; }
00405
00406 inline int ZAtomic_Swap(ZAtomic_t* iAtomic, int iParam)
00407 {
00408 asm volatile
00409 (
00410 ZooLib_SMPLockPrefix "xchg %1, %0"
00411 : "=m" (iAtomic->fValue), "=q" (iParam)
00412 : "m" (iAtomic->fValue), "1" (iParam)
00413 );
00414 return iParam;
00415 }
00416
00417 inline bool ZAtomic_CompareAndSwap(ZAtomic_t* iAtomic, int iOldValue, int iNewValue)
00418 {
00419 bool result;
00420 asm volatile
00421 (
00422 ZooLib_SMPLockPrefix "cmpxchg %2, %0\n"
00423 "sete %1"
00424 : "=m" (iAtomic->fValue), "=qm" (result)
00425 : "q" (iNewValue), "a" (iOldValue), "m" (iAtomic->fValue)
00426 : "cc"
00427 );
00428 return result;
00429 }
00430
00431 #define ZAtomic_Op_Macro(theOp) \
00432 int oldValue, temp1; \
00433 asm volatile \
00434 ( \
00435 "1: mov %0, %2\n" \
00436 "mov %2, %3\n" \
00437 #theOp" %1, %3\n" \
00438 ZooLib_SMPLockPrefix "cmpxchg %3, %0\n" \
00439 "jne 1b" \
00440 : "=m" (iAtomic->fValue), "=qm" (iParam), "=a" (oldValue), "=q" (temp1) \
00441 : "m" (iAtomic->fValue), "1" (iParam)\
00442 : "cc" \
00443 ); \
00444 return oldValue
00445
00446 inline int ZAtomic_Add(ZAtomic_t* iAtomic, int iParam)
00447 {
00448 asm volatile
00449 (
00450 ZooLib_SMPLockPrefix "xadd %1, %0"
00451 : "=m" (iAtomic->fValue), "=q" (iParam)
00452 : "m" (iAtomic->fValue), "1" (iParam)
00453 );
00454 return iParam;
00455 }
00456
00457 inline int ZAtomic_And(ZAtomic_t* iAtomic, int iParam)
00458 {
00459 ZAtomic_Op_Macro(and);
00460 }
00461
00462 inline int ZAtomic_Or(ZAtomic_t* iAtomic, int iParam)
00463 {
00464 ZAtomic_Op_Macro(or);
00465 }
00466
00467 inline int ZAtomic_Xor(ZAtomic_t* iAtomic, int iParam)
00468 {
00469 ZAtomic_Op_Macro(xor);
00470 }
00471
00472 #undef ZAtomic_Op_Macro
00473
00474 inline bool ZAtomic_DecAndTest(ZAtomic_t* iAtomic)
00475 {
00476 bool isZero;
00477 asm volatile
00478 (
00479 ZooLib_SMPLockPrefix "decl %0\n"
00480 "sete %1"
00481 : "=m" (iAtomic->fValue), "=qm" (isZero)
00482 : "m" (iAtomic->fValue)
00483 );
00484 return isZero;
00485 }
00486
00487 inline void ZAtomic_Inc(ZAtomic_t* iAtomic)
00488 {
00489 asm volatile
00490 (
00491 ZooLib_SMPLockPrefix "incl %0"
00492 : "=m" (iAtomic->fValue)
00493 : "m" (iAtomic->fValue)
00494 );
00495 }
00496
00497 inline void ZAtomic_Dec(ZAtomic_t* iAtomic)
00498 {
00499 asm volatile
00500 (
00501 ZooLib_SMPLockPrefix "decl %0"
00502 : "=m" (iAtomic->fValue)
00503 : "m" (iAtomic->fValue)
00504 );
00505 }
00506
00507 #undef ZooLib_SMPLockPrefix
00508
00509
00510 #elif ZCONFIG(Compiler, MSVC) && ZCONFIG(Processor, x86)
00511 #pragma mark -
00512 #pragma mark * MSVC/Intel x86
00513
00514
00515
00516
00517 inline int ZAtomic_Get(const ZAtomic_t* iAtomic)
00518 { return iAtomic->fValue; }
00519
00520 inline void ZAtomic_Set(ZAtomic_t* iAtomic, int iParam)
00521 { iAtomic->fValue = iParam; }
00522
00523 int ZAtomic_Swap(register ZAtomic_t* iAtomic, int iParam);
00524
00525 bool ZAtomic_CompareAndSwap(ZAtomic_t* iAtomic, int iOldValue, int iNewValue);
00526
00527 int ZAtomic_Add(ZAtomic_t* iAtomic, int iParam);
00528 int ZAtomic_And(ZAtomic_t* iAtomic, int iParam);
00529 int ZAtomic_Or(ZAtomic_t* iAtomic, int iParam);
00530 int ZAtomic_Xor(ZAtomic_t* iAtomic, int iParam);
00531
00532 bool ZAtomic_DecAndTest(ZAtomic_t* iAtomic);
00533 void ZAtomic_Inc(ZAtomic_t* iAtomic);
00534 void ZAtomic_Dec(ZAtomic_t* iAtomic);
00535
00536
00537
00538 #else // ZCONFIG(Compiler), ZCONFIG(Processor)
00539 #pragma mark -
00540 #pragma mark * Dumb version
00541
00542 #define ZCONFIG_AtomicDumb 1
00543
00544
00545
00546
00547 inline int ZAtomic_Get(const ZAtomic_t* iAtomic)
00548 { return iAtomic->fValue; }
00549
00550 inline void ZAtomic_Set(ZAtomic_t* iAtomic, int iParam)
00551 { iAtomic->fValue = iParam; }
00552
00553 int ZAtomic_Swap(register ZAtomic_t* iAtomic, int iParam);
00554
00555 bool ZAtomic_CompareAndSwap(ZAtomic_t* iAtomic, int iOldValue, int iNewValue);
00556
00557 int ZAtomic_Add(ZAtomic_t* iAtomic, int iParam);
00558 int ZAtomic_And(ZAtomic_t* iAtomic, int iParam);
00559 int ZAtomic_Or(ZAtomic_t* iAtomic, int iParam);
00560 int ZAtomic_Xor(ZAtomic_t* iAtomic, int iParam);
00561
00562 bool ZAtomic_DecAndTest(ZAtomic_t* iAtomic);
00563 void ZAtomic_Inc(ZAtomic_t* iAtomic);
00564 void ZAtomic_Dec(ZAtomic_t* iAtomic);
00565
00566 #endif // ZCONFIG(Compiler)/ZCONFIG(Processor)
00567
00568
00569
00570 #endif // __ZAtomic__