Skip to content
This repository was archived by the owner on Aug 11, 2019. It is now read-only.

Commit ac0951c

Browse files
robert-w-griestoor
authored andcommitted
Resolve all known deadlock issues with PIT scheduling (#6)
* Disable interrupts then restore to original state * Prevent exceptions from being interrupted * Wrap allocator to disable interrupts * Remove unnecessary wrapper for printing * Remove unnecessary comment
1 parent 23d6618 commit ac0951c

File tree

10 files changed

+188
-122
lines changed

10 files changed

+188
-122
lines changed

Cargo.toml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,6 @@ linked_list_allocator = { git = "https://github.com/phil-opp/linked-list-allocat
1818
bit_field = "0.7.0"
1919
x86 = "*"
2020

21-
[dependencies.hole_list_allocator]
22-
path = "libs/hole_list_allocator"
23-
2421
[dependencies.lazy_static]
2522
version = "0.2.4"
2623
features = ["spin_no_std"]

libs/hole_list_allocator/Cargo.toml

Lines changed: 0 additions & 8 deletions
This file was deleted.

libs/hole_list_allocator/src/lib.rs

Lines changed: 0 additions & 49 deletions
This file was deleted.

src/device/pic.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const MODE_8086: u8 = 0x01;
1818
pub struct Pic {
1919
offset: u8,
2020
command: Port<u8>,
21-
data: Port<u8>,
21+
pub data: Port<u8>,
2222
}
2323

2424
impl Pic {
@@ -37,7 +37,7 @@ impl Pic {
3737

3838
///A master and slave PIC.
3939
pub struct ChainedPics {
40-
pics: [Pic; 2],
40+
pub pics: [Pic; 2],
4141
}
4242

4343
impl ChainedPics {

src/interrupts/mod.rs

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ pub extern "x86-interrupt" fn timer_handler(_stack_frame: &mut ExceptionStackFra
8787
unsafe { PICS.lock().notify_end_of_interrupt(0x20) };
8888

8989
if PIT_TICKS.fetch_add(1, Ordering::SeqCst) >= 10 {
90+
PIT_TICKS.store(0, Ordering::SeqCst);
91+
9092
unsafe {
9193
disable_interrupts_and_then(|| {
9294
SCHEDULER.resched();
@@ -96,17 +98,20 @@ pub extern "x86-interrupt" fn timer_handler(_stack_frame: &mut ExceptionStackFra
9698
}
9799

98100
pub extern "x86-interrupt" fn keyboard_handler(_stack_frame: &mut ExceptionStackFrame) {
99-
if let Some(c) = read_char() {
100-
print!("{}", c);
101-
}
102-
103-
unsafe { PICS.lock().notify_end_of_interrupt(0x21) };
101+
disable_interrupts_and_then(|| {
102+
if let Some(c) = read_char() {
103+
print!("{}", c);
104+
}
105+
unsafe { PICS.lock().notify_end_of_interrupt(0x21) };
106+
});
104107
}
105108

106109

107110
pub extern "x86-interrupt" fn divide_by_zero_handler(stack_frame: &mut ExceptionStackFrame) {
108-
println!("\nEXCEPTION: DIVIDE BY ZERO\n{:#?}", stack_frame);
109-
loop {}
111+
disable_interrupts_and_then(|| {
112+
println!("\nEXCEPTION: DIVIDE BY ZERO\n{:#?}", stack_frame);
113+
loop {}
114+
});
110115
}
111116

112117
pub extern "x86-interrupt" fn breakpoint_handler(stack_frame: &mut ExceptionStackFrame) {
@@ -118,42 +123,50 @@ pub extern "x86-interrupt" fn breakpoint_handler(stack_frame: &mut ExceptionStac
118123
}
119124

120125
pub extern "x86-interrupt" fn invalid_opcode_handler(stack_frame: &mut ExceptionStackFrame) {
121-
println!(
122-
"\nEXCEPTION: INVALID OPCODE at {:#x}\n{:#?}",
123-
stack_frame.instruction_pointer,
124-
stack_frame
125-
);
126-
loop {}
126+
disable_interrupts_and_then(|| {
127+
println!(
128+
"\nEXCEPTION: INVALID OPCODE at {:#x}\n{:#?}",
129+
stack_frame.instruction_pointer,
130+
stack_frame
131+
);
132+
loop {}
133+
});
127134
}
128135

129136
pub extern "x86-interrupt" fn page_fault_handler(
130137
stack_frame: &mut ExceptionStackFrame,
131138
error_code: PageFaultErrorCode,
132139
) {
133-
use x86_64::registers::control_regs;
134-
println!(
135-
"\nEXCEPTION: PAGE FAULT while accessing {:#x}\nerror code: \
136-
{:?}\n{:#?}",
137-
control_regs::cr2(),
138-
error_code,
139-
stack_frame
140-
);
141-
loop {}
140+
disable_interrupts_and_then(|| {
141+
use x86_64::registers::control_regs;
142+
println!(
143+
"\nEXCEPTION: PAGE FAULT while accessing {:#x}\nerror code: \
144+
{:?}\n{:#?}",
145+
control_regs::cr2(),
146+
error_code,
147+
stack_frame
148+
);
149+
loop {}
150+
});
142151
}
143152

144153
pub extern "x86-interrupt" fn double_fault_handler(
145154
stack_frame: &mut ExceptionStackFrame,
146155
_error_code: u64,
147156
) {
148-
println!("\nEXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame);
149-
loop {}
157+
disable_interrupts_and_then(|| {
158+
println!("\nEXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame);
159+
loop {}
160+
});
150161
}
151162

152163
pub extern "x86-interrupt" fn gpf_handler(
153164
stack_frame: &mut ExceptionStackFrame,
154165
_error_code: u64,
155166
)
156167
{
157-
println!("\nEXCEPTION: GPF\n{:#?}", stack_frame);
158-
loop {}
168+
disable_interrupts_and_then(|| {
169+
println!("\nEXCEPTION: GPF\n{:#?}", stack_frame);
170+
loop {}
171+
});
159172
}

src/lib.rs

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#![feature(const_unique_new)]
99
#![feature(const_max_value)]
1010
#![feature(core_intrinsics)]
11+
#![feature(global_allocator)]
1112
#![no_std]
1213

1314
extern crate rlibc;
@@ -22,9 +23,9 @@ extern crate once;
2223
extern crate bit_field;
2324
#[macro_use]
2425
extern crate lazy_static;
25-
extern crate hole_list_allocator as allocator;
2626
#[macro_use]
2727
extern crate alloc;
28+
extern crate linked_list_allocator;
2829

2930
#[macro_use]
3031
mod macros;
@@ -42,21 +43,22 @@ pub use runtime_glue::*;
4243

4344
#[no_mangle]
4445
pub extern "C" fn kmain(multiboot_information_address: usize) {
45-
device::vga::buffer::clear_screen();
46-
println!("[ INFO ] lambdaOS: Begin init.");
47-
48-
//Load a multiboot BootInfo structure using the address passed in ebx.
49-
let boot_info = unsafe { multiboot2::load(multiboot_information_address) };
50-
51-
//Safety stuff.
52-
enable_nxe_bit();
53-
enable_write_protect_bit();
46+
// Ensure all interrupt masks are set to prevent issues during setup
47+
disable_interrupts();
48+
{
49+
device::vga::buffer::clear_screen();
50+
println!("[ INFO ] lambdaOS: Begin init.");
51+
52+
//Load a multiboot BootInfo structure using the address passed in ebx.
53+
let boot_info = unsafe { multiboot2::load(multiboot_information_address) };
54+
55+
//Safety stuff.
56+
enable_nxe_bit();
57+
enable_write_protect_bit();
5458

55-
// set up guard page and map the heap pages
56-
let mut memory_controller = memory::init(boot_info);
59+
// set up guard page and map the heap pages
60+
let mut memory_controller = memory::init(boot_info);
5761

58-
// Interrupts.
59-
disable_interrupts_and_then(|| {
6062
unsafe {
6163
// Load IDT.
6264
interrupts::init(&mut memory_controller);
@@ -65,17 +67,18 @@ pub extern "C" fn kmain(multiboot_information_address: usize) {
6567
// Initalise all other hardware devices.
6668
device::init();
6769
}
68-
});
69-
70-
/*let proc_closure = || {
70+
}
71+
enable_interrupts();
72+
73+
let proc_closure = || {
7174
let max_procs = 50;
7275

7376
for i in 0..max_procs {
7477
syscall::create(process_test, format!("test_process_{}", i));
7578
}
7679
};
7780

78-
disable_interrupts_and_then(proc_closure);*/
81+
proc_closure();
7982

8083
use alloc::String;
8184

@@ -92,3 +95,9 @@ pub extern "C" fn real_main() {
9295
pub extern "C" fn process_test() {
9396
println!("Inside test process.");
9497
}
98+
99+
use memory::heap_allocator::HeapAllocator;
100+
101+
//Attribute tells Rust to use this as the default heap allocator.
102+
#[global_allocator]
103+
static GLOBAL_ALLOC: HeapAllocator = HeapAllocator::new();

src/macros.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
macro_rules! print {
2-
($($arg:tt)*) => ({
3-
$crate::device::vga::buffer::print(format_args!($($arg)*));
4-
});
2+
($($arg:tt)*) => ({
3+
$crate::device::vga::buffer::print(format_args!($($arg)*));
4+
});
55
}
66

77
macro_rules! println {

src/memory/heap_allocator.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use alloc::allocator::{Alloc, AllocErr, Layout};
2+
use linked_list_allocator::LockedHeap;
3+
use utils::disable_interrupts_and_then;
4+
5+
pub const HEAP_START: usize = 0o_000_001_000_000_0000;
6+
pub const HEAP_SIZE: usize = 500 * 1024;
7+
8+
pub struct HeapAllocator {
9+
inner: LockedHeap,
10+
}
11+
12+
impl HeapAllocator {
13+
/// Creates an empty heap. All allocate calls will return `None`.
14+
pub const fn new() -> Self {
15+
HeapAllocator {
16+
inner: LockedHeap::empty(),
17+
}
18+
}
19+
20+
/// Initializes an empty heap
21+
///
22+
/// # Unsafety
23+
///
24+
/// This function must be called at most once and must only be used on an
25+
/// empty heap. Also, it is assumed that interrupts are disabled.
26+
pub unsafe fn init(&self, heap_bottom: usize, heap_size: usize) {
27+
self.inner.lock().init(heap_bottom, heap_size);
28+
}
29+
}
30+
31+
/// Wrappers for inner Alloc implementation
32+
unsafe impl<'a> Alloc for &'a HeapAllocator {
33+
unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
34+
disable_interrupts_and_then(|| -> Result<*mut u8, AllocErr> {
35+
self.inner.lock().alloc(layout)
36+
})
37+
}
38+
39+
unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
40+
disable_interrupts_and_then(|| {
41+
self.inner.lock().dealloc(ptr, layout);
42+
});
43+
}
44+
45+
fn oom(&mut self, _: AllocErr) -> ! {
46+
panic!("Out of memory");
47+
}
48+
}

src/memory/mod.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,12 @@ pub use self::paging::remap_the_kernel;
33
pub use self::stack_allocator::Stack;
44
use self::paging::PhysicalAddress;
55
use multiboot2::BootInformation;
6-
use allocator;
76

87
mod area_frame_allocator;
8+
pub mod heap_allocator;
99
pub mod paging;
1010
mod stack_allocator;
1111

12-
pub const HEAP_START: usize = 0o_000_001_000_000_0000;
13-
pub const HEAP_SIZE: usize = 500 * 1024;
14-
1512
pub const PAGE_SIZE: usize = 4096;
1613

1714
pub fn init(boot_info: &BootInformation) -> MemoryController {
@@ -57,6 +54,7 @@ pub fn init(boot_info: &BootInformation) -> MemoryController {
5754
let mut active_table = paging::remap_the_kernel(&mut frame_allocator, boot_info);
5855

5956
use self::paging::Page;
57+
use self::heap_allocator::{HEAP_SIZE, HEAP_START};
6058

6159
let heap_start_page = Page::containing_address(HEAP_START);
6260
let heap_end_page = Page::containing_address(HEAP_START + HEAP_SIZE - 1);
@@ -67,7 +65,7 @@ pub fn init(boot_info: &BootInformation) -> MemoryController {
6765

6866
//Init the heap
6967
unsafe {
70-
allocator::init(HEAP_START, HEAP_SIZE);
68+
::GLOBAL_ALLOC.init(HEAP_START, HEAP_SIZE);
7169
}
7270

7371
let stack_allocator = {

0 commit comments

Comments
 (0)