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/log.h"
#include "modules/modules.h" #include "modules/modules.h"
#include "modules/mutex.h"
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
#include "semphr.h"
#include <errno.h> #include <errno.h>
static StaticSemaphore_t hwlock_mutex_data[_HWLOCK_MAX]; static struct mutex hwlock_mutex[_HWLOCK_MAX] = { { 0 } };
static SemaphoreHandle_t hwlock_mutex[_HWLOCK_MAX];
/* Which task is holding the lock */
static TaskHandle_t hwlock_tasks[_HWLOCK_MAX];
void hwlock_init(void) void hwlock_init(void)
{ {
for (int i = 0; i < _HWLOCK_MAX; i++) { 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) int hwlock_acquire(enum hwlock_periph p, TickType_t wait)
{ {
if (p >= _HWLOCK_MAX) { assert(p < _HWLOCK_MAX);
return -EINVAL;
} /*
TaskHandle_t task = xTaskGetCurrentTaskHandle(); * Check for code still defining a timeout. It will be ignored in the
* new implementation but a warning is emitted so someone hopefully
if (xSemaphoreTake(hwlock_mutex[p], wait) != pdTRUE) { * eventually fixes the offending code ...
/* Don't print warnings for 0 wait acquires */ *
if (wait == 0) { * At some point, the signature of this function should be changed.
return -EBUSY; * Alternatively it could be split into two, similar to the mutex API.
} */
if (wait != 0 && wait != portMAX_DELAY) {
LOG_WARN( LOG_WARN(
"hwlock", "hwlock",
"Lock %u is busy! Held by \"%s\" and attempted to accquire by \"%s\"", "Attempting to lock %d with a timeout (from %p).",
p, p,
pcTaskGetName(hwlock_tasks[p]),
pcTaskGetName(task)
);
LOG_DEBUG(
"hwlock",
"...attempted to lock from pc %p",
__builtin_return_address(0) __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; return 0;
} }
int hwlock_release(enum hwlock_periph p) int hwlock_release(enum hwlock_periph p)
{ {
int ret = 0; assert(p < _HWLOCK_MAX);
mutex_unlock(&hwlock_mutex[p]);
if (p >= _HWLOCK_MAX) { return 0;
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;
} }
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