Skip to content
Open
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
11 changes: 11 additions & 0 deletions adapter/thread_metric/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,21 @@ tm_case("tm_memory_allocation_test") {
[ "//external/thread_metric/v6.4.2/src/tm_memory_allocation_test.c" ]
}

tm_case("tm_interrupt_preemption_processing_test") {
sources = [ "//external/thread_metric/v6.4.2/src/tm_interrupt_preemption_processing_test.c" ]
}

tm_case("tm_interrupt_processing_test") {
sources =
[ "//external/thread_metric/v6.4.2/src/tm_interrupt_processing_test.c" ]
}

group("run_tests") {
testonly = true
deps = [
":run_tm_basic_process_test",
":run_tm_interrupt_preemption_processing_test",
":run_tm_interrupt_processing_test",
":run_tm_memory_allocation_test",
":run_tm_preemptive_scheduling_test",
":run_tm_synchronization_processing_test",
Expand Down
31 changes: 30 additions & 1 deletion adapter/thread_metric/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,15 @@
// limitations under the License.

#![no_std]
#![feature(linkage)]

extern crate blueos;

extern crate alloc;

use alloc::alloc::{alloc as system_alloc, dealloc as system_dealloc};
use blueos::{
arch::arm::{self, Context, NR_DEBUG_SYSCALL},
scheduler,
scheduler::InsertToEnd,
sync::semaphore::Semaphore,
Expand Down Expand Up @@ -84,7 +88,7 @@ pub extern "C" fn tm_thread_resume(thread_id: c_int) -> c_int {
if scheduler::queue_ready_thread(SUSPENDED, t.clone()).is_ok()
|| scheduler::queue_ready_thread(IDLE, t).is_ok()
{
scheduler::relinquish_me();
scheduler::yield_me_now_or_later();
return TM_SUCCESS;
}
TM_ERROR
Expand Down Expand Up @@ -164,3 +168,28 @@ pub extern "C" fn tm_memory_pool_deallocate(_pool_id: c_int, result: *mut u8) ->
unsafe { system_dealloc(result, layout) };
TM_SUCCESS
}

#[no_mangle]
pub extern "C" fn tm_cause_interrupt() {
unsafe {
core::arch::asm!(
"movs {tmp}, r7",
"mov r7, #{nr}",
"svc 0",
"mov r7, {tmp}",
tmp = out(reg) _,
nr = const NR_DEBUG_SYSCALL,
options(nostack)
)
}
}

#[no_mangle]
#[linkage = "weak"]
pub extern "C" fn tm_interrupt_handler() {}

#[no_mangle]
pub extern "C" fn bk_debug_syscall(ctx: &Context) -> usize {
tm_interrupt_handler();
ctx as *const _ as usize
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// TOTAL-TIMEOUT: 10
// ASSERT-SUCC: Relative Time: 8
// ASSERT-FAIL: ERROR
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// TOTAL-TIMEOUT: 10
// ASSERT-SUCC: Relative Time: 8
// ASSERT-FAIL: ERROR
20 changes: 16 additions & 4 deletions kernel/src/arch/arm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub const CONTROL: usize = 0b110;
pub const THUMB_MODE: usize = 0x01000000;
pub const NR_SWITCH: usize = !0;
pub const NR_RET_FROM_SYSCALL: usize = NR_SWITCH - 1;
pub const NR_DEBUG_SYSCALL: usize = NR_SWITCH - 2;
pub const DISABLE_LOCAL_IRQ_BASEPRI: u8 = irq::IRQ_PRIORITY_FOR_SCHEDULER;

#[macro_export]
Expand Down Expand Up @@ -97,7 +98,6 @@ pub extern "C" fn reset_msp_and_start_schedule(msp: *mut u8, cont: extern "C" fn
msr control, {tmp}
ldr lr, =0
msr basepri, {basepri}
isb
cpsie i
bx {cont}
",
Expand Down Expand Up @@ -314,9 +314,10 @@ macro_rules! load_callee_saved_regs {
};
}

#[inline(always)]
pub(crate) extern "C" fn post_pendsv() {
SCB::set_pendsv();
unsafe { core::arch::asm!("dsb", "isb", options(nostack),) }
unsafe { core::arch::asm!("isb", options(nostack),) }
}

#[naked]
Expand All @@ -326,6 +327,7 @@ pub unsafe extern "C" fn handle_svc() {
"
ldr r12, ={basepri}
msr basepri, r12
isb
",
store_callee_saved_regs!(),
"
Expand All @@ -339,7 +341,6 @@ pub unsafe extern "C" fn handle_svc() {
"
ldr r12, =0
msr basepri, r12
isb
bx lr
",
),
Expand Down Expand Up @@ -388,7 +389,16 @@ fn handle_svc_switch(ctx: &Context) -> usize {
scheduler::save_context_finish_hook(&mut *hook, ctx as *const _ as usize)
}

#[no_mangle]
#[linkage = "weak"]
pub extern "C" fn bk_debug_syscall(ctx: &Context) -> usize {
ctx as *const _ as usize
}

extern "C" fn handle_syscall(ctx: &Context) -> usize {
if ctx.r7 == NR_DEBUG_SYSCALL {
return bk_debug_syscall(ctx);
}
if ctx.r7 == NR_SWITCH {
return handle_svc_switch(ctx);
}
Expand Down Expand Up @@ -434,6 +444,7 @@ pub unsafe extern "C" fn handle_pendsv() {
"
ldr r12, ={basepri}
msr basepri, r12
isb
",
store_callee_saved_regs!(),
"
Expand All @@ -447,7 +458,6 @@ pub unsafe extern "C" fn handle_pendsv() {
"
ldr r12, =0
msr basepri, r12
isb
bx lr
"
),
Expand Down Expand Up @@ -514,6 +524,7 @@ pub extern "C" fn disable_local_irq() {
unsafe {
core::arch::asm!(
"msr basepri, {}",
"isb",
in(reg) DISABLE_LOCAL_IRQ_BASEPRI,
options(nostack),
)
Expand All @@ -530,6 +541,7 @@ pub extern "C" fn disable_local_irq_save() -> usize {
"
mrs {old}, basepri
msr basepri, {val}
isb
",
),
old = out(reg) old,
Expand Down
19 changes: 10 additions & 9 deletions kernel/src/scheduler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@

extern crate alloc;
use crate::{
arch, signal,
arch::{self, Context},
signal,
support::DisableInterruptGuard,
sync::SpinLockGuard,
thread,
Expand Down Expand Up @@ -248,24 +249,24 @@ fn switch_current_thread(next: ThreadNode, old_sp: usize) -> usize {

// It's usually used in cortex-m's pendsv handler.
pub(crate) extern "C" fn relinquish_me_and_return_next_sp(old_sp: usize) -> usize {
debug_assert_eq!(old_sp % core::mem::align_of::<Context>(), 0);
debug_assert!(!arch::local_irq_enabled());
debug_assert!(!crate::irq::is_in_irq());
debug_assert_eq!(current_thread_ref().preempt_count(), 0);
let Some(next) = next_preferred_thread(current_thread_ref().priority()) else {
let old = current_thread_ref();
debug_assert_eq!(old.preempt_count(), 0);
let Some(next) = next_preferred_thread(old.priority()) else {
#[cfg(debugging_scheduler)]
crate::trace!("[TH:0x{:x}] keeps running", current_thread_id());
crate::trace!("[TH:0x{:x}] keeps running", Thread::id(old));
return old_sp;
};
debug_assert_eq!(next.state(), thread::READY);
let old = current_thread_ref();
if Thread::id(old) == Thread::id(idle::current_idle_thread_ref()) {
let ok = old.transfer_state(thread::RUNNING, thread::READY);
debug_assert_eq!(ok, Ok(()));
} else {
let ok = queue_ready_thread(thread::RUNNING, unsafe { Arc::clone_from(old) });
debug_assert_eq!(ok, Ok(()));
};

switch_current_thread(next, old_sp)
}

Expand All @@ -284,14 +285,14 @@ pub fn retire_me() -> ! {
}

fn inner_yield(next: ThreadNode) {
let old = current_thread();
let old = current_thread_ref();
let mut hook_holder = ContextSwitchHookHolder::new(next);
old.disable_preempt();
if Thread::id(&old) == Thread::id(idle::current_idle_thread_ref()) {
if Thread::id(old) == Thread::id(idle::current_idle_thread_ref()) {
let ok = old.transfer_state(thread::RUNNING, thread::READY);
debug_assert_eq!(ok, Ok(()));
} else {
let ok = queue_ready_thread(thread::RUNNING, old.clone());
let ok = queue_ready_thread(thread::RUNNING, unsafe { Arc::clone_from(old) });
debug_assert_eq!(ok, Ok(()));
};
arch::switch_context_with_hook(&mut hook_holder as *mut _);
Expand Down