diff options
author | Patrick Williams <iawillia@us.ibm.com> | 2010-05-18 22:56:14 -0500 |
---|---|---|
committer | Patrick Williams <iawillia@us.ibm.com> | 2010-05-18 22:56:14 -0500 |
commit | 78f5edabe6fd21f55ddff82f978a1b5d46d62ffa (patch) | |
tree | 1cb033e2447c993c7aada1ff8b6147ed0134f2bb /src/libc++ | |
parent | cf138201c24fdc83ee7835b65cce67e7d7a85e70 (diff) | |
download | talos-hostboot-78f5edabe6fd21f55ddff82f978a1b5d46d62ffa.tar.gz talos-hostboot-78f5edabe6fd21f55ddff82f978a1b5d46d62ffa.zip |
Add thread safe guard variable code.
Diffstat (limited to 'src/libc++')
-rw-r--r-- | src/libc++/builtins.C | 39 |
1 files changed, 26 insertions, 13 deletions
diff --git a/src/libc++/builtins.C b/src/libc++/builtins.C index ed373c8cc..70c9fcc35 100644 --- a/src/libc++/builtins.C +++ b/src/libc++/builtins.C @@ -2,25 +2,38 @@ extern "C" int __cxa_guard_acquire(volatile uint64_t* gv) { - // 0 .. uninitialized - // 1 .. locked - // 2 .. unlocked, initialized - if (0 == *gv) - { - *gv = 1; - return 1; - } - else if (1 == *gv) + // 0 -> uninitialized + // 1 -> locked + // 2 -> unlocked and initialized + + register volatile void* guard = gv; + register uint32_t c = 0; + + asm volatile( + "__cxa_guard_acquire_begin:" + "lwarx %0,0,%1;" // Load guard with reserve + "cmpi 0,%0,0;" // Compare with 0 + "bne+ __cxa_guard_acquire_finish;" // != 0, goto "finished" + "li %0, 1;" // Set to 1. + "stwcx. %0,0,%1;" // Store against reserve + "bne- __cxa_guard_acquire_begin;" // goto begin if failed store. + "li %0, 3;" // Set to 3 -> success in lock + "__cxa_guard_acquire_finish:" + : "+r" (c) : "r" (guard): "memory","cc" + ); + while (2 > c) { - while(1 == *gv); + asm volatile("lwz %0, 0(%1);" : "=r" (c) : "r" (guard)); } - - return 0; + return (3 == c ? 1 : 0); // 3 means success in lock, return 1 (obtained) + // 2 means initialized, return 0 } extern "C" void __cxa_guard_release(volatile uint64_t* gv) { - *gv = 2; + register volatile void* guard = gv; + register uint32_t c = 2; + asm volatile("stw %0, 0(%1)" :: "r"(c) , "r" (guard): "memory"); return; } |