Historically, these routines were placed in thread.c and would use the scheduler via exported, synchronized functions (e.g. "remove from ready queue"). But those steps were very fine grained, and there were races where the thread could be seen by other contexts (in particular under SMP) in an intermediate state. It's not completely clear to me that any of these were fatal bugs, but it's very hard to prove they weren't. At best, this is fragile. Move the z_thread_single_suspend/abort() functions into the scheduler and do the scheduler logic in a single critical section. Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
56 lines
1.4 KiB
C
56 lines
1.4 KiB
C
/*
|
|
* Copyright (c) 2016 Wind River Systems, Inc.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* @brief Primitive for aborting a thread when an arch-specific one is not
|
|
* needed..
|
|
*/
|
|
|
|
#include <kernel.h>
|
|
#include <kernel_structs.h>
|
|
#include <kernel_internal.h>
|
|
#include <kswap.h>
|
|
#include <string.h>
|
|
#include <toolchain.h>
|
|
#include <linker/sections.h>
|
|
#include <wait_q.h>
|
|
#include <ksched.h>
|
|
#include <sys/__assert.h>
|
|
#include <syscall_handler.h>
|
|
|
|
extern void z_thread_single_abort(struct k_thread *thread);
|
|
|
|
#if !defined(CONFIG_ARCH_HAS_THREAD_ABORT)
|
|
void z_impl_k_thread_abort(k_tid_t thread)
|
|
{
|
|
__ASSERT((thread->base.user_options & K_ESSENTIAL) == 0U,
|
|
"essential thread aborted");
|
|
|
|
z_thread_single_abort(thread);
|
|
z_thread_monitor_exit(thread);
|
|
|
|
if (thread == _current && !arch_is_in_isr()) {
|
|
/* Direct use of swap: reschedule doesn't have a test
|
|
* for "is _current dead" and we don't want one for
|
|
* performance reasons.
|
|
*/
|
|
struct k_spinlock lock = {};
|
|
|
|
z_swap(&lock, k_spin_lock(&lock));
|
|
} else {
|
|
/* Really, there's no good reason for this to be a
|
|
* scheduling point if we aren't aborting _current (by
|
|
* definition, no higher priority thread is runnable,
|
|
* because we're running!). But it always has been
|
|
* and is thus part of our API, and we have tests that
|
|
* rely on k_thread_abort() scheduling out of
|
|
* cooperative threads.
|
|
*/
|
|
z_reschedule_unlocked();
|
|
}
|
|
}
|
|
#endif
|