53 lines
1.6 KiB
C
53 lines
1.6 KiB
C
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdatomic.h>
|
|
#include <exec/list.h>
|
|
#include <exec/task.h>
|
|
#include <exec/sync.h>
|
|
|
|
void NewSemaphore(struct Semaphore *semaphore, int count, uint8_t type) {
|
|
semaphore->count = count;
|
|
semaphore->type = type;
|
|
}
|
|
|
|
void NewMutex(struct Semaphore *semaphore, uint8_t type) {
|
|
NewSemaphore(semaphore, 1, type);
|
|
}
|
|
|
|
void Acquire(struct Semaphore *semaphore) {
|
|
int expected;
|
|
int semtype = (semaphore->type & 3);
|
|
|
|
//if (!(semaphore->type & SF_NOTRECURSIVE) && semaphore->owner == ThisTask()) return;
|
|
|
|
if (semtype == SF_CLI) {
|
|
InterruptsSaveAndDisable();
|
|
} else {
|
|
for (;;) {
|
|
expected = atomic_load_explicit(&semaphore->count, memory_order_relaxed);
|
|
while (expected <= 0) {
|
|
if (semtype == SF_BLOCK) {
|
|
Block(ThisTask(), &semaphore->count, expected);
|
|
} else if ((semaphore->type & 3) == SF_NONE) {
|
|
return;
|
|
}
|
|
expected = atomic_load_explicit(&semaphore->count,
|
|
memory_order_relaxed);
|
|
}
|
|
if (atomic_compare_exchange_weak_explicit(
|
|
&semaphore->count, &expected, expected - 1,
|
|
memory_order_acquire, memory_order_relaxed)) {
|
|
//if (!(semaphore->type & SF_NOTRECURSIVE)) semaphore->owner = ThisTask();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Release(struct Semaphore *semaphore) {
|
|
if (semaphore->type == SF_CLI) {
|
|
InterruptsRestore();
|
|
} else {
|
|
atomic_fetch_add_explicit(&semaphore->count, 1, memory_order_release);
|
|
}
|
|
} |