Skip to content

Commit b8c6f83

Browse files
author
Alexander Korotkov
committed
LWLock optimization for PowerPC processors
PowerPC processors have quite specific implementation of atomic operations: they are implemented optimistically. If value is changed between our read and write, then we have to retry. So, CAS operation on this platform becomes potentially infinite loop. Thus, loop of CAS operations becomes two nested loops. This patch implements LWLockAttemptLock() as single loop in assembly. That shows great speedup on high concurrent workloads.
1 parent 6a2ea08 commit b8c6f83

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

src/backend/storage/lmgr/lwlock.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,56 @@ GetLWLockIdentifier(uint8 classId, uint16 eventId)
768768
return LWLockTrancheArray[eventId]->name;
769769
}
770770

771+
#if (defined(__GNUC__) || defined(__INTEL_COMPILER)) && (defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__) || defined(__powerpc64__))
772+
773+
/*
774+
* Special optimization for PowerPC processors: put logic dealing with LWLock
775+
* state between lwarx/stwcx operations.
776+
*/
777+
static bool
778+
LWLockAttemptLock(LWLock *lock, LWLockMode mode)
779+
{
780+
uint32 mask, increment;
781+
bool result;
782+
783+
AssertArg(mode == LW_EXCLUSIVE || mode == LW_SHARED);
784+
785+
if (mode == LW_EXCLUSIVE)
786+
{
787+
mask = LW_LOCK_MASK;
788+
increment = LW_VAL_EXCLUSIVE;
789+
}
790+
else
791+
{
792+
mask = LW_VAL_EXCLUSIVE;
793+
increment = LW_VAL_SHARED;
794+
}
795+
796+
__asm__ __volatile__(
797+
"0: lwarx 3,0,%4 \n"
798+
" and 4,3,%2 \n"
799+
" cmpwi 4,0 \n"
800+
" bne- 1f \n"
801+
" add 3,3,%3 \n"
802+
" stwcx. 3,0,%4 \n"
803+
" bne- 0b \n"
804+
" li %0,0 \n"
805+
" b 2f \n"
806+
"1: li %0,1 \n"
807+
#ifdef USE_PPC_LWSYNC
808+
"2: lwsync \n"
809+
#else
810+
"2: isync \n"
811+
#endif
812+
: "=&r"(result), "+m"(lock->state)
813+
: "r"(mask), "r"(increment), "r"(&lock->state)
814+
: "memory", "cc", "r3", "r4");
815+
816+
return result;
817+
}
818+
819+
#else
820+
771821
/*
772822
* Internal function that tries to atomically acquire the lwlock in the passed
773823
* in mode.
@@ -910,6 +960,8 @@ LWLockWaitListUnlock(LWLock *lock)
910960
Assert(old_state & LW_FLAG_LOCKED);
911961
}
912962

963+
#endif
964+
913965
/*
914966
* Wakeup all the lockers that currently have a chance to acquire the lock.
915967
*/

0 commit comments

Comments
 (0)