libroot: Add adaptive mutex implementation

This commit is contained in:
Pawel Dziepak 2013-11-08 03:37:30 +01:00
parent 03fb2d8868
commit 7e1c4534df
5 changed files with 33 additions and 9 deletions

View File

@ -18,6 +18,7 @@ typedef struct mutex {
} mutex; } mutex;
#define MUTEX_FLAG_CLONE_NAME 0x1 #define MUTEX_FLAG_CLONE_NAME 0x1
#define MUTEX_FLAG_ADAPTIVE 0x2
#define MUTEX_INITIALIZER(name) { name, 0, 0 } #define MUTEX_INITIALIZER(name) { name, 0, 0 }
void mutex_init(mutex *lock, const char *name); void mutex_init(mutex *lock, const char *name);

View File

@ -32,6 +32,7 @@ int __libc_argc;
char **__libc_argv; char **__libc_argv;
int __gABIVersion; int __gABIVersion;
int32 __gCPUCount;
char _single_threaded = true; char _single_threaded = true;
// determines if I/O locking needed; needed for BeOS compatibility // determines if I/O locking needed; needed for BeOS compatibility
@ -48,6 +49,7 @@ int _data_offset_main_;
void void
initialize_before(image_id imageID) initialize_before(image_id imageID)
{ {
system_info info;
char *programPath = __gRuntimeLoader->program_args->args[0]; char *programPath = __gRuntimeLoader->program_args->args[0];
__gCommPageAddress = __gRuntimeLoader->commpage_address; __gCommPageAddress = __gRuntimeLoader->commpage_address;
__gABIVersion = __gRuntimeLoader->abi_version; __gABIVersion = __gRuntimeLoader->abi_version;
@ -70,6 +72,9 @@ initialize_before(image_id imageID)
pthread_self()->id = find_thread(NULL); pthread_self()->id = find_thread(NULL);
get_system_info(&info);
__gCPUCount = info.cpu_count;
__init_time((addr_t)__gCommPageAddress); __init_time((addr_t)__gCommPageAddress);
__init_heap(); __init_heap();
__init_env(__gRuntimeLoader->program_args); __init_env(__gRuntimeLoader->program_args);

View File

@ -18,6 +18,12 @@
#include <user_mutex_defs.h> #include <user_mutex_defs.h>
#define MAX_UNSUCCESSFUL_SPINS 100
extern int32 __gCPUCount;
// #pragma mark - mutex // #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->name = (flags & MUTEX_FLAG_CLONE_NAME) != 0 ? strdup(name) : name;
lock->lock = 0; lock->lock = 0;
lock->flags = flags; lock->flags = flags;
if (__gCPUCount < 2)
lock->flags &= ~uint32(MUTEX_FLAG_ADAPTIVE);
} }
@ -50,15 +59,22 @@ mutex_destroy(mutex *lock)
status_t status_t
mutex_lock(mutex *lock) mutex_lock(mutex *lock)
{ {
// set the locked flag uint32 count;
int32 oldValue = atomic_or(&lock->lock, B_USER_MUTEX_LOCKED); const uint32 kMaxCount
= (lock->flags & MUTEX_FLAG_ADAPTIVE) != 0 ? MAX_UNSUCCESSFUL_SPINS : 1;
if ((oldValue & (B_USER_MUTEX_LOCKED | B_USER_MUTEX_WAITING)) == 0 int32 oldValue;
|| (oldValue & B_USER_MUTEX_DISABLED) != 0) { do {
// No one has the lock or is waiting for it, or the mutex has been // set the locked flag
// disabled. oldValue = atomic_or(&lock->lock, B_USER_MUTEX_LOCKED);
return B_OK;
} 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 // we have to call the kernel
status_t error; status_t error;

View File

@ -362,7 +362,7 @@ hoardUnsbrk(void *ptr, long size)
void void
hoardLockInit(hoardLockType &lock, const char *name) hoardLockInit(hoardLockType &lock, const char *name)
{ {
mutex_init(&lock, name); mutex_init_etc(&lock, name, MUTEX_FLAG_ADAPTIVE);
} }

View File

@ -24,6 +24,8 @@
struct user_space_program_args *gProgramArgs; struct user_space_program_args *gProgramArgs;
void *__gCommPageAddress; void *__gCommPageAddress;
int32 __gCPUCount = 1;
static const char * static const char *
search_path_for_type(image_type type) search_path_for_type(image_type type)