pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
plank_AtomicInline_Mac_X86_64.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          64
00043 #define PLANK_ATOMIC_XREFCOUNTBITS  32
00044 #define PLANK_ATOMIC_XWEAKCOUNTBITS 32
00045 #define PLANK_ATOMIC_XREFCOUNTMAX   0x00000000FFFFFFFFUL
00046 #define PLANK_ATOMIC_XREFCOUNTMASK  PLANK_ATOMIC_XREFCOUNTMAX
00047 #define PLANK_ATOMIC_XWEAKCOUNTMAX  0x00000000FFFFFFFFUL
00048 #define PLANK_ATOMIC_XWEAKCOUNTMASK 0xFFFFFFFF00000000UL
00049 #define PLANK_ATOMIC_XMAX           0xFFFFFFFFFFFFFFFFUL
00050 #define PLANK_ATOMIC_PMASK          0xFFFFFFFFFFFFFFFFUL
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(8);
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(8);
00082 
00083 typedef struct PlankAtomicPX
00084 {
00085     volatile PlankP ptr;
00086     volatile PlankUL extra;
00087 } PlankAtomicPX PLANK_ALIGN(16);
00088 #endif
00089 
00090 static inline void pl_AtomicMemoryBarrier()
00091 {
00092     OSMemoryBarrier();
00093 }
00094 
00095 //------------------------------------------------------------------------------
00096 static inline PlankResult pl_AtomicI_Init (PlankAtomicIRef p)
00097 {
00098     if (p == PLANK_NULL)
00099         return PlankResult_MemoryError;
00100     
00101     pl_MemoryZero (p, sizeof (PlankAtomicI));
00102     
00103     return PlankResult_OK;
00104 }
00105 
00106 static inline PlankResult pl_AtomicI_DeInit (PlankAtomicIRef p)
00107 {
00108     if (p == PLANK_NULL)
00109         return PlankResult_MemoryError;
00110     return PlankResult_OK;
00111 }
00112 
00113 static inline PlankI pl_AtomicI_Get (PlankAtomicIRef p)
00114 {
00115     return p->value; // should be aligned anyway and volatile so OK // pl_AtomicI_Add (p, 0);
00116 }
00117 
00118 static inline PlankI pl_AtomicI_GetUnchecked (PlankAtomicIRef p)
00119 {
00120     return p->value;
00121 }
00122 
00123 static inline PlankI pl_AtomicI_Swap (PlankAtomicIRef p, PlankI newValue)
00124 {
00125     PlankI oldValue;
00126     PlankB success;
00127     
00128     do {
00129         oldValue = *(PlankI*)p;
00130         success = pl_AtomicI_CompareAndSwap (p, oldValue, newValue);
00131     } while (!success);
00132     
00133     return oldValue;
00134 }
00135 
00136 static inline void pl_AtomicI_SwapOther (PlankAtomicIRef p1, PlankAtomicIRef p2)
00137 {
00138     PlankI value1, value2;
00139     PlankB success;
00140     
00141     do {
00142         value1 = *(PlankI*)p1;
00143         value2 = *(PlankI*)p2;
00144         success = pl_AtomicI_CompareAndSwap (p1, value1, value2);
00145     } while (!success);
00146     
00147     *(PlankI*)p2 = value1;
00148 }
00149 
00150 static inline void pl_AtomicI_Set (PlankAtomicIRef p, PlankI newValue)
00151 {
00152     pl_AtomicI_Swap (p, newValue);
00153 }
00154 
00155 static inline PlankI pl_AtomicI_Add (PlankAtomicIRef p, PlankI operand)
00156 {
00157     return OSAtomicAdd32Barrier (*(int32_t*)&operand, 
00158                                  (volatile int32_t*)p);
00159 }
00160 
00161 static inline PlankB  pl_AtomicI_CompareAndSwap (PlankAtomicIRef p, PlankI oldValue, PlankI newValue)
00162 {    
00163     return OSAtomicCompareAndSwap32Barrier (*(int32_t*)&oldValue, 
00164                                             *(int32_t*)&newValue, 
00165                                             (volatile int32_t*)p);
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 OSAtomicAdd64Barrier (*(int64_t*)&operand, 
00246                                  (volatile int64_t*)p);
00247 }
00248 
00249 static inline PlankB  pl_AtomicL_CompareAndSwap (PlankAtomicLRef p, PlankL oldValue, PlankL newValue)
00250 {    
00251     return OSAtomicCompareAndSwap64Barrier (*(int64_t*)&oldValue, 
00252                                             *(int64_t*)&newValue, 
00253                                             (volatile int64_t*)p);
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     p->value = 0;
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 p->value; // should be aligned anyway and volatile so OK
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 OSAtomicAdd64Barrier (*(int64_t*)&operand, 
00348                                  (volatile int64_t*)p);
00349 }
00350 
00351 static inline PlankB pl_AtomicLL_CompareAndSwap (PlankAtomicLLRef p, PlankLL oldValue, PlankLL newValue)
00352 {    
00353     return OSAtomicCompareAndSwap64Barrier (*(int64_t*)&oldValue, 
00354                                             *(int64_t*)&newValue, 
00355                                             (volatile int64_t*)p);
00356 }
00357 
00358 static inline PlankLL pl_AtomicLL_Subtract (PlankAtomicLLRef p, PlankLL operand)
00359 {
00360     return pl_AtomicLL_Add (p, -operand);
00361 }
00362 
00363 static inline PlankLL pl_AtomicLL_Increment (PlankAtomicLLRef p)
00364 {
00365     return pl_AtomicLL_Add (p, (PlankLL)1);
00366 }
00367 
00368 static inline PlankLL pl_AtomicLL_Decrement (PlankAtomicLLRef p)
00369 {
00370     return pl_AtomicLL_Add (p, (PlankLL)(-1));
00371 }
00372 
00373 //------------------------------------------------------------------------------
00374 
00375 static inline PlankResult pl_AtomicF_Init (PlankAtomicFRef p)
00376 {
00377     if (p == PLANK_NULL)
00378         return PlankResult_MemoryError;
00379     
00380     pl_MemoryZero (p, sizeof (PlankAtomicF));
00381     
00382     return PlankResult_OK;
00383 }
00384 
00385 static inline PlankResult pl_AtomicF_DeInit (PlankAtomicFRef p)
00386 {
00387     if (p == PLANK_NULL)
00388         return PlankResult_MemoryError;
00389     return PlankResult_OK;
00390 }
00391 
00392 static inline PlankF pl_AtomicF_Get (PlankAtomicFRef p)
00393 {    
00394     return p->value; // should be aligned anyway and volatile so OK
00395 }
00396 
00397 static inline PlankF pl_AtomicF_GetUnchecked (PlankAtomicFRef p)
00398 {
00399     return  p->value;
00400 }
00401 
00402 static inline PlankF pl_AtomicF_Swap (PlankAtomicFRef p, PlankF newValue)
00403 {
00404     PlankF oldValue;
00405     PlankB success;
00406     
00407     do
00408     {
00409         oldValue = *(PlankF*)p;
00410         success = pl_AtomicF_CompareAndSwap (p, oldValue, newValue);
00411     } while (!success);
00412     
00413     return oldValue;
00414 }
00415 
00416 static inline void pl_AtomicF_SwapOther (PlankAtomicFRef p1, PlankAtomicFRef p2)
00417 {
00418     PlankF value1, value2;
00419     PlankB success;
00420     
00421     do {
00422         value1 = *(PlankF*)p1;
00423         value2 = *(PlankF*)p2;
00424         success = pl_AtomicF_CompareAndSwap (p1, value1, value2);
00425     } while (!success);
00426     
00427     *(PlankF*)p2 = value1;
00428 }
00429 
00430 static inline void pl_AtomicF_Set (PlankAtomicFRef p, PlankF newValue)
00431 {
00432     pl_AtomicF_Swap (p, newValue);
00433 }
00434 
00435 static inline PlankF pl_AtomicF_Add (PlankAtomicFRef p, PlankF operand)
00436 {
00437     PlankF newValue, oldValue;
00438     PlankB success;
00439     
00440     do {
00441         oldValue = *(PlankF*)p;
00442         newValue = oldValue + operand;
00443         success = pl_AtomicF_CompareAndSwap (p, oldValue, newValue);
00444     } while (!success);
00445     
00446     return newValue;
00447 }
00448 
00449 static inline PlankB pl_AtomicF_CompareAndSwap (PlankAtomicFRef p, PlankF oldValue, PlankF newValue)
00450 {    
00451     return OSAtomicCompareAndSwap32Barrier (*(int32_t*)&oldValue, 
00452                                             *(int32_t*)&newValue, 
00453                                             (volatile int32_t*)p);
00454 }
00455 
00456 static inline PlankF pl_AtomicF_Subtract (PlankAtomicFRef p, PlankF operand)
00457 {
00458     return pl_AtomicF_Add (p, -operand);
00459 }
00460 
00461 static inline PlankF pl_AtomicF_Increment (PlankAtomicFRef p)
00462 {
00463     return pl_AtomicF_Add (p, 1.f);
00464 }
00465 
00466 static inline PlankF pl_AtomicF_Decrement (PlankAtomicFRef p)
00467 {
00468     return pl_AtomicF_Add (p, -1.f);
00469 }
00470 
00471 //------------------------------------------------------------------------------
00472 
00473 static inline PlankResult pl_AtomicD_Init (PlankAtomicDRef p)
00474 {
00475     PlankResult result = PlankResult_OK;
00476     
00477     if (p == PLANK_NULL)
00478     {
00479         result = PlankResult_MemoryError;
00480         goto exit;
00481     }
00482         
00483     p->value = 0.0;
00484     
00485 exit:
00486     return result;
00487 }
00488 
00489 static inline PlankResult pl_AtomicD_DeInit (PlankAtomicDRef p)
00490 {
00491     PlankResult result = PlankResult_OK;
00492     
00493     if (p == PLANK_NULL)
00494     {
00495         result = PlankResult_MemoryError;
00496         goto exit;
00497     }
00498         
00499 exit:
00500     return result;
00501 }
00502 
00503 static inline PlankD pl_AtomicD_Get (PlankAtomicDRef p)
00504 {
00505     return p->value; // should be aligned anyway and volatile so OK
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 OSAtomicCompareAndSwap64Barrier (*(int64_t*)&oldValue, 
00562                                             *(int64_t*)&newValue, 
00563                                             (volatile int64_t*)p);
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)OSAtomicAdd64Barrier (*(int64_t*)&operand, (volatile int64_t*)p);
00645 }
00646 
00647 static inline PlankB pl_AtomicP_CompareAndSwap (PlankAtomicPRef p, PlankP oldValue, PlankP newValue)
00648 {
00649     return OSAtomicCompareAndSwap64Barrier (*(int64_t*)&oldValue, 
00650                                             *(int64_t*)&newValue, 
00651                                             (volatile int64_t*)p);
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 //    char success;
00858 //#if __PIC__
00859 //    __asm__ __volatile__("xchg %%rsi, %%rbx;"
00860 //                         "lock; cmpxchg16b %0; setz %3;"
00861 //                         "xchg %%rbx, %%rsi;"
00862 //                         : "+m" (*p), "+a" (oldPtr), "+d" (oldExtra), "=q" (success)
00863 //                         : "S" (newPtr), "c" (newExtra)
00864 //                         : "cc", "memory");
00865 //#else // !__PIC__
00866 //    __asm__ __volatile__("lock; cmpxchg16b %0; setz %1"
00867 //                         : "=m"(*p), "=a"(success)
00868 //                         : "m"(*p), "d" (oldExtra), "a" (oldPtr), "c" (newExtra), "b" (newPtr)
00869 //                         : "cc", "memory");
00870 //#endif
00871 //    return success;
00872 //}
00873 
00874 static inline  PlankB pl_AtomicPX_CompareAndSwap (PlankAtomicPXRef p, PlankP oldPtr, PlankUL oldExtra, PlankP newPtr, PlankUL newExtra)
00875 {
00876     char success;
00877     __asm__ __volatile__("lock; cmpxchg16b %0; setz %1"
00878                          : "=m"(*p), "=a"(success)
00879                          : "m"(*p), "d" (oldExtra), "a" (oldPtr), "c" (newExtra), "b" (newPtr)
00880                          : "cc", "memory");
00881     return success;
00882 }
00883 
00884 static inline PlankB pl_AtomicPX_CompareAndSwapP (PlankAtomicPXRef p, PlankP oldPtr, PlankP newPtr)
00885 {
00886     return pl_AtomicP_CompareAndSwap ((PlankAtomicPRef)p, oldPtr, newPtr);
00887 }
00888 
00889 static inline void pl_AtomicPX_SetAllUnchecked (PlankAtomicPXRef p, PlankP newPtr, PlankUL newExtra)
00890 {
00891     p->ptr = newPtr;
00892     p->extra = newExtra;
00893 }
00894 
00895 #define PLANK_ATOMICS_DEFINED 1
00896 
00897 #endif // PLANK_INLINING_FUNCTIONS
00898 
 All Classes Functions Typedefs Enumerations Enumerator Properties