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;
#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);

View File

@ -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);

View File

@ -18,6 +18,12 @@
#include <user_mutex_defs.h>
#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;

View File

@ -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);
}

View File

@ -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)