Don't use os_unfair_lock on 32-bit platforms

This commit is contained in:
Ali 2022-07-08 19:54:18 +02:00
parent 76ab659aa2
commit 93664ad233
3 changed files with 104 additions and 5 deletions

View File

@ -32,6 +32,7 @@ void ASRecursiveUnfairLockLock(ASRecursiveUnfairLock *l)
// the lock, because we reset it to NULL before we unlock. So (thread == self) is // the lock, because we reset it to NULL before we unlock. So (thread == self) is
// invariant. // invariant.
#if AS_USE_OS_LOCK
const pthread_t s = pthread_self(); const pthread_t s = pthread_self();
if (os_unfair_lock_trylock(&l->_lock)) { if (os_unfair_lock_trylock(&l->_lock)) {
// Owned by nobody. We now have the lock. Assign self. // Owned by nobody. We now have the lock. Assign self.
@ -43,6 +44,19 @@ void ASRecursiveUnfairLockLock(ASRecursiveUnfairLock *l)
os_unfair_lock_lock(&l->_lock); os_unfair_lock_lock(&l->_lock);
rul_set_thread(l, s); rul_set_thread(l, s);
} }
#else
const pthread_t s = pthread_self();
if (OSSpinLockTry(&l->_lock)) {
// Owned by nobody. We now have the lock. Assign self.
rul_set_thread(l, s);
} else if (rul_get_thread(l) == s) {
// Owned by self (recursive lock). nop.
} else {
// Owned by other thread. Block and then set thread to self.
OSSpinLockLock(&l->_lock);
rul_set_thread(l, s);
}
#endif
l->_count++; l->_count++;
} }
@ -51,6 +65,7 @@ BOOL ASRecursiveUnfairLockTryLock(ASRecursiveUnfairLock *l)
{ {
// Same as Lock above. See comments there. // Same as Lock above. See comments there.
#if AS_USE_OS_LOCK
const pthread_t s = pthread_self(); const pthread_t s = pthread_self();
if (os_unfair_lock_trylock(&l->_lock)) { if (os_unfair_lock_trylock(&l->_lock)) {
// Owned by nobody. We now have the lock. Assign self. // Owned by nobody. We now have the lock. Assign self.
@ -61,6 +76,18 @@ BOOL ASRecursiveUnfairLockTryLock(ASRecursiveUnfairLock *l)
// Owned by other thread. Fail. // Owned by other thread. Fail.
return NO; return NO;
} }
#else
const pthread_t s = pthread_self();
if (OSSpinLockTry(&l->_lock)) {
// Owned by nobody. We now have the lock. Assign self.
rul_set_thread(l, s);
} else if (rul_get_thread(l) == s) {
// Owned by self (recursive lock). nop.
} else {
// Owned by other thread. Fail.
return NO;
}
#endif
l->_count++; l->_count++;
return YES; return YES;
@ -78,6 +105,10 @@ void ASRecursiveUnfairLockUnlock(ASRecursiveUnfairLock *l)
// try to re-lock, and fail the -tryLock, and read _thread, then we'll mistakenly // try to re-lock, and fail the -tryLock, and read _thread, then we'll mistakenly
// think that we still own the lock and proceed without blocking. // think that we still own the lock and proceed without blocking.
rul_set_thread(l, NULL); rul_set_thread(l, NULL);
#if AS_USE_OS_LOCK
os_unfair_lock_unlock(&l->_lock); os_unfair_lock_unlock(&l->_lock);
#else
OSSpinLockUnlock(&l->_lock);
#endif
} }
} }

View File

@ -10,6 +10,15 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import <AsyncDisplayKit/ASBaseDefines.h> #import <AsyncDisplayKit/ASBaseDefines.h>
#import <pthread/pthread.h> #import <pthread/pthread.h>
#if defined(__aarch64__)
#define AS_USE_OS_LOCK true
#else
#define AS_USE_OS_LOCK false
#endif
#if AS_USE_OS_LOCK
#import <os/lock.h> #import <os/lock.h>
// Note: We don't use ATOMIC_VAR_INIT here because C++ compilers don't like it, // Note: We don't use ATOMIC_VAR_INIT here because C++ compilers don't like it,
@ -46,3 +55,43 @@ AS_EXTERN OS_UNFAIR_LOCK_AVAILABILITY
void ASRecursiveUnfairLockUnlock(ASRecursiveUnfairLock *l); void ASRecursiveUnfairLockUnlock(ASRecursiveUnfairLock *l);
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END
#else
#import <libkern/OSAtomic.h>
// Note: We don't use ATOMIC_VAR_INIT here because C++ compilers don't like it,
// and it literally does absolutely nothing.
#define AS_RECURSIVE_UNFAIR_LOCK_INIT ((ASRecursiveUnfairLock){ OS_SPINLOCK_INIT, NULL, 0})
NS_ASSUME_NONNULL_BEGIN
typedef struct {
OSSpinLock _lock;
_Atomic(pthread_t) _thread; // Write-protected by lock
int _count; // Protected by lock
} ASRecursiveUnfairLock;
/**
* Lock, blocking if needed.
*/
AS_EXTERN
void ASRecursiveUnfairLockLock(ASRecursiveUnfairLock *l);
/**
* Try to lock without blocking. Returns whether we took the lock.
*/
AS_EXTERN
BOOL ASRecursiveUnfairLockTryLock(ASRecursiveUnfairLock *l);
/**
* Unlock. Calling this on a thread that does not own
* the lock will result in an assertion failure, and undefined
* behavior if foundation assertions are disabled.
*/
AS_EXTERN
void ASRecursiveUnfairLockUnlock(ASRecursiveUnfairLock *l);
NS_ASSUME_NONNULL_END
#endif

View File

@ -9,7 +9,6 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <os/lock.h>
#import <pthread.h> #import <pthread.h>
#import <AsyncDisplayKit/ASAssert.h> #import <AsyncDisplayKit/ASAssert.h>
@ -148,7 +147,11 @@ namespace AS {
success = _recursive.try_lock(); success = _recursive.try_lock();
break; break;
case Unfair: case Unfair:
#if AS_USE_OS_LOCK
success = os_unfair_lock_trylock(&_unfair); success = os_unfair_lock_trylock(&_unfair);
#else
success = OSSpinLockTry(&_unfair);
#endif
break; break;
case RecursiveUnfair: case RecursiveUnfair:
success = ASRecursiveUnfairLockTryLock(&_runfair); success = ASRecursiveUnfairLockTryLock(&_runfair);
@ -169,7 +172,11 @@ namespace AS {
_recursive.lock(); _recursive.lock();
break; break;
case Unfair: case Unfair:
#if AS_USE_OS_LOCK
os_unfair_lock_lock(&_unfair); os_unfair_lock_lock(&_unfair);
#else
OSSpinLockLock(&_unfair);
#endif
break; break;
case RecursiveUnfair: case RecursiveUnfair:
ASRecursiveUnfairLockLock(&_runfair); ASRecursiveUnfairLockLock(&_runfair);
@ -188,7 +195,11 @@ namespace AS {
_recursive.unlock(); _recursive.unlock();
break; break;
case Unfair: case Unfair:
#if AS_USE_OS_LOCK
os_unfair_lock_unlock(&_unfair); os_unfair_lock_unlock(&_unfair);
#else
OSSpinLockUnlock(&_unfair);
#endif
break; break;
case RecursiveUnfair: case RecursiveUnfair:
ASRecursiveUnfairLockUnlock(&_runfair); ASRecursiveUnfairLockUnlock(&_runfair);
@ -226,7 +237,11 @@ namespace AS {
} else { } else {
if (gMutex_unfair) { if (gMutex_unfair) {
_type = Unfair; _type = Unfair;
#if AS_USE_OS_LOCK
_unfair = OS_UNFAIR_LOCK_INIT; _unfair = OS_UNFAIR_LOCK_INIT;
#else
_unfair = OS_SPINLOCK_INIT;
#endif
} else { } else {
_type = Plain; _type = Plain;
new (&_plain) std::mutex(); new (&_plain) std::mutex();
@ -261,7 +276,11 @@ namespace AS {
Type _type; Type _type;
union { union {
#if AS_USE_OS_LOCK
os_unfair_lock _unfair; os_unfair_lock _unfair;
#else
OSSpinLock _unfair;
#endif
ASRecursiveUnfairLock _runfair; ASRecursiveUnfairLock _runfair;
std::mutex _plain; std::mutex _plain;
std::recursive_mutex _recursive; std::recursive_mutex _recursive;