From fbe2c1f2ceb855a8bfb78359c55a6f763ed5210b Mon Sep 17 00:00:00 2001 From: Kevoot Date: Sat, 30 Jun 2018 18:45:41 -0400 Subject: [PATCH] Add Semaphore (#125) --- nx/include/switch.h | 1 + nx/include/switch/kernel/semaphore.h | 44 ++++++++++++++++++++++++++++ nx/source/kernel/semaphore.c | 37 +++++++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 nx/include/switch/kernel/semaphore.h create mode 100644 nx/source/kernel/semaphore.c diff --git a/nx/include/switch.h b/nx/include/switch.h index 2ed024d1..c23aeea2 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -25,6 +25,7 @@ extern "C" { #include "switch/kernel/rwlock.h" #include "switch/kernel/condvar.h" #include "switch/kernel/thread.h" +#include "switch/kernel/semaphore.h" #include "switch/kernel/virtmem.h" #include "switch/kernel/detect.h" #include "switch/kernel/random.h" diff --git a/nx/include/switch/kernel/semaphore.h b/nx/include/switch/kernel/semaphore.h new file mode 100644 index 00000000..4eaa434b --- /dev/null +++ b/nx/include/switch/kernel/semaphore.h @@ -0,0 +1,44 @@ +/** + * @file semaphore.h + * @brief Thread synchronization based on Mutex. + * @author SciresM & Kevoot + * @copyright libnx Authors + */ +#pragma once + +#include "mutex.h" +#include "condvar.h" + +/// Semaphore structure. +typedef struct Semaphore +{ + CondVar condvar; ///< Conditional Variable Object. + Mutex mutex; ///< Mutex Object. + u64 count; ///< Internal Counter. +} Semaphore; + +/** + * @brief Initializes a semaphore and its internal counter. + * @param s Semaphore object. + * @param initial_count initial value for internal counter (typically the # of free resources). + */ +void semaphoreInit(Semaphore *s, u64 initial_count); + +/** + * @brief Increments the Semaphore to allow other threads to continue. + * @param s Semaphore object. + */ +void semaphoreSignal(Semaphore *s); + +/** + * @brief Decrements Semaphore and waits if 0. + * @param s Semaphore object. + */ +void semaphoreWait(Semaphore *s); + +/** + * @brief Attempts to get lock without waiting. + * @param s Semaphore object. + * @return true if no wait and successful lock, false otherwise. + */ +bool semaphoreTryWait(Semaphore *s); diff --git a/nx/source/kernel/semaphore.c b/nx/source/kernel/semaphore.c new file mode 100644 index 00000000..328e8414 --- /dev/null +++ b/nx/source/kernel/semaphore.c @@ -0,0 +1,37 @@ +// Copyright 2018 Kevoot +#include "kernel/semaphore.h" +#include "kernel/svc.h" + +void semaphoreInit(Semaphore *s, u64 initial_count) { + s->count = initial_count; + mutexInit(&s->mutex); + condvarInit(&s->condvar, &s->mutex); +} + +void semaphoreSignal(Semaphore *s) { + mutexLock(&s->mutex); + s->count++; + condvarWakeOne(&s->condvar); + mutexUnlock(&s->mutex); +} + +void semaphoreWait(Semaphore *s) { + mutexLock(&s->mutex); + // Wait until signalled. + while (!s->count) { + condvarWait(&s->condvar); + } + s->count--; + mutexUnlock(&s->mutex); +} + +bool semaphoreTryWait(Semaphore *s) { + mutexLock(&s->mutex); + bool success = false; + // Check and immediately return success. + if (s->count) { + s->count--; + success = true; + } + return success; +}