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