src/foundation/ZAtomic.h

00001 /*  @(#) $Id: ZAtomic.h,v 1.13 2006/04/26 22:31:27 agreen Exp $ */
00002 
00003 /* ------------------------------------------------------------
00004 Copyright (c) 2000 Andrew Green and Learning in Motion, Inc.
00005 http://www.zoolib.org
00006 
00007 Permission is hereby granted, free of charge, to any person obtaining a copy
00008 of this software and associated documentation files (the "Software"), to deal
00009 in the Software without restriction, including without limitation the rights
00010 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00011 copies of the Software, and to permit persons to whom the Software is
00012 furnished to do so, subject to the following conditions:
00013 
00014 The above copyright notice and this permission notice shall be included in
00015 all copies or substantial portions of the Software.
00016 
00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00020 COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00021 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023 ------------------------------------------------------------ */
00024 
00025 #ifndef __ZAtomic__
00026 #define __ZAtomic__ 1
00027 #include "zconfig.h"
00028 
00029 #include "ZDebug.h" // For ZAssertCompile
00030 
00031 // AG 2000-02-06. Much of the code in this file inlines. For that to work we need the various
00032 // compilers to see quite different code. The first section of this file is #ifed out of existence,
00033 // but should be considered to be the canonical API. The second section has the various versions of
00034 // the real code.
00035 
00036 struct ZAtomic_t
00037         {
00038         volatile int fValue;
00039         };
00040 
00041 // Ensure that ZAtomic_t packs properly
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 // AG 2003-06-17. I just came across a posting by Linus Torvalds to LKML wherein he says that
00063 // the lock prefix on operations causes a factor of 12 slowdown of those operations. It's
00064 // only needed on SMP machines which we continue to assume we may be running on. If you know
00065 // different, override by defining ZCONFIG_Atomic_SMP as 0 in your zconfig.h.
00066 #ifndef ZCONFIG_Atomic_SMP
00067 #       define ZCONFIG_Atomic_SMP 1
00068 #endif
00069 
00070 // =================================================================================================
00071 /* There's a reference in the Linux kernel source to Erratum #77 for the
00072 PowerPC 405. I'm not sure which, if any, Macintoshes use this processor.
00073 The issue is that a sync or dcbt instruction must be issued before any
00074 stwcx. instruction. I'm defining a null macro for this for now, but it
00075 can be enabled later if necessary. */
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 // cas.l d0, d1, (a0)
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 // cas.l d0, d1, (a0)
00112         seq d0
00113         moveq #1, d1
00114         and.l d1, d0
00115         }
00116 
00117 // dc.l 0x0ED00080 = cas.l d0, d2, (a0)
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 // Although CW can inline PPC assembler, for some reason it has a hard time satisfying the
00173 // constraints of enclosing code and the inlined stuff simultaneously. We're able to use one (!)
00174 // register in inlined code, but almost all this code requires two or more. The code is thus defined
00175 // out of line in ZAtomic.cpp.
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 // CodeWarrior for BeOS's inline assembly syntax is giving us problems. For now we call through to
00203 // the standard BeOS implementations from <support/SupportDefs.h>
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 // CodeWarrior sucks rocks when it comes to reliably including inline x86 assmbly with general C/C++
00244 // code, or generating the correct opcodes for parameters. To work around the problem the code has
00245 // to do superfluous register/register transfers, causing massive bloat. So for the time being these
00246 // routines are defined out of line in ZAtomic.cpp, which will also make it easier to tweak them
00247 // without having massive rebuilds.
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 // Defined out of line in ZAtomic.cpp till I can determine how effective MSVC is at
00515 // inlining assembly code.
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 // Defined out of line in ZAtomic.cpp, using a global mutex to ensure atomicity. Performance will
00545 // not be great, but it will at least work everywhere that we have a ZThread implementation.
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__

Generated on Thu Jul 26 11:21:51 2007 for ZooLib by  doxygen 1.4.7