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