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