Process handle: điều khiển đúng thread và giữ riêng giới hạn await/suspend

Khoảng 45 phútMức 3/3Bản nháp: một số khẳng định chưa đối chiếu spec

Sau bài này bạn sẽ

  • Lấy self bên trong đúng child và đọc trạng thái tại điểm có hợp đồng
  • Kiểm kill bằng cả status lẫn việc side effect dừng
  • Tách main self/status/kill khỏi probes await/suspend đang lỗi

Bạn cần hủy thread nào, không chỉ block nào?

Một worker chạy hữu hạn trả result 7; một background worker tăng ticks mãi; sentinel cần sống tới 6 ns. Test muốn dừng background ở 2 ns nhưng vẫn lấy được result và không giết sentinel. Disable fork ở parent của cả ba có thể hủy rộng hơn ý định đó.

Process handle cho phép nhắm tới một thread đã lấy được handle. Nó không thay ownership: nếu capture nhầm self của parent hoặc ghi đè handle của worker, lời gọi kill hợp lệ về cú pháp vẫn có thể hủy nhầm việc.

Self phải được gọi bên trong thread cần quản lý

Mỗi child trong main tự gọi process::self() rồi lưu handle của mình. Parent đợi cả worker/cancelled khác null trước khi sử dụng; khai báo một biến process chưa có nghĩa child đã khởi chạy hay đã gửi handle ra ngoài.

Process handle tham chiếu một luồng thực thi, khác với class object chứa dữ liệu transaction. Code không tự tạo một thread bằng cách khai báo handle, cũng không dùng new của một class tùy ý để thay việc spawn fork. Bài fork vẫn chịu trách nhiệm tạo các child.

[1]

Status là ảnh chụp tại thời điểm đọc

Các tên trạng thái gồm RUNNING, WAITING, SUSPENDED, FINISHED và KILLED. Chúng mô tả state process khi gọi status; không phải một lịch sử tự ghi mọi chuyển trạng thái. Kiểm status đúng lúc cần có quan hệ thời gian rõ trong testbench.

Không khẳng định một thread chắc chắn RUNNING chỉ vì nó cũng có statement đến hạn ở timestamp 10 ns: process khác đang đọc status có thể được chạy trước hoặc sau statement đó. Main chọn điểm 4 ns để kiểm worker đã hoàn tất công việc ở 3 ns, tránh suy ra thứ tự từ hai process cùng có event ở một cạnh.

Kill cần được kiểm bằng hành vi sau thời điểm hủy

Background tăng ticks mỗi 1 ns. Parent gọi cancelled.kill ở 2 ns, kiểm statusKILLED và lưu ticks hiện tại. Ở 6 ns, ticks phải còn đúng giá trị đã lưu. Như vậy một status được gán mà side effect vẫn tiếp tục sẽ không vượt qua oracle.

Tại 2 ns, tick thứ hai và kill có thể có hai thứ tự hợp lệ. Main chấp nhận at_kill1 hoặc 2, vì tick đầu ở 1 ns chắc chắn đã xảy ra; sau đó bắt buộc không có tick nào thêm. Đây là contract của race boundary, không phải nới tùy ý mọi giá trị hoặc bỏ phép kiểm tiếp diễn.

Worker hữu hạn và sentinel có bằng chứng độc lập

Worker gán result 7 ở 3 ns. Sau kill ở 2 ns, parent chờ thêm 2 ns rồi kiểm workerFINISHED/result 7 ở 4 ns. Nó tiếp tục đợi sentinel, phải bằng 1 ở 6 ns, đồng thời kiểm ticks bị giữ. Main không gọi await để lấy kết quả ấy.

Khoảng đợi explicit này chỉ kiểm scenario có độ trễ đã biết. Nó không phải thay thế tổng quát cho synchronization của một worker tùy thời lượng, cũng không chứng minh await đang được hỗ trợ. Khi mở rộng testbench, cần một completion contract có thể quan sát được như event/message/flag theo đúng môi trường.

Await tối giản bị watchdog trên tool hiện tại

Probe riêng chỉ spawn một child, child lưu self và kết thúc sau 3 ns. Parent gọi worker.await với kỳ vọng trở lại 3 ns rồi kiểm done/FINISHED. Trên Verilator 5.050, probe parse được nhưng không qua await trước watchdog 10 ns.

Case tối giản giữ assertion và timeout để phân biệt với main có kill/sentinel. Không đổi quy tắc bài thành “await luôn chờ vô hạn” hoặc thêm delay vào probe rồi gọi đó là proof await. Đây là failure của case/tool đang dùng; đổi simulator cần chạy lại trước khi nâng claim.

Suspend/resume không được main PASS chứng minh

Một probe khác gọi suspend trên child đang chạy rồi định kiểm giữ/resume. Tool dừng bằng thông báo thật std::process::suspend() not supported. Main không gọi suspend/resume nên nhãn simulated chỉ áp dụng self/status/kill của source chính.

Không xem suspend như kill rồi new lại task, hoặc suy các delay bên trong bị đóng băng theo một kiểu chưa đối chiếu LRM. Khi một capability chưa chạy được, vẫn có thể học mục đích và đọc signature, nhưng phải giữ ranh giới giữa mô tả chuẩn cần kiểm và ngữ nghĩa đã được oracle quan sát.

Result 7, background dừng và sentinel sống tới 6 ns

Expected trước chạy: PROCESS CHECK result=7 finished=1 killed=1 held_after_kill=1 sentinel=1 time_ns=6. Main parsed/simulated trên Verilator; await/suspend là hai capability failures riêng, không được tính là hai main success.

Process handle: điều khiển đúng thread và giữ riêng giới hạn await/suspend

Expected tính trước chạy: PROCESS CHECK result=7 finished=1 killed=1 held_after_kill=1 sentinel=1 time_ns=6

tb.sv testbench
`timescale 1ns/1ps// Kill may order before/after the tick at2ns, so record1..2 and require no later tick. Sentinel survives to6.module tb_process; process worker,cancelled; int result=0,ticks=0,at_kill=-1,sentinel=0; initial begin  fork   begin worker=process::self();#3;result=7;end   begin cancelled=process::self();forever begin #1;ticks++;end end   begin #6;sentinel=1;end  join_none  wait(worker!=null&&cancelled!=null);  #2;cancelled.kill();at_kill=ticks;  if(cancelled.status()!=process::KILLED||at_kill<1||at_kill>2)$fatal(1,"process kill status oracle");  #2;  if(worker.status()!=process::FINISHED||result!=7||$time!=4)$fatal(1,"process finished-state oracle");  wait(sentinel==1);  if(ticks!=at_kill||sentinel!=1||$time!=6)$fatal(1,"process kill isolation oracle");  $display("PROCESS CHECK result=7 finished=1 killed=1 held_after_kill=1 sentinel=1 time_ns=6");$finish; end initial begin #20;$fatal(1,"process watchdog");endendmodule

Đã kiểm chứng thế nào

  • Phân tích và elaborate theo LRM (pyslang 12.1.0)
  • Mô phỏng, exit 0 và output khớp kỳ vọng tính tay (Verilator 5.050, 2-state)

Output phải khớp: PROCESS CHECK result=7 finished=1 killed=1 held_after_kill=1 sentinel=1 time_ns=6

Main chỉ self/status/kill; completion quan sát 4/6 ns. Await tối giản watchdog 10 ns và suspend unsupported là failures riêng.

Kill ở 2 ns có thể trước/sau tick cùngtimestamp: at_kill1..2, bắt buộc không thêm tick sau kill.

Các kiểm tra chạy lúc xây dựng nội dung (2026-11-06), không chạy trong trình duyệt. Kỳ vọng được tính tay trước khi chạy.

Hai fault trong bản sao giữ oracle: bỏ kill và đổi result thành 8. Chúng bị bắt ở status/finished-state checks. Main không claim hủy cây descendants nhiều tầng, mọi scheduling order hoặc tự hoàn trả resource.

[2]

Tự kiểm tra

Tự kiểm tra: process

  1. Main process đã chứng minh phạm vi nào?
  2. Worker hữu hạn của main tạo result nào?
  3. Vì sao at_kill được chấp nhận 1 hoặc 2 nhưng ticks cuối phải bằng at_kill?
  4. Muốn lấy handle của background child, gọi self ở đâu?
  5. Await probe tối giản không về trước watchdog cần ghi thế nào?

Capture đúng identity, kiểm cả lifecycle lẫn side effect

Review process handle từ nơi gọi self tới nơi dùng kill/status. Chờ handle hợp lệ, ghi rõ event boundary nào có nhiều thứ tự hợp lệ và kiểm trạng thái sau hủy bằng dữ liệu độc lập. Giữ capability probes nhỏ để không dùng một ví dụ PASS phạm vi hẹp làm bảo đảm cho toàn bộ process API.

Nguồn và mức độ đối chiếu

  1. SystemVerilog Process Class — bản chụp resources.zip, What Is the process Class?; Process States; Basic Syntax; A Complete Example. Trích dẫn; nguồn đã đọc các mục liên quan.
  2. Thí nghiệm nguyên bản ex.b7.process, Source, self-checks, verification.json và concurrency probes. Trích dẫn; nguồn đã đọc toàn văn.
  3. IEEE 1800-2023 SystemVerilog LRM, Processes, synchronization and IPC methods — chưa đối chiếu LRM. Chưa đối chiếu với văn bản nguồn (chưa mở).