i think it works
This commit is contained in:
commit
0e1479b168
167 files changed
+27008
No files matched your search
@@ -0,0 +1,64 @@
|
||||
// ke_semaphore.c - counting semaphore
|
||||
#include "ke_semaphore.h"
|
||||
#include "ke_thread.h"
|
||||
#include "ke_sched.h"
|
||||
#include "ob_object.h"
|
||||
|
||||
static void SemDestroy(OBJECT* obj) { (void)obj; }
|
||||
|
||||
KSTATUS SemaphoreCreate(int32_t initial, int32_t max, SEMAPHORE **out) {
|
||||
if (!out || initial < 0 || max < 1 || initial > max)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
SEMAPHORE* s = (SEMAPHORE *)ObAllocateObject(ObjectTypeSemaphore, sizeof(SEMAPHORE));
|
||||
if (!s) return STATUS_NO_MEMORY;
|
||||
s->Header.Destroy = SemDestroy;
|
||||
s->Lock = (SPINLOCK)SPINLOCK_INIT;
|
||||
s->Count = initial;
|
||||
s->MaxCount = max;
|
||||
LIST_INIT(&s->WaitList);
|
||||
*out = s;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KSTATUS KeWaitSemaphore(SEMAPHORE* sem) {
|
||||
if (!sem) return STATUS_INVALID_PARAMETER;
|
||||
THREAD* self = KeCurrentThread();
|
||||
|
||||
for (;;) {
|
||||
KeAcquireSpinlock(&sem->Lock);
|
||||
if (sem->Count > 0) {
|
||||
sem->Count--;
|
||||
KeReleaseSpinlock(&sem->Lock);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
ListInsertTail(&sem->WaitList, &self->SchedulerLink);
|
||||
KeReleaseSpinlock(&sem->Lock);
|
||||
KeBlockThread(self, &sem->Header);
|
||||
}
|
||||
}
|
||||
|
||||
KSTATUS KeTrySemaphore(SEMAPHORE* sem) {
|
||||
if (!sem) return STATUS_INVALID_PARAMETER;
|
||||
KeAcquireSpinlock(&sem->Lock);
|
||||
if (sem->Count > 0) {
|
||||
sem->Count--;
|
||||
KeReleaseSpinlock(&sem->Lock);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
KeReleaseSpinlock(&sem->Lock);
|
||||
return STATUS_FAILURE;
|
||||
}
|
||||
|
||||
void KeSignalSemaphore(SEMAPHORE* sem) {
|
||||
if (!sem) return;
|
||||
KeAcquireSpinlock(&sem->Lock);
|
||||
if (!LIST_IS_EMPTY(&sem->WaitList)) {
|
||||
LIST_ENTRY* node = ListPopHead(&sem->WaitList);
|
||||
THREAD* waiter = CONTAINING_RECORD(node, THREAD, SchedulerLink);
|
||||
KeReleaseSpinlock(&sem->Lock);
|
||||
KeUnblockThread(waiter);
|
||||
return;
|
||||
}
|
||||
if (sem->Count < sem->MaxCount) sem->Count++;
|
||||
KeReleaseSpinlock(&sem->Lock);
|
||||
}
|
||||
Reference in new issue
Block a user