Skip to content

Fix/smp#83

Open
KyleMao2023 wants to merge 9 commits into
mainfrom
fix/smp
Open

Fix/smp#83
KyleMao2023 wants to merge 9 commits into
mainfrom
fix/smp

Conversation

@KyleMao2023

Copy link
Copy Markdown
Collaborator

No description provided.

**机制**:全局 shootdown 要所有核 ACK 一个 IPI;任何核在 `SpinNoIrqLock` 临界区(关 SIE)里都收不到 IPI。若该核卡在临界区出不来(自旋等一把被 shootdown 等待链持有的锁),就成环 -> 硬楔死(Ctrl+C 也无效)。

| 子类 | 根因 | 修复 | 状态 |
| :--- | :--- | :--- | :--- |
| **heap-grow ABBA** | `grow_virtual` / `reclaim` 持 `KERNEL_HEAP_VIRTUAL_LOCK` 跨 `shootdown_global_quiet` | 预留后放锁、CAS 回退;shootdown 移出锁 | ✅ 根修(消环) |
| **grow 全局 shootdown 风暴** | `map_heap_pages` 对全新映射发无谓的全局 shootdown | 改本核 `sfence.vma` | ✅ 根修(消除主要触发源) |
| **timer 全任务扫描(我引入的回归)** | `warn_lost_runnable_tasks` 同时持 16 把 `processor/rq` 锁,且持 `process_inner` 跨 `task_inner` | 回退 timer 调用 | ✅ 回退消除 |
| **exec 长持锁** | `init_user_stack_from_strings`(拷 args/envs,慢)在 `task_inner` 内 | 移出锁,两头各短暂取锁 | ✅(exec 内仍有 1 处慢串操作待查) |
| **Ctrl+C 调试 dump 长持锁** | `debug_dump_pgrp_tasks` 持 process/task 锁做 `warn!`(格式化+UART),多核同时跑互抢 | 锁内只快照、锁外再 `warn!` | ✅ |

---

| 子类 | 根因 | 修复 | 状态 |
| :--- | :--- | :--- | :--- |
| **丢 IRQ** | `peek_used()` 读 DMA 写的 used ring 只用 `Acquire`(不保证对设备 DMA 可见) -> `handle_irq` 在「ISR 空+used 假空」窗口返回 | 三处 peek 前加 `virtio_dma_rmb()`(`fence iorw, iorw`) | ✅ 根修 + 丢 IRQ 自愈兜底 |

---

| 子类 | 根因 | 修复 | 状态 |
| :--- | :--- | :--- | :--- |
| **`wake_current` 孤儿** | `wake_running_or_queued_task` 把仍 current 的任务置 Runnable 但不入队,靠「所在核会继续跑它」的脆弱假设 | 加 `resched_hart(last_cpu)` + worker 单任务自愈 | ⚠️ 缓解(根因 `trap_from_kernel` 末尾无 `schedule_if_needed` 未补) |
| **快照脏读假阳性** | `block_worker_debug_snapshot` 在取 `task_inner` 锁前用 Relaxed 读 `on_cpu` -> 错位 | 移到锁内读 | ✅ |
| **mutex 级联(下游)** | unlock 只 `wake_one`,被唤醒者成孤儿 -> 链断 | 依赖 C 的自愈 | ⚠️ 软问题(Ctrl+C 可救) |

TODO

- 理论上不应该触发 `self-heal`,其原理有待考究
- `SpinNoIrqLock` 中减少慢操作只是实际操作上减少概率,没有理论上完全消除
Copilot AI review requested due to automatic review settings July 20, 2026 01:28

Copilot AI left a comment

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.

Pull request overview

Note

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

This PR primarily addresses SMP/interrupt-safety issues (notably around TLB shootdowns and long IRQ-disabled lock holds), while also expanding OS/user functionality for sockets, signals, file locking, and diagnostics.

Changes:

  • Reduce system-wedge risks by shortening IRQ-disabled critical sections (exec/heap/scheduler dumps) and adding stall diagnostics/self-heal paths.
  • Add missing/extended syscall support (sockopts, rt_sigpending, MSG_NOSIGNAL, UDP/TCP sendmsg/recvmsg name handling).
  • Implement POSIX record locks (fcntl), plus release-on-close/exec/exit integration; add tty winsize probing and a DNS probe user app.

Reviewed changes

Copilot reviewed 28 out of 28 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
user/src/syscall.rs Adds setsockopt/getsockopt syscall numbers and user wrappers.
user/src/net.rs Introduces socket option constants for timeouts.
user/src/lib.rs Adds safe-ish convenience wrappers for setting sockopts from bytes/timeval.
user/src/bin/dns_probe.rs New DNS UDP probe utility with optional recv timeout.
os/src/timer.rs Adds periodic block-device stall warning call from timer interrupt.
os/src/task/task.rs Adds per-task last scheduler op stamp + new WaitReason::FileLock.
os/src/task/process.rs Releases POSIX locks on cloexec during exec; reduces IRQ-off lock hold during exec stack init.
os/src/task/mod.rs Exports LastSchedOp; releases POSIX locks on process exit; avoids logging under locks in task dump.
os/src/syscall/signal.rs Implements rt_sigpending(2).
os/src/syscall/net.rs Allows MSG_NOSIGNAL; adds UDP/TCP support for sendmsg/recvmsg name handling.
os/src/syscall/mod.rs Wires SYSCALL_RT_SIGPENDING into dispatcher.
os/src/syscall/fs.rs Adds fcntl POSIX record locks and releases locks on close/close_range/dup2.
os/src/sched/runqueue.rs Adds lost-runnable detection/self-heal + logging counters; refactors wake/enqueue paths.
os/src/sched/processor.rs Makes current_ptr() available without feature gating.
os/src/net/udp.rs Adjusts wildcard bind behavior to preserve external reachability.
os/src/mm/tlb_shootdown.rs Adds stall-progress logging in shootdown ack wait loop.
os/src/mm/oom.rs Removes warn_heap_state_lockfree.
os/src/mm/mod.rs Stops re-exporting removed warn_heap_state_lockfree.
os/src/mm/memory_set.rs Improves munmap teardown to avoid per-page VMA lookups; tweaks merge/flush behavior.
os/src/mm/heap_allocator.rs Avoids deadlocks by dropping virtual-heap lock before mapping/unmapping; removes global shootdown for fresh heap mappings.
os/src/fs/tty.rs Adds xterm-style winsize probing + SIGWINCH emission on resize.
os/src/fs/mod.rs Implements POSIX record locks and conflict querying with wait queues.
os/src/drivers/virtio/mod.rs Adds LoongArch DMA fences and a write-barrier helper.
os/src/drivers/block/virtio_blk.rs Adds DMA-read fencing + extensive stall diagnostics counters and helpers.
os/src/drivers/block/mod.rs Adds block-worker debug snapshot + timer-driven stall warnings and self-heal.
Makefile Adds rootfs init stamps, LA arch validation, and reduces rootfs variant resync.
CosmOS-rootfs Updates rootfs submodule pointer.
.vscode/settings.json Adjusts rust-analyzer settings and expands watcher excludes.

Comment thread os/src/fs/tty.rs
Comment on lines +610 to +633
WinSizeReportParser::Esc { mut len, mut buf } => {
if len >= buf.len() {
state.winsize_parser = WinSizeReportParser::idle();
state.winsize_probe_pending = false;
return WinSizeReportResult::Replay { buf, len };
}
buf[len] = raw;
len += 1;
if raw == b'[' {
state.winsize_parser = WinSizeReportParser::Csi {
len,
buf,
field: 0,
value: 0,
kind: 0,
rows: 0,
cols: 0,
};
WinSizeReportResult::Consumed
} else {
state.winsize_parser = WinSizeReportParser::idle();
WinSizeReportResult::Replay { buf, len }
}
}
Comment thread os/src/sched/runqueue.rs
Comment on lines +513 to +523
for (pid, process) in processes {
let process_inner = process.inner_exclusive_access();
let pgid = process_inner.cred.pgid;
let process_zombie = process_inner.is_zombie;
let exec_path = process_inner.exec_path.clone();
for (tid, task) in process_inner.tasks.iter().enumerate() {
let Some(task) = task.as_ref() else {
continue;
};
let task_ptr = Arc::as_ptr(task) as usize;
let task_inner = task.inner_exclusive_access();
Comment thread os/src/sched/runqueue.rs
Comment on lines +546 to +572
warn!(
"[sched-inv][lost-runnable] reason={} count={} task={:#x} pid={} \
tid={} pgid={} exec={} process_zombie={} wait={:?} last_cpu={} \
policy={:?} on_cpu={} on_rq={} has_wq={} task_pending={:#x} \
mask={:#x} resched={:?} currents={:?} rq_snapshot={:?} \
last_sched_op={:?}",
reason,
count,
task_ptr,
pid,
tid,
pgid,
exec_path,
process_zombie,
task_inner.wait_reason,
task_inner.sched.last_cpu,
task_inner.sched.policy,
on_cpu,
task_inner.sched.on_rq,
task_inner.current_wq_handle.is_some(),
task_inner.pending_signals.bits(),
task_inner.signal_mask.bits(),
task_inner.sched.resched_reason,
current_ptrs,
rq_snapshot,
task_inner.last_sched_op,
);
Comment thread os/src/sched/runqueue.rs
Comment on lines +529 to +536
if !matches!(task_inner.task_status, TaskStatus::Runnable)
|| on_cpu
|| task_inner.sched.on_rq
|| current_ptrs.contains(&task_ptr)
|| runnable_ptrs.contains(&task_ptr)
{
continue;
}
Comment thread os/src/sched/runqueue.rs
Comment on lines +1027 to 1033
let mut removed_from = None;
for (hart, rq) in RUN_QUEUES.iter().enumerate() {
if rq.lock().remove_task(&task) {
removed_from = Some(hart);
break;
}
}
Comment thread os/src/fs/mod.rs
Comment on lines 505 to +508
static ref FLOCK_TABLE: SpinNoIrqLock<Vec<FlockRecord>> = SpinNoIrqLock::new(Vec::new());
static ref POSIX_LOCK_TABLE: SpinNoIrqLock<BTreeMap<(u64, u64), Arc<PosixLockState>>> =
SpinNoIrqLock::new(BTreeMap::new());
}
Comment thread os/src/fs/mod.rs
Comment on lines +519 to +530
fn posix_lock_state(fs_id: u64, ino: u64, create: bool) -> Option<Arc<PosixLockState>> {
let mut table = POSIX_LOCK_TABLE.lock();
if let Some(state) = table.get(&(fs_id, ino)) {
return Some(Arc::clone(state));
}
if !create {
return None;
}
let state = Arc::new(PosixLockState::new());
table.insert((fs_id, ino), Arc::clone(&state));
Some(state)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants