pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
plank_AtomicInline_Android_ARM_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 typedef struct PlankAtomicLL
00064 {
00065     volatile PlankLL value;
00066 } PlankAtomicLL PLANK_ALIGN(8);
00067 
00068 typedef struct PlankAtomicF
00069 {
00070     volatile PlankF value;
00071 } PlankAtomicF PLANK_ALIGN(4);
00072 
00073 typedef struct PlankAtomicD
00074 {
00075     volatile PlankD value;
00076 } PlankAtomicD PLANK_ALIGN(8);
00077 
00078 typedef struct PlankAtomicP
00079 {
00080     volatile PlankP ptr;
00081 } PlankAtomicP PLANK_ALIGN(4);
00082 
00083 typedef struct PlankAtomicPX
00084 {
00085     volatile PlankP ptr;
00086     volatile PlankUL extra;
00087 } PlankAtomicPX PLANK_ALIGN(8);
00088 #endif
00089 
00090 static inline void pl_AtomicMemoryBarrier()
00091 {
00092     __sync_synchronize();
00093 }
00094 
00095 //------------------------------------------------------------------------------
00096 
00097 static inline PlankResult pl_AtomicI_Init (PlankAtomicIRef p)
00098 {
00099     if (p == PLANK_NULL)
00100         return PlankResult_MemoryError;
00101     
00102     pl_MemoryZero (p, sizeof (PlankAtomicI));
00103     
00104     return PlankResult_OK;
00105 }
00106 
00107 static inline PlankResult pl_AtomicI_DeInit (PlankAtomicIRef p)
00108 {
00109     if (p == PLANK_NULL)
00110         return PlankResult_MemoryError;
00111     return PlankResult_OK;
00112 }
00113 
00114 static inline PlankI pl_AtomicI_Get (PlankAtomicIRef p)
00115 {
00116     return p->value; // should be aligned anyway and volatile so OK // pl_AtomicI_Add (p, 0);
00117 }
00118 
00119 static inline PlankI pl_AtomicI_GetUnchecked (PlankAtomicIRef p)
00120 {
00121     return p->value;
00122 }
00123 
00124 static inline PlankI pl_AtomicI_Swap (PlankAtomicIRef p, PlankI newValue)
00125 {
00126     PlankI oldValue;
00127     PlankB success;
00128     
00129     do {
00130         oldValue = *(PlankI*)p;
00131         success = pl_AtomicI_CompareAndSwap (p, oldValue, newValue);
00132     } while (!success);
00133     
00134     return oldValue;
00135 }
00136 
00137 static inline void pl_AtomicI_SwapOther (PlankAtomicIRef p1, PlankAtomicIRef p2)
00138 {
00139     PlankI value1, value2;
00140     PlankB success;
00141     
00142     do {
00143         value1 = *(PlankI*)p1;
00144         value2 = *(PlankI*)p2;
00145         success = pl_AtomicI_CompareAndSwap (p1, value1, value2);
00146     } while (!success);
00147     
00148     *(PlankI*)p2 = value1;
00149 }
00150 
00151 static inline void pl_AtomicI_Set (PlankAtomicIRef p, PlankI newValue)
00152 {
00153     pl_AtomicI_Swap (p, newValue);
00154 }
00155 
00156 static inline PlankI pl_AtomicI_Add (PlankAtomicIRef p, PlankI operand)
00157 {
00158     return __sync_add_and_fetch ((volatile PlankI*)p, operand);
00159 }
00160 
00161 static inline PlankB  pl_AtomicI_CompareAndSwap (PlankAtomicIRef p, PlankI oldValue, PlankI newValue)
00162 {
00163     return __sync_bool_compare_and_swap ((volatile PlankI*)p,
00164                                          oldValue,
00165                                          newValue);
00166 }
00167 
00168 static inline PlankI pl_AtomicI_Subtract (PlankAtomicIRef p, PlankI operand)
00169 {
00170     return pl_AtomicI_Add (p, -operand);
00171 }
00172 
00173 static inline PlankI pl_AtomicI_Increment (PlankAtomicIRef p)
00174 {
00175     return pl_AtomicI_Add (p, 1);
00176 }
00177 
00178 static inline PlankI pl_AtomicI_Decrement (PlankAtomicIRef p)
00179 {
00180     return pl_AtomicI_Add (p, -1);
00181 }
00182 
00183 //------------------------------------------------------------------------------
00184 
00185 static inline PlankResult pl_AtomicL_Init (PlankAtomicLRef p)
00186 {
00187     if (p == PLANK_NULL)
00188         return PlankResult_MemoryError;
00189     
00190     pl_MemoryZero (p, sizeof (PlankAtomicL));
00191     
00192     return PlankResult_OK;
00193 }
00194 
00195 static inline PlankResult pl_AtomicL_DeInit (PlankAtomicLRef p)
00196 {
00197     if (p == PLANK_NULL)
00198         return PlankResult_MemoryError;
00199     return PlankResult_OK;
00200 }
00201 
00202 static inline PlankL pl_AtomicL_Get (PlankAtomicLRef p)
00203 {
00204     return p->value; // should be aligned anyway and volatile so OK // pl_AtomicL_Add (p, (PlankL)0);
00205 }
00206 
00207 static inline PlankL pl_AtomicL_GetUnchecked (PlankAtomicLRef p)
00208 {
00209     return p->value;
00210 }
00211 
00212 static inline PlankL pl_AtomicL_Swap (PlankAtomicLRef p, PlankL newValue)
00213 {
00214     PlankL oldValue;
00215     PlankB success;
00216     
00217     do {
00218         oldValue = *(PlankL*)p;
00219         success = pl_AtomicL_CompareAndSwap (p, oldValue, newValue);
00220     } while (!success);
00221     
00222     return oldValue;
00223 }
00224 
00225 static inline void pl_AtomicL_SwapOther (PlankAtomicLRef p1, PlankAtomicLRef p2)
00226 {
00227     PlankL value1, value2;
00228     PlankB success;
00229     
00230     do {
00231         value1 = *(PlankL*)p1;
00232         value2 = *(PlankL*)p2;
00233         success = pl_AtomicL_CompareAndSwap (p1, value1, value2);
00234     } while (!success);
00235     
00236     *(PlankL*)p2 = value1;
00237 }
00238 
00239 static inline void pl_AtomicL_Set (PlankAtomicLRef p, PlankL newValue)
00240 {
00241     pl_AtomicL_Swap (p, newValue);
00242 }
00243 
00244 static inline PlankL pl_AtomicL_Add (PlankAtomicLRef p, PlankL operand)
00245 {
00246     return __sync_add_and_fetch ((volatile PlankL*)p, operand);
00247 }
00248 
00249 static inline PlankB pl_AtomicL_CompareAndSwap (PlankAtomicLRef p, PlankL oldValue, PlankL newValue)
00250 {
00251     return __sync_bool_compare_and_swap ((volatile PlankL*)p,
00252                                          oldValue,
00253                                          newValue);
00254 }
00255 
00256 static inline PlankL pl_AtomicL_Subtract (PlankAtomicLRef p, PlankL operand)
00257 {
00258     return pl_AtomicL_Add (p, -operand);
00259 }
00260 
00261 static inline PlankL pl_AtomicL_Increment (PlankAtomicLRef p)
00262 {
00263     return pl_AtomicL_Add (p, (PlankL)1);
00264 }
00265 
00266 static inline PlankL pl_AtomicL_Decrement (PlankAtomicLRef p)
00267 {
00268     return pl_AtomicL_Add (p, (PlankL)(-1));
00269 }
00270 
00271 //------------------------------------------------------------------------------
00272 
00273 static inline PlankResult pl_AtomicLL_Init (PlankAtomicLLRef p)
00274 {
00275     PlankResult result = PlankResult_OK;
00276     
00277     if (p == PLANK_NULL)
00278     {
00279         result = PlankResult_MemoryError;
00280         goto exit;
00281     }
00282     
00283     pl_MemoryZero (p, sizeof (PlankAtomicLL));
00284     
00285 exit:
00286     return result;
00287 }
00288 
00289 static inline PlankResult pl_AtomicLL_DeInit (PlankAtomicLLRef p)
00290 {
00291     PlankResult result = PlankResult_OK;
00292     
00293     if (p == PLANK_NULL)
00294     {
00295         result = PlankResult_MemoryError;
00296         goto exit;
00297     }
00298         
00299 exit:
00300     return result;
00301 }
00302 
00303 static inline PlankLL pl_AtomicLL_Get (PlankAtomicLLRef p)
00304 {
00305     return pl_AtomicLL_Add (p, (PlankLL)0);
00306 }
00307 
00308 static inline PlankLL pl_AtomicLL_GetUnchecked (PlankAtomicLLRef p)
00309 {
00310     return p->value;
00311 }
00312 
00313 static inline PlankLL pl_AtomicLL_Swap (PlankAtomicLLRef p, PlankLL newValue)
00314 {
00315     PlankLL oldValue;
00316     PlankB success;
00317     
00318     do {
00319         oldValue = *(PlankLL*)p;
00320         success = pl_AtomicLL_CompareAndSwap (p, oldValue, newValue);
00321     } while (!success);
00322     
00323     return oldValue;
00324 }
00325 
00326 static inline void pl_AtomicLL_SwapOther (PlankAtomicLLRef p1, PlankAtomicLLRef p2)
00327 {
00328     PlankLL value1, value2;
00329     PlankB success;
00330     
00331     do {
00332         value1 = *(PlankLL*)p1;
00333         value2 = *(PlankLL*)p2;
00334         success = pl_AtomicLL_CompareAndSwap (p1, value1, value2);
00335     } while (!success);
00336     
00337     *(PlankLL*)p2 = value1;
00338 }
00339 
00340 static inline void pl_AtomicLL_Set (PlankAtomicLLRef p, PlankLL newValue)
00341 {
00342     pl_AtomicLL_Swap (p, newValue);
00343 }
00344 
00345 static inline PlankLL pl_AtomicLL_Add (PlankAtomicLLRef p, PlankLL operand)
00346 {
00347     return __sync_add_and_fetch ((volatile PlankLL*)p, operand);
00348 }
00349 
00350 static inline PlankB pl_AtomicLL_CompareAndSwap (PlankAtomicLLRef p, PlankLL oldValue, PlankLL newValue)
00351 {
00352     return __sync_bool_compare_and_swap ((volatile PlankLL*)p,
00353                                          oldValue,
00354                                          newValue);
00355 }
00356 
00357 static inline PlankLL pl_AtomicLL_Subtract (PlankAtomicLLRef p, PlankLL operand)
00358 {
00359     return pl_AtomicLL_Add (p, -operand);
00360 }
00361 
00362 static inline PlankLL pl_AtomicLL_Increment (PlankAtomicLLRef p)
00363 {
00364     return pl_AtomicLL_Add (p, (PlankLL)1);
00365 }
00366 
00367 static inline PlankLL pl_AtomicLL_Decrement (PlankAtomicLLRef p)
00368 {
00369     return pl_AtomicLL_Add (p, (PlankLL)(-1));
00370 }
00371 
00372 //------------------------------------------------------------------------------
00373 
00374 static inline PlankResult pl_AtomicF_Init (PlankAtomicFRef p)
00375 {
00376     if (p == PLANK_NULL)
00377         return PlankResult_MemoryError;
00378     
00379     pl_MemoryZero (p, sizeof (PlankAtomicF));
00380     
00381     return PlankResult_OK;
00382 }
00383 
00384 static inline PlankResult pl_AtomicF_DeInit (PlankAtomicFRef p)
00385 {
00386     if (p == PLANK_NULL)
00387         return PlankResult_MemoryError;
00388     return PlankResult_OK;
00389 }
00390 
00391 static inline PlankF pl_AtomicF_Get (PlankAtomicFRef p)
00392 {    
00393     return p->value; // should be aligned anyway and volatile so OK
00394 }
00395 
00396 static inline PlankF pl_AtomicF_GetUnchecked (PlankAtomicFRef p)
00397 {
00398     return  p->value;
00399 }
00400 
00401 static inline PlankF pl_AtomicF_Swap (PlankAtomicFRef p, PlankF newValue)
00402 {
00403     PlankF oldValue;
00404     PlankB success;
00405     
00406     do
00407     {
00408         oldValue = *(PlankF*)p;
00409         success = pl_AtomicF_CompareAndSwap (p, oldValue, newValue);
00410     } while (!success);
00411     
00412     return oldValue;
00413 }
00414 
00415 static inline void pl_AtomicF_SwapOther (PlankAtomicFRef p1, PlankAtomicFRef p2)
00416 {
00417     PlankF value1, value2;
00418     PlankB success;
00419     
00420     do {
00421         value1 = *(PlankF*)p1;
00422         value2 = *(PlankF*)p2;
00423         success = pl_AtomicF_CompareAndSwap (p1, value1, value2);
00424     } while (!success);
00425     
00426     *(PlankF*)p2 = value1;
00427 }
00428 
00429 static inline void pl_AtomicF_Set (PlankAtomicFRef p, PlankF newValue)
00430 {
00431     pl_AtomicF_Swap (p, newValue);
00432 }
00433 
00434 static inline PlankF pl_AtomicF_Add (PlankAtomicFRef p, PlankF operand)
00435 {
00436     PlankF newValue, oldValue;
00437     PlankB success;
00438     
00439     do {
00440         oldValue = *(PlankF*)p;
00441         newValue = oldValue + operand;
00442         success = pl_AtomicF_CompareAndSwap (p, oldValue, newValue);
00443     } while (!success);
00444     
00445     return newValue;
00446 }
00447 
00448 static inline PlankB pl_AtomicF_CompareAndSwap (PlankAtomicFRef p, PlankF oldValue, PlankF newValue)
00449 {
00450     return __sync_bool_compare_and_swap ((volatile PlankI*)p,
00451                                          *(PlankI*)&oldValue,
00452                                          *(PlankI*)&newValue);
00453 }
00454 
00455 static inline PlankF pl_AtomicF_Subtract (PlankAtomicFRef p, PlankF operand)
00456 {
00457     return pl_AtomicF_Add (p, -operand);
00458 }
00459 
00460 static inline PlankF pl_AtomicF_Increment (PlankAtomicFRef p)
00461 {
00462     return pl_AtomicF_Add (p, 1.f);
00463 }
00464 
00465 static inline PlankF pl_AtomicF_Decrement (PlankAtomicFRef p)
00466 {
00467     return pl_AtomicF_Add (p, -1.f);
00468 }
00469 
00470 //------------------------------------------------------------------------------
00471 
00472 static inline PlankResult pl_AtomicD_Init (PlankAtomicDRef p)
00473 {
00474     PlankResult result = PlankResult_OK;
00475     
00476     if (p == PLANK_NULL)
00477     {
00478         result = PlankResult_MemoryError;
00479         goto exit;
00480     }
00481     
00482     pl_MemoryZero (p, sizeof (PlankAtomicD));
00483     
00484 exit:
00485     return result;
00486 }
00487 
00488 static inline PlankResult pl_AtomicD_DeInit (PlankAtomicDRef p)
00489 {
00490     PlankResult result = PlankResult_OK;
00491     
00492     if (p == PLANK_NULL)
00493     {
00494         result = PlankResult_MemoryError;
00495         goto exit;
00496     }
00497         
00498 exit:
00499     return result;
00500 }
00501 
00502 static inline PlankD pl_AtomicD_Get (PlankAtomicDRef p)
00503 {
00504     PlankLL bits = pl_AtomicLL_Add ((PlankAtomicLLRef)p, (PlankLL)0); // use the LL version
00505     return *(PlankD*)&bits;
00506 }
00507 
00508 static inline PlankD pl_AtomicD_GetUnchecked (PlankAtomicDRef p)
00509 {
00510     return p->value;
00511 }
00512 
00513 static inline PlankD pl_AtomicD_Swap (PlankAtomicDRef p, PlankD newValue)
00514 {
00515     PlankD oldValue;
00516     PlankB success;
00517     
00518     do {
00519         oldValue = *(PlankD*)p;
00520         success = pl_AtomicD_CompareAndSwap (p, oldValue, newValue);
00521     } while (!success);
00522     
00523     return oldValue;
00524 }
00525 
00526 static inline void pl_AtomicD_SwapOther (PlankAtomicDRef p1, PlankAtomicDRef p2)
00527 {
00528     PlankD value1, value2;
00529     PlankB success;
00530     
00531     do {
00532         value1 = *(PlankD*)p1;
00533         value2 = *(PlankD*)p2;
00534         success = pl_AtomicD_CompareAndSwap (p1, value1, value2);
00535     } while (!success);
00536     
00537     *(PlankD*)p2 = value1;
00538 }
00539 
00540 static inline void pl_AtomicD_Set (PlankAtomicDRef p, PlankD newValue)
00541 {
00542     pl_AtomicD_Swap (p, newValue);
00543 }
00544 
00545 static inline PlankD pl_AtomicD_Add (PlankAtomicDRef p, PlankD operand)
00546 {
00547     PlankD newValue, oldValue;
00548     PlankB success;
00549     
00550     do {
00551         oldValue = *(PlankD*)p;
00552         newValue = oldValue + operand;
00553         success = pl_AtomicD_CompareAndSwap (p, oldValue, newValue);
00554     } while (!success);
00555     
00556     return newValue;
00557 }
00558 
00559 static inline PlankB pl_AtomicD_CompareAndSwap (PlankAtomicDRef p, PlankD oldValue, PlankD newValue)
00560 {
00561     return __sync_bool_compare_and_swap ((volatile PlankLL*)p,
00562                                          *(PlankLL*)&oldValue,
00563                                          *(PlankLL*)&newValue);
00564 }
00565 
00566 static inline PlankD pl_AtomicD_Subtract (PlankAtomicDRef p, PlankD operand)
00567 {
00568     return pl_AtomicD_Add (p, -operand);
00569 }
00570 
00571 static inline PlankD pl_AtomicD_Increment (PlankAtomicDRef p)
00572 {
00573     return pl_AtomicD_Add (p, 1.0);
00574 }
00575 
00576 static inline PlankD pl_AtomicD_Decrement (PlankAtomicDRef p)
00577 {
00578     return pl_AtomicD_Add (p, -1.0);
00579 }
00580 
00581 //------------------------------------------------------------------------------
00582 
00583 static inline PlankResult pl_AtomicP_Init (PlankAtomicPRef p)
00584 {
00585     if (p == PLANK_NULL)
00586         return PlankResult_MemoryError;
00587     
00588     pl_MemoryZero (p, sizeof (PlankAtomicP));
00589     
00590     return PlankResult_OK;
00591 }
00592 
00593 static inline PlankResult pl_AtomicP_DeInit (PlankAtomicPRef p)
00594 {
00595     if (p == PLANK_NULL)
00596         return PlankResult_MemoryError;
00597     return PlankResult_OK;
00598 }
00599 
00600 static inline PlankP pl_AtomicP_Get (PlankAtomicPRef p)
00601 {
00602     return p->ptr; // should be aligned anyway and volatile so OK // pl_AtomicP_Add (p, (PlankL)0);
00603 }
00604 
00605 static inline PlankP pl_AtomicP_GetUnchecked (PlankAtomicPRef p)
00606 {
00607     return p->ptr;
00608 }
00609 
00610 static inline PlankP pl_AtomicP_Swap (PlankAtomicPRef p, PlankP newPtr)
00611 {
00612     PlankP oldPtr;
00613     PlankB success;
00614     
00615     do {
00616         oldPtr = *(PlankP*)p;
00617         success = pl_AtomicP_CompareAndSwap (p, oldPtr, newPtr);
00618     } while (!success);
00619     
00620     return oldPtr;    
00621 }
00622 
00623 static inline void pl_AtomicP_SwapOther (PlankAtomicPRef p1, PlankAtomicPRef p2)
00624 {
00625     PlankP value1, value2;
00626     PlankB success;
00627     
00628     do {
00629         value1 = *(PlankP*)p1;
00630         value2 = *(PlankP*)p2;
00631         success = pl_AtomicP_CompareAndSwap (p1, value1, value2);
00632     } while (!success);
00633     
00634     *(PlankP*)p2 = value1;
00635 }
00636 
00637 static inline void pl_AtomicP_Set (PlankAtomicPRef p, PlankP newPtr)
00638 {
00639     pl_AtomicP_Swap (p, newPtr);
00640 }
00641 
00642 static inline PlankP pl_AtomicP_Add (PlankAtomicPRef p, PlankL operand)
00643 {
00644     return (PlankP)__sync_add_and_fetch ((volatile PlankL*)p, operand);
00645 }
00646 
00647 static inline PlankB pl_AtomicP_CompareAndSwap (PlankAtomicPRef p, PlankP oldValue, PlankP newValue)
00648 {
00649     return __sync_bool_compare_and_swap ((volatile PlankL*)p,
00650                                          *(PlankL*)&oldValue,
00651                                          *(PlankL*)&newValue);
00652 }
00653 
00654 static inline PlankP pl_AtomicP_Subtract (PlankAtomicPRef p, PlankL operand)
00655 {
00656     return pl_AtomicP_Add (p, -operand);
00657 }
00658 
00659 static inline PlankP pl_AtomicP_Increment (PlankAtomicPRef p)
00660 {
00661     return pl_AtomicP_Add (p, (PlankL)1);
00662 }
00663 
00664 static inline PlankP pl_AtomicP_Decrement (PlankAtomicPRef p)
00665 {
00666     return pl_AtomicP_Add (p, (PlankL)(-1));
00667 }
00668 
00669 //------------------------------------------------------------------------------
00670 
00671 static inline PlankAtomicPXRef pl_AtomicPX_CreateAndInit()
00672 {
00673     PlankAtomicPXRef p = pl_AtomicPX_Create();
00674     if (p != PLANK_NULL) pl_AtomicPX_Init (p);
00675     return p;
00676 }
00677 
00678 static inline PlankAtomicPXRef pl_AtomicPX_Create()
00679 {
00680     PlankMemoryRef m;
00681     PlankAtomicPXRef p;
00682     
00683     m = pl_MemoryGlobal();
00684     p = (PlankAtomicPXRef)pl_Memory_AllocateBytes (m, sizeof (PlankAtomicPX));
00685     
00686     if (p != PLANK_NULL)
00687         pl_MemoryZero (p, sizeof (PlankAtomicPX));
00688     
00689     return p;
00690 }
00691 
00692 static inline PlankResult pl_AtomicPX_Init (PlankAtomicPXRef p)
00693 {
00694     PlankResult result = PlankResult_OK;
00695     
00696     if (p == PLANK_NULL)
00697     {
00698         result = PlankResult_MemoryError;
00699         goto exit;
00700     }
00701     
00702     pl_MemoryZero (p, sizeof (PlankAtomicPX));
00703     
00704 exit:
00705     return result;
00706 }
00707 
00708 static inline PlankResult pl_AtomicPX_DeInit (PlankAtomicPXRef p)
00709 {
00710     PlankResult result = PlankResult_OK;
00711     
00712     if (p == PLANK_NULL)
00713     {
00714         result = PlankResult_MemoryError;
00715         goto exit;
00716     }
00717         
00718 exit:
00719     return result;
00720 }
00721 
00722 static inline PlankResult pl_AtomicPX_Destroy (PlankAtomicPXRef p)
00723 {
00724     PlankResult result;
00725     PlankMemoryRef m;
00726     
00727     result = PlankResult_OK;
00728     m = pl_MemoryGlobal();
00729     
00730     if ((result = pl_AtomicPX_DeInit (p)) != PlankResult_OK)
00731         goto exit;
00732     
00733     result = pl_Memory_Free (m, p);
00734     
00735 exit:
00736     return result;
00737 }
00738 
00739 static inline PlankP pl_AtomicPX_Get (PlankAtomicPXRef p)
00740 {
00741     return p->ptr; // should be aligned anyway and volatile so OK // pl_AtomicP_Get ((PlankAtomicPRef)p);
00742 }
00743 
00744 static inline PlankP pl_AtomicPX_GetUnchecked (PlankAtomicPXRef p)
00745 {
00746     return p->ptr;
00747 }
00748 
00749 static inline PlankUL pl_AtomicPX_GetExtra (PlankAtomicPXRef p)
00750 {
00751     return p->extra; // should be aligned anyway and volatile so OK // pl_AtomicL_Get ((PlankAtomicLRef)&(p->extra));
00752 }
00753 
00754 static inline PlankUL pl_AtomicPX_GetExtraUnchecked (PlankAtomicPXRef p)
00755 {
00756     return p->extra;
00757 }
00758 
00759 static inline PlankP pl_AtomicPX_SwapAll (PlankAtomicPXRef p, PlankP newPtr, PlankUL newExtra, PlankUL* oldExtraPtr)
00760 {
00761     PlankP oldPtr;
00762     PlankUL oldExtra;
00763     PlankB success;
00764     
00765     do {
00766         oldPtr = p->ptr;
00767         oldExtra = p->extra;
00768         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, newExtra);
00769     } while (!success);
00770     
00771     if (oldExtraPtr != PLANK_NULL)
00772         *oldExtraPtr = oldExtra;
00773     
00774     return oldPtr;
00775 }
00776 
00777 static inline PlankP pl_AtomicPX_Swap (PlankAtomicPXRef p, PlankP newPtr)
00778 {
00779     PlankP oldPtr;
00780     PlankUL oldExtra;
00781     PlankB success;
00782     
00783     do {
00784         oldPtr = p->ptr;
00785         oldExtra = p->extra;
00786         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, oldExtra + 1);
00787     } while (!success);
00788     
00789     return oldPtr;
00790 }
00791 
00792 static inline void pl_AtomicPX_SwapOther (PlankAtomicPXRef p1, PlankAtomicPXRef p2)
00793 {
00794     PlankAtomicPX tmp1, tmp2;
00795     PlankB success;
00796     
00797     do {
00798         tmp1 = *p1;
00799         tmp2 = *p2;
00800         success = pl_AtomicPX_CompareAndSwap (p1, tmp1.ptr, tmp1.extra, tmp2.ptr, tmp1.extra + 1);
00801     } while (!success);
00802     
00803     pl_AtomicPX_Set (p2, tmp1.ptr);
00804 }
00805 
00806 static inline void pl_AtomicPX_SetAll (PlankAtomicPXRef p, PlankP newPtr, PlankUL newExtra)
00807 {
00808     pl_AtomicPX_SwapAll (p, newPtr, newExtra, (PlankUL*)PLANK_NULL);
00809 }
00810 
00811 static inline void pl_AtomicPX_Set (PlankAtomicPXRef p, PlankP newPtr)
00812 {
00813     PlankP oldPtr;
00814     PlankUL oldExtra;
00815     PlankB success;
00816     
00817     do {
00818         oldPtr = p->ptr;
00819         oldExtra = p->extra;
00820         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, oldExtra + 1);
00821     } while (!success);
00822 }
00823 
00824 static inline PlankP pl_AtomicPX_Add (PlankAtomicPXRef p, PlankL operand)
00825 {
00826     PlankP newPtr, oldPtr;
00827     PlankUL oldExtra;
00828     PlankB success;
00829     
00830     do {
00831         oldPtr = p->ptr;
00832         oldExtra = p->extra;
00833         newPtr = (PlankUC*)oldPtr + operand;
00834         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, oldExtra + 1);
00835     } while (!success);
00836     
00837     return newPtr;
00838 }
00839 
00840 static inline PlankP pl_AtomicPX_Subtract (PlankAtomicPXRef p, PlankL operand)
00841 {
00842     return pl_AtomicPX_Add (p, -operand);
00843 }
00844 
00845 static inline PlankP pl_AtomicPX_Increment (PlankAtomicPXRef p)
00846 {
00847     return pl_AtomicPX_Add (p, (PlankL)1);
00848 }
00849 
00850 static inline PlankP pl_AtomicPX_Decrement (PlankAtomicPXRef p)
00851 {
00852     return pl_AtomicPX_Add (p, (PlankL)(-1));
00853 }
00854 
00855 static inline  PlankB pl_AtomicPX_CompareAndSwap (PlankAtomicPXRef p, PlankP oldPtr, PlankUL oldExtra, PlankP newPtr, PlankUL newExtra)
00856 {
00857     PlankAtomicPX oldAll = { oldPtr, oldExtra };
00858     PlankAtomicPX newAll = { newPtr, newExtra };
00859     
00860     return __sync_bool_compare_and_swap ((volatile PlankLL*)p,
00861                                          *(PlankLL*)&oldAll,
00862                                          *(PlankLL*)&newAll);
00863 }
00864 
00865 static inline PlankB pl_AtomicPX_CompareAndSwapP (PlankAtomicPXRef p, PlankP oldPtr, PlankP newPtr)
00866 {
00867     return pl_AtomicP_CompareAndSwap ((PlankAtomicPRef)p, oldPtr, newPtr);
00868 }
00869 
00870 static inline void pl_AtomicPX_SetAllUnchecked (PlankAtomicPXRef p, PlankP newPtr, PlankUL newExtra)
00871 {
00872     p->ptr = newPtr;
00873     p->extra = newExtra;
00874 }
00875 
00876 #define PLANK_ATOMICS_DEFINED 1
00877 
00878 #endif // PLANK_INLINING_FUNCTIONS
00879 
 All Classes Functions Typedefs Enumerations Enumerator Properties