Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
b97948b
feat(axtask): add work-stealing load balancing for SMP
nina-ysml May 28, 2026
4bcde68
fix(axtask): drop local scheduler lock before work-stealing
nina-ysml May 28, 2026
70a2167
fix(axtask): check cpumask in try_steal to respect CPU affinity
nina-ysml May 29, 2026
2769b4e
fix(axtask): set cpu_id on stolen task in try_steal
nina-ysml May 29, 2026
34f5ba3
fix(axtask): add pick_next_task_matching to eliminate try_steal race …
nina-ysml May 30, 2026
754a8aa
fix(axtask): skip uninitialized run queues in try_steal()
nina-ysml May 31, 2026
732fb36
fix(axtask): gate AtomicBool/Ordering imports behind smp feature
nina-ysml May 31, 2026
f2a3678
fix(axtask): revert sched_policy/sched_priority fields from TaskInner
nina-ysml May 31, 2026
2f401df
fix(axsched): preserve queue order in pick_next_task_matching
nina-ysml Jun 10, 2026
5f6432b
fix(axtask): allow modulo_one and reversed_empty_ranges in try_steal
nina-ysml Jun 10, 2026
f8783d6
trigger CI
nina-ysml Jun 10, 2026
8b55fb1
fix(axtask): move set_cpu_id inside scheduler lock scope in try_steal
nina-ysml Jun 10, 2026
07326e6
fix(axtask): add diagnostics for mutex ownership panic on loongarch64
nina-ysml Jun 10, 2026
df95e32
fix(axtask): fix clippy::manual_inspect and cargo fmt issues
nina-ysml Jun 11, 2026
3259fda
fix(axsync): remove ax_hal dependency from mutex unlock diagnostic
nina-ysml Jun 11, 2026
2840e69
fix(axtask): downgrade context switch log from info! to trace!
nina-ysml Jun 11, 2026
585fba4
trigger CI
nina-ysml Jun 11, 2026
bc5c352
fix(axtask): skip non-ready tasks in try_steal
nina-ysml Jun 12, 2026
73ac5e0
fix(axtask): check !on_cpu in try_steal to prevent race with clear_pr…
nina-ysml Jun 12, 2026
85b54f6
fix(axtask): formatting for try_steal on_cpu check
nina-ysml Jun 12, 2026
6acc246
Revert SCHED_STATES BTreeMap and add SMP work-stealing test
nina-ysml Jun 13, 2026
cbaf784
trigger CI
nina-ysml Jun 16, 2026
c86f162
fix(test): reduce work-stealing test intensity to avoid kernel bug #1296
nina-ysml Jun 17, 2026
644c1a3
fix(axtask): filter stealable tasks inside pick_next_task_matching pr…
nina-ysml Jun 17, 2026
d2e4e21
trigger CI: re-run after board infra failures
nina-ysml Jun 18, 2026
fb2e36e
fix(starry): add FdTable task_count tracking to fix clone-files-race …
nina-ysml Jun 21, 2026
1484008
fix(test): flatten test-work-stealing directory layout and reduce log…
nina-ysml Jun 21, 2026
9e9f145
trigger CI: re-run after board infra timeout
nina-ysml Jun 21, 2026
b664dba
fix(starry): replace as_thread() with try_as_thread() in handle_syscall
nina-ysml Jun 21, 2026
1a1ffa1
trigger CI: re-run to verify infrastructure timeout was transient
nina-ysml Jun 21, 2026
22d998e
trigger CI: verify orangepi-5-plus-linux board failure consistency
nina-ysml Jun 21, 2026
6206c8a
DEBUG: temporarily disable work-stealing to bisect orangepi board hang
nina-ysml Jun 22, 2026
14bdf34
fix(axtask): use try_lock in try_steal to avoid remote scheduler dead…
nina-ysml Jun 22, 2026
ae3ed2c
trigger CI: re-run to get orangepi try_lock result
nina-ysml Jun 22, 2026
38be233
DEBUG: disable fail-fast in test_checks to get orangepi result
nina-ysml Jun 22, 2026
05183fa
fix(axtask): restrict work-stealing to idle CPUs only
nina-ysml Jun 22, 2026
0922b7a
fix(axtask): add preempt_count gate and back-off in try_steal
nina-ysml Jun 22, 2026
c7219f6
fix(starry): decrement old FdTable task_count on CLOSE_RANGE_UNSHARE
nina-ysml Jun 22, 2026
1173159
test(starry): add CLONE_FILES + CLOSE_RANGE_UNSHARE + exit regression…
nina-ysml Jun 22, 2026
e3b9b7f
fix(axtask): skip empty remote queues before try_lock in try_steal
nina-ysml Jun 22, 2026
7727677
fix(axtask): use get_mut() to access scheduler for is_empty() check
nina-ysml Jun 22, 2026
2e229b7
fix(axtask): use shared ref for racy is_empty() check, not &mut
nina-ysml Jun 22, 2026
47c9fb5
fix(kspin): wrap raw pointer deref in unsafe block for clippy
nina-ysml Jun 22, 2026
bb4b4f0
fix(kspin): add missing `# Safety` docs for data_unchecked()
nina-ysml Jun 22, 2026
7c9cfe1
fix(axtask): gate work-stealing behind preempt feature
nina-ysml Jun 22, 2026
18169f1
fix: replace preempt gate with unconditional idle-steal + ForceUnlock…
nina-ysml Jun 23, 2026
4d749da
fix: apply cargo fmt formatting fixes
nina-ysml Jun 23, 2026
a0f6f84
Revert "fix: replace preempt gate with unconditional idle-steal"
nina-ysml Jun 23, 2026
844acc9
fix: gate try_steal call site on both smp and preempt
nina-ysml Jun 23, 2026
75416e5
trigger CI: re-run after phytiumpi board hardware flake
nina-ysml Jun 23, 2026
494f6d8
fix: restore original resched() structure with smp gate + preempt + i…
nina-ysml Jun 23, 2026
ed38ca4
trigger CI: re-run phytiumpi board test after cooldown
nina-ysml Jun 23, 2026
98211ce
trigger CI: re-run board tests
nina-ysml Jun 24, 2026
2f3a943
fix(axtask): scope ForceUnlockGuard counter per-CPU instead of global
nina-ysml Jun 24, 2026
3b553ed
Merge branch 'upstream/dev' into feat/workstealing
nina-ysml Jun 24, 2026
60bf0dc
trigger CI: re-run starry riscv64 test after board infra failure
nina-ysml Jun 24, 2026
b081e29
fix(axtask): fix FIFO ordering in pick_next_task_matching and yield i…
nina-ysml Jun 24, 2026
22530ce
fix(axsched): remove List::len dependency in matching pick
nina-ysml Jun 25, 2026
20db4db
chore(repo): trigger ci
nina-ysml Jun 26, 2026
d68b534
Merge upstream/dev into feat/workstealing
nina-ysml Jun 26, 2026
83f48c4
fix(axbuild): normalize grouped qemu test commands
nina-ysml Jun 27, 2026
146e1c9
chore(ci): retrigger loongarch check
nina-ysml Jun 27, 2026
ecf535b
chore(ci): final retry
nina-ysml Jun 27, 2026
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
21 changes: 21 additions & 0 deletions components/axsched/src/cfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,13 +168,34 @@ impl<T> BaseScheduler for CFScheduler<T> {
}
}

fn pick_next_task_matching(
&mut self,
predicate: impl Fn(&Self::SchedItem) -> bool,
) -> Option<Self::SchedItem> {
let key = {
let mut found = None;
for ((v, id), task) in &self.ready_queue {
if predicate(task) {
found = Some((*v, *id));
break;
}
}
found
};
key.and_then(|k| self.ready_queue.remove(&k))
}

fn put_prev_task(&mut self, prev: Self::SchedItem, _preempt: bool) {
let taskid = self.id_pool.fetch_add(1, Ordering::Release);
prev.set_id(taskid);
self.ready_queue
.insert((prev.clone().get_vruntime(), taskid), prev);
}

fn is_empty(&self) -> bool {
self.ready_queue.is_empty()
}

fn task_tick(&mut self, current: &Self::SchedItem) -> bool {
current.task_tick();
if self.ready_queue.is_empty() {
Expand Down
25 changes: 25 additions & 0 deletions components/axsched/src/fifo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,35 @@ impl<T> BaseScheduler for FifoScheduler<T> {
self.ready_queue.pop_front()
}

fn pick_next_task_matching(
Comment thread
ZR233 marked this conversation as resolved.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[建议] pick_next_task_matchingVecDeque pop_front 逐个取出,不匹配的任务暂存到 Vecpush_front 反序放回,会打乱队列原始顺序。

例如 [A, B, C, D],C 匹配:[A, B] → skipped → 放回 → [D, B, A]。A 和 B 的相对顺序被反转。

虽然在 work-stealing 场景下影响有限(大部分任务匹配即返回),但作为公开 trait 方法,重排可能引入调度公平性问题。

建议改用 cursor/索引遍历 + 原位删除,或者在 trait doc 中说明 pick_next_task_matching 可能改变队列顺序。

参考 CFS 实现(BTreeMap::remove 不改变排序),FifoScheduler/RRScheduler 也可以用类似思路:遍历 VecDeque 找到匹配项索引,用 VecDeque::remove(idx) 移除。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[建议] SCHED 语义注意:pick_next_task_matching 不应重排队列顺序。

经验证当前实现正确保持 FIFO 顺序:.rev() 确保 skipped 任务以原始顺序 push_front。但如果后续有人修改此实现(例如移除 .rev()),会静默打乱 FIFO 语义。建议在函数注释中明确说明此约束,或添加排序保持的单元测试。

&mut self,
predicate: impl Fn(&Self::SchedItem) -> bool,
) -> Option<Self::SchedItem> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 [建议] pick_next_task_matching 使用 pop_front + Vec 暂存 + push_front 恢复的模式,会改变非匹配任务的 FIFO 顺序。虽然不影响正确性(被跳过的任务不在当前 CPU 的 cpumask 中),但如果未来需要更严格的 FIFO 语义,可以考虑改为 cursor 遍历 + 原地删除(如 VecDequeretain 或手动索引)。低优先级,不影响合入。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[建议/非阻塞] alloc::vec::Vec 暂存在 no_std 内核中会触发堆分配。虽然 try_steal 非热路径,后续可考虑用 cursor API 原地遍历。当前实现语义正确,不作为合入阻塞条件。

let mut cursor = self.ready_queue.cursor_front_mut();
loop {
let task_ptr = cursor.current_ptr()?;
let matched = unsafe {
Arc::increment_strong_count(task_ptr.as_ptr());
let task = Arc::from_raw(task_ptr.as_ptr());
let matched = predicate(&task);
drop(task);
matched
};
if matched {
return cursor.remove_current();
}
cursor.move_next();
}
}

fn put_prev_task(&mut self, prev: Self::SchedItem, _preempt: bool) {
self.ready_queue.push_back(prev);
}

fn is_empty(&self) -> bool {
self.ready_queue.is_empty()
}

fn task_tick(&mut self, _current: &Self::SchedItem) -> bool {
false // no reschedule
}
Expand Down
18 changes: 18 additions & 0 deletions components/axsched/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@ pub trait BaseScheduler {
/// Returns [`None`] if there is not runnable task.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 [建议] pick_next_task_matching 是新的必须实现方法(无默认实现),对 BaseScheduler 的外部实现者是 breaking change。建议在 doc comment 中注明此为新增必须方法,或提供一个基于 pick_next_task + put_prev_task 的默认实现作为 fallback。

fn pick_next_task(&mut self) -> Option<Self::SchedItem>;

/// Picks the next task matching a predicate, removing it from the
/// scheduler. Returns [`None`] if no matching task exists.
///
/// The predicate check and removal happen atomically within a single
/// lock acquisition — the task is never left in an "out of queue"
/// window observable by other CPUs.
fn pick_next_task_matching(
&mut self,
predicate: impl Fn(&Self::SchedItem) -> bool,
) -> Option<Self::SchedItem>;

/// Puts the previous task back to the scheduler. The previous task is
/// usually placed at the end of the ready queue, making it less likely
/// to be re-scheduled.
Expand All @@ -58,4 +69,11 @@ pub trait BaseScheduler {

/// set priority for a task
fn set_priority(&mut self, task: &Self::SchedItem, prio: isize) -> bool;

/// Returns `true` if the ready queue has no runnable tasks.
///
/// Used as a fast, racy heuristic (without holding the lock) to skip
/// empty queues before attempting work-stealing — mirrors Linux's
/// `src_rq->nr_running > 1` check in `idle_balance()`.
fn is_empty(&self) -> bool;
}
25 changes: 25 additions & 0 deletions components/axsched/src/round_robin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,27 @@ impl<T, const S: usize> BaseScheduler for RRScheduler<T, S> {
self.ready_queue.pop_front()
}

fn pick_next_task_matching(
&mut self,
predicate: impl Fn(&Self::SchedItem) -> bool,
) -> Option<Self::SchedItem> {
let mut cursor = self.ready_queue.cursor_front_mut();
loop {
let task_ptr = cursor.current_ptr()?;
let matched = unsafe {
Arc::increment_strong_count(task_ptr.as_ptr());
let task = Arc::from_raw(task_ptr.as_ptr());
let matched = predicate(&task);
drop(task);
matched
};
if matched {
return cursor.remove_current();
}
cursor.move_next();
}
}

fn put_prev_task(&mut self, prev: Self::SchedItem, preempt: bool) {
if prev.time_slice() > 0 && preempt {
self.ready_queue.push_front(prev)
Expand All @@ -111,6 +132,10 @@ impl<T, const S: usize> BaseScheduler for RRScheduler<T, S> {
}
}

fn is_empty(&self) -> bool {
self.ready_queue.is_empty()
}

fn task_tick(&mut self, current: &Self::SchedItem) -> bool {
let old_slice = current.time_slice.fetch_sub(1, Ordering::Release);
old_slice <= 1
Expand Down
19 changes: 19 additions & 0 deletions components/kspin/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,25 @@ impl<G: BaseGuard, T: ?Sized> BaseSpinLock<G, T> {
// there's no need to lock the inner mutex.
unsafe { &mut *self.data.get() }
}

/// Returns a shared reference to the inner data without acquiring the
/// lock. The data may be concurrently modified — the result is stale
/// the instant this returns. Only use for racy heuristics analoguous
/// to Linux's `src_rq->nr_running > 1` check.
///
/// This is a shared (`&`) reference rather than `&mut`, so it does not
/// carry `noalias` — the compiler will not assume exclusivity and will

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[建议 - 非阻塞] data_unchecked() 在无锁状态下读取 scheduler 的 is_empty()。虽然注释中说明了是 racy heuristic 且返回 &T(不携带 noalias),但实际读取 List::is_empty() / VecDeque::is_empty() 在并发修改时是形式上的 data race。

建议在 SAFETY 注释中更明确地说明:

  • List::is_empty() 读取 head 指针是否为 null,对齐指针读写在主流架构上是原子的
  • VecDeque::is_empty() 读取 len 字段
  • 在实际 SMP 硬件上可接受,但严格来说不符合 Rust 内存模型

/// not miscompile concurrent accesses to the same data from other CPUs.
///
/// # Safety
///
/// The caller must ensure that no other thread is concurrently writing
/// to the inner data in a way that would cause a data race for the
/// specific fields being read.
#[inline(always)]
pub unsafe fn data_unchecked(&self) -> &T {
unsafe { &*self.data.get() }
}
}

impl<G: BaseGuard, T: Default> Default for BaseSpinLock<G, T> {
Expand Down
85 changes: 73 additions & 12 deletions os/StarryOS/kernel/src/file/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub mod timerfd;
mod wext;

use alloc::{borrow::Cow, sync::Arc};
use core::{ffi::c_int, time::Duration};
use core::{ffi::c_int, sync::atomic::AtomicI32, time::Duration};

use ax_errno::{AxError, AxResult};
use ax_fs_ng::vfs::{FS_CONTEXT, FileBackend, FileFlags, OpenOptions};
Expand Down Expand Up @@ -262,9 +262,65 @@ pub struct FileDescriptor {
pub cloexec: bool,
}

/// Shared file descriptor table with task-count tracking.
///
/// Mirrors Linux's `files_struct.count`: `task_count` tracks how many live
/// tasks share this table via CLONE_FILES. Unlike `Arc::strong_count`, it is
/// decremented synchronously in `close_all_fds()` (the exiting task's context),
/// so the last exiting task always closes FDs in user-task context — never in
/// the GC task's context.
pub struct FdTable {
inner: RwLock<FlattenObjects<FileDescriptor, AX_FILE_LIMIT>>,
task_count: AtomicI32,
}

impl FdTable {
pub fn read(
&self,
) -> impl core::ops::Deref<Target = FlattenObjects<FileDescriptor, AX_FILE_LIMIT>> + '_ {
self.inner.read()
}

pub fn write(
&self,
) -> impl core::ops::DerefMut<Target = FlattenObjects<FileDescriptor, AX_FILE_LIMIT>> + '_ {
self.inner.write()
}

/// Record a new task sharing this table (clone with CLONE_FILES).
pub fn inc_task_count(&self) {
self.task_count
.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
}

/// Record a task exiting. Returns `true` if this was the last live task.
pub fn dec_task_count(&self) -> bool {
self.task_count
.fetch_sub(1, core::sync::atomic::Ordering::Relaxed)
== 1
}

/// Wrap an existing inner table (used in unshare)
pub fn from_inner(inner: RwLock<FlattenObjects<FileDescriptor, AX_FILE_LIMIT>>) -> Self {
Self {
inner,
task_count: AtomicI32::new(1),
}
}
}

impl Default for FdTable {
fn default() -> Self {
Self {
inner: RwLock::new(FlattenObjects::default()),
task_count: AtomicI32::new(1),
}
}
}

scope_local::scope_local! {
/// The current file descriptor table.
pub static FD_TABLE: Arc<RwLock<FlattenObjects<FileDescriptor, AX_FILE_LIMIT>>> = Arc::default();
pub static FD_TABLE: Arc<FdTable> = Arc::default();
}

/// Get a file-like object by `fd`.
Expand Down Expand Up @@ -336,8 +392,10 @@ fn notify_close_write(fd: &FileDescriptor) {
pub fn release_locks_on_close(fd: FileDescriptor) {
let key = fd.inner.inode_key();
notify_close_write(&fd);
if let Some(k) = key {
let pid = current().as_thread().proc_data.proc.pid();
if let Some(k) = key
&& let Some(thr) = current().try_as_thread()
{
let pid = thr.proc_data.proc.pid();
crate::syscall::release_inode_posix_locks(pid, k);
}
drop(fd);
Expand All @@ -352,20 +410,23 @@ pub fn release_locks_on_close(fd: FileDescriptor) {
/// This must be called when a process exits, so that pipe write ends and other
/// resources are properly released. Without this, parent processes blocking on
/// pipe reads will never receive EOF.
///
/// Uses per-FdTable `task_count` (mirroring Linux's `files_struct.count`) to
/// determine the last live task sharing the table. The count is decremented
/// inside the FD_TABLE write lock, synchronized with the CLONE_FILES path
/// that holds the read lock before incrementing it.
pub fn close_all_fds() {
// Acquire the write lock before checking strong_count. The clone(CLONE_FILES)
// path in syscall/task/clone.rs also acquires FD_TABLE.read() before cloning
// the Arc, creating a shared synchronization boundary. This ensures:
// - If close_all_fds acquires the write lock first, clone blocks on read lock
// until we release, so strong_count cannot change during our check.
// - If clone holds the read lock first, we block on write lock, and by the
// time we proceed strong_count already reflects the clone.
let mut table = FD_TABLE.write();

// CLONE_FILES may share the same fd table across multiple tasks/processes.
// In that case, an exiting sharer must not clear the whole table, or other
// live sharers (including the parent) will lose stdout/stderr unexpectedly.
if Arc::strong_count(&FD_TABLE) > 1 {
//
// dec_task_count() returns true when this is the last live task — the
// check is done under FD_TABLE.write() so it serialises with the
// inc_task_count() in the clone(CLONE_FILES) path (which holds
// FD_TABLE.read()).
if !FD_TABLE.dec_task_count() {
return;
}

Expand Down
8 changes: 6 additions & 2 deletions os/StarryOS/kernel/src/syscall/fs/fd_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use starry_vm::{VmMutPtr, VmPtr};

use crate::{
file::{
Directory, FD_TABLE, File, FileDescriptor, FileLike, NsFd, Pipe, add_file_like,
Directory, FD_TABLE, FdTable, File, FileDescriptor, FileLike, NsFd, Pipe, add_file_like,
close_file_like, get_file_like, memfd::Memfd, with_fs,
},
mm::vm_load_string,
Expand Down Expand Up @@ -374,7 +374,11 @@ pub fn sys_close_range(first: i32, last: i32, flags: u32) -> AxResult<isize> {
if flags.contains(CloseRangeFlags::UNSHARE) {
let curr = current();
let proc_data = &curr.as_thread().proc_data;
let new_files = Arc::new(spin::RwLock::new(FD_TABLE.read().clone()));
let new_inner = spin::RwLock::new(FD_TABLE.read().clone());
let new_files = Arc::new(FdTable::from_inner(new_inner));
// Unshare stops sharing the old fd table; mirror the dec_task_count
// that the CLONE_FILES path pairs with inc_task_count.
FD_TABLE.dec_task_count();
proc_data.with_current_scope_mut(|scope| {
*FD_TABLE.scope_mut(scope).deref_mut() = new_files;
Comment thread
ZR233 marked this conversation as resolved.
});
Expand Down
44 changes: 21 additions & 23 deletions os/StarryOS/kernel/src/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,27 +49,25 @@ pub fn handle_syscall(uctx: &mut UserContext) {
};

trace!("Syscall {sysno:?}");
match ax_task::current()
.as_thread()
.seccomp_state()
.evaluate(uctx)
{
SeccompDecision::Allow => {}
SeccompDecision::Errno(errno) => {
uctx.set_retval(seccomp_errno(errno));
return;
}
SeccompDecision::KillProcess => {
do_exit(Signo::SIGSYS as i32, true);
return;
}
SeccompDecision::KillThread => {
do_exit(Signo::SIGSYS as i32, false);
return;
}
SeccompDecision::UnsupportedAction => {
uctx.set_retval(-LinuxError::ENOSYS.code() as usize);
return;
if let Some(thr) = ax_task::current().try_as_thread() {
match thr.seccomp_state().evaluate(uctx) {
SeccompDecision::Allow => {}
SeccompDecision::Errno(errno) => {
uctx.set_retval(seccomp_errno(errno));
return;
}
SeccompDecision::KillProcess => {
do_exit(Signo::SIGSYS as i32, true);
return;
}
SeccompDecision::KillThread => {
do_exit(Signo::SIGSYS as i32, false);
return;
}
SeccompDecision::UnsupportedAction => {
uctx.set_retval(-LinuxError::ENOSYS.code() as usize);
return;
}
}
}

Expand Down Expand Up @@ -953,8 +951,8 @@ pub fn handle_syscall(uctx: &mut UserContext) {
Sysno::timer_delete => sys_timer_delete(uctx.arg0() as _),

_ => {
let tid = ax_task::current().as_thread().tid();
warn!("Unimplemented syscall: {sysno} (tid={tid})");
let tid = ax_task::current().try_as_thread().map(|t| t.tid());
warn!("Unimplemented syscall: {sysno} (tid={tid:?})");
Err(AxError::Unsupported)
}
};
Expand Down
3 changes: 2 additions & 1 deletion os/StarryOS/kernel/src/syscall/task/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,10 +325,11 @@ impl CloneArgs {
let mut scope = proc_data.scope.write();
if flags.contains(CloneFlags::FILES) {
// Synchronize with close_all_fds: holding a read lock
// ensures close_all_fds either observes our strong_count
// ensures close_all_fds either observes our task_count
// increment or blocks on write lock until we release.
let _guard = FD_TABLE.read();
FD_TABLE.scope_mut(&mut scope).clone_from(&FD_TABLE);
FD_TABLE.inc_task_count();
} else {
FD_TABLE
.scope_mut(&mut scope)
Expand Down
9 changes: 7 additions & 2 deletions os/StarryOS/kernel/src/task/signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -471,11 +471,16 @@ fn do_job_stop(thr: &Thread, signo: Signo) {
}

pub fn block_next_signal() {
current().as_thread().block_next_signal_check();
if let Some(thr) = current().try_as_thread() {
thr.block_next_signal_check();
}
}

pub fn unblock_next_signal() -> bool {
current().as_thread().unblock_next_signal_check()
current()
.try_as_thread()
.map(|thr| thr.unblock_next_signal_check())
.unwrap_or(false)
}

pub fn with_blocked_signals<R>(
Expand Down
Loading
Loading