diff options
author | Egor Ananyin <ananinegor@gmail.com> | 2020-06-20 11:00:20 +0300 |
---|---|---|
committer | Egor Ananyin <ananinegor@gmail.com> | 2020-06-20 11:00:20 +0300 |
commit | 9fba6d2b34c67d4b14bb1a17d0b1d6d5d6d19b08 (patch) | |
tree | 4fe4daf2baef42c3954f54db7ebe21294a4ba738 /arm7/lib/src | |
parent | abd2d1e16494867989e710e5235c6425fa4e8c34 (diff) |
OS_mutext done!
Diffstat (limited to 'arm7/lib/src')
-rw-r--r-- | arm7/lib/src/OS_mutex.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/arm7/lib/src/OS_mutex.c b/arm7/lib/src/OS_mutex.c index 8fe167f3..7e9b05ec 100644 --- a/arm7/lib/src/OS_mutex.c +++ b/arm7/lib/src/OS_mutex.c @@ -1,8 +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; + } +} |