Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions components/khal/system/include/khal_system.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@ size_t khal_task_list(khal_task_info_t *out, size_t max, size_t *total);
*/
uint32_t khal_task_stack_free(void);

/**
* @brief Change the calling task's priority.
* @param priority The FreeRTOS priority to run at from here on.
* @return The priority the task had, to give it back with.
*/
uint32_t khal_task_priority_set(uint32_t priority);

/**
* @brief The name of the running task. Safe from a critical section.
* @return The name, or NULL before the scheduler runs.
Expand Down
8 changes: 8 additions & 0 deletions components/khal/system/src/khal_system_esp.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,14 @@ size_t khal_task_list(khal_task_info_t *out, size_t max, size_t *total)
#endif
}

uint32_t khal_task_priority_set(uint32_t priority)
{
uint32_t const was = (uint32_t)uxTaskPriorityGet(NULL);

vTaskPrioritySet(NULL, (UBaseType_t)priority);
return was;
}

uint32_t khal_task_stack_free(void)
{
/* StackType_t is a byte here, so the mark is already in bytes. */
Expand Down
6 changes: 6 additions & 0 deletions components/kode_sys/src/kode_sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,11 @@ const kode_sys_row_t kode_sys_rows[KODE_SYS_ROWS] = {

void kode_sys_rows_walk(const kode_sys_row_t *rows, size_t n)
{
/* The walk outranks the renderer the early row starts: every row comes
* up at the pace of its own bring-up, on whichever core the renderer
* landed. The boot task has its own priority back when it ends. */
uint32_t const was = khal_task_priority_set(KODE_PRIO_BOOT_WALK);

for ( size_t i = 0U; i < n; ++i )
{
if ( NULL != rows[i].start )
Expand All @@ -193,6 +198,7 @@ void kode_sys_rows_walk(const kode_sys_row_t *rows, size_t n)
rows[i].park();
}
}
(void)khal_task_priority_set(was);
}

/** @brief The bring-up itself; kode_init() runs it behind the one-shot. */
Expand Down
2 changes: 2 additions & 0 deletions components/kode_sys/src/kode_sys_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ extern const kode_sys_row_t kode_sys_rows[KODE_SYS_ROWS];
* @brief Start every linked row in order, then park every absent one.
*
* A park waits for the last start, so the core it may ask (AO_IoExp) is up.
* The calling task runs the walk at KODE_PRIO_BOOT_WALK and has the priority
* it came with back when the walk ends.
* @param rows The rows, in order.
* @param n How many.
*/
Expand Down
6 changes: 6 additions & 0 deletions components/kqp/include/kqp_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@
/* 3 is the renderer's - a consumer level, defined with its family below as
* KODE_PRIO_USER_GUI. */
#define KODE_PRIO_READER 4U /**< Console reader task (blocking). */
/* The boot task is FreeRTOS's main task, at priority 1, and it runs every
* owner's initial transition. The renderer starts in the early row and draws
* without a pause; where the port puts it on the boot task's core, a walk at
* priority 1 gets only the gaps between its passes, and the rows below the
* early one come up seconds late. One level above the renderer is enough. */
#define KODE_PRIO_BOOT_WALK (KODE_PRIO_USER_GUI + 1U) /**< The boot task while kode_init() starts and parks the rows. */
#define KODE_PRIO_RADIO 4U /**< AO_Radio + its worker task. */
#define KODE_PRIO_STORAGE 5U /**< AO_Storage + its storage_sd worker task. */
#define KODE_PRIO_LOG 6U /**< AO_Log (the console device). */
Expand Down
40 changes: 40 additions & 0 deletions tests/host/cases/test_kode_init_rows.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,46 @@ TEST_CASE("every row linked: each starts in order and nothing is parked",
TEST_ASSERT_EQUAL_STRING("start c", s_log[2]);
}

/** @brief The boot task's own priority before kode_init(): FreeRTOS's main task's. */
#define ROWS_MAIN_PRIO 1U

/** @brief The boot task's priority while a row started, and while one parked. */
static uint32_t s_prio_at_start;
static uint32_t s_prio_at_park;

static void start_notes_prio(void)
{
s_prio_at_start = fake_task_priority();
}

static void park_notes_prio(void)
{
s_prio_at_park = fake_task_priority();
}

/* The interface starts in the early row and draws without a pause from then
* on. On the boot task's core it holds every row below it back, so the walk
* outranks it and hands the boot task its own priority back at the end. */
TEST_CASE("the rows start and park above the renderer, and the boot task gets "
"its priority back", "[kode_init]")
{
static const kode_sys_row_t rows[] = {
{ .start = &start_notes_prio, .park = NULL },
{ .start = NULL, .park = &park_notes_prio },
};

fake_task_priority_set(ROWS_MAIN_PRIO);
s_prio_at_start = 0U;
s_prio_at_park = 0U;

kode_sys_rows_walk(rows, sizeof(rows) / sizeof(rows[0]));

TEST_ASSERT_EQUAL_UINT32(KODE_PRIO_BOOT_WALK, s_prio_at_start);
TEST_ASSERT_EQUAL_UINT32(KODE_PRIO_BOOT_WALK, s_prio_at_park);
TEST_ASSERT_TRUE(KODE_PRIO_BOOT_WALK > KODE_PRIO_USER_GUI);
TEST_ASSERT_EQUAL_UINT32(ROWS_MAIN_PRIO, fake_task_priority());
}

TEST_CASE("an absent row is not started, and its park runs after every start",
"[kode_init]")
{
Expand Down
21 changes: 21 additions & 0 deletions tests/host/main/fakes/fake_khal_system.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,27 @@ const char *khal_task_name(void)
return "host";
}

/** @brief The priority the calling task is at, as the cases set and read it. */
static uint32_t s_task_priority = 1U;

uint32_t khal_task_priority_set(uint32_t priority)
{
uint32_t const was = s_task_priority;

s_task_priority = priority;
return was;
}

void fake_task_priority_set(uint32_t priority)
{
s_task_priority = priority;
}

uint32_t fake_task_priority(void)
{
return s_task_priority;
}

/* The task helpers call the same FreeRTOS functions the board does, on the
* linux port: a started task is a real thread, and the slot is a real
* thread-local pointer. Only the stack's home differs - the port allocates it. */
Expand Down
6 changes: 6 additions & 0 deletions tests/host/main/fakes/fakes.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,12 @@ void fake_mutex_real(bool on);
*/
void fake_env_release_hook(void (*hook)(void));

/** @brief Set the priority khal_task_priority_set() reports the calling task had. */
void fake_task_priority_set(uint32_t priority);

/** @brief The priority khal_task_priority_set() last left the calling task at. */
uint32_t fake_task_priority(void);

/** @brief Forget every captured line and re-install the capture sink. */
void fake_klog_reset(void);

Expand Down
Loading