From 7e1c4534df199347d63bf7235ced8cc60170bfa7 Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Fri, 8 Nov 2013 03:37:30 +0100 Subject: [PATCH] libroot: Add adaptive mutex implementation --- headers/private/shared/locks.h | 1 + src/system/libroot/libroot_init.c | 5 +++ src/system/libroot/os/locks/mutex.cpp | 32 ++++++++++++++----- .../libroot/posix/malloc/arch-specific.cpp | 2 +- src/system/runtime_loader/runtime_loader.cpp | 2 ++ 5 files changed, 33 insertions(+), 9 deletions(-) diff --git a/headers/private/shared/locks.h b/headers/private/shared/locks.h index 23b227d2c8..27da7fc212 100644 --- a/headers/private/shared/locks.h +++ b/headers/private/shared/locks.h @@ -18,6 +18,7 @@ typedef struct mutex { } mutex; #define MUTEX_FLAG_CLONE_NAME 0x1 +#define MUTEX_FLAG_ADAPTIVE 0x2 #define MUTEX_INITIALIZER(name) { name, 0, 0 } void mutex_init(mutex *lock, const char *name); diff --git a/src/system/libroot/libroot_init.c b/src/system/libroot/libroot_init.c index 867cbd25a6..caef95b2fc 100644 --- a/src/system/libroot/libroot_init.c +++ b/src/system/libroot/libroot_init.c @@ -32,6 +32,7 @@ int __libc_argc; char **__libc_argv; int __gABIVersion; +int32 __gCPUCount; char _single_threaded = true; // determines if I/O locking needed; needed for BeOS compatibility @@ -48,6 +49,7 @@ int _data_offset_main_; void initialize_before(image_id imageID) { + system_info info; char *programPath = __gRuntimeLoader->program_args->args[0]; __gCommPageAddress = __gRuntimeLoader->commpage_address; __gABIVersion = __gRuntimeLoader->abi_version; @@ -70,6 +72,9 @@ initialize_before(image_id imageID) pthread_self()->id = find_thread(NULL); + get_system_info(&info); + __gCPUCount = info.cpu_count; + __init_time((addr_t)__gCommPageAddress); __init_heap(); __init_env(__gRuntimeLoader->program_args); diff --git a/src/system/libroot/os/locks/mutex.cpp b/src/system/libroot/os/locks/mutex.cpp index 2e755bb9c2..7c017e73ff 100644 --- a/src/system/libroot/os/locks/mutex.cpp +++ b/src/system/libroot/os/locks/mutex.cpp @@ -18,6 +18,12 @@ #include +#define MAX_UNSUCCESSFUL_SPINS 100 + + +extern int32 __gCPUCount; + + // #pragma mark - mutex @@ -36,6 +42,9 @@ mutex_init_etc(mutex *lock, const char *name, uint32 flags) lock->name = (flags & MUTEX_FLAG_CLONE_NAME) != 0 ? strdup(name) : name; lock->lock = 0; lock->flags = flags; + + if (__gCPUCount < 2) + lock->flags &= ~uint32(MUTEX_FLAG_ADAPTIVE); } @@ -50,15 +59,22 @@ mutex_destroy(mutex *lock) status_t mutex_lock(mutex *lock) { - // set the locked flag - int32 oldValue = atomic_or(&lock->lock, B_USER_MUTEX_LOCKED); + uint32 count; + const uint32 kMaxCount + = (lock->flags & MUTEX_FLAG_ADAPTIVE) != 0 ? MAX_UNSUCCESSFUL_SPINS : 1; - if ((oldValue & (B_USER_MUTEX_LOCKED | B_USER_MUTEX_WAITING)) == 0 - || (oldValue & B_USER_MUTEX_DISABLED) != 0) { - // No one has the lock or is waiting for it, or the mutex has been - // disabled. - return B_OK; - } + int32 oldValue; + do { + // set the locked flag + oldValue = atomic_or(&lock->lock, B_USER_MUTEX_LOCKED); + + if ((oldValue & (B_USER_MUTEX_LOCKED | B_USER_MUTEX_WAITING)) == 0 + || (oldValue & B_USER_MUTEX_DISABLED) != 0) { + // No one has the lock or is waiting for it, or the mutex has been + // disabled. + return B_OK; + } + } while (count++ < kMaxCount && (oldValue & B_USER_MUTEX_WAITING) != 0); // we have to call the kernel status_t error; diff --git a/src/system/libroot/posix/malloc/arch-specific.cpp b/src/system/libroot/posix/malloc/arch-specific.cpp index 81a39945a8..4b9572e868 100644 --- a/src/system/libroot/posix/malloc/arch-specific.cpp +++ b/src/system/libroot/posix/malloc/arch-specific.cpp @@ -362,7 +362,7 @@ hoardUnsbrk(void *ptr, long size) void hoardLockInit(hoardLockType &lock, const char *name) { - mutex_init(&lock, name); + mutex_init_etc(&lock, name, MUTEX_FLAG_ADAPTIVE); } diff --git a/src/system/runtime_loader/runtime_loader.cpp b/src/system/runtime_loader/runtime_loader.cpp index 82a58ec7dd..14f5eb9936 100644 --- a/src/system/runtime_loader/runtime_loader.cpp +++ b/src/system/runtime_loader/runtime_loader.cpp @@ -24,6 +24,8 @@ struct user_space_program_args *gProgramArgs; void *__gCommPageAddress; +int32 __gCPUCount = 1; + static const char * search_path_for_type(image_type type)