diff --git a/blog/content/second-edition/posts/05-cpu-exceptions/index.md b/blog/content/second-edition/posts/05-cpu-exceptions/index.md index 37806581..7a327c67 100644 --- a/blog/content/second-edition/posts/05-cpu-exceptions/index.md +++ b/blog/content/second-edition/posts/05-cpu-exceptions/index.md @@ -406,7 +406,7 @@ pub extern "C" fn _start() -> ! { } ``` -When we run it in QEMU now (using `cargo xrun`), we see the following: +When we run it in QEMU now (using `cargo run`), we see the following: ![QEMU printing `EXCEPTION: BREAKPOINT` and the interrupt stack frame](qemu-breakpoint-exception.png) @@ -421,7 +421,7 @@ Let's create a test that ensures that the above continues to work. First, we upd ```rust // in src/lib.rs -/// Entry point for `cargo xtest` +/// Entry point for `cargo test` #[cfg(test)] #[no_mangle] pub extern "C" fn _start() -> ! { @@ -431,7 +431,7 @@ pub extern "C" fn _start() -> ! { } ``` -Remember, this `_start` function is used when running `cargo xtest --lib`, since Rust's tests the `lib.rs` completely independent of the `main.rs`. We need to call `init` here to set up an IDT before running the tests. +Remember, this `_start` function is used when running `cargo test --lib`, since Rust's tests the `lib.rs` completely independent of the `main.rs`. We need to call `init` here to set up an IDT before running the tests. Now we can create a `test_breakpoint_exception` test: @@ -447,7 +447,7 @@ fn test_breakpoint_exception() { The test invokes the `int3` function to trigger a breakpoint exception. By checking that the execution continues afterwards, we verify that our breakpoint handler is working correctly. -You can try this new test by running `cargo xtest` (all tests) or `cargo xtest --lib` (only tests of `lib.rs` and its modules). You should see the following in the output: +You can try this new test by running `cargo test` (all tests) or `cargo test --lib` (only tests of `lib.rs` and its modules). You should see the following in the output: ``` blog_os::interrupts::test_breakpoint_exception... [ok] diff --git a/blog/content/second-edition/posts/06-double-faults/index.md b/blog/content/second-edition/posts/06-double-faults/index.md index 5262157a..c8580f53 100644 --- a/blog/content/second-edition/posts/06-double-faults/index.md +++ b/blog/content/second-edition/posts/06-double-faults/index.md @@ -444,7 +444,7 @@ harness = false [without a test harness]: @/second-edition/posts/04-testing/index.md#no-harness-tests -Now `cargo xtest --test stack_overflow` should compile successfully. The test fails of course, since the `unimplemented` macro panics. +Now `cargo test --test stack_overflow` should compile successfully. The test fails of course, since the `unimplemented` macro panics. ### Implementing `_start` @@ -537,7 +537,7 @@ extern "x86-interrupt" fn test_double_fault_handler( When the double fault handler is called, we exit QEMU with a success exit code, which marks the test as passed. Since integration tests are completely separate executables, we need to set `#![feature(abi_x86_interrupt)]` attribute again at the top of our test file. -Now we can run our test through `cargo xtest --test stack_overflow` (or `cargo xtest` to run all tests). As expected, we see the `stack_overflow... [ok]` output in the console. Try to comment out the `set_stack_index` line: it should cause the test to fail. +Now we can run our test through `cargo test --test stack_overflow` (or `cargo test` to run all tests). As expected, we see the `stack_overflow... [ok]` output in the console. Try to comment out the `set_stack_index` line: it should cause the test to fail. ## Summary In this post we learned what a double fault is and under which conditions it occurs. We added a basic double fault handler that prints an error message and added an integration test for it. diff --git a/blog/content/second-edition/posts/07-hardware-interrupts/index.md b/blog/content/second-edition/posts/07-hardware-interrupts/index.md index 824a7eb4..8c98e75a 100644 --- a/blog/content/second-edition/posts/07-hardware-interrupts/index.md +++ b/blog/content/second-edition/posts/07-hardware-interrupts/index.md @@ -127,7 +127,7 @@ We use the [`initialize`] function to perform the PIC initialization. Like the ` [`initialize`]: https://docs.rs/pic8259_simple/0.2.0/pic8259_simple/struct.ChainedPics.html#method.initialize -If all goes well we should continue to see the "It did not crash" message when executing `cargo xrun`. +If all goes well we should continue to see the "It did not crash" message when executing `cargo run`. ## Enabling Interrupts @@ -144,7 +144,7 @@ pub fn init() { } ``` -The `interrupts::enable` function of the `x86_64` crate executes the special `sti` instruction (“set interrupts”) to enable external interrupts. When we try `cargo xrun` now, we see that a double fault occurs: +The `interrupts::enable` function of the `x86_64` crate executes the special `sti` instruction (“set interrupts”) to enable external interrupts. When we try `cargo run` now, we see that a double fault occurs: ![QEMU printing `EXCEPTION: DOUBLE FAULT` because of hardware timer](qemu-hardware-timer-double-fault.png) @@ -240,7 +240,7 @@ The `notify_end_of_interrupt` figures out whether the primary or secondary PIC s We need to be careful to use the correct interrupt vector number, otherwise we could accidentally delete an important unsent interrupt or cause our system to hang. This is the reason that the function is unsafe. -When we now execute `cargo xrun` we see dots periodically appearing on the screen: +When we now execute `cargo run` we see dots periodically appearing on the screen: ![QEMU printing consecutive dots showing the hardware timer](qemu-hardware-timer-dots.gif) @@ -359,10 +359,10 @@ Note that disabling interrupts shouldn't be a general solution. The problem is t ## Fixing a Race Condition -If you run `cargo xtest` you might see the `test_println_output` test failing: +If you run `cargo test` you might see the `test_println_output` test failing: ``` -> cargo xtest --lib +> cargo test --lib […] Running 4 tests test_breakpoint_exception...[ok] @@ -425,7 +425,7 @@ We performed the following changes: [`writeln`]: https://doc.rust-lang.org/core/macro.writeln.html -With the above changes, `cargo xtest` now deterministically succeeds again. +With the above changes, `cargo test` now deterministically succeeds again. This was a very harmless race condition that only caused a test failure. As you can imagine, other race conditions can be much more difficult to debug due to their non-deterministic nature. Luckily, Rust prevents us from data races, which are the most serious class of race conditions since they can cause all kinds of undefined behavior, including system crashes and silent memory corruptions. @@ -479,7 +479,7 @@ Let's update our `lib.rs` as well: ```rust // in src/lib.rs -/// Entry point for `cargo xtest` +/// Entry point for `cargo test` #[cfg(test)] #[no_mangle] pub extern "C" fn _start() -> ! { diff --git a/blog/content/second-edition/posts/09-paging-implementation/index.md b/blog/content/second-edition/posts/09-paging-implementation/index.md index 67fe6742..8113da67 100644 --- a/blog/content/second-edition/posts/09-paging-implementation/index.md +++ b/blog/content/second-edition/posts/09-paging-implementation/index.md @@ -340,7 +340,7 @@ use bootloader::{entry_point, BootInfo}; #[cfg(test)] entry_point!(test_kernel_main); -/// Entry point for `cargo xtest` +/// Entry point for `cargo test` #[cfg(test)] fn test_kernel_main(_boot_info: &'static BootInfo) -> ! { // like before diff --git a/blog/content/second-edition/posts/10-heap-allocation/index.md b/blog/content/second-edition/posts/10-heap-allocation/index.md index a2b7518c..f86eb7ec 100644 --- a/blog/content/second-edition/posts/10-heap-allocation/index.md +++ b/blog/content/second-edition/posts/10-heap-allocation/index.md @@ -762,7 +762,7 @@ This test ensures that the allocator reuses freed memory for subsequent allocati Let's run our new integration test: ``` -> cargo xtest --test heap_allocation +> cargo test --test heap_allocation […] Running 3 tests simple_allocation... [ok] @@ -770,7 +770,7 @@ large_vec... [ok] many_boxes... [ok] ``` -All three tests succeeded! You can also invoke `cargo xtest` (without `--test` argument) to run all unit and integration tests. +All three tests succeeded! You can also invoke `cargo test` (without `--test` argument) to run all unit and integration tests. ## Summary diff --git a/blog/content/second-edition/posts/11-allocator-designs/index.md b/blog/content/second-edition/posts/11-allocator-designs/index.md index c8a501ba..b47f4a3e 100644 --- a/blog/content/second-edition/posts/11-allocator-designs/index.md +++ b/blog/content/second-edition/posts/11-allocator-designs/index.md @@ -373,7 +373,7 @@ Now our kernel uses our bump allocator! Everything should still work, including [`heap_allocation` tests]: @/second-edition/posts/10-heap-allocation/index.md#adding-a-test ``` -> cargo xtest --test heap_allocation +> cargo test --test heap_allocation […] Running 3 tests simple_allocation... [ok] @@ -416,7 +416,7 @@ Like the `many_boxes` test, this test creates a large number of allocations to p When we try run our new test, we see that it indeed fails: ``` -> cargo xtest --test heap_allocation +> cargo test --test heap_allocation Running 4 tests simple_allocation... [ok] large_vec... [ok] @@ -791,7 +791,7 @@ Since the `init` function behaves the same for the bump and linked list allocato When we now run our `heap_allocation` tests again, we see that all tests pass now, including the `many_boxes_long_lived` test that failed with the bump allocator: ``` -> cargo xtest --test heap_allocation +> cargo test --test heap_allocation simple_allocation... [ok] large_vec... [ok] many_boxes... [ok] @@ -1158,7 +1158,7 @@ Since the `init` function behaves the same for all allocators we implemented, we When we now run our `heap_allocation` tests again, all tests should still pass: ``` -> cargo xtest --test heap_allocation +> cargo test --test heap_allocation simple_allocation... [ok] large_vec... [ok] many_boxes... [ok] diff --git a/blog/content/second-edition/posts/12-async-await/index.md b/blog/content/second-edition/posts/12-async-await/index.md index e65326f3..0bad1bea 100644 --- a/blog/content/second-edition/posts/12-async-await/index.md +++ b/blog/content/second-edition/posts/12-async-await/index.md @@ -1153,7 +1153,7 @@ extern "x86-interrupt" fn keyboard_interrupt_handler( We removed all the keyboard handling code from this function and instead added a call to the `add_scancode` function. The rest of the function stays the same as before. -As expected, keypresses are no longer printed to the screen when we run our project using `cargo xrun` now. Instead, we see the warning that the scancode queue is uninitialized for every keystroke. +As expected, keypresses are no longer printed to the screen when we run our project using `cargo run` now. Instead, we see the warning that the scancode queue is uninitialized for every keystroke. #### Scancode Stream @@ -1393,7 +1393,7 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { } ``` -When we execute `cargo xrun` now, we see that keyboard input works again: +When we execute `cargo run` now, we see that keyboard input works again: ![QEMU printing ".....H...e...l...l..o..... ...W..o..r....l...d...!"](qemu-keyboard-output.gif) @@ -1709,7 +1709,7 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { We only need to change the import and the type name. Since our `run` function is marked as diverging, the compiler knows that it never returns so that we no longer need a call to `hlt_loop` at the end of our `kernel_main` function. -When we run our kernel using `cargo xrun` now, we see that keyboard input still works: +When we run our kernel using `cargo run` now, we see that keyboard input still works: ![QEMU printing ".....H...e...l...l..o..... ...a..g..a....i...n...!"](qemu-keyboard-output-again.gif) @@ -1783,7 +1783,7 @@ impl Executor { To avoid race conditions, we disable interrupts before checking whether the `task_queue` is empty. If it is, we use the [`enable_interrupts_and_hlt`] function to enable interrupts and put the CPU to sleep as a single atomic operation. In case the queue is no longer empty, it means that an interrupt woke a task after `run_ready_tasks` returned. In that case, we enable interrupts again and directly continue execution without executing `hlt`. -Now our executor properly puts the CPU to sleep when there is nothing to do. We can see that the QEMU process has a much lower CPU utilization when we run our kernel using `cargo xrun` again. +Now our executor properly puts the CPU to sleep when there is nothing to do. We can see that the QEMU process has a much lower CPU utilization when we run our kernel using `cargo run` again. #### Possible Extensions