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