![]() |
pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
|
00001 /* 00002 ------------------------------------------------------------------------------- 00003 This file is part of the Plink, Plonk, Plank libraries 00004 by Martin Robinson 00005 00006 http://code.google.com/p/pl-nk/ 00007 00008 Copyright University of the West of England, Bristol 2011-14 00009 All rights reserved. 00010 00011 Redistribution and use in source and binary forms, with or without 00012 modification, are permitted provided that the following conditions are met: 00013 00014 * Redistributions of source code must retain the above copyright 00015 notice, this list of conditions and the following disclaimer. 00016 * Redistributions in binary form must reproduce the above copyright 00017 notice, this list of conditions and the following disclaimer in the 00018 documentation and/or other materials provided with the distribution. 00019 * Neither the name of University of the West of England, Bristol nor 00020 the names of its contributors may be used to endorse or promote products 00021 derived from this software without specific prior written permission. 00022 00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00024 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00025 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00026 DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF THE WEST OF ENGLAND, BRISTOL BE 00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 00034 This software makes use of third party libraries. For more information see: 00035 doc/license.txt included in the distribution. 00036 ------------------------------------------------------------------------------- 00037 */ 00038 00039 // help prevent accidental inclusion other than via the intended header 00040 #if PLANK_INLINING_FUNCTIONS 00041 00042 #define PLANK_ATOMIC_XBITS 32 00043 #define PLANK_ATOMIC_XREFCOUNTBITS 16 00044 #define PLANK_ATOMIC_XWEAKCOUNTBITS 16 00045 #define PLANK_ATOMIC_XREFCOUNTMAX 0x0000FFFFUL 00046 #define PLANK_ATOMIC_XREFCOUNTMASK PLANK_ATOMIC_XREFCOUNTMAX 00047 #define PLANK_ATOMIC_XWEAKCOUNTMAX 0x0000FFFFUL 00048 #define PLANK_ATOMIC_XWEAKCOUNTMASK 0xFFFF0000UL 00049 #define PLANK_ATOMIC_XMAX 0xFFFFFFFFUL 00050 #define PLANK_ATOMIC_PMASK 0xFFFFFFFFUL 00051 00052 #if !DOXYGEN 00053 typedef struct PlankAtomicI 00054 { 00055 volatile PlankI value; 00056 } PlankAtomicI PLANK_ALIGN(4); 00057 00058 typedef struct PlankAtomicL 00059 { 00060 volatile PlankL value; 00061 } PlankAtomicL PLANK_ALIGN(4); 00062 00063 typedef struct PlankAtomicLL 00064 { 00065 volatile PlankLL value; 00066 } PlankAtomicLL PLANK_ALIGN(8); 00067 00068 typedef struct PlankAtomicF 00069 { 00070 volatile PlankF value; 00071 } PlankAtomicF PLANK_ALIGN(4); 00072 00073 typedef struct PlankAtomicD 00074 { 00075 volatile PlankD value; 00076 } PlankAtomicD PLANK_ALIGN(8); 00077 00078 typedef struct PlankAtomicP 00079 { 00080 volatile PlankP ptr; 00081 } PlankAtomicP PLANK_ALIGN(4); 00082 00083 typedef struct PlankAtomicPX 00084 { 00085 volatile PlankP ptr; 00086 volatile PlankUL extra; 00087 } PlankAtomicPX PLANK_ALIGN(8); 00088 #endif 00089 00090 static inline void pl_AtomicMemoryBarrier() 00091 { 00092 __sync_synchronize(); 00093 } 00094 00095 //------------------------------------------------------------------------------ 00096 00097 static inline PlankResult pl_AtomicI_Init (PlankAtomicIRef p) 00098 { 00099 if (p == PLANK_NULL) 00100 return PlankResult_MemoryError; 00101 00102 pl_MemoryZero (p, sizeof (PlankAtomicI)); 00103 00104 return PlankResult_OK; 00105 } 00106 00107 static inline PlankResult pl_AtomicI_DeInit (PlankAtomicIRef p) 00108 { 00109 if (p == PLANK_NULL) 00110 return PlankResult_MemoryError; 00111 return PlankResult_OK; 00112 } 00113 00114 static inline PlankI pl_AtomicI_Get (PlankAtomicIRef p) 00115 { 00116 return p->value; // should be aligned anyway and volatile so OK // pl_AtomicI_Add (p, 0); 00117 } 00118 00119 static inline PlankI pl_AtomicI_GetUnchecked (PlankAtomicIRef p) 00120 { 00121 return p->value; 00122 } 00123 00124 static inline PlankI pl_AtomicI_Swap (PlankAtomicIRef p, PlankI newValue) 00125 { 00126 PlankI oldValue; 00127 PlankB success; 00128 00129 do { 00130 oldValue = *(PlankI*)p; 00131 success = pl_AtomicI_CompareAndSwap (p, oldValue, newValue); 00132 } while (!success); 00133 00134 return oldValue; 00135 } 00136 00137 static inline void pl_AtomicI_SwapOther (PlankAtomicIRef p1, PlankAtomicIRef p2) 00138 { 00139 PlankI value1, value2; 00140 PlankB success; 00141 00142 do { 00143 value1 = *(PlankI*)p1; 00144 value2 = *(PlankI*)p2; 00145 success = pl_AtomicI_CompareAndSwap (p1, value1, value2); 00146 } while (!success); 00147 00148 *(PlankI*)p2 = value1; 00149 } 00150 00151 static inline void pl_AtomicI_Set (PlankAtomicIRef p, PlankI newValue) 00152 { 00153 pl_AtomicI_Swap (p, newValue); 00154 } 00155 00156 static inline PlankI pl_AtomicI_Add (PlankAtomicIRef p, PlankI operand) 00157 { 00158 return __sync_add_and_fetch ((volatile PlankI*)p, operand); 00159 } 00160 00161 static inline PlankB pl_AtomicI_CompareAndSwap (PlankAtomicIRef p, PlankI oldValue, PlankI newValue) 00162 { 00163 return __sync_bool_compare_and_swap ((volatile PlankI*)p, 00164 oldValue, 00165 newValue); 00166 } 00167 00168 static inline PlankI pl_AtomicI_Subtract (PlankAtomicIRef p, PlankI operand) 00169 { 00170 return pl_AtomicI_Add (p, -operand); 00171 } 00172 00173 static inline PlankI pl_AtomicI_Increment (PlankAtomicIRef p) 00174 { 00175 return pl_AtomicI_Add (p, 1); 00176 } 00177 00178 static inline PlankI pl_AtomicI_Decrement (PlankAtomicIRef p) 00179 { 00180 return pl_AtomicI_Add (p, -1); 00181 } 00182 00183 //------------------------------------------------------------------------------ 00184 00185 static inline PlankResult pl_AtomicL_Init (PlankAtomicLRef p) 00186 { 00187 if (p == PLANK_NULL) 00188 return PlankResult_MemoryError; 00189 00190 pl_MemoryZero (p, sizeof (PlankAtomicL)); 00191 00192 return PlankResult_OK; 00193 } 00194 00195 static inline PlankResult pl_AtomicL_DeInit (PlankAtomicLRef p) 00196 { 00197 if (p == PLANK_NULL) 00198 return PlankResult_MemoryError; 00199 return PlankResult_OK; 00200 } 00201 00202 static inline PlankL pl_AtomicL_Get (PlankAtomicLRef p) 00203 { 00204 return p->value; // should be aligned anyway and volatile so OK // pl_AtomicL_Add (p, (PlankL)0); 00205 } 00206 00207 static inline PlankL pl_AtomicL_GetUnchecked (PlankAtomicLRef p) 00208 { 00209 return p->value; 00210 } 00211 00212 static inline PlankL pl_AtomicL_Swap (PlankAtomicLRef p, PlankL newValue) 00213 { 00214 PlankL oldValue; 00215 PlankB success; 00216 00217 do { 00218 oldValue = *(PlankL*)p; 00219 success = pl_AtomicL_CompareAndSwap (p, oldValue, newValue); 00220 } while (!success); 00221 00222 return oldValue; 00223 } 00224 00225 static inline void pl_AtomicL_SwapOther (PlankAtomicLRef p1, PlankAtomicLRef p2) 00226 { 00227 PlankL value1, value2; 00228 PlankB success; 00229 00230 do { 00231 value1 = *(PlankL*)p1; 00232 value2 = *(PlankL*)p2; 00233 success = pl_AtomicL_CompareAndSwap (p1, value1, value2); 00234 } while (!success); 00235 00236 *(PlankL*)p2 = value1; 00237 } 00238 00239 static inline void pl_AtomicL_Set (PlankAtomicLRef p, PlankL newValue) 00240 { 00241 pl_AtomicL_Swap (p, newValue); 00242 } 00243 00244 static inline PlankL pl_AtomicL_Add (PlankAtomicLRef p, PlankL operand) 00245 { 00246 return __sync_add_and_fetch ((volatile PlankL*)p, operand); 00247 } 00248 00249 static inline PlankB pl_AtomicL_CompareAndSwap (PlankAtomicLRef p, PlankL oldValue, PlankL newValue) 00250 { 00251 return __sync_bool_compare_and_swap ((volatile PlankL*)p, 00252 oldValue, 00253 newValue); 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 pl_MemoryZero (p, sizeof (PlankAtomicLL)); 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 __sync_add_and_fetch ((volatile PlankLL*)p, operand); 00348 } 00349 00350 static inline PlankB pl_AtomicLL_CompareAndSwap (PlankAtomicLLRef p, PlankLL oldValue, PlankLL newValue) 00351 { 00352 return __sync_bool_compare_and_swap ((volatile PlankLL*)p, 00353 oldValue, 00354 newValue); 00355 } 00356 00357 static inline PlankLL pl_AtomicLL_Subtract (PlankAtomicLLRef p, PlankLL operand) 00358 { 00359 return pl_AtomicLL_Add (p, -operand); 00360 } 00361 00362 static inline PlankLL pl_AtomicLL_Increment (PlankAtomicLLRef p) 00363 { 00364 return pl_AtomicLL_Add (p, (PlankLL)1); 00365 } 00366 00367 static inline PlankLL pl_AtomicLL_Decrement (PlankAtomicLLRef p) 00368 { 00369 return pl_AtomicLL_Add (p, (PlankLL)(-1)); 00370 } 00371 00372 //------------------------------------------------------------------------------ 00373 00374 static inline PlankResult pl_AtomicF_Init (PlankAtomicFRef p) 00375 { 00376 if (p == PLANK_NULL) 00377 return PlankResult_MemoryError; 00378 00379 pl_MemoryZero (p, sizeof (PlankAtomicF)); 00380 00381 return PlankResult_OK; 00382 } 00383 00384 static inline PlankResult pl_AtomicF_DeInit (PlankAtomicFRef p) 00385 { 00386 if (p == PLANK_NULL) 00387 return PlankResult_MemoryError; 00388 return PlankResult_OK; 00389 } 00390 00391 static inline PlankF pl_AtomicF_Get (PlankAtomicFRef p) 00392 { 00393 return p->value; // should be aligned anyway and volatile so OK 00394 } 00395 00396 static inline PlankF pl_AtomicF_GetUnchecked (PlankAtomicFRef p) 00397 { 00398 return p->value; 00399 } 00400 00401 static inline PlankF pl_AtomicF_Swap (PlankAtomicFRef p, PlankF newValue) 00402 { 00403 PlankF oldValue; 00404 PlankB success; 00405 00406 do 00407 { 00408 oldValue = *(PlankF*)p; 00409 success = pl_AtomicF_CompareAndSwap (p, oldValue, newValue); 00410 } while (!success); 00411 00412 return oldValue; 00413 } 00414 00415 static inline void pl_AtomicF_SwapOther (PlankAtomicFRef p1, PlankAtomicFRef p2) 00416 { 00417 PlankF value1, value2; 00418 PlankB success; 00419 00420 do { 00421 value1 = *(PlankF*)p1; 00422 value2 = *(PlankF*)p2; 00423 success = pl_AtomicF_CompareAndSwap (p1, value1, value2); 00424 } while (!success); 00425 00426 *(PlankF*)p2 = value1; 00427 } 00428 00429 static inline void pl_AtomicF_Set (PlankAtomicFRef p, PlankF newValue) 00430 { 00431 pl_AtomicF_Swap (p, newValue); 00432 } 00433 00434 static inline PlankF pl_AtomicF_Add (PlankAtomicFRef p, PlankF operand) 00435 { 00436 PlankF newValue, oldValue; 00437 PlankB success; 00438 00439 do { 00440 oldValue = *(PlankF*)p; 00441 newValue = oldValue + operand; 00442 success = pl_AtomicF_CompareAndSwap (p, oldValue, newValue); 00443 } while (!success); 00444 00445 return newValue; 00446 } 00447 00448 static inline PlankB pl_AtomicF_CompareAndSwap (PlankAtomicFRef p, PlankF oldValue, PlankF newValue) 00449 { 00450 return __sync_bool_compare_and_swap ((volatile PlankI*)p, 00451 *(PlankI*)&oldValue, 00452 *(PlankI*)&newValue); 00453 } 00454 00455 static inline PlankF pl_AtomicF_Subtract (PlankAtomicFRef p, PlankF operand) 00456 { 00457 return pl_AtomicF_Add (p, -operand); 00458 } 00459 00460 static inline PlankF pl_AtomicF_Increment (PlankAtomicFRef p) 00461 { 00462 return pl_AtomicF_Add (p, 1.f); 00463 } 00464 00465 static inline PlankF pl_AtomicF_Decrement (PlankAtomicFRef p) 00466 { 00467 return pl_AtomicF_Add (p, -1.f); 00468 } 00469 00470 //------------------------------------------------------------------------------ 00471 00472 static inline PlankResult pl_AtomicD_Init (PlankAtomicDRef p) 00473 { 00474 PlankResult result = PlankResult_OK; 00475 00476 if (p == PLANK_NULL) 00477 { 00478 result = PlankResult_MemoryError; 00479 goto exit; 00480 } 00481 00482 pl_MemoryZero (p, sizeof (PlankAtomicD)); 00483 00484 exit: 00485 return result; 00486 } 00487 00488 static inline PlankResult pl_AtomicD_DeInit (PlankAtomicDRef p) 00489 { 00490 PlankResult result = PlankResult_OK; 00491 00492 if (p == PLANK_NULL) 00493 { 00494 result = PlankResult_MemoryError; 00495 goto exit; 00496 } 00497 00498 exit: 00499 return result; 00500 } 00501 00502 static inline PlankD pl_AtomicD_Get (PlankAtomicDRef p) 00503 { 00504 PlankLL bits = pl_AtomicLL_Add ((PlankAtomicLLRef)p, (PlankLL)0); // use the LL version 00505 return *(PlankD*)&bits; 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 __sync_bool_compare_and_swap ((volatile PlankLL*)p, 00562 *(PlankLL*)&oldValue, 00563 *(PlankLL*)&newValue); 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)__sync_add_and_fetch ((volatile PlankL*)p, operand); 00645 } 00646 00647 static inline PlankB pl_AtomicP_CompareAndSwap (PlankAtomicPRef p, PlankP oldValue, PlankP newValue) 00648 { 00649 return __sync_bool_compare_and_swap ((volatile PlankL*)p, 00650 *(PlankL*)&oldValue, 00651 *(PlankL*)&newValue); 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 PlankAtomicPX oldAll = { oldPtr, oldExtra }; 00858 PlankAtomicPX newAll = { newPtr, newExtra }; 00859 00860 return __sync_bool_compare_and_swap ((volatile PlankLL*)p, 00861 *(PlankLL*)&oldAll, 00862 *(PlankLL*)&newAll); 00863 } 00864 00865 static inline PlankB pl_AtomicPX_CompareAndSwapP (PlankAtomicPXRef p, PlankP oldPtr, PlankP newPtr) 00866 { 00867 return pl_AtomicP_CompareAndSwap ((PlankAtomicPRef)p, oldPtr, newPtr); 00868 } 00869 00870 static inline void pl_AtomicPX_SetAllUnchecked (PlankAtomicPXRef p, PlankP newPtr, PlankUL newExtra) 00871 { 00872 p->ptr = newPtr; 00873 p->extra = newExtra; 00874 } 00875 00876 #define PLANK_ATOMICS_DEFINED 1 00877 00878 #endif // PLANK_INLINING_FUNCTIONS 00879