From f64c46e6365b121138040982da296b50c0a16a3b Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Tue, 25 Jul 2023 16:26:22 -0400 Subject: [PATCH] kernel & libroot: Implement per-team unnamed semaphores. This requires breaking syscall ABI to add the "flags" parameter to _kern_mutex_sem_release. Resolves a TODO. --- headers/private/kernel/user_mutex.h | 2 +- headers/private/system/syscalls.h | 2 +- src/system/kernel/locks/user_mutex.cpp | 43 +++++++++----------------- src/system/libroot/posix/semaphore.cpp | 13 ++++++-- 4 files changed, 26 insertions(+), 34 deletions(-) diff --git a/headers/private/kernel/user_mutex.h b/headers/private/kernel/user_mutex.h index 622037a379..4a21c7a3ba 100644 --- a/headers/private/kernel/user_mutex.h +++ b/headers/private/kernel/user_mutex.h @@ -25,7 +25,7 @@ status_t _user_mutex_switch_lock(int32* fromMutex, uint32 fromFlags, int32* toMutex, const char* name, uint32 toFlags, bigtime_t timeout); status_t _user_mutex_sem_acquire(int32* sem, const char* name, uint32 flags, bigtime_t timeout); -status_t _user_mutex_sem_release(int32* sem); +status_t _user_mutex_sem_release(int32* sem, uint32 flags); #ifdef __cplusplus } diff --git a/headers/private/system/syscalls.h b/headers/private/system/syscalls.h index d963215627..0239db8d13 100644 --- a/headers/private/system/syscalls.h +++ b/headers/private/system/syscalls.h @@ -83,7 +83,7 @@ extern status_t _kern_mutex_switch_lock(int32* fromMutex, uint32 fromFlags, bigtime_t timeout); extern status_t _kern_mutex_sem_acquire(int32* sem, const char* name, uint32 flags, bigtime_t timeout); -extern status_t _kern_mutex_sem_release(int32* sem); +extern status_t _kern_mutex_sem_release(int32* sem, uint32 flags); /* sem functions */ extern sem_id _kern_create_sem(int count, const char *name); diff --git a/src/system/kernel/locks/user_mutex.cpp b/src/system/kernel/locks/user_mutex.cpp index 35abcff8aa..bfb4671c92 100644 --- a/src/system/kernel/locks/user_mutex.cpp +++ b/src/system/kernel/locks/user_mutex.cpp @@ -660,58 +660,43 @@ _user_mutex_sem_acquire(int32* sem, const char* name, uint32 flags, syscall_restart_handle_timeout_pre(flags, timeout); - struct user_mutex_context* context; + UserMutexContextFetcher contextFetcher(sem, flags); + if (contextFetcher.InitCheck() != B_OK) + return contextFetcher.InitCheck(); + struct user_mutex_context* context = contextFetcher.Context(); - // TODO: use the per-team context when possible - context = &sSharedUserMutexContext; - - // wire the page and get the physical address - VMPageWiringInfo wiringInfo; - status_t error = vm_wire_page(B_CURRENT_TEAM, (addr_t)sem, true, - &wiringInfo); - if (error != B_OK) - return error; - - UserMutexEntry* entry = get_user_mutex_entry(context, wiringInfo.physicalAddress); + UserMutexEntry* entry = get_user_mutex_entry(context, contextFetcher.Address()); if (entry == NULL) return B_NO_MEMORY; + status_t error; { ReadLocker entryLocker(entry->lock); error = user_mutex_sem_acquire_locked(entry, sem, - flags | B_CAN_INTERRUPT, timeout, entryLocker, true); + flags | B_CAN_INTERRUPT, timeout, entryLocker, contextFetcher.IsWired()); } put_user_mutex_entry(context, entry); - vm_unwire_page(&wiringInfo); return syscall_restart_handle_timeout_post(error, timeout); } status_t -_user_mutex_sem_release(int32* sem) +_user_mutex_sem_release(int32* sem, uint32 flags) { if (sem == NULL || !IS_USER_ADDRESS(sem) || (addr_t)sem % 4 != 0) return B_BAD_ADDRESS; - struct user_mutex_context* context; - - // TODO: use the per-team context when possible - context = &sSharedUserMutexContext; - - // wire the page and get the physical address - VMPageWiringInfo wiringInfo; - status_t error = vm_wire_page(B_CURRENT_TEAM, (addr_t)sem, true, - &wiringInfo); - if (error != B_OK) - return error; + UserMutexContextFetcher contextFetcher(sem, flags); + if (contextFetcher.InitCheck() != B_OK) + return contextFetcher.InitCheck(); + struct user_mutex_context* context = contextFetcher.Context(); UserMutexEntry* entry = get_user_mutex_entry(context, - wiringInfo.physicalAddress); + contextFetcher.Address()); { - user_mutex_sem_release(entry, sem, true); + user_mutex_sem_release(entry, sem, contextFetcher.IsWired()); } put_user_mutex_entry(context, entry); - vm_unwire_page(&wiringInfo); return B_OK; } diff --git a/src/system/libroot/posix/semaphore.cpp b/src/system/libroot/posix/semaphore.cpp index 41c72eebcc..f02b1ade3f 100644 --- a/src/system/libroot/posix/semaphore.cpp +++ b/src/system/libroot/posix/semaphore.cpp @@ -24,6 +24,7 @@ #define SEM_TYPE_NAMED 1 #define SEM_TYPE_UNNAMED 2 +#define SEM_TYPE_UNNAMED_SHARED 3 static int32 @@ -114,7 +115,7 @@ sem_unlink(const char* name) int sem_init(sem_t* semaphore, int shared, unsigned value) { - semaphore->type = SEM_TYPE_UNNAMED; + semaphore->type = shared ? SEM_TYPE_UNNAMED_SHARED : SEM_TYPE_UNNAMED; semaphore->u.unnamed_sem = value; return 0; } @@ -123,7 +124,7 @@ sem_init(sem_t* semaphore, int shared, unsigned value) int sem_destroy(sem_t* semaphore) { - if (semaphore->type != SEM_TYPE_UNNAMED) + if (semaphore->type != SEM_TYPE_UNNAMED && semaphore->type != SEM_TYPE_UNNAMED_SHARED) RETURN_AND_SET_ERRNO(EINVAL); return 0; @@ -138,7 +139,11 @@ unnamed_sem_post(sem_t* semaphore) if (oldValue > -1) return 0; - return _kern_mutex_sem_release(sem); + uint32 flags = 0; + if (semaphore->type == SEM_TYPE_UNNAMED_SHARED) + flags |= B_USER_MUTEX_SHARED; + + return _kern_mutex_sem_release(sem, flags); } @@ -162,6 +167,8 @@ unnamed_sem_timedwait(sem_t* semaphore, clockid_t clock_id, bigtime_t timeoutMicros = B_INFINITE_TIMEOUT; uint32 flags = 0; + if (semaphore->type == SEM_TYPE_UNNAMED_SHARED) + flags |= B_USER_MUTEX_SHARED; if (timeout != NULL) { timeoutMicros = ((bigtime_t)timeout->tv_sec) * 1000000 + timeout->tv_nsec / 1000;