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