k_thread_create(): allow K_FOREVER delay
It's now possible to instantiate a thread object, but delay its execution indefinitely. This was already supported with K_THREAD_DEFINE. A new API, k_thread_start(), now exists to start threads that are in this state. The intended use-case is to initialize a thread with K_USER, then grant it various access permissions, and only then start it. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
parent
8e51f36bbf
commit
7d627c5971
4 changed files with 46 additions and 5 deletions
|
@ -496,7 +496,8 @@ typedef struct _k_thread_stack_element *k_thread_stack_t;
|
||||||
* @param p3 3rd entry point parameter.
|
* @param p3 3rd entry point parameter.
|
||||||
* @param prio Thread priority.
|
* @param prio Thread priority.
|
||||||
* @param options Thread options.
|
* @param options Thread options.
|
||||||
* @param delay Scheduling delay (in milliseconds), or K_NO_WAIT (for no delay).
|
* @param delay Scheduling delay (in milliseconds), or K_NO_WAIT (for no delay),
|
||||||
|
* or K_FOREVER (to not run until k_thread_start() is called)
|
||||||
*
|
*
|
||||||
* @return ID of new thread.
|
* @return ID of new thread.
|
||||||
*/
|
*/
|
||||||
|
@ -626,6 +627,18 @@ extern int k_thread_cancel(k_tid_t thread);
|
||||||
*/
|
*/
|
||||||
extern void k_thread_abort(k_tid_t thread);
|
extern void k_thread_abort(k_tid_t thread);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Start an inactive thread
|
||||||
|
*
|
||||||
|
* If a thread was created with K_FOREVER in the delay parameter, it will
|
||||||
|
* not be added to the scheduling queue until this function is called
|
||||||
|
* on it.
|
||||||
|
*
|
||||||
|
* @param thread thread to start
|
||||||
|
*/
|
||||||
|
extern void k_thread_start(k_tid_t thread);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @cond INTERNAL_HIDDEN
|
* @cond INTERNAL_HIDDEN
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -209,10 +209,15 @@ FUNC_NORETURN void _thread_entry(void (*entry)(void *, void *, void *),
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_MULTITHREADING
|
#ifdef CONFIG_MULTITHREADING
|
||||||
static void start_thread(struct k_thread *thread)
|
void k_thread_start(struct k_thread *thread)
|
||||||
{
|
{
|
||||||
int key = irq_lock(); /* protect kernel queues */
|
int key = irq_lock(); /* protect kernel queues */
|
||||||
|
|
||||||
|
if (_has_thread_started(thread)) {
|
||||||
|
irq_unlock(key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_mark_thread_as_started(thread);
|
_mark_thread_as_started(thread);
|
||||||
|
|
||||||
if (_is_thread_ready(thread)) {
|
if (_is_thread_ready(thread)) {
|
||||||
|
@ -232,7 +237,7 @@ static void schedule_new_thread(struct k_thread *thread, s32_t delay)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_SYS_CLOCK_EXISTS
|
#ifdef CONFIG_SYS_CLOCK_EXISTS
|
||||||
if (delay == 0) {
|
if (delay == 0) {
|
||||||
start_thread(thread);
|
k_thread_start(thread);
|
||||||
} else {
|
} else {
|
||||||
s32_t ticks = _TICK_ALIGN + _ms_to_ticks(delay);
|
s32_t ticks = _TICK_ALIGN + _ms_to_ticks(delay);
|
||||||
int key = irq_lock();
|
int key = irq_lock();
|
||||||
|
@ -242,7 +247,7 @@ static void schedule_new_thread(struct k_thread *thread, s32_t delay)
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
ARG_UNUSED(delay);
|
ARG_UNUSED(delay);
|
||||||
start_thread(thread);
|
k_thread_start(thread);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -260,7 +265,9 @@ k_tid_t k_thread_create(struct k_thread *new_thread,
|
||||||
prio, options);
|
prio, options);
|
||||||
_k_object_init(new_thread);
|
_k_object_init(new_thread);
|
||||||
|
|
||||||
schedule_new_thread(new_thread, delay);
|
if (delay != K_FOREVER) {
|
||||||
|
schedule_new_thread(new_thread, delay);
|
||||||
|
}
|
||||||
return new_thread;
|
return new_thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
extern void test_threads_spawn_params(void);
|
extern void test_threads_spawn_params(void);
|
||||||
extern void test_threads_spawn_priority(void);
|
extern void test_threads_spawn_priority(void);
|
||||||
extern void test_threads_spawn_delay(void);
|
extern void test_threads_spawn_delay(void);
|
||||||
|
extern void test_threads_spawn_forever(void);
|
||||||
extern void test_threads_suspend_resume_cooperative(void);
|
extern void test_threads_suspend_resume_cooperative(void);
|
||||||
extern void test_threads_suspend_resume_preemptible(void);
|
extern void test_threads_suspend_resume_preemptible(void);
|
||||||
extern void test_threads_cancel_undelayed(void);
|
extern void test_threads_cancel_undelayed(void);
|
||||||
|
@ -31,6 +32,7 @@ void test_main(void)
|
||||||
ztest_unit_test(test_threads_spawn_params),
|
ztest_unit_test(test_threads_spawn_params),
|
||||||
ztest_unit_test(test_threads_spawn_priority),
|
ztest_unit_test(test_threads_spawn_priority),
|
||||||
ztest_unit_test(test_threads_spawn_delay),
|
ztest_unit_test(test_threads_spawn_delay),
|
||||||
|
ztest_unit_test(test_threads_spawn_forever),
|
||||||
ztest_unit_test(test_threads_suspend_resume_cooperative),
|
ztest_unit_test(test_threads_suspend_resume_cooperative),
|
||||||
ztest_unit_test(test_threads_suspend_resume_preemptible),
|
ztest_unit_test(test_threads_suspend_resume_preemptible),
|
||||||
ztest_unit_test(test_threads_cancel_undelayed),
|
ztest_unit_test(test_threads_cancel_undelayed),
|
||||||
|
|
|
@ -80,3 +80,22 @@ void test_threads_spawn_delay(void)
|
||||||
zassert_true(tp2 == 100, NULL);
|
zassert_true(tp2 == 100, NULL);
|
||||||
k_thread_abort(tid);
|
k_thread_abort(tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_threads_spawn_forever(void)
|
||||||
|
{
|
||||||
|
/* spawn thread with highest priority. It will run immediately once
|
||||||
|
* started.
|
||||||
|
*/
|
||||||
|
tp2 = 10;
|
||||||
|
k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
|
||||||
|
thread_entry_delay, NULL, NULL, NULL,
|
||||||
|
K_HIGHEST_THREAD_PRIO, 0, K_FOREVER);
|
||||||
|
k_yield();
|
||||||
|
/* checkpoint: check spawn thread not execute */
|
||||||
|
zassert_true(tp2 == 10, NULL);
|
||||||
|
/* checkpoint: check spawn thread executed */
|
||||||
|
k_thread_start(tid);
|
||||||
|
k_yield();
|
||||||
|
zassert_true(tp2 == 100, NULL);
|
||||||
|
k_thread_abort(tid);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue