diff --git a/headers/os/kernel/OS.h b/headers/os/kernel/OS.h index b738d747b9..7ad1f346ca 100644 --- a/headers/os/kernel/OS.h +++ b/headers/os/kernel/OS.h @@ -170,6 +170,11 @@ extern status_t acquire_sem(sem_id id); extern status_t acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout); extern status_t release_sem(sem_id id); extern status_t release_sem_etc(sem_id id, int32 count, uint32 flags); +// ToDo: the following two calls are not part of the BeOS API, and might be +// changed or even removed for the final release of Haiku R1 +extern status_t switch_sem(sem_id semToBeReleased, sem_id id); +extern status_t switch_sem_etc(sem_id semToBeReleased, sem_id id, int32 count, + uint32 flags, bigtime_t timeout); extern status_t get_sem_count(sem_id id, int32 *threadCount); extern status_t set_sem_owner(sem_id id, team_id team); diff --git a/headers/private/kernel/sem.h b/headers/private/kernel/sem.h index ac0a7eea9d..684ec9db43 100755 --- a/headers/private/kernel/sem.h +++ b/headers/private/kernel/sem.h @@ -1,5 +1,5 @@ /* - * Copyright 2002-2004, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2002-2005, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. @@ -12,7 +12,6 @@ #include #include - struct kernel_args; @@ -33,6 +32,8 @@ sem_id _user_create_sem(int32 count, const char *name); status_t _user_delete_sem(sem_id id); status_t _user_acquire_sem(sem_id id); status_t _user_acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout); +status_t _user_switch_sem(sem_id releaseSem, sem_id id); +status_t _user_switch_sem_etc(sem_id releaseSem, sem_id id, int32 count, uint32 flags, bigtime_t timeout); status_t _user_release_sem(sem_id id); status_t _user_release_sem_etc(sem_id id, int32 count, uint32 flags); status_t _user_get_sem_count(sem_id id, int32* thread_count); diff --git a/headers/private/kernel/syscalls.h b/headers/private/kernel/syscalls.h index 3c7fe18b7c..39c6736448 100644 --- a/headers/private/kernel/syscalls.h +++ b/headers/private/kernel/syscalls.h @@ -46,6 +46,9 @@ extern status_t _kern_get_safemode_option(const char *parameter, char *buffer, /* sem functions */ extern sem_id _kern_create_sem(int count, const char *name); extern status_t _kern_delete_sem(sem_id id); +extern status_t _kern_switch_sem(sem_id releaseSem, sem_id id); +extern status_t _kern_switch_sem_etc(sem_id releaseSem, sem_id id, uint32 count, + uint32 flags, bigtime_t timeout); extern status_t _kern_acquire_sem(sem_id id); extern status_t _kern_acquire_sem_etc(sem_id id, uint32 count, uint32 flags, bigtime_t timeout); extern status_t _kern_release_sem(sem_id id); diff --git a/src/kernel/core/sem.c b/src/kernel/core/sem.c index 07dac4fdf9..47df6fa40f 100644 --- a/src/kernel/core/sem.c +++ b/src/kernel/core/sem.c @@ -407,12 +407,29 @@ sem_timeout(timer *data) status_t acquire_sem(sem_id id) { - return acquire_sem_etc(id, 1, 0, 0); + return switch_sem_etc(-1, id, 1, 0, 0); } + status_t acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout) { + return switch_sem_etc(-1, id, count, flags, timeout); +} + + +status_t +switch_sem(sem_id toBeReleased, sem_id toBeAcquired) +{ + return switch_sem_etc(toBeReleased, toBeAcquired, 1, 0, 0); +} + + +status_t +switch_sem_etc(sem_id semToBeReleased, sem_id id, int32 count, + uint32 flags, bigtime_t timeout) +{ + // ToDo: add support for B_CHECK_PERMISSION int slot = id % sMaxSems; int state; status_t status = B_OK; @@ -494,6 +511,10 @@ acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout) } RELEASE_SEM_LOCK(sSems[slot]); + + if (semToBeReleased >= B_OK) + release_sem_etc(semToBeReleased, 1, B_DO_NOT_RESCHEDULE); + GRAB_THREAD_LOCK(); // check again to see if a signal is pending. // it may have been delivered while setting up the sem, though it's pretty unlikely @@ -553,6 +574,7 @@ release_sem(sem_id id) status_t release_sem_etc(sem_id id, int32 count, uint32 flags) { + // ToDo: add support for B_CHECK_PERMISSION struct thread_queue releaseQueue; int32 slot = id % sMaxSems; cpu_status state; @@ -998,28 +1020,42 @@ _user_delete_sem(sem_id id) status_t _user_acquire_sem(sem_id id) { - return _user_acquire_sem_etc(id, 1, 0, 0); + return switch_sem_etc(-1, id, 1, B_CAN_INTERRUPT | B_CHECK_PERMISSION, 0); } status_t _user_acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout) { - return acquire_sem_etc(id, count, flags | B_CAN_INTERRUPT, timeout); + return switch_sem_etc(-1, id, count, flags | B_CAN_INTERRUPT | B_CHECK_PERMISSION, timeout); +} + + +status_t +_user_switch_sem(sem_id releaseSem, sem_id id) +{ + return switch_sem_etc(releaseSem, id, 1, B_CAN_INTERRUPT | B_CHECK_PERMISSION, 0); +} + + +status_t +_user_switch_sem_etc(sem_id releaseSem, sem_id id, int32 count, uint32 flags, bigtime_t timeout) +{ + return switch_sem_etc(releaseSem, id, count, flags | B_CAN_INTERRUPT | B_CHECK_PERMISSION, timeout); } status_t _user_release_sem(sem_id id) { - return release_sem_etc(id, 1, 0); + return release_sem_etc(id, 1, B_CHECK_PERMISSION); } status_t _user_release_sem_etc(sem_id id, int32 count, uint32 flags) { - return release_sem_etc(id, count, flags); + return release_sem_etc(id, count, flags | B_CHECK_PERMISSION); } diff --git a/src/kernel/libroot/os/sem.c b/src/kernel/libroot/os/sem.c index ca5921375c..b07143d05f 100644 --- a/src/kernel/libroot/os/sem.c +++ b/src/kernel/libroot/os/sem.c @@ -1,5 +1,5 @@ /* - * Copyright 2002-2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2002-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. * Distributed under the terms of the MIT License. */ @@ -36,6 +36,23 @@ acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout) } +// ToDo: the next two calls (switch_sem()) are not yet public API; no decision +// has been made yet, so they may get changed or removed until R1 + +status_t +switch_sem(sem_id releaseSem, sem_id id) +{ + return _kern_switch_sem(releaseSem, id); +} + + +status_t +switch_sem_etc(sem_id releaseSem, sem_id id, int32 count, uint32 flags, bigtime_t timeout) +{ + return _kern_switch_sem_etc(releaseSem, id, count, flags, timeout); +} + + status_t release_sem(sem_id id) {