forked from RIOT-OS/RIOT
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request RIOT-OS#17093 from maribu/core/change_prio
core/sched: add sched_change_priority()
- Loading branch information
Showing
10 changed files
with
305 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* | ||
* Copyright (C) 2014 Freie Universität Berlin | ||
* Copyright (C) 2014-2017 Freie Universität Berlin | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser | ||
* General Public License v2.1. See the file LICENSE in the top level | ||
|
@@ -75,6 +75,7 @@ | |
* @brief Scheduler API definition | ||
* | ||
* @author Kaspar Schleiser <[email protected]> | ||
* @author Hauke Petersen <[email protected]> | ||
*/ | ||
|
||
#ifndef SCHED_H | ||
|
@@ -252,6 +253,19 @@ extern clist_node_t sched_runqueues[SCHED_PRIO_LEVELS]; | |
*/ | ||
NORETURN void sched_task_exit(void); | ||
|
||
/** | ||
* @brief Change the priority of the given thread | ||
* | ||
* @note This functions expects interrupts to be disabled when called! | ||
* | ||
* @pre (thread != NULL) | ||
* @pre (priority < SCHED_PRIO_LEVELS) | ||
* | ||
* @param[in,out] thread target thread | ||
* @param[in] priority new priority to assign to @p thread | ||
*/ | ||
void sched_change_priority(thread_t *thread, uint8_t priority); | ||
|
||
/** | ||
* @brief Set CPU to idle mode (CPU dependent) | ||
* | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* | ||
* Copyright (C) 2014 Freie Universität Berlin | ||
* Copyright (C) 2014-2017 Freie Universität Berlin | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser | ||
* General Public License v2.1. See the file LICENSE in the top level | ||
|
@@ -15,6 +15,7 @@ | |
* | ||
* @author Kaspar Schleiser <[email protected]> | ||
* @author René Kijewski <[email protected]> | ||
* @author Hauke Petersen <[email protected]> | ||
* | ||
* @} | ||
*/ | ||
|
@@ -86,21 +87,21 @@ static void (*sched_cb)(kernel_pid_t active_thread, | |
* and readout away, switching between the two orders depending on the CLZ | ||
* instruction availability | ||
*/ | ||
static inline void _set_runqueue_bit(thread_t *process) | ||
static inline void _set_runqueue_bit(uint8_t priority) | ||
{ | ||
#if defined(BITARITHM_HAS_CLZ) | ||
runqueue_bitcache |= BIT31 >> process->priority; | ||
runqueue_bitcache |= BIT31 >> priority; | ||
#else | ||
runqueue_bitcache |= 1 << process->priority; | ||
runqueue_bitcache |= 1 << priority; | ||
#endif | ||
} | ||
|
||
static inline void _clear_runqueue_bit(thread_t *process) | ||
static inline void _clear_runqueue_bit(uint8_t priority) | ||
{ | ||
#if defined(BITARITHM_HAS_CLZ) | ||
runqueue_bitcache &= ~(BIT31 >> process->priority); | ||
runqueue_bitcache &= ~(BIT31 >> priority); | ||
#else | ||
runqueue_bitcache &= ~(1 << process->priority); | ||
runqueue_bitcache &= ~(1 << priority); | ||
#endif | ||
} | ||
|
||
|
@@ -218,41 +219,54 @@ thread_t *__attribute__((used)) sched_run(void) | |
return next_thread; | ||
} | ||
|
||
/* Note: Forcing the compiler to inline this function will reduce .text for applications | ||
* not linking in sched_change_priority(), which benefits the vast majority of apps. | ||
*/ | ||
static inline __attribute__((always_inline)) void _runqueue_push(thread_t *thread, uint8_t priority) | ||
{ | ||
DEBUG("sched_set_status: adding thread %" PRIkernel_pid " to runqueue %" PRIu8 ".\n", | ||
thread->pid, priority); | ||
clist_rpush(&sched_runqueues[priority], &(thread->rq_entry)); | ||
_set_runqueue_bit(priority); | ||
|
||
/* some thread entered a runqueue | ||
* if it is the active runqueue | ||
* inform the runqueue_change callback */ | ||
#if (IS_USED(MODULE_SCHED_RUNQ_CALLBACK)) | ||
thread_t *active_thread = thread_get_active(); | ||
if (active_thread && active_thread->priority == priority) { | ||
sched_runq_callback(priority); | ||
} | ||
#endif | ||
} | ||
|
||
/* Note: Forcing the compiler to inline this function will reduce .text for applications | ||
* not linking in sched_change_priority(), which benefits the vast majority of apps. | ||
*/ | ||
static inline __attribute__((always_inline)) void _runqueue_pop(thread_t *thread) | ||
{ | ||
DEBUG("sched_set_status: removing thread %" PRIkernel_pid " from runqueue %" PRIu8 ".\n", | ||
thread->pid, thread->priority); | ||
clist_lpop(&sched_runqueues[thread->priority]); | ||
|
||
if (!sched_runqueues[thread->priority].next) { | ||
_clear_runqueue_bit(thread->priority); | ||
#if (IS_USED(MODULE_SCHED_RUNQ_CALLBACK)) | ||
sched_runq_callback(thread->priority); | ||
#endif | ||
} | ||
} | ||
|
||
void sched_set_status(thread_t *process, thread_status_t status) | ||
{ | ||
if (status >= STATUS_ON_RUNQUEUE) { | ||
if (!(process->status >= STATUS_ON_RUNQUEUE)) { | ||
DEBUG( | ||
"sched_set_status: adding thread %" PRIkernel_pid " to runqueue %" PRIu8 ".\n", | ||
process->pid, process->priority); | ||
clist_rpush(&sched_runqueues[process->priority], | ||
&(process->rq_entry)); | ||
_set_runqueue_bit(process); | ||
|
||
/* some thread entered a runqueue | ||
* if it is the active runqueue | ||
* inform the runqueue_change callback */ | ||
#if (IS_USED(MODULE_SCHED_RUNQ_CALLBACK)) | ||
thread_t *active_thread = thread_get_active(); | ||
if (active_thread && active_thread->priority == process->priority) { | ||
sched_runq_callback(process->priority); | ||
} | ||
#endif | ||
_runqueue_push(process, process->priority); | ||
} | ||
} | ||
else { | ||
if (process->status >= STATUS_ON_RUNQUEUE) { | ||
DEBUG( | ||
"sched_set_status: removing thread %" PRIkernel_pid " from runqueue %" PRIu8 ".\n", | ||
process->pid, process->priority); | ||
clist_lpop(&sched_runqueues[process->priority]); | ||
|
||
if (!sched_runqueues[process->priority].next) { | ||
_clear_runqueue_bit(process); | ||
#if (IS_USED(MODULE_SCHED_RUNQ_CALLBACK)) | ||
sched_runq_callback(process->priority); | ||
#endif | ||
} | ||
_runqueue_pop(process); | ||
} | ||
} | ||
|
||
|
@@ -306,3 +320,40 @@ void sched_register_cb(void (*callback)(kernel_pid_t, kernel_pid_t)) | |
sched_cb = callback; | ||
} | ||
#endif | ||
|
||
void sched_change_priority(thread_t *thread, uint8_t priority) | ||
{ | ||
assert(thread && (priority < SCHED_PRIO_LEVELS)); | ||
|
||
if (thread->priority == priority) { | ||
return; | ||
} | ||
|
||
unsigned irq_state = irq_disable(); | ||
|
||
if (thread_is_active(thread)) { | ||
_runqueue_pop(thread); | ||
_runqueue_push(thread, priority); | ||
} | ||
thread->priority = priority; | ||
|
||
irq_restore(irq_state); | ||
|
||
thread_t *active = thread_get_active(); | ||
|
||
if ((active == thread) | ||
|| ((active != NULL) && (active->priority > priority) && thread_is_active(thread)) | ||
) { | ||
/* If the change in priority would result in a different decision of | ||
* the scheduler, we need to yield to make sure the change in priority | ||
* takes effect immediately. This can be due to one of the following: | ||
* | ||
* 1) The priority of the thread currently running has been reduced | ||
* (higher numeric value), so that other threads now have priority | ||
* over the currently running. | ||
* 2) The priority of a pending thread has been increased (lower numeric value) so that it | ||
* now has priority over the running thread. | ||
*/ | ||
thread_yield_higher(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/* | ||
* Copyright (C) 2021 Otto-von-Guericke-Universität Magdeburg | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser | ||
* General Public License v2.1. See the file LICENSE in the top level | ||
* directory for more details. | ||
*/ | ||
|
||
/** | ||
* @ingroup sys_shell_commands | ||
* @{ | ||
* | ||
* @file | ||
* @brief A shell command to change the niceness (inverse priority) of a thread | ||
* | ||
* @note Enable this by using the modules shell_commands and nice | ||
* | ||
* @author Marian Buschsieweke <[email protected]> | ||
* | ||
* @} | ||
*/ | ||
|
||
#include <stdio.h> | ||
#include <stdlib.h> | ||
|
||
#include "sched.h" | ||
#include "thread.h" | ||
|
||
int _sc_nice(int argc, char **argv) | ||
{ | ||
if (argc != 3) { | ||
printf("Usage: %s <THREAD_ID> <PRIORITY>\n" | ||
"Note: Lower number means higher priority (niceness)\n", | ||
argv[0]); | ||
return EXIT_FAILURE; | ||
} | ||
|
||
/* Note: thread_get() does bounds checking and returns NULL on out of bounds PID */ | ||
thread_t *thread = thread_get(atoi(argv[1])); | ||
if (!thread) { | ||
printf("No active thread found for ID \"%s\"\n", argv[1]); | ||
return EXIT_FAILURE; | ||
} | ||
|
||
uint8_t prio = atoi(argv[2]); | ||
if (prio >= SCHED_PRIO_LEVELS) { | ||
printf("Priority \"%s\" is invalid (try 0..%u)\n", | ||
argv[2], (unsigned)SCHED_PRIO_LEVELS - 1); | ||
} | ||
|
||
sched_change_priority(thread, prio); | ||
return EXIT_SUCCESS; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
include ../Makefile.tests_common | ||
|
||
USEMODULE += nice | ||
USEMODULE += ps | ||
USEMODULE += shell | ||
USEMODULE += shell_commands | ||
|
||
# Use a terminal that does not introduce extra characters into the stream. | ||
RIOT_TERMINAL ?= socat | ||
|
||
APP_SHELL_FMT ?= NONE | ||
|
||
include $(RIOTBASE)/Makefile.include |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
BOARD_INSUFFICIENT_MEMORY := \ | ||
arduino-duemilanove \ | ||
arduino-leonardo \ | ||
arduino-nano \ | ||
arduino-uno \ | ||
atmega328p \ | ||
atmega328p-xplained-mini \ | ||
nucleo-l011k4 \ | ||
# |
Oops, something went wrong.