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