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_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     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;
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;
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 OSAtomicAdd32Barrier (*(int32_t*)&operand, 
00246                                  (volatile int32_t*)p);
00247 }
00248 
00249 static inline PlankB pl_AtomicL_CompareAndSwap (PlankAtomicLRef p, PlankL oldValue, PlankL newValue)
00250 {    
00251     return OSAtomicCompareAndSwap32Barrier (*(int32_t*)&oldValue, 
00252                                             *(int32_t*)&newValue, 
00253                                             (volatile int32_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 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 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     PlankLL bits = pl_AtomicLL_Add ((PlankAtomicLLRef)p, (PlankLL)0); // use the LL version
00506     return *(PlankD*)&bits;
00507 }
00508 
00509 static inline PlankD pl_AtomicD_GetUnchecked (PlankAtomicDRef p)
00510 {
00511     return p->value;
00512 }
00513 
00514 static inline PlankD pl_AtomicD_Swap (PlankAtomicDRef p, PlankD newValue)
00515 {
00516     PlankD oldValue;
00517     PlankB success;
00518     
00519     do {
00520         oldValue = *(PlankD*)p;
00521         success = pl_AtomicD_CompareAndSwap (p, oldValue, newValue);
00522     } while (!success);
00523     
00524     return oldValue;
00525 }
00526 
00527 static inline void pl_AtomicD_SwapOther (PlankAtomicDRef p1, PlankAtomicDRef p2)
00528 {
00529     PlankD value1, value2;
00530     PlankB success;
00531     
00532     do {
00533         value1 = *(PlankD*)p1;
00534         value2 = *(PlankD*)p2;
00535         success = pl_AtomicD_CompareAndSwap (p1, value1, value2);
00536     } while (!success);
00537     
00538     *(PlankD*)p2 = value1;
00539 }
00540 
00541 static inline void pl_AtomicD_Set (PlankAtomicDRef p, PlankD newValue)
00542 {
00543     pl_AtomicD_Swap (p, newValue);
00544 }
00545 
00546 static inline PlankD pl_AtomicD_Add (PlankAtomicDRef p, PlankD operand)
00547 {
00548     PlankD newValue, oldValue;
00549     PlankB success;
00550     
00551     do {
00552         oldValue = *(PlankD*)p;
00553         newValue = oldValue + operand;
00554         success = pl_AtomicD_CompareAndSwap (p, oldValue, newValue);
00555     } while (!success);
00556     
00557     return newValue;
00558 }
00559 
00560 static inline PlankB pl_AtomicD_CompareAndSwap (PlankAtomicDRef p, PlankD oldValue, PlankD newValue)
00561 {    
00562     return OSAtomicCompareAndSwap64Barrier (*(int64_t*)&oldValue, 
00563                                             *(int64_t*)&newValue, 
00564                                             (volatile int64_t*)p);
00565 }
00566 
00567 static inline PlankD pl_AtomicD_Subtract (PlankAtomicDRef p, PlankD operand)
00568 {
00569     return pl_AtomicD_Add (p, -operand);
00570 }
00571 
00572 static inline PlankD pl_AtomicD_Increment (PlankAtomicDRef p)
00573 {
00574     return pl_AtomicD_Add (p, 1.0);
00575 }
00576 
00577 static inline PlankD pl_AtomicD_Decrement (PlankAtomicDRef p)
00578 {
00579     return pl_AtomicD_Add (p, -1.0);
00580 }
00581 
00582 //------------------------------------------------------------------------------
00583 
00584 static inline PlankResult pl_AtomicP_Init (PlankAtomicPRef p)
00585 {
00586     if (p == PLANK_NULL)
00587         return PlankResult_MemoryError;
00588     
00589     pl_MemoryZero (p, sizeof (PlankAtomicP));
00590     
00591     return PlankResult_OK;
00592 }
00593 
00594 static inline PlankResult pl_AtomicP_DeInit (PlankAtomicPRef p)
00595 {
00596     if (p == PLANK_NULL)
00597         return PlankResult_MemoryError;
00598     return PlankResult_OK;
00599 }
00600 
00601 static inline PlankP pl_AtomicP_Get (PlankAtomicPRef p)
00602 {
00603     return p->ptr; // should be aligned anyway and volatile so OK // pl_AtomicP_Add (p, (PlankL)0);
00604 }
00605 
00606 static inline PlankP pl_AtomicP_GetUnchecked (PlankAtomicPRef p)
00607 {
00608     return p->ptr;
00609 }
00610 
00611 static inline PlankP pl_AtomicP_Swap (PlankAtomicPRef p, PlankP newPtr)
00612 {
00613     PlankP oldPtr;
00614     PlankB success;
00615     
00616     do {
00617         oldPtr = *(PlankP*)p;
00618         success = pl_AtomicP_CompareAndSwap (p, oldPtr, newPtr);
00619     } while (!success);
00620     
00621     return oldPtr;    
00622 }
00623 
00624 static inline void pl_AtomicP_SwapOther (PlankAtomicPRef p1, PlankAtomicPRef p2)
00625 {
00626     PlankP value1, value2;
00627     PlankB success;
00628     
00629     do {
00630         value1 = *(PlankP*)p1;
00631         value2 = *(PlankP*)p2;
00632         success = pl_AtomicP_CompareAndSwap (p1, value1, value2);
00633     } while (!success);
00634     
00635     *(PlankP*)p2 = value1;
00636 }
00637 
00638 static inline void pl_AtomicP_Set (PlankAtomicPRef p, PlankP newPtr)
00639 {
00640     pl_AtomicP_Swap (p, newPtr);
00641 }
00642 
00643 static inline PlankP pl_AtomicP_Add (PlankAtomicPRef p, PlankL operand)
00644 {
00645     return (PlankP)OSAtomicAdd32Barrier (*(int32_t*)&operand, (volatile int32_t*)p);
00646 }
00647 
00648 static inline PlankB pl_AtomicP_CompareAndSwap (PlankAtomicPRef p, PlankP oldValue, PlankP newValue)
00649 {
00650     return OSAtomicCompareAndSwap32Barrier (*(int32_t*)&oldValue, 
00651                                             *(int32_t*)&newValue, 
00652                                             (volatile int32_t*)p);
00653 }
00654 
00655 static inline PlankP pl_AtomicP_Subtract (PlankAtomicPRef p, PlankL operand)
00656 {
00657     return pl_AtomicP_Add (p, -operand);
00658 }
00659 
00660 static inline PlankP pl_AtomicP_Increment (PlankAtomicPRef p)
00661 {
00662     return pl_AtomicP_Add (p, (PlankL)1);
00663 }
00664 
00665 static inline PlankP pl_AtomicP_Decrement (PlankAtomicPRef p)
00666 {
00667     return pl_AtomicP_Add (p, (PlankL)(-1));
00668 }
00669 
00670 //------------------------------------------------------------------------------
00671 
00672 static inline PlankAtomicPXRef pl_AtomicPX_CreateAndInit()
00673 {
00674     PlankAtomicPXRef p = pl_AtomicPX_Create();
00675     if (p != PLANK_NULL) pl_AtomicPX_Init (p);
00676     return p;
00677 }
00678 
00679 static inline PlankAtomicPXRef pl_AtomicPX_Create()
00680 {
00681     PlankMemoryRef m;
00682     PlankAtomicPXRef p;
00683     
00684     m = pl_MemoryGlobal();
00685     p = (PlankAtomicPXRef)pl_Memory_AllocateBytes (m, sizeof (PlankAtomicPX));
00686     
00687     if (p != PLANK_NULL)
00688         pl_MemoryZero (p, sizeof (PlankAtomicPX));
00689     
00690     return p;
00691 }
00692 
00693 static inline PlankResult pl_AtomicPX_Init (PlankAtomicPXRef p)
00694 {
00695     PlankResult result = PlankResult_OK;
00696     
00697     if (p == PLANK_NULL)
00698     {
00699         result = PlankResult_MemoryError;
00700         goto exit;
00701     }
00702     
00703     pl_MemoryZero (p, sizeof (PlankAtomicPX));
00704     
00705 exit:
00706     return result;
00707 }
00708 
00709 static inline PlankResult pl_AtomicPX_DeInit (PlankAtomicPXRef p)
00710 {
00711     PlankResult result = PlankResult_OK;
00712     
00713     if (p == PLANK_NULL)
00714     {
00715         result = PlankResult_MemoryError;
00716         goto exit;
00717     }
00718     
00719 exit:
00720     return result;
00721 }
00722 
00723 static inline PlankResult pl_AtomicPX_Destroy (PlankAtomicPXRef p)
00724 {
00725     PlankResult result;
00726     PlankMemoryRef m;
00727     
00728     result = PlankResult_OK;
00729     m = pl_MemoryGlobal();
00730     
00731     if ((result = pl_AtomicPX_DeInit (p)) != PlankResult_OK)
00732         goto exit;
00733     
00734     result = pl_Memory_Free (m, p);
00735     
00736 exit:
00737     return result;
00738 }
00739 
00740 static inline PlankP pl_AtomicPX_Get (PlankAtomicPXRef p)
00741 {
00742     return p->ptr; // should be aligned anyway and volatile so OK // pl_AtomicP_Get ((PlankAtomicPRef)p);
00743 }
00744 
00745 static inline PlankP pl_AtomicPX_GetUnchecked (PlankAtomicPXRef p)
00746 {
00747     return p->ptr;
00748 }
00749 
00750 static inline PlankUL pl_AtomicPX_GetExtra (PlankAtomicPXRef p)
00751 {
00752     return p->extra; // should be aligned anyway and volatile so OK // pl_AtomicL_Get ((PlankAtomicLRef)&(p->extra));
00753 }
00754 
00755 static inline PlankUL pl_AtomicPX_GetExtraUnchecked (PlankAtomicPXRef p)
00756 {
00757     return p->extra;
00758 }
00759 
00760 static inline PlankP pl_AtomicPX_SwapAll (PlankAtomicPXRef p, PlankP newPtr, PlankUL newExtra, PlankUL* oldExtraPtr)
00761 {
00762     PlankP oldPtr;
00763     PlankUL oldExtra;
00764     PlankB success;
00765     
00766     do {
00767         oldPtr = p->ptr;
00768         oldExtra = p->extra;
00769         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, newExtra);
00770     } while (!success);
00771     
00772     if (oldExtraPtr != PLANK_NULL)
00773         *oldExtraPtr = oldExtra;
00774     
00775     return oldPtr;
00776 }
00777 
00778 static inline PlankP pl_AtomicPX_Swap (PlankAtomicPXRef p, PlankP newPtr)
00779 {
00780     PlankP oldPtr;
00781     PlankUL oldExtra;
00782     PlankB success;
00783     
00784     do {
00785         oldPtr = p->ptr;
00786         oldExtra = p->extra;
00787         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, oldExtra + 1);
00788     } while (!success);
00789     
00790     return oldPtr;
00791 }
00792 
00793 static inline void pl_AtomicPX_SwapOther (PlankAtomicPXRef p1, PlankAtomicPXRef p2)
00794 {
00795     PlankAtomicPX tmp1, tmp2;
00796     PlankB success;
00797     
00798     do {
00799         tmp1 = *p1;
00800         tmp2 = *p2;
00801         success = pl_AtomicPX_CompareAndSwap (p1, tmp1.ptr, tmp1.extra, tmp2.ptr, tmp1.extra + 1);
00802     } while (!success);
00803     
00804     pl_AtomicPX_Set (p2, tmp1.ptr);
00805 }
00806 
00807 static inline void pl_AtomicPX_SetAll (PlankAtomicPXRef p, PlankP newPtr, PlankUL newExtra)
00808 {
00809     pl_AtomicPX_SwapAll (p, newPtr, newExtra, (PlankUL*)PLANK_NULL);
00810 }
00811 
00812 static inline void pl_AtomicPX_Set (PlankAtomicPXRef p, PlankP newPtr)
00813 {
00814     PlankP oldPtr;
00815     PlankUL oldExtra;
00816     PlankB success;
00817     
00818     do {
00819         oldPtr = p->ptr;
00820         oldExtra = p->extra;
00821         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, oldExtra + 1);
00822     } while (!success);
00823 }
00824 
00825 static inline PlankP pl_AtomicPX_Add (PlankAtomicPXRef p, PlankL operand)
00826 {
00827     PlankP newPtr, oldPtr;
00828     PlankUL oldExtra;
00829     PlankB success;
00830     
00831     do {
00832         oldPtr = p->ptr;
00833         oldExtra = p->extra;
00834         newPtr = (PlankUC*)oldPtr + operand;
00835         success = pl_AtomicPX_CompareAndSwap (p, oldPtr, oldExtra, newPtr, oldExtra + 1);
00836     } while (!success);
00837     
00838     return newPtr;
00839 }
00840 
00841 static inline PlankP pl_AtomicPX_Subtract (PlankAtomicPXRef p, PlankL operand)
00842 {
00843     return pl_AtomicPX_Add (p, -operand);
00844 }
00845 
00846 static inline PlankP pl_AtomicPX_Increment (PlankAtomicPXRef p)
00847 {
00848     return pl_AtomicPX_Add (p, (PlankL)1);
00849 }
00850 
00851 static inline PlankP pl_AtomicPX_Decrement (PlankAtomicPXRef p)
00852 {
00853     return pl_AtomicPX_Add (p, (PlankL)(-1));
00854 }
00855 
00856 //static inline  PlankB pl_AtomicPX_CompareAndSwap (PlankAtomicPXRef p, PlankP oldPtr, PlankUL oldExtra, PlankP newPtr, PlankUL newExtra)
00857 //{
00858 //    char success;
00859 //#if __PIC__
00860 //    __asm__ __volatile__("pushl %%ebx;"
00861 //                         "movl %6,%%ebx;"
00862 //                         "lock; cmpxchg8b %0; setz %1;"
00863 //                         "pop %%ebx;"
00864 //                         : "=m"(*p), "=a"(success)
00865 //                         : "m"(*p), "d" (oldExtra), "a" (oldPtr), "c" (newExtra), "m" (newPtr)
00866 //                         : "cc", "memory");
00867 //#else // !__PIC__
00868 //    __asm__ __volatile__("lock; cmpxchg8b %0; setz %1;"
00869 //                         : "=m"(*p), "=a"(success)
00870 //                         : "m"(*p), "d" (oldExtra), "a" (oldPtr), "c" (newExtra), "b" (newPtr)
00871 //                         : "cc", "memory");
00872 //#endif
00873 //    return success;
00874 //}
00875 
00876 static inline  PlankB pl_AtomicPX_CompareAndSwap (PlankAtomicPXRef p, PlankP oldPtr, PlankUL oldExtra, PlankP newPtr, PlankUL newExtra)
00877 {
00878     PlankAtomicPX oldAll = { oldPtr, oldExtra };
00879     PlankAtomicPX newAll = { newPtr, newExtra };
00880     
00881     return __sync_bool_compare_and_swap ((volatile PlankLL*)p,
00882                                          *(PlankLL*)&oldAll,
00883                                          *(PlankLL*)&newAll);
00884 }
00885 
00886 static inline PlankB pl_AtomicPX_CompareAndSwapP (PlankAtomicPXRef p, PlankP oldPtr, PlankP newPtr)
00887 {
00888     return pl_AtomicP_CompareAndSwap ((PlankAtomicPRef)p, oldPtr, newPtr);
00889 }
00890 
00891 static inline void pl_AtomicPX_SetAllUnchecked (PlankAtomicPXRef p, PlankP newPtr, PlankUL newExtra)
00892 {
00893     p->ptr = newPtr;
00894     p->extra = newExtra;
00895 }
00896 
00897 #define PLANK_ATOMICS_DEFINED 1
00898 
00899 #endif // PLANK_INLINING_FUNCTIONS
00900 
 All Classes Functions Typedefs Enumerations Enumerator Properties