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.
This commit is contained in:
Augustin Cavalier
2023-07-25 16:26:22 -04:00
parent b3b7b89334
commit f64c46e636
4 changed files with 26 additions and 34 deletions
+1 -1
View File
@@ -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
}
+1 -1
View File
@@ -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);
+14 -29
View File
@@ -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;
}
+10 -3
View File
@@ -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;