Split off RecursiveMutex from Mutex (#437)
* Split off RecursiveMutex from Mutex * Fix * Code quality
This commit is contained in:
committed by
GitHub
parent
f48654d3dc
commit
3fc2ff8bc6
@@ -1,34 +1,25 @@
|
||||
/**
|
||||
* @file mutex.h
|
||||
* @file Mutex.h
|
||||
* Mutex
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "Check.h"
|
||||
#include "Lock.h"
|
||||
#include "RtosCompatSemaphore.h"
|
||||
#include "Thread.h"
|
||||
#include "kernel/Kernel.h"
|
||||
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
|
||||
namespace tt {
|
||||
|
||||
/**
|
||||
* Wrapper for FreeRTOS xSemaphoreCreateMutex and xSemaphoreCreateRecursiveMutex
|
||||
* Wrapper for FreeRTOS xSemaphoreCreateMutex
|
||||
* Cannot be used in IRQ mode (within ISR context)
|
||||
*/
|
||||
class Mutex final : public Lock {
|
||||
|
||||
public:
|
||||
/**
|
||||
* A "Normal" mutex can only be locked once. Even from within the same task/thread.
|
||||
* A "Recursive" mutex can be locked again from the same task/thread.
|
||||
*/
|
||||
enum class Type {
|
||||
Normal,
|
||||
Recursive,
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
struct SemaphoreHandleDeleter {
|
||||
@@ -38,29 +29,40 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<std::remove_pointer_t<QueueHandle_t>, SemaphoreHandleDeleter> handle;
|
||||
Type type;
|
||||
std::unique_ptr<std::remove_pointer_t<QueueHandle_t>, SemaphoreHandleDeleter> handle = std::unique_ptr<std::remove_pointer_t<QueueHandle_t>, SemaphoreHandleDeleter>(xSemaphoreCreateMutex());
|
||||
|
||||
public:
|
||||
|
||||
using Lock::lock;
|
||||
|
||||
explicit Mutex(Type type = Type::Normal);
|
||||
explicit Mutex() {
|
||||
assert(handle != nullptr);
|
||||
}
|
||||
|
||||
~Mutex() override = default;
|
||||
|
||||
/** Attempt to lock the mutex. Blocks until timeout passes or lock is acquired.
|
||||
* @param[in] timeout
|
||||
* @return success result
|
||||
*/
|
||||
bool lock(TickType_t timeout) const override;
|
||||
bool lock(TickType_t timeout) const override {
|
||||
assert(!kernel::isIsr());
|
||||
return xSemaphoreTake(handle.get(), timeout) == pdPASS;
|
||||
}
|
||||
|
||||
/** Attempt to unlock the mutex.
|
||||
* @return success result
|
||||
*/
|
||||
bool unlock() const override;
|
||||
bool unlock() const override {
|
||||
assert(!kernel::isIsr());
|
||||
return xSemaphoreGive(handle.get()) == pdPASS;
|
||||
}
|
||||
|
||||
/** @return the owner of the thread */
|
||||
ThreadId getOwner() const;
|
||||
ThreadId getOwner() const {
|
||||
assert(!kernel::isIsr());
|
||||
return xSemaphoreGetMutexHolder(handle.get());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace tt
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* @file RecursiveMutex.h
|
||||
* RecursiveMutex
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "Lock.h"
|
||||
#include "RtosCompatSemaphore.h"
|
||||
#include "Thread.h"
|
||||
#include "kernel/Kernel.h"
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
|
||||
namespace tt {
|
||||
|
||||
/**
|
||||
* Wrapper for FreeRTOS xSemaphoreCreateRecursiveMutex
|
||||
* Cannot be used in IRQ mode (within ISR context)
|
||||
*/
|
||||
class RecursiveMutex final : public Lock {
|
||||
|
||||
private:
|
||||
|
||||
struct SemaphoreHandleDeleter {
|
||||
void operator()(QueueHandle_t handleToDelete) {
|
||||
assert(!kernel::isIsr());
|
||||
vSemaphoreDelete(handleToDelete);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<std::remove_pointer_t<QueueHandle_t>, SemaphoreHandleDeleter> handle = std::unique_ptr<std::remove_pointer_t<QueueHandle_t>, SemaphoreHandleDeleter>(xSemaphoreCreateRecursiveMutex());
|
||||
|
||||
public:
|
||||
|
||||
using Lock::lock;
|
||||
|
||||
explicit RecursiveMutex() {
|
||||
assert(handle != nullptr);
|
||||
}
|
||||
|
||||
~RecursiveMutex() override = default;
|
||||
|
||||
/** Attempt to lock the mutex. Blocks until timeout passes or lock is acquired.
|
||||
* @param[in] timeout
|
||||
* @return success result
|
||||
*/
|
||||
bool lock(TickType_t timeout) const override {
|
||||
assert(!kernel::isIsr());
|
||||
return xSemaphoreTakeRecursive(handle.get(), timeout) == pdPASS;
|
||||
}
|
||||
|
||||
/** Attempt to unlock the mutex.
|
||||
* @return success result
|
||||
*/
|
||||
bool unlock() const override {
|
||||
assert(!kernel::isIsr());
|
||||
return xSemaphoreGiveRecursive(handle.get()) == pdPASS;
|
||||
}
|
||||
|
||||
/** @return the owner of the thread */
|
||||
ThreadId getOwner() const {
|
||||
assert(!kernel::isIsr());
|
||||
return xSemaphoreGetMutexHolder(handle.get());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@@ -1,77 +0,0 @@
|
||||
#include "Tactility/Mutex.h"
|
||||
|
||||
#include "Tactility/Check.h"
|
||||
#include "Tactility/CoreDefines.h"
|
||||
#include "Tactility/Log.h"
|
||||
|
||||
namespace tt {
|
||||
|
||||
#define MUTEX_DEBUGGING false
|
||||
|
||||
#if MUTEX_DEBUGGING
|
||||
#define TAG "mutex"
|
||||
void tt_mutex_info(Mutex mutex, const char* label) {
|
||||
MutexData* data = (MutexData*)mutex;
|
||||
if (data == NULL) {
|
||||
TT_LOG_I(TAG, "mutex %s: is NULL", label);
|
||||
} else {
|
||||
TT_LOG_I(TAG, "mutex %s: handle=%0X type=%d owner=%0x", label, data->handle, data->type, tt_mutex_get_owner(mutex));
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define tt_mutex_info(mutex, text)
|
||||
#endif
|
||||
|
||||
static inline SemaphoreHandle_t createSemaphoreHandle(Mutex::Type type) {
|
||||
switch (type) {
|
||||
case Mutex::Type::Normal:
|
||||
return xSemaphoreCreateMutex();
|
||||
case Mutex::Type::Recursive:
|
||||
return xSemaphoreCreateRecursiveMutex();
|
||||
default:
|
||||
tt_crash("Mutex type unknown/corrupted");
|
||||
}
|
||||
}
|
||||
|
||||
Mutex::Mutex(Type type) : handle(createSemaphoreHandle(type)), type(type) {
|
||||
tt_mutex_info(data, "alloc");
|
||||
assert(handle != nullptr);
|
||||
}
|
||||
|
||||
bool Mutex::lock(TickType_t timeout) const {
|
||||
assert(!kernel::isIsr());
|
||||
assert(handle != nullptr);
|
||||
tt_mutex_info(mutex, "acquire");
|
||||
|
||||
switch (type) {
|
||||
case Type::Normal:
|
||||
return xSemaphoreTake(handle.get(), timeout) == pdPASS;
|
||||
case Type::Recursive:
|
||||
return xSemaphoreTakeRecursive(handle.get(), timeout) == pdPASS;
|
||||
default:
|
||||
tt_crash();
|
||||
}
|
||||
}
|
||||
|
||||
bool Mutex::unlock() const {
|
||||
assert(!kernel::isIsr());
|
||||
assert(handle != nullptr);
|
||||
tt_mutex_info(mutex, "release");
|
||||
|
||||
switch (type) {
|
||||
case Type::Normal:
|
||||
return xSemaphoreGive(handle.get()) == pdPASS;
|
||||
case Type::Recursive:
|
||||
return xSemaphoreGiveRecursive(handle.get()) == pdPASS;
|
||||
default:
|
||||
tt_crash();
|
||||
}
|
||||
}
|
||||
|
||||
ThreadId Mutex::getOwner() const {
|
||||
assert(!kernel::isIsr());
|
||||
assert(handle != nullptr);
|
||||
return (ThreadId)xSemaphoreGetMutexHolder(handle.get());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
Reference in New Issue
Block a user