diff --git a/.cargo/config.toml b/.cargo/config.toml index b973bcda506f0e4b037625efd476dff7ae598d7d..295be3eec6e12413237b5f5bdea8d63ddf449ca5 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -51,6 +51,6 @@ rustflags = [ 'LOS_PATH="../../../c/LiteOS/"', ] -# [build] -# # Always compile for the instruction set of the STM32F1 -# target = "thumbv7m-none-eabi" +[build] +# Always compile for the instruction set of the STM32F1 +target = "thumbv7m-none-eabi" diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000000000000000000000000000000000000..77d74a0880dd9fc13502c34e4c93edee6dba75fb --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,28 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "/home/shuaihu/project/c/LiteOS/**", + "/home/shuaihu/project/c/LiteOS/kernel/include", + "/home/shuaihu/project/c/LiteOS/kernel/base/include", + "/home/shuaihu/project/c/LiteOS/targets/STM32F103_FIRE_Arbitrary/Inc", + "/home/shuaihu/project/c/LiteOS/targets/STM32F103_FIRE_Arbitrary/include", + "/home/shuaihu/project/c/LiteOS/arch/arm/cortex_m/include", + "/home/shuaihu/project/c/LiteOS/arch/arm/cortex_m/cmsis", + "/home/shuaihu/project/c/LiteOS/drivers/timer/include", + "/home/shuaihu/project/c/LiteOS/drivers/base/include", + "/home/shuaihu/project/c/LiteOS/drivers/interrupt/include", + "/home/shuaihu/project/c/LiteOS/drivers/uart/include", + "/home/shuaihu/project/c/LiteOS/lib/libsec/include" + ], + "defines": [], + "compilerPath": "/home/shuaihu/.local/bin/arm-none-eabi-gcc", + "cStandard": "gnu17", + "cppStandard": "gnu++17", + "intelliSenseMode": "linux-gcc-arm", + "configurationProvider": "ms-vscode.makefile-tools" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/configurationCache.log b/.vscode/configurationCache.log new file mode 100644 index 0000000000000000000000000000000000000000..bab9054b3db60df7a22779b0178b4e22b8badef1 --- /dev/null +++ b/.vscode/configurationCache.log @@ -0,0 +1 @@ +{"buildTargets":[],"launchTargets":[],"customConfigurationProvider":{"workspaceBrowse":{"browsePath":[],"compilerArgs":[]},"fileIndex":[]}} \ No newline at end of file diff --git a/.vscode/dryrun.log b/.vscode/dryrun.log new file mode 100644 index 0000000000000000000000000000000000000000..2293befe490d3b1cf0af1b8dc5cdede534b4e461 --- /dev/null +++ b/.vscode/dryrun.log @@ -0,0 +1,6 @@ +make --dry-run --always-make --keep-going --print-directory +make: Entering directory '/home/shuaihu/project/rust/opcua/arch' +make: Leaving directory '/home/shuaihu/project/rust/opcua/arch' + +make: *** No targets specified and no makefile found. Stop. + diff --git a/.vscode/targets.log b/.vscode/targets.log new file mode 100644 index 0000000000000000000000000000000000000000..c097b0184e5ce59bf1be7ec91dc2ab79f65de094 --- /dev/null +++ b/.vscode/targets.log @@ -0,0 +1,216 @@ +make all --print-data-base --no-builtin-variables --no-builtin-rules --question +make: *** No rule to make target 'all'. Stop. + +# GNU Make 4.2.1 +# Built for x86_64-pc-linux-gnu +# Copyright (C) 1988-2016 Free Software Foundation, Inc. +# License GPLv3+: GNU GPL version 3 or later +# This is free software: you are free to change and redistribute it. +# There is NO WARRANTY, to the extent permitted by law. + +# Make data base, printed on Fri Aug 5 09:34:04 2022 + +# Variables + +# automatic + 0 { println!("cargo:rustc_cfg='{}={}'", key, value); + if key == "LOSCFG_PLATFORM" { + liteos_add_padding(&los_path, &manifest_path, value.trim_matches('\"')); + } } } } @@ -105,3 +107,44 @@ fn main() { top_path.join(".cargo/config.toml").to_str().unwrap() ); } + +fn liteos_add_padding(los_path: &PathBuf, manifest_path: &PathBuf, platform: &str) { + let target = los_path.join("targets").join(platform); + copy( + manifest_path.join("src/liteos/rust.c"), + target.join("Src/rust.c"), + ) + .unwrap(); + println!( + "cargo:rerun-if-changed={}", + manifest_path.join("src/liteos/rust.c").to_str().unwrap() + ); + if !target.join("Makefile.org").exists() { + rename(target.join("Makefile"), target.join("Makefile.org")).unwrap(); + } + let fmake = File::options() + .read(true) + .open(target.join("Makefile.org")) + .unwrap(); + let mut _fmake = File::options() + .write(true) + .create(true) + .open(target.join("Makefile")) + .unwrap(); + let fmake = BufReader::new(fmake); + for line in fmake.lines() { + if let Ok(line) = line { + write!(&mut _fmake, "{}\n", line).unwrap(); + if line.trim().starts_with("C_SOURCES") { + write!( + &mut _fmake, + "{}\n{}\n", + "RUST_SRC = $(LITEOSTOPDIR)/targets/$(LITEOS_PLATFORM)/Src/rust.c", + "C_SOURCES += $(RUST_SRC)" + ) + .unwrap(); + } + } + } + drop(_fmake); +} diff --git a/examples/liteos/lazyobj_test.rs b/examples/liteos/lazyobj_test.rs index 5f39863bdec1fd88c273dd3863f471f99b672ade..12cbf0d694b42a28188f47a3f11279c77b695f14 100644 --- a/examples/liteos/lazyobj_test.rs +++ b/examples/liteos/lazyobj_test.rs @@ -1,4 +1,4 @@ -// Copyright (C) 2022-2022 Agilor Co.,Ltd. All rights reserved. +// Copyright (C) 2022-2022 Agilor Co.,Ltd. All rights reserved. // SPDX-License-Identifier: Apache-2.0 use arch::lazy::*; use arch::os::printf; @@ -9,6 +9,7 @@ struct TestStruct { q: u64, } impl Drop for TestStruct { + #[inline(never)] fn drop(&mut self) { unsafe { printf("Droped1\n\0".as_ptr()) }; } @@ -27,10 +28,11 @@ pub fn lazyobj_test() { } struct TestStruct2 { - a: u32, - q: u128, + a: u8, + q: u64, } impl Drop for TestStruct2 { + #[inline(never)] fn drop(&mut self) { unsafe { printf("Droped2\n\0".as_ptr()) }; } @@ -133,4 +135,3 @@ pub fn lazyobj_test6() { let c = abc.a; assert_eq!(c, 33); } - diff --git a/examples/liteos/mod.rs b/examples/liteos/mod.rs index d1b6a154bec64f2c56b63183fe73895d5706007e..5d83cba2867abbffe0c6085c276c87c516fe7d18 100644 --- a/examples/liteos/mod.rs +++ b/examples/liteos/mod.rs @@ -1,4 +1,4 @@ -// Copyright (C) 2022-2022 Agilor Co.,Ltd. All rights reserved. +// Copyright (C) 2022-2022 Agilor Co.,Ltd. All rights reserved. // SPDX-License-Identifier: Apache-2.0 mod lazyobj_test; pub use lazyobj_test::*; @@ -8,4 +8,3 @@ mod os; pub use os::*; mod parker; pub use parker::*; - diff --git a/examples/liteos/os.rs b/examples/liteos/os.rs index 9a4dcb62d995db0f12eb3cb51a6cd749543995aa..4ef9067a1a4431ec1e4050f19d66b06ff595fdfe 100644 --- a/examples/liteos/os.rs +++ b/examples/liteos/os.rs @@ -1,12 +1,65 @@ -// Copyright (C) 2022-2022 Agilor Co.,Ltd. All rights reserved. +// Copyright (C) 2022-2022 Agilor Co.,Ltd. All rights reserved. // SPDX-License-Identifier: Apache-2.0 +use alloc::alloc::{alloc, dealloc, Layout}; use arch::instant::Instant; +use arch::locks::MovableMutex; use arch::os::printf; use arch::thread; +use arch::thread::Thread; pub fn get_tickcount_test() { let i = Instant::now(); thread::Thread::sleep(100); let t = i.elapsed(); - unsafe { printf("elapsed time:%d\n\r".as_ptr(), t) }; + unsafe { printf("elapsed time:%d\n\r\0".as_ptr(), t) }; } +// static MUTEX: MovableMutex = MovableMutex::new(); +// pub unsafe fn los_event_check() { +// let ly = Layout::new::(); +// let p = alloc(ly).cast(); + +// LOS_EventInit(p); +// let th1 = Thread::new(1536, box move || { +// for _ in 0..10 { +// let rtn = LOS_EventRead(p, 1, LOS_WAITMODE_AND | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER); +// let tick = Instant::now(); +// MUTEX.lock(); +// printf("Task0:tick:%u;:%d\r\n\0".as_ptr(), tick, rtn); +// MUTEX.unlock(); +// } +// }) +// .unwrap(); + +// let th2 = Thread::new(1536, box move || { +// for _ in 0..10 { +// let rtn = LOS_EventRead(p, 1, LOS_WAITMODE_AND | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER); +// let tick = Instant::now(); +// MUTEX.lock(); +// printf("Task1:tick:%u;:%u\r\n\0".as_ptr(), tick, rtn); +// MUTEX.unlock(); +// } +// }) +// .unwrap(); + +// let th3 = Thread::new(1536, box move || { +// for _ in 0..10 { +// let rtn = LOS_EventRead(p, 1, LOS_WAITMODE_AND | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER); +// let tick = Instant::now(); +// MUTEX.lock(); +// printf("Task2:tick:%u;:%u\r\n\0".as_ptr(), tick, rtn); +// MUTEX.unlock(); +// } +// }) +// .unwrap(); + +// for _ in 0..10 { +// Thread::sleep(1000); +// printf("send------\r\n\0".as_ptr()); +// LOS_EventWrite(p, 1); +// } +// th2.join(); +// th1.join(); +// th3.join(); +// LOS_EventDestroy(p); +// dealloc(p.cast(), ly); +// } diff --git a/examples/liteos/parker.rs b/examples/liteos/parker.rs index 19e48801d6fea4d79278ef22584f17a89c8baef6..62a4b19f1e032dac5ab42a10e90fad81fa788064 100644 --- a/examples/liteos/parker.rs +++ b/examples/liteos/parker.rs @@ -9,7 +9,7 @@ pub fn parker_led() { let (p, u) = pair(); unsafe { thread::Thread::new( - 400, + 800, Box::new(move || { for _ in 0..2 { p.park(); @@ -25,7 +25,3 @@ pub fn parker_led() { u.unpark(); } } - -pub fn los_event_check() { - unsafe { arch::os::los_event_check() }; -} diff --git a/examples/liteos/rwlock_test.rs b/examples/liteos/rwlock_test.rs index 671c664930bd9a6db93d333f386851d5d54772de..160ef2a49dec02256c4ce5a6eb5c9156ef01ee90 100644 --- a/examples/liteos/rwlock_test.rs +++ b/examples/liteos/rwlock_test.rs @@ -1,13 +1,74 @@ -// Copyright (C) 2022-2022 Agilor Co.,Ltd. All rights reserved. +// Copyright (C) 2022-2022 Agilor Co.,Ltd. All rights reserved. // SPDX-License-Identifier: Apache-2.0 -use arch::locks::MovableRwLock; -pub fn rwlock_smoke() { - let l = MovableRwLock::new(); - l.read(); - l.read(); - // drop(l.read().unwrap()); - // drop(l.write().unwrap()); - // drop((l.read().unwrap(), l.read().unwrap())); - // drop(l.write().unwrap()); -} +use core::hint::spin_loop; +use alloc::vec::Vec; +use arch::{ + instant::Instant, + locks::MovableRwLock, + os::{printf, rand}, + thread::Thread, +}; +pub unsafe fn rwlock_smoke() { + static L: MovableRwLock = MovableRwLock::new(); + if L.try_read() { + printf("true\r\n\0".as_ptr()); + } else { + printf("false\r\n\0".as_ptr()); + } + L.read(); + L.read(); + if L.try_write() { + printf("true\r\n\0".as_ptr()); + } else { + printf("false\r\n\0".as_ptr()); + } + Thread::new(4096, box || { + L.write(); + printf("Locked Write\r\n\0".as_ptr()); + }) + .unwrap_unchecked(); + L.read_unlock(); + L.read_unlock(); + Thread::yield_now(); + L.read_unlock(); + printf("UnLock Ok\r\n\0".as_ptr()); +} +#[no_mangle] +pub static RWLOCK: MovableRwLock = MovableRwLock::new(); +pub unsafe fn frob() { + const N: u32 = 4; + const M: usize = 100000; + RWLOCK.read(); + RWLOCK.read_unlock(); + let mut t = Vec::::new(); + for _ in 0..N { + let th = Thread::new(2048, box move || { + for _s in 0..M { + let i = rand(); + if i % 2 == 0 { + RWLOCK.write(); + for _ in 0..10000 { + spin_loop(); + } + RWLOCK.write_unlock(); + } else { + RWLOCK.read(); + for _ in 0..5000 { + spin_loop(); + } + RWLOCK.read_unlock(); + } + } + }) + .unwrap_unchecked(); + t.push(th); + } + let a = Instant::now(); + for t in t.drain(..) { + t.join(); + } + let p = a.elapsed(); + printf("elapsed time:%d\r\n\0".as_ptr(), p); + assert_eq!(1, 1); +} diff --git a/examples/test_liteos.rs b/examples/test_liteos.rs index 2bf74b5b38fd219ffa62e4a82a86b69825e95d0f..05effcee7495f9900fb8debe30eaf8b6bfde5ea5 100644 --- a/examples/test_liteos.rs +++ b/examples/test_liteos.rs @@ -1,9 +1,10 @@ -// Copyright (C) 2022-2022 Agilor Co.,Ltd. All rights reserved. +// Copyright (C) 2022-2022 Agilor Co.,Ltd. All rights reserved. // SPDX-License-Identifier: Apache-2.0 #![no_std] #![feature(default_alloc_error_handler)] #![feature(panic_info_message)] #![feature(bench_black_box)] +#![feature(box_syntax)] use core::alloc::Layout; @@ -29,7 +30,7 @@ pub unsafe fn painc_handler(info: &core::panic::PanicInfo<'_>) -> ! { printf("%s\n\0".as_ptr().cast(), s.as_ptr()); loop {} } - +#[allow(unused, unused_imports)] mod liteos; use liteos::*; #[no_mangle] @@ -50,11 +51,11 @@ unsafe extern "C" fn app_init() { lazyobj_test6(); printf("getTickCount Test\n\0".as_ptr()); get_tickcount_test(); - printf("RWLock smolk Test\n\0".as_ptr()); - rwlock_smoke(); printf("parker led Test\n\0".as_ptr()); parker_led(); - printf("LOS Event Check\n\0".as_ptr()); - los_event_check() + printf("RWLock smolk Test\n\0".as_ptr()); + rwlock_smoke(); + printf("RWLock frob Test\n\0".as_ptr()); + frob(); } diff --git a/src/common/lazyobj.rs b/src/common/lazyobj.rs index b7941101abd2d270c2acd371568921cc4030c1a2..74422c67e451bd292e9876b89a2ecc9549c844ff 100644 --- a/src/common/lazyobj.rs +++ b/src/common/lazyobj.rs @@ -1,4 +1,4 @@ -// Copyright (C) 2022-2022 Agilor Co.,Ltd. All rights reserved. +// Copyright (C) 2022-2022 Agilor Co.,Ltd. All rights reserved. // SPDX-License-Identifier: Apache-2.0 #[cfg(all(test, not(target_os = "none")))] mod tests; @@ -12,7 +12,7 @@ use core::{ ops::{Deref, DerefMut}, sync::atomic::{ AtomicUsize, - Ordering::{Acquire, Relaxed, Release}, + Ordering::{Relaxed, Release}, }, }; const EMPTY: usize = usize::MAX; @@ -42,11 +42,11 @@ impl LazyObj { let mut state = self.value.load(Relaxed); if state > COMPLETE { if ISBOX { - state = initialize_box(&self.value, state, Self::LY, unsafe { + state = initialize_box(&self.value, Self::LY, unsafe { transmute(T::init as *mut u8) }); } else { - initialize_nobox(&self.value, state, unsafe { transmute(T::init as *mut u8) }); + initialize_nobox(&self.value, unsafe { transmute(T::init as *mut u8) }); } } if ISBOX { @@ -58,11 +58,13 @@ impl LazyObj { } //放置到全局的目的是禁止泛化,造成的代码膨胀。 #[cold] -fn initialize_box(ptr: &AtomicUsize, mut state: usize, ly: Layout, init: fn(*mut ())) -> usize { +fn initialize_box(ptr: &AtomicUsize, ly: Layout, init: fn(*mut ())) -> usize { + let mut state = ptr.load(Relaxed); loop { match state { + s if s < RUNING => return state, EMPTY => { - let result = ptr.compare_exchange_weak(state, RUNING, Acquire, Acquire); + let result = ptr.compare_exchange_weak(state, RUNING, Relaxed, Relaxed); if let Err(old) = result { state = old; continue; @@ -72,7 +74,6 @@ fn initialize_box(ptr: &AtomicUsize, mut state: usize, ly: Layout, init: fn(*mut ptr.swap(t.addr(), Release); return t.addr(); } - s if s < RUNING => return state, _ => { if CPU_CORE_NUMBERS > 1 { core::hint::spin_loop(); @@ -80,7 +81,7 @@ fn initialize_box(ptr: &AtomicUsize, mut state: usize, ly: Layout, init: fn(*mut thread::Thread::yield_now(); } debug_assert!(state == RUNING); - state = ptr.load(Acquire); + state = ptr.load(Relaxed); continue; } } @@ -88,27 +89,28 @@ fn initialize_box(ptr: &AtomicUsize, mut state: usize, ly: Layout, init: fn(*mut } #[cold] //放置到全局的目的是禁止泛化,造成的代码膨胀。 -fn initialize_nobox(ptr: &AtomicUsize, mut status: usize, init: fn(*mut ())) { +fn initialize_nobox(ptr: &AtomicUsize, init: fn(*mut ())) { + let mut state = ptr.load(Relaxed); loop { - match status { + match state { EMPTY => { - let result = ptr.compare_exchange_weak(status, RUNING, Acquire, Acquire); + let result = ptr.compare_exchange_weak(state, RUNING, Relaxed, Relaxed); if let Err(old) = result { - status = old; + state = old; continue; } - unsafe { init(transmute(&status)) }; - ptr.swap(status, Release); + unsafe { init(transmute(&state)) }; + ptr.swap(state, Release); } s if s < RUNING => return, _ => { - debug_assert!(status == RUNING); + debug_assert!(state == RUNING); if CPU_CORE_NUMBERS > 1 { core::hint::spin_loop(); } else { thread::Thread::yield_now(); } - status = ptr.load(Acquire); + state = ptr.load(Relaxed); continue; } } diff --git a/src/lib.rs b/src/lib.rs index 62a814d39899cf9931bd751257770fd83c152f41..a089082c0ca094960307b8710a0c9629002d0e12 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,8 @@ #![feature(negative_impls)] #![feature(const_mut_refs)] #![feature(bench_black_box)] +#![feature(let_chains)] +#![feature(const_ptr_offset_from)] #[allow(unused_imports)] #[macro_use] diff --git a/src/liteos/libc.rs b/src/liteos/libc.rs index 7b806175daba4f2653c38f1fd956abb064e1db26..c6b44078ef9b4430d14b3e69f9300fae19231e02 100644 --- a/src/liteos/libc.rs +++ b/src/liteos/libc.rs @@ -14,6 +14,8 @@ pub mod heap { uwUsageWaterLine: u32, } extern "C" { + #[link_name = "__los_heap_addr_start__"] + pub static mut GLOBAL_POOL: u8; // 初始化和删除内存池 // LOS_MemInit 初始化一块指定的动态内存池,大小为size pub fn LOS_MemInit(poll: *mut u8, size: u32) -> u32; @@ -97,8 +99,6 @@ pub mod sys { pub fn abort() -> !; pub fn __errno_location() -> *const i32; pub fn strerror_r(err: i32, buf: *mut u8, buflen: size_t) -> i32; - pub fn strnlen(cs: *const u8, maxlen: size_t) -> size_t; - pub fn LOS_TickCountGet() -> u64; } } pub mod pthread { @@ -135,18 +135,128 @@ pub mod pthread { pub mod timer { extern "C" { pub fn LOS_MS2Tick(millisec: u32) -> u32; + pub fn LOS_TickCountGet() -> u64; } } pub mod task { + use super::super::sysinfo::*; + use super::event::EVENT_CB_S; + use super::list::{SortLinkList, LOS_DL_LIST}; + use super::spinlock::SPIN_LOCK_S; use super::LOSCFG_BASE_CORE_TSK_LIMIT; + use crate::os::CPU_CORE_NUMBERS; + use core::ffi::c_void; pub const KERNEL_TSK_LIMIT: u32 = LOSCFG_BASE_CORE_TSK_LIMIT as u32; pub const LOS_ERRNO_TSK_ID_INVALID: u32 = 0x02000207; + + pub const OS_TASK_STATUS_READY: u16 = 0x0004; + pub const OS_TASK_STATUS_PEND: u16 = 0x0008; + + #[cfg(LOSCFG_KERNEL_SMP_LOCKDEP)] + #[repr(C)] + pub struct HeldLocks { + lockPtr: *const c_void, + lockAddr: *const c_void, + waitTime: u64, + holdTime: u64, + } + #[cfg(LOSCFG_KERNEL_SMP_LOCKDEP)] + const MAX_LOCK_DEPTH: usize = 16; + #[cfg(LOSCFG_KERNEL_SMP_LOCKDEP)] + #[repr(C)] + pub struct LockDep { + waitLock: *const c_void, + lockDepth: i32, + heldLocks: [HeldLocks; MAX_LOCK_DEPTH], + } + #[cfg(LOSCFG_DEBUG_SCHED_STATISTICS)] + #[repr(C)] + pub struct SchedPercpu { + runtime: u64, + contexSwitch: u32, + } + #[cfg(LOSCFG_DEBUG_SCHED_STATISTICS)] + #[repr(C)] + pub struct SchedStat { + startRuntime: u64, + allRuntime: u64, + allContextSwitch: u32, + schedPercpu: [SchedPercpu; CPU_CORE_NUMBERS], + } + #[repr(C)] + pub struct LosTaskCB { + pub stackPointer: *const core::ffi::c_void, /* Task stack pointer */ + pub taskStatus: u16, /* Task status */ + pub priority: u16, /* Task priority */ + pub taskFlags: u32, /* Task extend flags: taskFlags uses 8 bits now. 23 bits left */ + pub stackSize: u32, /* Task stack size */ + pub topOfStack: *const u32, /* Task stack top */ + pub taskId: u32, /* Task ID */ + pub taskEntry: *const c_void, /* Task entrance function */ + pub taskSem: *const core::ffi::c_void, /* Task-held semaphore */ + #[cfg(LOSCFG_COMPAT_POSIX)] + pub threadJoin: *const core::ffi::c_void, /* pthread adaption */ + #[cfg(LOSCFG_COMPAT_POSIX)] + pub threadJoinRetval: *const core::ffi::c_void, /* pthread adaption */ + + pub taskMux: *const core::ffi::c_void, /* Task-held mutex */ + #[cfg(LOSCFG_OBSOLETE_API)] + pub args: [*const u32; 4], /* Parameter, of which the maximum number is 4 */ + #[cfg(not(LOSCFG_OBSOLETE_API))] + pub args: *const core::ffi::c_void, /* Parameter, of which the type is void * */ + + pub taskName: *const u8, /* Task name */ + pub pendList: LOS_DL_LIST, /* Task pend node */ + pub sortList: SortLinkList, /* Task sortlink node */ + #[cfg(LOSCFG_BASE_IPC_EVENT)] + pub event: EVENT_CB_S, + #[cfg(LOSCFG_BASE_IPC_EVENT)] + pub eventMask: u32, /* Event mask */ + #[cfg(LOSCFG_BASE_IPC_EVENT)] + pub eventMode: u32, /* Event mode */ + + pub msg: *const core::ffi::c_void, /* Memory allocated to queues */ + pub priBitMap: u32, /* BitMap for recording the change of task priority, + the priority can not be greater than 31 */ + pub signal: u32, /* Task signal */ + #[cfg(LOSCFG_BASE_CORE_TIMESLICE)] + pub timeSlice: u16, /* Remaining time slice */ + + #[cfg(LOSCFG_KERNEL_SMP)] + pub currCpu: u16, /* CPU core number of this task is running on */ + #[cfg(LOSCFG_KERNEL_SMP)] + pub lastCpu: u16, /* CPU core number of this task is running on last time */ + #[cfg(LOSCFG_KERNEL_SMP)] + pub timerCpu: u32, /* CPU core number of this task is delayed or pended */ + #[cfg(LOSCFG_KERNEL_SMP)] + pub cpuAffiMask: u16, /* CPU affinity mask, support up to 16 cores */ + #[cfg(all(LOSCFG_KERNEL_SMP, LOSCFG_KERNEL_SMP_TASK_SYNC))] + pub syncSignal: u32, /* Synchronization for signal handling */ + #[cfg(all(LOSCFG_KERNEL_SMP, LOSCFG_KERNEL_SMP_LOCKDEP))] + pub lockDep: LockDep, + + #[cfg(LOSCFG_DEBUG_SCHED_STATISTICS)] + pub schedStat: SchedStat, /* Schedule statistics */ + + #[cfg(LOSCFG_KERNEL_PERF)] + pub pc: *const u32, + #[cfg(LOSCFG_KERNEL_PERF)] + pub fp: *const u32, + } + extern "C" { + pub static g_taskSpin: SPIN_LOCK_S; pub fn LOS_TaskDelay(tick: u32) -> u32; pub fn LOS_CurTaskIDGet() -> u32; pub fn LOS_TaskSuspend(taskId: u32) -> u32; pub fn LOS_TaskResume(taskId: u32) -> u32; + pub fn LOS_TaskLock(); + pub fn LOS_TaskUnlock(); + pub fn OsSchedResched(); + #[inline(always)] + #[link_name = "_OsCurrTaskGet"] + pub fn OsCurrTaskGet() -> *mut LosTaskCB; } } pub mod mutex { @@ -161,7 +271,6 @@ pub mod mutex { } } pub mod event { - pub const LOS_WAITMODE_AND: u32 = 4u32; pub const LOS_WAITMODE_CLR: u32 = 1u32; pub const LOS_WAITMODE_OR: u32 = 2u32; @@ -181,6 +290,148 @@ pub mod event { ) -> u32; pub fn LOS_EventWrite(eventCB: *const EVENT_CB_S, events: u32) -> u32; pub fn LOS_EventDestroy(eventCB: *const EVENT_CB_S) -> u32; + pub fn OsEventWriteOnce(eventCB: *const EVENT_CB_S, events: u32) -> u32; + pub fn LOS_EventClear(eventCB: *const EVENT_CB_S, events: u32) -> u32; + } +} +pub mod c { + use super::size_t; + + extern "C" { + pub fn rand() -> i32; + pub fn strnlen(cs: *const u8, maxlen: size_t) -> size_t; + } +} +pub mod spinlock { + use cfg_if::cfg_if; + cfg_if! { + if #[cfg(LOSCFG_KERNEL_SMP_LOCKDEP)]{ + #[repr(C)] + pub struct SPIN_LOCK_S { + rawLock: usize, + cpuid: u32, + owner: *const core::ffi::c_void, + name: *const u8, + } + impl SPIN_LOCK_S{ + pub const fn default() -> Self { + Self{ + rawLock:0, + cpuid:u32::MAX, + owner:core::ptr::null(), + name:b"".as_ptr(), + } + } + } + }else{ + #[repr(C)] + pub struct SPIN_LOCK_S { + rawLock: usize, + } + impl SPIN_LOCK_S{ + pub const fn default() -> Self { + Self { rawLock: 0 } + } + } + } + } + + extern "C" { + #[inline(always)] + #[link_name = "_LOS_SpinHeld"] + pub fn LOS_SpinHeld(lock: *const SPIN_LOCK_S) -> bool; + + #[inline(always)] + #[link_name = "_LOS_SpinInit"] + pub fn LOS_SpinInit(lock: *const SPIN_LOCK_S); + + #[inline(always)] + #[link_name = "_LOS_SpinLock"] + pub fn LOS_SpinLock(lock: *const SPIN_LOCK_S); + + #[inline(always)] + #[link_name = "_LOS_SpinLockSave"] + pub fn LOS_SpinLockSave(lock: *const SPIN_LOCK_S, intsave: &mut u32); + + #[inline(always)] + #[link_name = "_LOS_SpinTrylock"] + pub fn LOS_SpinTrylock(lock: *const SPIN_LOCK_S) -> u32; + + #[inline(always)] + #[link_name = "_LOS_SpinUnlock"] + pub fn LOS_SpinUnlock(lock: *const SPIN_LOCK_S); + + #[inline(always)] + #[link_name = "_LOS_SpinUnlockRestore"] + pub fn LOS_SpinUnlockRestore(lock: *const SPIN_LOCK_S, intsave: u32); + } +} +pub mod interrupt { + extern "C" { + #[inline(always)] + #[link_name = "_LOS_IntLock"] + pub fn LOS_IntLock() -> u32; + + #[inline(always)] + #[link_name = "_LOS_IntUnLock"] + pub fn LOS_IntUnLock() -> u32; + + #[inline(always)] + #[link_name = "_LOS_IntRestore"] + pub fn LOS_IntRestore(intsave: u32); + } +} +pub mod list { + use core::{mem::transmute, num::NonZeroUsize, ptr::NonNull}; + + #[repr(C)] + pub struct LOS_DL_LIST { + //**< Current node's pointer to the previous node + pstPrev: NonNull, + //**< Current node's pointer to the next node + pstNext: NonNull, + } + unsafe impl Sync for LOS_DL_LIST {} + #[repr(C)] + pub struct SortLinkList { + sortLinkNode: LOS_DL_LIST, + idxRollNum: u32, + } + + pub fn LOS_ListAdd(list: &mut LOS_DL_LIST, node: &mut LOS_DL_LIST) { + unsafe { + node.pstNext = list.pstNext; + node.pstPrev = list.into(); + list.pstNext.as_mut().pstPrev = node.into(); + list.pstNext = node.into(); + } + } + pub fn LOS_ListTailInsert(list: &mut LOS_DL_LIST, node: &mut LOS_DL_LIST) { + LOS_ListAdd(list, node); + } + pub fn LOS_ListEmpty(list: &LOS_DL_LIST) -> bool { + return list.pstNext == list.into(); + } + pub const fn LOS_ListInit(list: &mut LOS_DL_LIST) { + unsafe { + list.pstPrev = NonNull::new_unchecked(list); + list.pstNext = NonNull::new_unchecked(list); + } + } +} +pub mod futex { + use core::sync::atomic::AtomicU32; + + use super::list::LOS_DL_LIST; + extern "C" { + pub fn Futex_Wake(list: *const LOS_DL_LIST, once: bool) -> bool; + pub fn Futex_Wait( + futex: &AtomicU32, + expected: u32, + list: *const LOS_DL_LIST, + timeout: u32, + ) -> bool; + } } diff --git a/src/liteos/locks/mod.rs b/src/liteos/locks/mod.rs index aa340ac08907dd364bb2b1c6d4ad52f311959505..35adc4ac0eb2081690ae7158d1d66918b6f003d2 100644 --- a/src/liteos/locks/mod.rs +++ b/src/liteos/locks/mod.rs @@ -1,8 +1,7 @@ -// Copyright (C) 2022-2022 Agilor Co.,Ltd. All rights reserved. +// Copyright (C) 2022-2022 Agilor Co.,Ltd. All rights reserved. // SPDX-License-Identifier: Apache-2.0 mod mutex; pub use mutex::*; pub mod parker; mod rwlock; pub use rwlock::*; - diff --git a/src/liteos/locks/parker.rs b/src/liteos/locks/parker.rs index 90e916ed65bdab2981056d13f534e062f9c7561c..af43610af940743be19869c952604185354ef5cf 100644 --- a/src/liteos/locks/parker.rs +++ b/src/liteos/locks/parker.rs @@ -1,4 +1,4 @@ -// Copyright (C) 2022-2022 Agilor Co.,Ltd. All rights reserved. +// Copyright (C) 2022-2022 Agilor Co.,Ltd. All rights reserved. // SPDX-License-Identifier: Apache-2.0 use crate::liteos::libc::event::{ LOS_EventDestroy, LOS_EventInit, LOS_EventRead, LOS_EventWrite, EVENT_CB_S, @@ -11,7 +11,7 @@ use core::mem::MaybeUninit; use core::ptr::NonNull; use core::sync::atomic::{ AtomicU32, - Ordering::{Acquire, Relaxed}, + Ordering::{Acquire, Relaxed, Release}, }; #[allow(unused)] const PARKED: u32 = 0x00000000; @@ -38,7 +38,7 @@ impl Inner { debug_assert!(rtn == LOS_OK); } unsafe fn park(&self) { - if self.flag.fetch_sub(EMPTY, Acquire) == NOTIFIED { + if self.flag.fetch_sub(EMPTY, Release) == NOTIFIED { return; } let rtn = LOS_EventRead( @@ -47,15 +47,17 @@ impl Inner { LOS_WAITMODE_AND | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER, ); - debug_assert!(rtn == 1); + //If multiple threads use the same Parker, only one thread will return 1 and other threads will return zero. + debug_assert!(rtn == 1 || rtn == 0); self.flag.swap(EMPTY, Relaxed); } unsafe fn park_timeout(&self, timeout: u32) -> bool { - if self.flag.fetch_sub(EMPTY, Acquire) == NOTIFIED { + if self.flag.fetch_sub(EMPTY, Release) == NOTIFIED { return true; } let rtn = LOS_EventRead(&self.evb, 1, LOS_WAITMODE_AND | LOS_WAITMODE_CLR, timeout); - debug_assert!(rtn == 1 || rtn == LOS_ERRNO_EVENT_READ_TIMEOUT); + //If multiple threads use the same Parker, only one thread will return 1 and other threads will return zero. + debug_assert!(rtn == 1 || rtn == 0 || rtn == LOS_ERRNO_EVENT_READ_TIMEOUT); if self.flag.swap(EMPTY, Acquire) == NOTIFIED { true } else { diff --git a/src/liteos/locks/rwlock.rs b/src/liteos/locks/rwlock.rs index 9bd6611e271b4211bae70391d71c74d82c58a064..89067c9e48e2f0d9bca4b4f61a7636b13f3b0bfd 100644 --- a/src/liteos/locks/rwlock.rs +++ b/src/liteos/locks/rwlock.rs @@ -1,4 +1,4 @@ -// Copyright (C) 2022-2022 Agilor Co.,Ltd. All rights reserved. +// Copyright (C) 2022-2022 Agilor Co.,Ltd. All rights reserved. // SPDX-License-Identifier: Apache-2.0 use core::{ mem::MaybeUninit, @@ -6,16 +6,17 @@ use core::{ sync::atomic::Ordering::{Acquire, Relaxed, Release}, }; +use crate::liteos::libc::{ + futex::{Futex_Wait, Futex_Wake}, + list::{LOS_ListInit, LOS_DL_LIST}, +}; +#[allow(unused_imports)] +use crate::os::printf; use crate::{ lazy::{LazyObj, LazyObjInit}, - liteos::libc::{ - event::{LOS_EventDestroy, LOS_EventInit, LOS_EventRead, EVENT_CB_S, LOS_WAITMODE_AND}, - sys::{LOS_OK, LOS_WAIT_FOREVER}, - }, + liteos::libc::sys::LOS_WAIT_FOREVER, os::CPU_CORE_NUMBERS, - thread::Thread, }; - const READ_LOCKED: u32 = 1; const MASK: u32 = (1 << 30) - 1; const WRITE_LOCKED: u32 = MASK; @@ -23,79 +24,106 @@ const MAX_READERS: u32 = MASK - 1; const READERS_WAITING: u32 = 1 << 30; const WRITERS_WAITING: u32 = 1 << 31; +#[inline] fn is_unlocked(state: u32) -> bool { state & MASK == 0 } +#[inline] fn is_write_locked(state: u32) -> bool { state & MASK == WRITE_LOCKED } +#[inline] fn has_readers_waiting(state: u32) -> bool { state & READERS_WAITING != 0 } +#[inline] fn has_writers_waiting(state: u32) -> bool { state & WRITERS_WAITING != 0 } +#[inline] fn is_read_lockable(state: u32) -> bool { - state & !MASK == 0 && state & MASK < MAX_READERS + (state & MASK < MAX_READERS) && (state & (!MASK) == 0) } +#[inline] fn has_reached_max_readers(state: u32) -> bool { state & MASK == MAX_READERS } pub struct RwLock { state: AtomicU32, - event: EVENT_CB_S, + wrcnt: AtomicU32, + readers: LOS_DL_LIST, + writers: LOS_DL_LIST, } pub type MovableRwLock = LazyObj; impl LazyObjInit for RwLock { fn init(v: &mut MaybeUninit) { - let v = v.write(RwLock::new()); + let v = unsafe { v.assume_init_mut() }; v.init(); } } +/// NB that during the initialization of liteos event, +/// The head and tail of the double linked list point to itself as an empty tag. +/// Therefore, events must be placed on the heap and cannot be moved. impl RwLock { - #[inline] - pub const fn new() -> Self { - Self { - state: AtomicU32::new(0), - event: unsafe { MaybeUninit::uninit().assume_init() }, - } + fn init(&mut self) { + self.state = AtomicU32::new(0); + self.wrcnt = AtomicU32::new(0); + LOS_ListInit(&mut self.readers); + LOS_ListInit(&mut self.writers); } - fn init(&self) { - let rtn = unsafe { LOS_EventInit(&self.event) }; - debug_assert!(rtn == LOS_OK); - } - pub fn try_read(&self) -> bool { + // Here only need to test and lock it once, and the successful locking returns true + pub unsafe fn try_read(&self) -> bool { self.state .fetch_update(Acquire, Relaxed, |s| { is_read_lockable(s).then(|| s + READ_LOCKED) }) .is_ok() } - #[cold] - pub fn read(&self) { - let state = self.state.load(Relaxed); - if !is_read_lockable(state) - || self - .state - .compare_exchange_weak(state, state + READ_LOCKED, Acquire, Relaxed) - .is_err() - { - self.read_contended(); + pub unsafe fn read(&self) { + let mut state = self.state.load(Relaxed); + while is_read_lockable(state) { + if let Err(s) = + self.state + .compare_exchange_weak(state, state + READ_LOCKED, Acquire, Relaxed) + { + state = s; + continue; + } + // Successfully locked, Return; + return; + } + // Resolve lock contention + self.read_contended(); + } + pub fn read_unlock(&self) { + let state = self.state.fetch_sub(READ_LOCKED, Release) - READ_LOCKED; + + // There can be no task waiting to be read, unless there is a task waiting to be written. + debug_assert!(!has_readers_waiting(state) || has_writers_waiting(state)); + + // If we are the last reader,and there are tasks waiting to be written, wake up the task which waiting to be written. + if is_unlocked(state) && has_writers_waiting(state) { + unsafe { self.wake_writer_or_readers(state) }; } } #[cold] fn read_contended(&self) { - let mut state = self.spin_read(); + // For a single core processor, spin only causes the problem of priority inversion. + let mut state = if CPU_CORE_NUMBERS > 1 { + self.spin_read() + } else { + self.state.load(Acquire) + }; loop { if is_read_lockable(state) { match self .state .compare_exchange_weak(state, state + READ_LOCKED, Acquire, Relaxed) { - Ok(_) => return, + Ok(_) => return, // Locked! Err(s) => { state = s; continue; @@ -107,6 +135,7 @@ impl RwLock { if has_reached_max_readers(state) { panic!("too many active read locks on RwLock"); } + // If there are no readers waiting for lock, we set it up. if !has_readers_waiting(state) { if let Err(s) = self.state @@ -116,11 +145,158 @@ impl RwLock { continue; } } - let rtn = unsafe { LOS_EventRead(&self.event, 1, LOS_WAITMODE_AND, LOS_WAIT_FOREVER) }; - debug_assert!(rtn == 1); - state = self.spin_read(); + // blocking current thread , and wait for notify. + unsafe { + Futex_Wait( + &self.state, + state | READERS_WAITING, + &self.readers, + LOS_WAIT_FOREVER, + ) + }; + state = if CPU_CORE_NUMBERS > 1 { + self.spin_read() + } else { + self.state.load(Acquire) + }; + } + } + // Test and locked it; + pub unsafe fn try_write(&self) -> bool { + self.state + .fetch_update(Acquire, Relaxed, |s| { + is_unlocked(s).then(|| s + WRITE_LOCKED) + }) + .is_ok() + } + pub unsafe fn write(&self) { + // In most cases, entering the write-lock is in the lock idle state. + if self + .state + .compare_exchange_weak(0, WRITE_LOCKED, Acquire, Relaxed) + .is_err() + { + self.write_contended(); + } + } + + pub unsafe fn write_unlock(&self) { + let state = self.state.fetch_sub(WRITE_LOCKED, Release) - WRITE_LOCKED; + // After unlocked the write-lock, it is only possible to enter the unlocked state + debug_assert!(is_unlocked(state)); + + if has_writers_waiting(state) || has_readers_waiting(state) { + self.wake_writer_or_readers(state); + } + } + + #[cold] + unsafe fn write_contended(&self) { + // For a single core processor, spin only causes the problem of priority inversion. + let mut state = if CPU_CORE_NUMBERS > 1 { + self.spin_write() + } else { + self.state.load(Acquire) + }; + let mut other_writers_waiting = 0; + loop { + // If it's unlocked, we try to lock it. + if is_unlocked(state) { + match self.state.compare_exchange_weak( + state, + state | WRITE_LOCKED | other_writers_waiting, + Acquire, + Relaxed, + ) { + Ok(_) => return, // Locked! + Err(s) => { + state = s; + continue; + } + } + } + + if !has_writers_waiting(state) { + if let Err(s) = + self.state + .compare_exchange(state, state | WRITERS_WAITING, Relaxed, Relaxed) + { + state = s; + continue; + } + } + // Because there may be other tasks waiting to write the lock, + // so,we need to keep this state in the next retry. + other_writers_waiting = WRITERS_WAITING; + let seq = self.wrcnt.load(Acquire); + // Confirm again whether to wait. + state = self.state.load(Relaxed); + if is_unlocked(state) || !has_writers_waiting(state) { + continue; + } + Futex_Wait(&self.wrcnt, seq, &self.writers, LOS_WAIT_FOREVER); + // Retry lock + state = if CPU_CORE_NUMBERS > 1 { + self.spin_write() + } else { + self.state.load(Acquire) + }; } } + + /// Wake up waiting tasks after unlocking + /// + /// If there are tasks waiting to be written, wake up one of them first。 + /// Otherwise, wake up all tasks waiting for reading。 + + #[cold] + unsafe fn wake_writer_or_readers(&self, mut state: u32) { + debug_assert!(is_unlocked(state)); + // If there are only tasks which waiting to write locks,We just need to wake one of them. + // NB. There is no need to judge whether the task is really awakened. + // If no task is awakened, it means that the current task is the last one. The lock state is restored to the initial state + if state == WRITERS_WAITING { + match self.state.compare_exchange(state, 0, Relaxed, Relaxed) { + Ok(_) => { + self.wrcnt.fetch_add(1, Release); + Futex_Wake(&self.writers, true); + return; + } + Err(s) => { + // Maybe some readers are now waiting too. So, continue to the next `if`. + state = s; + } + } + } + if state == READERS_WAITING + WRITERS_WAITING { + if self + .state + .compare_exchange(state, READERS_WAITING, Relaxed, Relaxed) + .is_err() + { + // Only other tasks have acquired the write lock, so no processing is required. + return; + } + // Wake up the task which waiting for writing. + // If no task were actually blocking on Futex,We continue wake up the task which waiting for reading. + self.wrcnt.fetch_add(1, Relaxed); + if Futex_Wake(&self.writers, true) { + return; + } + state = READERS_WAITING; + } + // Wake up tasks which waiting to be read + if state == READERS_WAITING { + if self + .state + .compare_exchange(state, 0, Relaxed, Relaxed) + .is_ok() + { + Futex_Wake(&self.readers, false); + } + } + } + fn spin_until(&self, f: impl Fn(u32) -> bool) -> u32 { let mut spin = 100; // Chosen by fair dice roll. loop { @@ -128,25 +304,22 @@ impl RwLock { if f(state) || spin == 0 { return state; } - if CPU_CORE_NUMBERS > 1 { - core::hint::spin_loop(); - } else { - Thread::yield_now(); - } + core::hint::spin_loop(); spin -= 1; } } + + fn spin_write(&self) -> u32 { + // Stop spinning when it's unlocked or when there's waiting writers. + self.spin_until(|state| is_unlocked(state) || has_writers_waiting(state)) + } + fn spin_read(&self) -> u32 { - // Stop spinning when it's unlocked or read locked, or when there's waiting threads. + // 1:Is no writer locked it; At this time, we need to try to lock it again + // 2:There is a reader waiting for lock; At this time, we should also directly block the current thread and wait for wakeup + // 3:There is a writer waiting for lock; At this time, we should also directly block the current thread and wait for wakeup self.spin_until(|state| { !is_write_locked(state) || has_readers_waiting(state) || has_writers_waiting(state) }) } } -impl Drop for RwLock { - fn drop(&mut self) { - let rtn = unsafe { LOS_EventDestroy(&self.event) }; - debug_assert!(rtn == LOS_OK); - } -} - diff --git a/src/liteos/malloc.rs b/src/liteos/malloc.rs index 6cf008a935bc3585088c00eee82b7b097b421cf9..efcd1cc86790d6628135c89554c7814588b11ab3 100644 --- a/src/liteos/malloc.rs +++ b/src/liteos/malloc.rs @@ -4,10 +4,6 @@ use super::libc::heap::*; use crate::common::malloc::{realloc_fallback, System, MIN_ALIGN}; use core::alloc::{GlobalAlloc, Layout}; -extern "C" { - #[link_name = "__los_heap_addr_start__"] - static mut POOL: u8; -} unsafe impl GlobalAlloc for System { #[inline] unsafe fn alloc(&self, layout: Layout) -> *mut u8 { @@ -15,15 +11,15 @@ unsafe impl GlobalAlloc for System { let size = layout.size() as u32; let size = (size + (4 - 1)) & (-4i32 as u32); let ptr = if layout.align() <= MIN_ALIGN { - LOS_MemAlloc(&mut POOL, size) + LOS_MemAlloc(&mut GLOBAL_POOL, size) } else { - LOS_MemAllocAlign(&mut POOL, size, layout.align() as u32) + LOS_MemAllocAlign(&mut GLOBAL_POOL, size, layout.align() as u32) }; ptr } #[inline] unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { - LOS_MemFree(&mut POOL, ptr); + LOS_MemFree(&mut GLOBAL_POOL, ptr); } #[inline] @@ -31,7 +27,7 @@ unsafe impl GlobalAlloc for System { let size = new_size as u32; let size = (size + (4 - 1)) & (-4i32 as u32); if layout.align() <= MIN_ALIGN { - LOS_MemRealloc(&mut POOL, ptr, size) + LOS_MemRealloc(&mut GLOBAL_POOL, ptr, size) } else { realloc_fallback(self, ptr, layout, new_size) } diff --git a/src/liteos/os.rs b/src/liteos/os.rs index 6f5bf775d409aa03c4c5417c9e4150d16f42cca3..d84a2e4dfc5a09505e04bbd109e4b405cb2837d8 100644 --- a/src/liteos/os.rs +++ b/src/liteos/os.rs @@ -1,17 +1,15 @@ -// Copyright (C) 2022-2022 Agilor Co.,Ltd. All rights reserved. +// Copyright (C) 2022-2022 Agilor Co.,Ltd. All rights reserved. // SPDX-License-Identifier: Apache-2.0 use core::{alloc::Layout, mem::MaybeUninit, str::from_utf8_unchecked}; use crate::thread::Thread; +use super::libc; +use super::libc::timer::LOS_TickCountGet; + use super::{ - libc::{ - event::{ - LOS_EventInit, LOS_EventRead, LOS_EventWrite, EVENT_CB_S, LOS_WAITMODE_AND, - LOS_WAITMODE_CLR, LOS_WAITMODE_OR, - }, - sys::{self, *}, - }, + libc::c::strnlen, + libc::sys::{self, __errno_location, strerror_r}, sysinfo::LOSCFG_BASE_CORE_TICK_PER_SECOND, }; use alloc::{ @@ -56,44 +54,7 @@ pub fn abort() -> ! { unsafe { sys::abort() }; } -pub unsafe fn los_event_check() { - let ly = Layout::new::(); - let p = alloc(ly).cast(); - LOS_EventInit(p); - let th1 = Thread::new(1024, box move || { - for _ in 0..2 { - let rtn = LOS_EventRead(p, 1, LOS_WAITMODE_AND | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER); - let tick = get_tickcount(); - printf("Task0:tick:%u;:%d\r\n\0".as_ptr(), tick, rtn); - } - }) - .unwrap_unchecked(); - - let th2 = Thread::new(1024, box move || { - for _ in 0..2 { - let rtn = LOS_EventRead(p, 1, LOS_WAITMODE_AND | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER); - let tick = get_tickcount(); - printf("Task1:tick:%u;:%u\r\n\0".as_ptr(), tick, rtn); - } - }) - .unwrap_unchecked(); - - let th3 = Thread::new(1024, box move || { - for _ in 0..2 { - let rtn = LOS_EventRead(p, 1, LOS_WAITMODE_AND | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER); - let tick = get_tickcount(); - printf("Task2:tick:%u;:%u\r\n\0".as_ptr(), tick, rtn); - } - }) - .unwrap_unchecked(); - - for _ in 0..2 { - Thread::sleep(1000); - printf("send------\r\n\0".as_ptr()); - LOS_EventWrite(p, 1); - } - th1.join(); - th2.join(); - th3.join(); +#[inline(always)] +pub fn rand() -> i32 { + unsafe { libc::c::rand() } } - diff --git a/src/liteos/rust.c b/src/liteos/rust.c new file mode 100644 index 0000000000000000000000000000000000000000..29587b9d89fda0d6cdbe0a5df3834f9333bf7d40 --- /dev/null +++ b/src/liteos/rust.c @@ -0,0 +1,109 @@ +#include "los_spinlock.h" +#include "los_task_pri.h" +#include "los_atomic.h" +#include "los_list.h" +#include "los_mp_pri.h" +LITE_OS_SEC_TEXT BOOL _LOS_SpinHeld(const SPIN_LOCK_S *lock) +{ + return LOS_SpinHeld(lock); +} + +LITE_OS_SEC_TEXT VOID _LOS_SpinInit(SPIN_LOCK_S *lock) +{ + LOS_SpinInit(lock); +} + +LITE_OS_SEC_TEXT VOID _LOS_SpinLock(SPIN_LOCK_S *lock) +{ + LOS_SpinLock(lock); +} + +LITE_OS_SEC_TEXT VOID _LOS_SpinLockSave(SPIN_LOCK_S *lock, UINT32 *intSave) +{ + LOS_SpinLockSave(lock, intSave); +} + +LITE_OS_SEC_TEXT INT32 _LOS_SpinTrylock(SPIN_LOCK_S *lock) +{ + return LOS_SpinTrylock(lock); +} + +LITE_OS_SEC_TEXT VOID _LOS_SpinUnlock(SPIN_LOCK_S *lock) +{ + LOS_SpinUnlock(lock); +} + +LITE_OS_SEC_TEXT VOID _LOS_SpinUnlockRestore(SPIN_LOCK_S *lock, + UINT32 intSave) +{ + LOS_SpinUnlockRestore(lock, intSave); +} + +LITE_OS_SEC_TEXT UINT32 _LOS_IntLock(VOID) +{ + return LOS_IntLock(); +} + +LITE_OS_SEC_TEXT UINT32 _LOS_IntUnLock(VOID) +{ + return LOS_IntUnLock(); +} + +LITE_OS_SEC_TEXT VOID _LOS_IntRestore(UINT32 intSave) +{ + LOS_IntRestore(intSave); +} + +LITE_OS_SEC_TEXT BOOL Futex_Wait(Atomic *futex, INT32 expected, LOS_DL_LIST *list, UINT32 timeout) +{ + UINT32 intSave; + LosTaskCB *runTask = OsCurrTaskGet(); + SCHEDULER_LOCK(intSave); + if (LOS_AtomicRead(futex) == expected) + { + OsTaskWait(list, OS_TASK_STATUS_PEND, timeout); + OsSchedResched(); + SCHEDULER_UNLOCK(intSave); + SCHEDULER_LOCK(intSave); + if (runTask->taskStatus & OS_TASK_STATUS_TIMEOUT) + { + runTask->taskStatus &= ~OS_TASK_STATUS_TIMEOUT; + SCHEDULER_UNLOCK(intSave); + return false; + } + } + SCHEDULER_UNLOCK(intSave); + return true; +} + +LITE_OS_SEC_TEXT BOOL Futex_Wake(LOS_DL_LIST *list, BOOL once) +{ + LosTaskCB *resumedTask = NULL; + LosTaskCB *nextTask = NULL; + UINT8 exitFlag = 0; + UINT32 intSave; + SCHEDULER_LOCK(intSave); + if (!LOS_ListEmpty(list)) + { + for (resumedTask = LOS_DL_LIST_ENTRY(list->pstNext, LosTaskCB, pendList); + &resumedTask->pendList != list;) + { + nextTask = LOS_DL_LIST_ENTRY(resumedTask->pendList.pstNext, LosTaskCB, pendList); + exitFlag++; + OsTaskWake(resumedTask, OS_TASK_STATUS_PEND); + if (once) + { + break; + } + resumedTask = nextTask; + } + } + SCHEDULER_UNLOCK(intSave); + if (exitFlag > 0) + { + LOS_MpSchedule(OS_MP_CPU_ALL); + LOS_Schedule(); + return true; + } + return false; +} diff --git a/src/liteos/thread.rs b/src/liteos/thread.rs index b4f5c4cc93fc20b2e92f94310724263647c86b62..76e09547265b74d0f393e6e8ae9f407691096f24 100644 --- a/src/liteos/thread.rs +++ b/src/liteos/thread.rs @@ -54,8 +54,7 @@ impl Thread { } #[inline] pub fn yield_now() { - let ret = unsafe { sched_yield() }; - debug_assert_eq!(ret, 0); + unsafe { sched_yield() }; } #[inline] pub fn set_name(_name: &str) {}