[Kernel] ReleaseSemaphore for Posix to match Windows semantics
This commit is contained in:
@@ -320,14 +320,15 @@ class PosixCondition<Semaphore> final : public PosixConditionBase {
|
|||||||
bool Signal() override { return Release(1, nullptr); }
|
bool Signal() override { return Release(1, nullptr); }
|
||||||
|
|
||||||
bool Release(uint32_t release_count, int* out_previous_count) {
|
bool Release(uint32_t release_count, int* out_previous_count) {
|
||||||
if (maximum_count_ - count_ >= release_count) {
|
auto lock = std::unique_lock(mutex_);
|
||||||
auto lock = std::unique_lock(mutex_);
|
// Validate that releasing would not exceed the maximum count
|
||||||
if (out_previous_count) *out_previous_count = count_;
|
if (count_ + release_count > maximum_count_) {
|
||||||
count_ += release_count;
|
return false;
|
||||||
cond_.notify_all();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
if (out_previous_count) *out_previous_count = count_;
|
||||||
|
count_ += release_count;
|
||||||
|
cond_.notify_all();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -718,7 +718,10 @@ uint32_t xeKeReleaseSemaphore(X_KSEMAPHORE* semaphore_ptr, uint32_t increment,
|
|||||||
// TODO(benvanik): increment thread priority?
|
// TODO(benvanik): increment thread priority?
|
||||||
// TODO(benvanik): wait?
|
// TODO(benvanik): wait?
|
||||||
|
|
||||||
return sem->ReleaseSemaphore(adjustment);
|
int32_t previous_count = 0;
|
||||||
|
[[maybe_unused]] bool success =
|
||||||
|
sem->ReleaseSemaphore(adjustment, &previous_count);
|
||||||
|
return static_cast<uint32_t>(previous_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
dword_result_t KeReleaseSemaphore_entry(pointer_t<X_KSEMAPHORE> semaphore_ptr,
|
dword_result_t KeReleaseSemaphore_entry(pointer_t<X_KSEMAPHORE> semaphore_ptr,
|
||||||
@@ -777,7 +780,17 @@ dword_result_t NtReleaseSemaphore_entry(dword_t sem_handle,
|
|||||||
auto sem =
|
auto sem =
|
||||||
kernel_state()->object_table()->LookupObject<XSemaphore>(sem_handle);
|
kernel_state()->object_table()->LookupObject<XSemaphore>(sem_handle);
|
||||||
if (sem) {
|
if (sem) {
|
||||||
previous_count = sem->ReleaseSemaphore((int32_t)release_count);
|
bool success =
|
||||||
|
sem->ReleaseSemaphore((int32_t)release_count, &previous_count);
|
||||||
|
if (!success) {
|
||||||
|
// Releasing would exceed the semaphore's maximum count
|
||||||
|
// Windows returns STATUS_SEMAPHORE_LIMIT_EXCEEDED (0x0000012B)
|
||||||
|
XELOGW(
|
||||||
|
"NtReleaseSemaphore: release_count={} would exceed maximum (current "
|
||||||
|
"count={})",
|
||||||
|
uint32_t(release_count), previous_count);
|
||||||
|
result = 0x0000012B;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
result = X_STATUS_INVALID_HANDLE;
|
result = X_STATUS_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,10 +40,14 @@ bool XSemaphore::InitializeNative(void* native_ptr, X_DISPATCH_HEADER* header) {
|
|||||||
return !!semaphore_;
|
return !!semaphore_;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t XSemaphore::ReleaseSemaphore(int32_t release_count) {
|
bool XSemaphore::ReleaseSemaphore(int32_t release_count,
|
||||||
|
int32_t* out_previous_count) {
|
||||||
int32_t previous_count = 0;
|
int32_t previous_count = 0;
|
||||||
semaphore_->Release(release_count, &previous_count);
|
bool success = semaphore_->Release(release_count, &previous_count);
|
||||||
return previous_count;
|
if (out_previous_count) {
|
||||||
|
*out_previous_count = previous_count;
|
||||||
|
}
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool XSemaphore::Save(ByteStream* stream) {
|
bool XSemaphore::Save(ByteStream* stream) {
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ class XSemaphore : public XObject {
|
|||||||
[[nodiscard]] bool InitializeNative(void* native_ptr,
|
[[nodiscard]] bool InitializeNative(void* native_ptr,
|
||||||
X_DISPATCH_HEADER* header);
|
X_DISPATCH_HEADER* header);
|
||||||
|
|
||||||
int32_t ReleaseSemaphore(int32_t release_count);
|
[[nodiscard]] bool ReleaseSemaphore(int32_t release_count,
|
||||||
|
int32_t* out_previous_count);
|
||||||
|
|
||||||
bool Save(ByteStream* stream) override;
|
bool Save(ByteStream* stream) override;
|
||||||
static object_ref<XSemaphore> Restore(KernelState* kernel_state,
|
static object_ref<XSemaphore> Restore(KernelState* kernel_state,
|
||||||
|
|||||||
Reference in New Issue
Block a user