Skip to content
Snippets Groups Projects
Commit d93c7f00 authored by rahix's avatar rahix
Browse files

feat(hw-locks): Switch to new mutex API


Reimplement the hw-lock module to use the new mutex API.  This slightly
changes the semantics of locking a hw-lock as the new mutex API does not
allow timeouts.  When a hwlock_acquire() with a (non-infinite) timeout
is attempted, a warning is printed to the serial console.

Additionally, instead of returning -EINVAL on use of a non-existent
hardware lock, the new implementation triggers a firmware panic.

Signed-off-by: default avatarRahix <rahix@rahix.de>
parent 181617d3
No related branches found
No related tags found
No related merge requests found
#include "modules/log.h"
#include "modules/modules.h"
#include "modules/mutex.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include <errno.h>
static StaticSemaphore_t hwlock_mutex_data[_HWLOCK_MAX];
static SemaphoreHandle_t hwlock_mutex[_HWLOCK_MAX];
/* Which task is holding the lock */
static TaskHandle_t hwlock_tasks[_HWLOCK_MAX];
static struct mutex hwlock_mutex[_HWLOCK_MAX] = { { 0 } };
void hwlock_init(void)
{
for (int i = 0; i < _HWLOCK_MAX; i++) {
hwlock_mutex[i] =
xSemaphoreCreateMutexStatic(&hwlock_mutex_data[i]);
/*
* TODO: mutex_create() names these all these mutexes
* "&hwlock_mutex[i]" which is not helpful at all. We
* should somehow rename them to the actual hwlock names.
*/
mutex_create(&hwlock_mutex[i]);
}
}
int hwlock_acquire(enum hwlock_periph p, TickType_t wait)
{
if (p >= _HWLOCK_MAX) {
return -EINVAL;
}
TaskHandle_t task = xTaskGetCurrentTaskHandle();
if (xSemaphoreTake(hwlock_mutex[p], wait) != pdTRUE) {
/* Don't print warnings for 0 wait acquires */
if (wait == 0) {
return -EBUSY;
}
assert(p < _HWLOCK_MAX);
/*
* Check for code still defining a timeout. It will be ignored in the
* new implementation but a warning is emitted so someone hopefully
* eventually fixes the offending code ...
*
* At some point, the signature of this function should be changed.
* Alternatively it could be split into two, similar to the mutex API.
*/
if (wait != 0 && wait != portMAX_DELAY) {
LOG_WARN(
"hwlock",
"Lock %u is busy! Held by \"%s\" and attempted to accquire by \"%s\"",
"Attempting to lock %d with a timeout (from %p).",
p,
pcTaskGetName(hwlock_tasks[p]),
pcTaskGetName(task)
);
LOG_DEBUG(
"hwlock",
"...attempted to lock from pc %p",
__builtin_return_address(0)
);
return -EBUSY;
}
hwlock_tasks[p] = task;
/* Non-blocking lock attempt */
if (wait == 0) {
if (mutex_trylock(&hwlock_mutex[p]) == true) {
return 0;
} else {
return -EBUSY;
}
}
mutex_lock(&hwlock_mutex[p]);
return 0;
}
int hwlock_release(enum hwlock_periph p)
{
int ret = 0;
if (p >= _HWLOCK_MAX) {
return -EINVAL;
}
if (hwlock_tasks[p] != xTaskGetCurrentTaskHandle()) {
LOG_ERR("hwlock",
"Lock %u is released by task \"%s\" while it was acquired by \"%s\"",
p,
pcTaskGetName(NULL),
pcTaskGetName(hwlock_tasks[p]));
ret = -EACCES;
}
if (xSemaphoreGive(hwlock_mutex[p]) != pdTRUE) {
LOG_ERR("hwlock", "Lock %u not released correctly.", p);
ret = -EINVAL;
}
return ret;
assert(p < _HWLOCK_MAX);
mutex_unlock(&hwlock_mutex[p]);
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment