diff options
author | PikalaxALT <pikalaxalt@gmail.com> | 2020-06-20 09:48:40 -0400 |
---|---|---|
committer | PikalaxALT <pikalaxalt@gmail.com> | 2020-06-20 09:48:40 -0400 |
commit | ae9380cad03effaef52810db07105ca3f2c1a3f8 (patch) | |
tree | 3e766233037a6058d704f695204ff3e23e7edac8 /arm7/lib/src/OS_mutex.c | |
parent | faad0fa28601101d5dc10a231fc6f11dc8d85d5f (diff) | |
parent | 01c4d4b1858149c2da1ce76368ac861f16fd066d (diff) |
Merge branch 'master' of https://github.com/martmists/pokediamond into pikalax_work
Diffstat (limited to 'arm7/lib/src/OS_mutex.c')
-rw-r--r-- | arm7/lib/src/OS_mutex.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/arm7/lib/src/OS_mutex.c b/arm7/lib/src/OS_mutex.c new file mode 100644 index 00000000..7e9b05ec --- /dev/null +++ b/arm7/lib/src/OS_mutex.c @@ -0,0 +1,95 @@ +#include "function_target.h" +#include "OS_mutex.h" +#include "OS_system.h" +#include "OS_thread.h" + +ARM_FUNC void OS_InitMutex(OSMutex* mutex) { + OS_InitThreadQueue(&mutex->queue); + mutex->thread = NULL; + mutex->count = 0; +} + +ARM_FUNC void OS_LockMutex(OSMutex* mutex) { + OSIntrMode mode; + OSThread* current; + + mode = OS_DisableInterrupts(); + current = OS_GetCurrentThread(); + while (1) { + OSThread* owner = mutex->thread; + if (owner == NULL) { + mutex->thread = current; + mutex->count++; + OSi_EnqueueTail(current, mutex); + break; + } + else if (owner == current) { + mutex->count++; + break; + } + else { + current->mutex = mutex; + OS_SleepThread(&mutex->queue); + current->mutex = NULL; + } + } + (void)OS_RestoreInterrupts(mode); +} + +ARM_FUNC void OS_UnlockMutex(OSMutex* mutex) { + OSIntrMode mode; + OSThread* current; + + mode = OS_DisableInterrupts(); + current = OS_GetCurrentThread(); + if (mutex->thread == current) { + if (--mutex->count == 0) { + OSi_DequeueItem(current, mutex); + mutex->thread = NULL; + OS_WakeupThread(&mutex->queue); + } + } + (void)OS_RestoreInterrupts(mode); +} + +ARM_FUNC void OSi_UnlockAllMutex(OSThread * thread) { + OSMutex * mutex; + while (thread->mutexQueue.head) { + mutex = OSi_RemoveMutexLinkFromQueue(&thread->mutexQueue); + mutex->count = 0; + mutex->thread = NULL; + OS_WakeupThread(&mutex->queue); + } +} + +ARM_FUNC void OSi_EnqueueTail(OSThread * thread, OSMutex * mutex) { + OSMutex * tail = thread->mutexQueue.tail; + if (tail == NULL) { + thread->mutexQueue.head = mutex; + } + else { + tail->link.next = mutex; + } + mutex->link.prev = tail; + mutex->link.next = NULL; + thread->mutexQueue.tail = mutex; +} + +ARM_FUNC void OSi_DequeueItem(OSThread * thread, OSMutex * mutex) { + OSMutex *next = mutex->link.next; + OSMutex *prev = mutex->link.prev; + + if (next == NULL) { + thread->mutexQueue.tail = prev; + } + else { + next->link.prev = prev; + } + + if (prev == NULL) { + thread->mutexQueue.head = next; + } + else { + prev->link.next = next; + } +} |