Commit 144957a9 authored by arkeks's avatar arkeks
Browse files

Add priority inversion example

parent 39466465
No related merge requests found
Showing with 184 additions and 0 deletions
+184 -0
# name of your application
APPLICATION = priority_inv
USEMODULE += core_mutex_priority_inheritance
BOARD ?= bluepill-stm32f103c8
USEMODULE += ztimer_msec
USEMODULE += periph_gpio_irq
# This has to be the absolute path to the RIOT base directory:
RIOTBASE ?= $(CURDIR)/../../
include $(RIOTBASE)/Makefile.include
CFLAGS += -DTHREAD_STACKSIZE_MAIN=THREAD_STACKSIZE_SMALL
#include "board.h"
#include "periph/gpio.h"
#include "ztimer.h"
// pinout params
#define LED_HIGH_PRIO GPIO_PIN(PORT_B, 10) // green
#define LED_MED_PRIO GPIO_PIN(PORT_A, 0) // yellow
#define LED_LOW_PRIO GPIO_PIN(PORT_A, 3) // red
// timing params
#define DEADLINE_S (6U)
#define DEADLINE_MS (DEADLINE_S*MS_PER_SEC)
#define LOW_BUSY_S (5U)
#define MED_BUSY_S (1U)
#define HIGH_BUSY_S (0.6)
static mutex_t shared_mutex = MUTEX_INIT;
static ztimer_t watchdog_timer;
static kernel_pid_t high_pid;
// Thread priorities (7 is highest)
static char stack_high[THREAD_STACKSIZE_SMALL];
static char stack_med[THREAD_STACKSIZE_SMALL];
static char stack_low[THREAD_STACKSIZE_SMALL];
static void busy_delay_1s(void)
{
int j;
/* About 1 second if assuming one loop iteration takes ~20 CPU cycles.*/
for (volatile uint32_t i = 0; i < CLOCK_CORECLOCK / 18; i++)
{
j++;
}
}
static void busy_delay_0_5s(void)
{
int j;
/* About 1 second if assuming one loop iteration takes ~20 CPU cycles.*/
for (volatile uint32_t i = 0; i < CLOCK_CORECLOCK / 36; i++)
{
j++;
}
}
static void panic_led(void) {
gpio_toggle(LED_HIGH_PRIO);
busy_delay_0_5s();
}
static void watchdog_timeout(void *arg) {
(void)arg;
printf("!!! Deadline missed - priority inversion detected!\n");
while(1) { panic_led(); } // Critical failure state
}
static void *high_prio_thread(void *arg) {
(void)arg;
msg_t msg;
// Store our PID for button handler
high_pid = thread_getpid();
gpio_init(LED_HIGH_PRIO, GPIO_OUT);
gpio_init(LED_LOW_PRIO, GPIO_OUT);
while(1) {
gpio_clear(LED_HIGH_PRIO);
printf("High: Waiting for msg from low...\n");
// Wait for message from low prio thread
msg_receive(&msg);
// printf("High: Button received - attempting lock\n");
printf("High: Msg from low received - attempting lock\n");
gpio_set(LED_HIGH_PRIO);
ztimer_set(ZTIMER_MSEC, &watchdog_timer, DEADLINE_MS);
ztimer_now_t start_time = ztimer_now(ZTIMER_MSEC);
mutex_lock(&shared_mutex);
printf("High: Lock acquired after %d ms\n",
(int)(ztimer_now(ZTIMER_MSEC) - start_time));
// Critical section - simulate emergency response
gpio_set(LED_LOW_PRIO);
ztimer_sleep(ZTIMER_MSEC, HIGH_BUSY_S*MS_PER_SEC);
gpio_clear(LED_LOW_PRIO);
mutex_unlock(&shared_mutex);
ztimer_remove(ZTIMER_MSEC, &watchdog_timer);
printf("High: Critical completed after %d ms\n",
(int)(ztimer_now(ZTIMER_MSEC) - start_time));
}
return NULL;
}
static void *med_prio_thread(void *arg) {
(void)arg;
gpio_init(LED_MED_PRIO, GPIO_OUT);
while(1) {
printf("Med : Starting medium task...\n");
gpio_set(LED_MED_PRIO);
// Simulate CPU-intensive task
for (int i = 0; i < MED_BUSY_S; i++) {
busy_delay_1s();
gpio_toggle(LED_MED_PRIO);
}
gpio_clear(LED_MED_PRIO);
printf("Med : Completed\n");
ztimer_sleep(ZTIMER_MSEC, 0.5*MS_PER_SEC);
}
return NULL;
}
static void *low_prio_thread(void *arg) {
(void)arg;
while(1) {
printf("Low : Starting low task\n");
mutex_lock(&shared_mutex);
gpio_set(LED_LOW_PRIO);
msg_t msg;
msg_send(&msg, high_pid);
// Simulate long resource access
ztimer_now_t start_time = ztimer_now(ZTIMER_MSEC);
for (int i = 0; i < LOW_BUSY_S; i++) {
busy_delay_1s();
}
printf("Low: Loop lasted %d ms\n",
(int)(ztimer_now(ZTIMER_MSEC) - start_time));
mutex_unlock(&shared_mutex);
gpio_clear(LED_LOW_PRIO);
printf("Low : Completed\n");
ztimer_sleep(ZTIMER_MSEC, 0.5*MS_PER_SEC);
}
return NULL;
}
int main(void) {
printf("\n=== Priority Inversion Demo ===\n");
printf("Press button to trigger high-prio task\n");
printf("Expected behavior:\n");
printf("- Normal: High completes within %d ms\n", DEADLINE_MS);
printf("- Inversion: High misses deadline (LED flashes fast)\n");
watchdog_timer.callback = watchdog_timeout;
thread_create(stack_high, sizeof(stack_high), 7, 0,
high_prio_thread, NULL, "high");
thread_create(stack_med, sizeof(stack_med), 8, 0,
med_prio_thread, NULL, "med");
thread_create(stack_low, sizeof(stack_low), 9, 0,
low_prio_thread, NULL, "low");
return 0;
}
#include <string.h>
#include "board.h"
#include "irq.h"
#include "mutex.h"
#include "periph_conf.h"
#include "thread.h"
#include "ztimer.h"
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment