From 78f5edabe6fd21f55ddff82f978a1b5d46d62ffa Mon Sep 17 00:00:00 2001 From: Patrick Williams Date: Tue, 18 May 2010 22:56:14 -0500 Subject: Add thread safe guard variable code. --- src/libc++/builtins.C | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) (limited to 'src/libc++/builtins.C') 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; } -- cgit v1.2.1