pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
plank_AtomicInline_Mac_PPC_32.h
00001 /*
00002  -------------------------------------------------------------------------------
00003  This file is part of the Plink, Plonk, Plank libraries
00004   by Martin Robinson
00005  
00006  http://code.google.com/p/pl-nk/
00007  
00008  Copyright University of the West of England, Bristol 2011-14
00009  All rights reserved.
00010  
00011  Redistribution and use in source and binary forms, with or without
00012  modification, are permitted provided that the following conditions are met:
00013  
00014  * Redistributions of source code must retain the above copyright
00015    notice, this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright
00017    notice, this list of conditions and the following disclaimer in the
00018    documentation and/or other materials provided with the distribution.
00019  * Neither the name of University of the West of England, Bristol nor 
00020    the names of its contributors may be used to endorse or promote products
00021    derived from this software without specific prior written permission.
00022  
00023  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00024  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00025  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00026  DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF THE WEST OF ENGLAND, BRISTOL BE 
00027  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
00028  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
00029  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
00030  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
00031  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
00032  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00033  
00034  This software makes use of third party libraries. For more information see:
00035  doc/license.txt included in the distribution.
00036  -------------------------------------------------------------------------------
00037  */
00038 
00039 // help prevent accidental inclusion other than via the intended header
00040 #if PLANK_INLINING_FUNCTIONS
00041 
00042 #define PLANK_ATOMIC_XBITS          32
00043 #define PLANK_ATOMIC_XREFCOUNTBITS  16
00044 #define PLANK_ATOMIC_XWEAKCOUNTBITS 16
00045 #define PLANK_ATOMIC_XREFCOUNTMAX   0x0000FFFFUL
00046 #define PLANK_ATOMIC_XREFCOUNTMASK  PLANK_ATOMIC_XREFCOUNTMAX
00047 #define PLANK_ATOMIC_XWEAKCOUNTMAX  0x0000FFFFUL
00048 #define PLANK_ATOMIC_XWEAKCOUNTMASK 0xFFFF0000UL
00049 #define PLANK_ATOMIC_XMAX           0xFFFFFFFFUL
00050 #define PLANK_ATOMIC_PMASK          0xFFFFFFFFUL
00051 
00052 #if !DOXYGEN
00053 typedef struct PlankAtomicI
00054 {
00055     volatile PlankI value;
00056 } PlankAtomicI PLANK_ALIGN(4);
00057 
00058 typedef struct PlankAtomicL
00059 {
00060     volatile PlankL value;
00061 } PlankAtomicL PLANK_ALIGN(4);
00062 
00063 #include "../../../core/plank_ThreadSpinLock.h"
00064 
00065 typedef struct PlankAtomicLL
00066 {
00067     volatile PlankLL value;
00068     PlankThreadSpinLock lock;
00069 } PlankAtomicLL PLANK_ALIGN(8);
00070 
00071 typedef struct PlankAtomicF
00072 {
00073     volatile PlankF value;
00074 } PlankAtomicF PLANK_ALIGN(4);
00075 
00076 typedef struct PlankAtomicD
00077 {
00078     volatile PlankD value;
00079     PlankThreadSpinLock lock;
00080 } PlankAtomicD PLANK_ALIGN(8);
00081 
00082 typedef struct PlankAtomicP
00083 {
00084     volatile PlankP ptr;
00085 } PlankAtomicP PLANK_ALIGN(4);
00086 
00087 typedef struct PlankAtomicPX
00088 {
00089     volatile PlankP ptr;
00090     volatile PlankUL extra;
00091     PlankThreadSpinLock lock;
00092 } PlankAtomicPX PLANK_ALIGN(8);
00093 #endif
00094 
00095 static inline void pl_AtomicMemoryBarrier()
00096 {
00097     OSMemoryBarrier();
00098 }
00099 
00100 //------------------------------------------------------------------------------
00101 static inline PlankResult pl_AtomicI_Init (PlankAtomicIRef p)
00102 {
00103     if (p == PLANK_NULL)
00104         return PlankResult_MemoryError;
00105     
00106     pl_MemoryZero (p, sizeof (PlankAtomicI));
00107     
00108     return PlankResult_OK;
00109 }
00110 
00111 static inline PlankResult pl_AtomicI_DeInit (PlankAtomicIRef p)
00112 {
00113     if (p == PLANK_NULL)
00114         return PlankResult_MemoryError;
00115     return PlankResult_OK;
00116 }
00117 
00118 static inline PlankI pl_AtomicI_Get (PlankAtomicIRef p)
00119 {
00120     return p->value; // should be aligned anyway and volatile so OK // pl_AtomicI_Add (p, 0);
00121 }
00122 
00123 static inline PlankI pl_AtomicI_GetUnchecked (PlankAtomicIRef p)
00124 {
00125     return p->value;
00126 }
00127 
00128 static inline PlankI pl_AtomicI_Swap (PlankAtomicIRef p, PlankI newValue)
00129 {
00130     PlankI oldValue;
00131     PlankB success;
00132     
00133     do {
00134         oldValue = *(PlankI*)p;
00135         success = pl_AtomicI_CompareAndSwap (p, oldValue, newValue);
00136     } while (!success);
00137     
00138     return oldValue;
00139 }
00140 
00141 static inline void pl_AtomicI_SwapOther (PlankAtomicIRef p1, PlankAtomicIRef p2)
00142 {
00143     PlankI value1, value2;
00144     PlankB success;
00145     
00146     do {
00147         value1 = *(PlankI*)p1;
00148         value2 = *(PlankI*)p2;
00149         success = pl_AtomicI_CompareAndSwap (p1, value1, value2);
00150     } while (!success);
00151     
00152     *(PlankI*)p2 = value1;
00153 }
00154 
00155 static inline void pl_AtomicI_Set (PlankAtomicIRef p, PlankI newValue)
00156 {
00157     pl_AtomicI_Swap (p, newValue);
00158 }
00159 
00160 static inline PlankI pl_AtomicI_Add (PlankAtomicIRef p, PlankI operand)
00161 {
00162     return OSAtomicAdd32Barrier (*(int32_t*)&operand, 
00163                                  (volatile int32_t*)p);
00164 }
00165 
00166 static inline PlankB  pl_AtomicI_CompareAndSwap (PlankAtomicIRef p, PlankI oldValue, PlankI newValue)
00167 {    
00168     return OSAtomicCompareAndSwap32Barrier (*(int32_t*)&oldValue, 
00169                                             *(int32_t*)&newValue, 
00170                                             (volatile int32_t*)p);
00171 }
00172 
00173 static inline PlankI pl_AtomicI_Subtract (PlankAtomicIRef p, PlankI operand)
00174 {
00175     return pl_AtomicI_Add (p, -operand);
00176 }
00177 
00178 static inline PlankI pl_AtomicI_Increment (PlankAtomicIRef p)
00179 {
00180     return pl_AtomicI_Add (p, 1);
00181 }
00182 
00183 static inline PlankI pl_AtomicI_Decrement (PlankAtomicIRef p)
00184 {
00185     return pl_AtomicI_Add (p, -1);
00186 }
00187 
00188 //------------------------------------------------------------------------------
00189 static inline PlankResult pl_AtomicL_Init (PlankAtomicLRef p)
00190 {
00191     if (p == PLANK_NULL)
00192         return PlankResult_MemoryError;
00193     
00194     pl_MemoryZero (p, sizeof (PlankAtomicL));
00195     
00196     return PlankResult_OK;
00197 }
00198 
00199 static inline PlankResult pl_AtomicL_DeInit (PlankAtomicLRef p)
00200 {
00201     if (p == PLANK_NULL)
00202         return PlankResult_MemoryError;
00203     return PlankResult_OK;
00204 }
00205 
00206 static inline PlankL pl_AtomicL_Get (PlankAtomicLRef p)
00207 {
00208     return p->value; // should be aligned anyway and volatile so OK // pl_AtomicL_Add (p, (PlankL)0);
00209 }
00210 
00211 static inline PlankL pl_AtomicL_GetUnchecked (PlankAtomicLRef p)
00212 {
00213     return p->value;
00214 }
00215 
00216 static inline PlankL pl_AtomicL_Swap (PlankAtomicLRef p, PlankL newValue)
00217 {
00218     PlankL oldValue;
00219     PlankB success;
00220     
00221     do {
00222         oldValue = *(PlankL*)p;
00223         success = pl_AtomicL_CompareAndSwap (p, oldValue, newValue);
00224     } while (!success);
00225     
00226     return oldValue;
00227 }
00228 
00229 static inline void pl_AtomicL_SwapOther (PlankAtomicLRef p1, PlankAtomicLRef p2)
00230 {
00231     PlankL value1, value2;
00232     PlankB success;
00233     
00234     do {
00235         value1 = *(PlankL*)p1;
00236         value2 = *(PlankL*)p2;
00237         success = pl_AtomicL_CompareAndSwap (p1, value1, value2);
00238     } while (!success);
00239     
00240     *(PlankL*)p2 = value1;
00241 }
00242 
00243 static inline void pl_AtomicL_Set (PlankAtomicLRef p, PlankL newValue)
00244 {
00245     pl_AtomicL_Swap (p, newValue);
00246 }
00247 
00248 static inline PlankL pl_AtomicL_Add (PlankAtomicLRef p, PlankL operand)
00249 {
00250     return OSAtomicAdd32Barrier (*(int32_t*)&operand, 
00251                                  (volatile int32_t*)p);
00252 }
00253 
00254 static inline PlankB pl_AtomicL_CompareAndSwap (PlankAtomicLRef p, PlankL oldValue, PlankL newValue)
00255 {    
00256     return OSAtomicCompareAndSwap32Barrier (*(int32_t*)&oldValue, 
00257                                             *(int32_t*)&newValue, 
00258                                             (volatile int32_t*)p);
00259 }
00260 
00261 static inline PlankL pl_AtomicL_Subtract (PlankAtomicLRef p, PlankL operand)
00262 {
00263     return pl_AtomicL_Add (p, -operand);
00264 }
00265 
00266 static inline PlankL pl_AtomicL_Increment (PlankAtomicLRef p)
00267 {
00268     return pl_AtomicL_Add (p, (PlankL)1);
00269 }
00270 
00271 static inline PlankL pl_AtomicL_Decrement (PlankAtomicLRef p)
00272 {
00273     return pl_AtomicL_Add (p, (PlankL)(-1));
00274 }
00275 
00276 //------------------------------------------------------------------------------
00277 
00278 static inline PlankResult pl_AtomicLL_Init (PlankAtomicLLRef p)
00279 {
00280     PlankResult result = PlankResult_OK;
00281     
00282     if (p == PLANK_NULL)
00283     {
00284         result = PlankResult_MemoryError;
00285         goto exit;
00286     }
00287     
00288     pl_MemoryZero (p, sizeof (PlankAtomicLL));
00289     
00290 exit:
00291     return result;
00292 }
00293 
00294 static inline PlankResult pl_AtomicLL_DeInit (PlankAtomicLLRef p)
00295 {
00296     PlankResult result = PlankResult_OK;
00297     
00298     if (p == PLANK_NULL)
00299     {
00300         result = PlankResult_MemoryError;
00301         goto exit;
00302     }
00303     
00304 exit:
00305     return result;
00306 }
00307 
00308 static inline PlankLL pl_AtomicLL_Get (PlankAtomicLLRef p)
00309 {
00310     return pl_AtomicLL_Add (p, (PlankLL)0);
00311 }
00312 
00313 static inline PlankLL pl_AtomicLL_GetUnchecked (PlankAtomicLLRef p)
00314 {
00315     return p->value;
00316 }
00317 
00318 static inline PlankLL pl_AtomicLL_Swap (PlankAtomicLLRef p, PlankLL newValue)
00319 {
00320     PlankLL oldValue;
00321     PlankB success;
00322     
00323     do {
00324         oldValue = *(PlankLL*)p;
00325         success = pl_AtomicLL_CompareAndSwap (p, oldValue, newValue);
00326     } while (!success);
00327     
00328     return oldValue;
00329 }
00330 
00331 static inline void pl_AtomicLL_SwapOther (PlankAtomicLLRef p1, PlankAtomicLLRef p2)
00332 {
00333     PlankLL value1, value2;
00334     PlankB success;
00335     
00336     do {
00337         value1 = *(PlankLL*)p1;
00338         value2 = *(PlankLL*)p2;
00339         success = pl_AtomicLL_CompareAndSwap (p1, value1, value2);
00340     } while (!success);
00341     
00342     *(PlankLL*)p2 = value1;
00343 }
00344 
00345 static inline void pl_AtomicLL_Set (PlankAtomicLLRef p, PlankLL newValue)
00346 {
00347     pl_AtomicLL_Swap (p, newValue);
00348 }
00349 
00350 static inline PlankLL pl_AtomicLL_Add (PlankAtomicLLRef p, PlankLL operand)
00351 {
00352     PlankLL oldValue, newValue;
00353     PlankB success;
00354     
00355     do {
00356         oldValue = *(PlankLL*)p;
00357         newValue = oldValue + operand;
00358         success = pl_AtomicLL_CompareAndSwap (p, oldValue, newValue);
00359     } while (!success);
00360     
00361     return newValue;
00362 }
00363 
00364 static inline PlankB pl_AtomicLL_CompareAndSwap (PlankAtomicLLRef p, PlankLL oldValue, PlankLL newValue)
00365 {    
00366     if (! pl_ThreadSpinLock_TryLock (&p->lock))
00367         return PLANK_FALSE;
00368     
00369     if (p->value != oldValue)
00370     {
00371         pl_ThreadSpinLock_Unlock (&p->lock);
00372         return PLANK_FALSE;
00373     }
00374     
00375     p->value = newValue;
00376     pl_ThreadSpinLock_Unlock (&p->lock);
00377     
00378     return PLANK_TRUE;
00379 }
00380 
00381 static inline PlankLL pl_AtomicLL_Subtract (PlankAtomicLLRef p, PlankLL operand)
00382 {
00383     return pl_AtomicLL_Add (p, -operand);
00384 }
00385 
00386 static inline PlankLL pl_AtomicLL_Increment (PlankAtomicLLRef p)
00387 {
00388     return pl_AtomicLL_Add (p, (PlankLL)1);
00389 }
00390 
00391 static inline PlankLL pl_AtomicLL_Decrement (PlankAtomicLLRef p)
00392 {
00393     return pl_AtomicLL_Add (p, (PlankLL)(-1));
00394 }
00395 
00396 //------------------------------------------------------------------------------
00397 
00398 static inline PlankResult pl_AtomicF_Init (PlankAtomicFRef p)
00399 {
00400     if (p == PLANK_NULL)
00401         return PlankResult_MemoryError;
00402     
00403     pl_MemoryZero (p, sizeof (PlankAtomicF));
00404     
00405     return PlankResult_OK;
00406 }
00407 
00408 static inline PlankResult pl_AtomicF_DeInit (PlankAtomicFRef p)
00409 {
00410     if (p == PLANK_NULL)
00411         return PlankResult_MemoryError;
00412     return PlankResult_OK;
00413 }
00414 
00415 static inline PlankF pl_AtomicF_Get (PlankAtomicFRef p)
00416 {    
00417     return p->value; // should be aligned anyway and volatile so OK
00418 }
00419 
00420 static inline PlankF pl_AtomicF_GetUnchecked (PlankAtomicFRef p)
00421 {
00422     return  p->value;
00423 }
00424 
00425 static inline PlankF pl_AtomicF_Swap (PlankAtomicFRef p, PlankF newValue)
00426 {
00427     PlankF oldValue;
00428     PlankB success;
00429     
00430     do
00431     {
00432         oldValue = *(PlankF*)p;
00433         success = pl_AtomicF_CompareAndSwap (p, oldValue, newValue);
00434     } while (!success);
00435     
00436     return oldValue;
00437 }
00438 
00439 static inline void pl_AtomicF_SwapOther (PlankAtomicFRef p1, PlankAtomicFRef p2)
00440 {
00441     PlankF value1, value2;
00442     PlankB success;
00443     
00444     do {
00445         value1 = *(PlankF*)p1;
00446         value2 = *(PlankF*)p2;
00447         success = pl_AtomicF_CompareAndSwap (p1, value1, value2);
00448     } while (!success);
00449     
00450     *(PlankF*)p2 = value1;
00451 }
00452 
00453 static inline void pl_AtomicF_Set (PlankAtomicFRef p, PlankF newValue)
00454 {
00455     pl_AtomicF_Swap (p, newValue);
00456 }
00457 
00458 static inline PlankF pl_AtomicF_Add (PlankAtomicFRef p, PlankF operand)
00459 {
00460     PlankF newValue, oldValue;
00461     PlankB success;
00462     
00463     do {
00464         oldValue = *(PlankF*)p;
00465         newValue = oldValue + operand;
00466         success = pl_AtomicF_CompareAndSwap (p, oldValue, newValue);
00467     } while (!success);
00468     
00469     return newValue;
00470 }
00471 
00472 static inline PlankB pl_AtomicF_CompareAndSwap (PlankAtomicFRef p, PlankF oldValue, PlankF newValue)
00473 {    
00474     return OSAtomicCompareAndSwap32Barrier (*(int32_t*)&oldValue, 
00475                                             *(int32_t*)&newValue, 
00476                                             (volatile int32_t*)p);
00477 }
00478 
00479 static inline PlankF pl_AtomicF_Subtract (PlankAtomicFRef p, PlankF operand)
00480 {
00481     return pl_AtomicF_Add (p, -operand);
00482 }
00483 
00484 static inline PlankF pl_AtomicF_Increment (PlankAtomicFRef p)
00485 {
00486     return pl_AtomicF_Add (p, 1.f);
00487 }
00488 
00489 static inline PlankF pl_AtomicF_Decrement (PlankAtomicFRef p)
00490 {
00491     return pl_AtomicF_Add (p, -1.f);
00492 }
00493 
00494 //------------------------------------------------------------------------------
00495 
00496 static inline PlankResult pl_AtomicD_Init (PlankAtomicDRef p)
00497 {
00498     PlankResult result = PlankResult_OK;
00499     
00500     if (p == PLANK_NULL)
00501     {
00502         result = PlankResult_MemoryError;
00503         goto exit;
00504     }
00505     
00506     pl_MemoryZero (p, sizeof (PlankAtomicD));
00507         
00508 exit:
00509     return result;
00510 }
00511 
00512 static inline PlankResult pl_AtomicD_DeInit (PlankAtomicDRef p)
00513 {
00514     PlankResult result = PlankResult_OK;
00515     
00516     if (p == PLANK_NULL)
00517     {
00518         result = PlankResult_MemoryError;
00519         goto exit;
00520     }
00521     
00522 exit:
00523     return result;
00524 }
00525 
00526 static inline PlankD pl_AtomicD_Get (PlankAtomicDRef p)
00527 {
00528     PlankLL bits = pl_AtomicLL_Add ((PlankAtomicLLRef)p, (PlankLL)0); // use the LL version
00529     return *(PlankD*)&bits;
00530 }
00531 
00532 static inline PlankD pl_AtomicD_GetUnchecked (PlankAtomicDRef p)
00533 {
00534     return p->value;
00535 }
00536 
00537 static inline PlankD pl_AtomicD_Swap (PlankAtomicDRef p, PlankD newValue)
00538 {
00539     PlankD oldValue;
00540     PlankB success;
00541     
00542     do {
00543         oldValue = *(PlankD*)p;
00544         success = pl_AtomicD_CompareAndSwap (p, oldValue, newValue);
00545     } while (!success);
00546     
00547     return oldValue;
00548 }
00549 
00550 static inline void pl_AtomicD_SwapOther (PlankAtomicDRef p1, PlankAtomicDRef p2)
00551 {
00552     PlankD value1, value2;
00553     PlankB success;
00554     
00555     do {
00556         value1 = *(PlankD*)p1;
00557         value2 = *(PlankD*)p2;
00558         success = pl_AtomicD_CompareAndSwap (p1, value1, value2);
00559     } while (!success);
00560     
00561     *(PlankD*)p2 = value1;
00562 }
00563 
00564 static inline void pl_AtomicD_Set (PlankAtomicDRef p, PlankD newValue)
00565 {
00566     pl_AtomicD_Swap (p, newValue);
00567 }
00568 
00569 static inline PlankD pl_AtomicD_Add (PlankAtomicDRef p, PlankD operand)
00570 {
00571     PlankD newValue, oldValue;
00572     PlankB success;
00573     
00574     do {
00575         oldValue = *(PlankD*)p;
00576         newValue = oldValue + operand;
00577         success = pl_AtomicD_CompareAndSwap (p, oldValue, newValue);
00578     } while (!success);
00579     
00580     return newValue;
00581 }
00582 
00583 static inline PlankB pl_AtomicD_CompareAndSwap (PlankAtomicDRef p, PlankD oldValue, PlankD newValue)
00584 {    
00585     // must use an integer compare since comparing floating point 
00586     // values doesn't do a bitwise comparison
00587     return pl_AtomicLL_CompareAndSwap ((PlankAtomicLLRef)p, 
00588                                        *(PlankLL*)&oldValue, 
00589                                        *(PlankLL*)&newValue);
00590 }
00591 
00592 static inline PlankD pl_AtomicD_Subtract (PlankAtomicDRef p, PlankD operand)
00593 {
00594     return pl_AtomicD_Add (p, -operand);
00595 }
00596 
00597 static inline PlankD pl_AtomicD_Increment (PlankAtomicDRef p)
00598 {
00599     return pl_AtomicD_Add (p, 1.0);
00600 }
00601 
00602 static inline PlankD pl_AtomicD_Decrement (PlankAtomicDRef p)
00603 {
00604     return pl_AtomicD_Add (p, -1.0);
00605 }
00606 
00607 //------------------------------------------------------------------------------
00608 
00609 static inline PlankResult pl_AtomicP_Init (PlankAtomicPRef p)
00610 {
00611     if (p == PLANK_NULL)
00612         return PlankResult_MemoryError;
00613     
00614     pl_MemoryZero (p, sizeof (PlankAtomicP));
00615     
00616     return PlankResult_OK;
00617 }
00618 
00619 static inline PlankResult pl_AtomicP_DeInit (PlankAtomicPRef p)
00620 {
00621     if (p == PLANK_NULL)
00622         return PlankResult_MemoryError;
00623     return PlankResult_OK;
00624 }
00625 
00626 static inline PlankP pl_AtomicP_Get (PlankAtomicPRef p)
00627 {
00628     return p->ptr; // should be aligned anyway and volatile so OK // pl_AtomicP_Add (p, (PlankL)0);
00629 }
00630 
00631 static inline PlankP pl_AtomicP_GetUnchecked (PlankAtomicPRef p)
00632 {
00633     return p->ptr;
00634 }
00635 
00636 static inline PlankP pl_AtomicP_Swap (PlankAtomicPRef p, PlankP newPtr)
00637 {
00638     PlankP oldPtr;
00639     PlankB success;
00640     
00641     do {
00642         oldPtr = *(PlankP*)p;
00643         success = pl_AtomicP_CompareAndSwap (p, oldPtr, newPtr);
00644     } while (!success);
00645     
00646     return oldPtr;    
00647 }
00648 
00649 static inline void pl_AtomicP_SwapOther (PlankAtomicPRef p1, PlankAtomicPRef p2)
00650 {
00651     PlankP value1, value2;
00652     PlankB success;
00653     
00654     do {
00655         value1 = *(PlankP*)p1;
00656         value2 = *(PlankP*)p2;
00657         success = pl_AtomicP_CompareAndSwap (p1, value1, value2);
00658     } while (!success);
00659     
00660     *(PlankP*)p2 = value1;
00661 }
00662 
00663 static inline void pl_AtomicP_Set (PlankAtomicPRef p, PlankP newPtr)
00664 {
00665     pl_AtomicP_Swap (p, newPtr);
00666 }
00667 
00668 static inline PlankP pl_AtomicP_Add (PlankAtomicPRef p, PlankL operand)
00669 {
00670     return (PlankP)OSAtomicAdd32Barrier (*(int32_t*)&operand, (volatile int32_t*)p);
00671 }
00672 
00673 static inline PlankB pl_AtomicP_CompareAndSwap (PlankAtomicPRef p, PlankP oldValue, PlankP newValue)
00674 {
00675     return OSAtomicCompareAndSwap32Barrier (*(int32_t*)&oldValue, 
00676                                             *(int32_t*)&newValue, 
00677                                             (volatile int32_t*)p);
00678 }
00679 
00680 static inline PlankP pl_AtomicP_Subtract (PlankAtomicPRef p, PlankL operand)
00681 {
00682     return pl_AtomicP_Add (p, -operand);
00683 }
00684 
00685 static inline PlankP pl_AtomicP_Increment (PlankAtomicPRef p)
00686 {
00687     return pl_AtomicP_Add (p, (PlankL)1);
00688 }
00689 
00690 static inline PlankP pl_AtomicP_Decrement (PlankAtomicPRef p)
00691 {
00692     return pl_AtomicP_Add (p, (PlankL)(-1));
00693 }
00694 
00695 //------------------------------------------------------------------------------
00696 
00697 static inline PlankAtomicPXRef pl_AtomicPX_CreateAndInit()
00698 {
00699     PlankAtomicPXRef p = pl_AtomicPX_Create();
00700     if (p != PLANK_NULL) pl_AtomicPX_Init (p);
00701     return p;
00702 }
00703 
00704 static inline PlankAtomicPXRef pl_AtomicPX_Create()
00705 {
00706     PlankMemoryRef m;
00707     PlankAtomicPXRef p;
00708     
00709     m = pl_MemoryGlobal();
00710     p = (PlankAtomicPXRef)pl_Memory_AllocateBytes (m, sizeof (PlankAtomicPX));
00711     
00712     if (p != PLANK_NULL)
00713         pl_MemoryZero (p, sizeof (PlankAtomicPX));
00714     
00715     return p;
00716 }
00717 
00718 static inline PlankResult pl_AtomicPX_Init (PlankAtomicPXRef p)
00719 {
00720     PlankResult result = PlankResult_OK;
00721     
00722     if (p == PLANK_NULL)
00723     {
00724         result = PlankResult_MemoryError;
00725         goto exit;
00726     }
00727     
00728     pl_MemoryZero (p, sizeof (PlankAtomicPX));
00729     
00730 exit:
00731     return result;
00732 }
00733 
00734 static inline PlankResult pl_AtomicPX_DeInit (PlankAtomicPXRef p)
00735 {
00736     PlankResult result = PlankResult_OK;
00737     
00738     if (p == PLANK_NULL)
00739     {
00740         result = PlankResult_MemoryError;
00741         goto exit;
00742     }
00743         
00744 exit:
00745     return result;
00746 }
00747 
00748 static inline PlankResult pl_AtomicPX_Destroy (PlankAtomicPXRef p)
00749 {
00750     PlankResult result;
00751     PlankMemoryRef m;
00752     
00753     result = PlankResult_OK;
00754     m = pl_MemoryGlobal();
00755     
00756     if ((result = pl_AtomicPX_DeInit (p)) != PlankResult_OK)
00757         goto exit;
00758     
00759     result = pl_Memory_Free (m, p);
00760     
00761 exit:
00762     return result;
00763 }
00764 
00765 static inline PlankP pl_AtomicPX_Get (PlankAtomicPXRef p)
00766 {
00767     return p->ptr; // should be aligned anyway and volatile so OK // pl_AtomicP_Get ((PlankAtomicPRef)p);
00768 }
00769 
00770 static inline PlankP pl_AtomicPX_GetUnchecked (PlankAtomicPXRef p)
00771 {
00772     return p->ptr;
00773 }
00774 
00775 static inline PlankUL pl_AtomicPX_GetExtra (PlankAtomicPXRef p)
00776 {
00777     return p->extra; // should be aligned anyway and volatile so OK // pl_AtomicL_Get ((PlankAtomicLRef)&(p->extra));
00778 }
00779 
00780 static inline PlankUL pl_AtomicPX_GetExtraUnchecked (PlankAtomicPXRef p)
00781 {
00782     return p->extra;
00783 }
00784 
00785 static inline PlankP pl_AtomicPX_SwapAll (PlankAtomicPXRef p, PlankP newPtr, PlankUL newExtra, PlankUL* oldExtraPtr)
00786 {
00787     PlankP oldPtr;
00788     PlankUL oldExtra;
00789     PlankB success;
00790     
00791     do {
00792         oldPtr = p->ptr;
00793         oldExtra = p->extra;
00794         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, newExtra);
00795     } while (!success);
00796     
00797     if (oldExtraPtr != PLANK_NULL)
00798         *oldExtraPtr = oldExtra;
00799     
00800     return oldPtr;
00801 }
00802 
00803 static inline PlankP pl_AtomicPX_Swap (PlankAtomicPXRef p, PlankP newPtr)
00804 {
00805     PlankP oldPtr;
00806     PlankUL oldExtra;
00807     PlankB success;
00808     
00809     do {
00810         oldPtr = p->ptr;
00811         oldExtra = p->extra;
00812         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, oldExtra + 1);
00813     } while (!success);
00814     
00815     return oldPtr;
00816 }
00817 
00818 static inline void pl_AtomicPX_SwapOther (PlankAtomicPXRef p1, PlankAtomicPXRef p2)
00819 {
00820     PlankAtomicPX tmp1, tmp2;
00821     PlankB success;
00822     
00823     do {
00824         tmp1 = *p1;
00825         tmp2 = *p2;
00826         success = pl_AtomicPX_CompareAndSwap (p1, tmp1.ptr, tmp1.extra, tmp2.ptr, tmp1.extra + 1);
00827     } while (!success);
00828     
00829     pl_AtomicPX_Set (p2, tmp1.ptr);
00830 }
00831 
00832 static inline void pl_AtomicPX_SetAll (PlankAtomicPXRef p, PlankP newPtr, PlankUL newExtra)
00833 {
00834     pl_AtomicPX_SwapAll (p, newPtr, newExtra, (PlankUL*)PLANK_NULL);
00835 }
00836 
00837 static inline void pl_AtomicPX_Set (PlankAtomicPXRef p, PlankP newPtr)
00838 {
00839     PlankP oldPtr;
00840     PlankUL oldExtra;
00841     PlankB success;
00842     
00843     do {
00844         oldPtr = p->ptr;
00845         oldExtra = p->extra;
00846         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, oldExtra + 1);
00847     } while (!success);
00848 }
00849 
00850 static inline PlankP pl_AtomicPX_Add (PlankAtomicPXRef p, PlankL operand)
00851 {
00852     PlankP newPtr, oldPtr;
00853     PlankUL oldExtra;
00854     PlankB success;
00855     
00856     do {
00857         oldPtr = p->ptr;
00858         oldExtra = p->extra;
00859         newPtr = (PlankUC*)oldPtr + operand;
00860         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, oldExtra + 1);
00861     } while (!success);
00862     
00863     return newPtr;
00864 }
00865 
00866 static inline PlankP pl_AtomicPX_Subtract (PlankAtomicPXRef p, PlankL operand)
00867 {
00868     return pl_AtomicPX_Add (p, -operand);
00869 }
00870 
00871 static inline PlankP pl_AtomicPX_Increment (PlankAtomicPXRef p)
00872 {
00873     return pl_AtomicPX_Add (p, (PlankL)1);
00874 }
00875 
00876 static inline PlankP pl_AtomicPX_Decrement (PlankAtomicPXRef p)
00877 {
00878     return pl_AtomicPX_Add (p, (PlankL)(-1));
00879 }
00880 
00881 static inline PlankB pl_AtomicPX_CompareAndSwap (PlankAtomicPXRef p, PlankP oldPtr, PlankUL oldExtra, PlankP newPtr, PlankL newExtra)
00882 {
00883     PlankAtomicPX oldAll = { oldPtr, oldExtra, { { 0 } } };
00884     PlankAtomicPX newAll = { newPtr, newExtra, { { 0 } } };
00885     
00886     return pl_AtomicLL_CompareAndSwap ((PlankAtomicLLRef)p,
00887                                        *(PlankLL*)&oldAll,
00888                                        *(PlankLL*)&newAll);
00889 }
00890 
00891 static inline PlankB pl_AtomicPX_CompareAndSwapP (PlankAtomicPXRef p, PlankP oldPtr, PlankP newPtr)
00892 {
00893     return pl_AtomicP_CompareAndSwap ((PlankAtomicPRef)p, oldPtr, newPtr);
00894 }
00895 
00896 static inline void pl_AtomicPX_SetAllUnchecked (PlankAtomicPXRef p, PlankP newPtr, PlankUL newExtra)
00897 {
00898     p->ptr = newPtr;
00899     p->extra = newExtra;
00900 }
00901 
00902 #define PLANK_ATOMICS_DEFINED 1
00903 
00904 #endif // PLANK_INLINING_FUNCTIONS
00905 
 All Classes Functions Typedefs Enumerations Enumerator Properties