Process handle: điều khiển đúng thread và giữ riêng giới hạn await/suspend
Tiên quyết
- Module B4: Interface & TB timing: Đang tải
- Module B5: OOP: Đang tải
- Fork/join: đợi kết quả, thu dọn nhánh và giữ đúng phạm vi hủy: Đang tải
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.
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.
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.
Tự kiểm tra
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
- 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.
- 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.
- 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ở).