-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[#closes 243] Procdump debug & Refactor console struct. #286
Changes from 11 commits
4dcb43f
91a7381
779ac15
9108c3a
239f597
480b020
f0ac9d7
53930a9
38f7f15
fa1dd1c
8d9363e
c02ce31
69fa134
72f2a0d
38b6dde
46cacaa
991ac04
a98abe9
5009196
92d1db3
e4dfdd5
0361330
b2c26c4
2451fed
427eed5
5b40d8f
1d3eb69
29a18d9
be7288a
5dee6fa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -3,48 +3,29 @@ use crate::{ | |||||||||
kernel::kernel, | ||||||||||
param::NDEV, | ||||||||||
proc::myproc, | ||||||||||
sleepablelock::SleepablelockGuard, | ||||||||||
sleepablelock::Sleepablelock, | ||||||||||
spinlock::Spinlock, | ||||||||||
uart::Uart, | ||||||||||
utils::spin_loop, | ||||||||||
vm::{UVAddr, VAddr}, | ||||||||||
}; | ||||||||||
use core::fmt; | ||||||||||
use core::fmt::{self, Write}; | ||||||||||
|
||||||||||
const CONSOLE_IN_DEVSW: usize = 1; | ||||||||||
/// Size of console input buffer. | ||||||||||
const INPUT_BUF: usize = 128; | ||||||||||
|
||||||||||
pub struct Console { | ||||||||||
buf: [u8; INPUT_BUF], | ||||||||||
|
||||||||||
/// Read index. | ||||||||||
r: u32, | ||||||||||
|
||||||||||
/// Write index. | ||||||||||
w: u32, | ||||||||||
|
||||||||||
/// Edit index. | ||||||||||
e: u32, | ||||||||||
|
||||||||||
terminal: Sleepablelock<Terminal>, | ||||||||||
pub printer: Spinlock<Printer>, | ||||||||||
uart: Uart, | ||||||||||
} | ||||||||||
|
||||||||||
impl fmt::Write for Console { | ||||||||||
fn write_str(&mut self, s: &str) -> fmt::Result { | ||||||||||
for c in s.bytes() { | ||||||||||
self.putc(c as _); | ||||||||||
} | ||||||||||
Ok(()) | ||||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
impl Console { | ||||||||||
pub const fn new() -> Self { | ||||||||||
Self { | ||||||||||
buf: [0; INPUT_BUF], | ||||||||||
r: 0, | ||||||||||
w: 0, | ||||||||||
e: 0, | ||||||||||
terminal: Sleepablelock::new("Terminal", Terminal::new()), | ||||||||||
printer: Spinlock::new("Println", Printer::new()), | ||||||||||
uart: Uart::new(), | ||||||||||
} | ||||||||||
} | ||||||||||
|
@@ -54,22 +35,23 @@ impl Console { | |||||||||
} | ||||||||||
|
||||||||||
/// Send one character to the uart. | ||||||||||
pub fn putc(&mut self, c: i32) { | ||||||||||
pub fn putc(&self, c: i32) { | ||||||||||
// From printf.rs. | ||||||||||
if kernel().is_panicked() { | ||||||||||
spin_loop(); | ||||||||||
} | ||||||||||
if c == BACKSPACE { | ||||||||||
// If the user typed backspace, overwrite with a space. | ||||||||||
Uart::putc_sync('\u{8}' as i32); | ||||||||||
Uart::putc_sync(' ' as i32); | ||||||||||
Uart::putc_sync('\u{8}' as i32); | ||||||||||
self.uart.putc_sync('\u{8}' as i32); | ||||||||||
self.uart.putc_sync(' ' as i32); | ||||||||||
self.uart.putc_sync('\u{8}' as i32); | ||||||||||
} else { | ||||||||||
Uart::putc_sync(c); | ||||||||||
self.uart.putc_sync(c); | ||||||||||
}; | ||||||||||
} | ||||||||||
|
||||||||||
unsafe fn write(&mut self, src: UVAddr, n: i32) -> i32 { | ||||||||||
unsafe fn write(&self, src: UVAddr, n: i32) -> i32 { | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @anemoneflower 소유권 표현 상으로는 kernel()을 부르더라도 Terminal으로 이동하는 것이 좋다는 말씀이시죠? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 소유권만 보면 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저는 ownership을 중점적으로 생각해 Lines 201 to 204 in 53d87f7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jeehoonkang 교수님, 현재 논점이 global function There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 같은 질문을 드리고자 하는데 왜 &self로 해도 안전한가요? 여러 쓰레드가 동시 접근해도 문제가 안생기나요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||
self.terminal.lock(); | ||||||||||
for i in 0..n { | ||||||||||
let mut c = [0 as u8]; | ||||||||||
if VAddr::copyin(&mut c, UVAddr::new(src.into_usize() + (i as usize))).is_err() { | ||||||||||
|
@@ -80,27 +62,28 @@ impl Console { | |||||||||
n | ||||||||||
} | ||||||||||
|
||||||||||
unsafe fn read(this: &mut SleepablelockGuard<'_, Self>, mut dst: UVAddr, mut n: i32) -> i32 { | ||||||||||
unsafe fn read(&self, mut dst: UVAddr, mut n: i32) -> i32 { | ||||||||||
let mut terminal = self.terminal.lock(); | ||||||||||
let target = n as u32; | ||||||||||
while n > 0 { | ||||||||||
// Wait until interrupt handler has put some | ||||||||||
// input into CONS.buffer. | ||||||||||
while this.r == this.w { | ||||||||||
while terminal.r == terminal.w { | ||||||||||
if (*myproc()).killed() { | ||||||||||
return -1; | ||||||||||
} | ||||||||||
this.sleep(); | ||||||||||
terminal.sleep(); | ||||||||||
} | ||||||||||
let fresh0 = this.r; | ||||||||||
this.r = this.r.wrapping_add(1); | ||||||||||
let cin = this.buf[fresh0.wrapping_rem(INPUT_BUF as u32) as usize] as i32; | ||||||||||
let fresh0 = terminal.r; | ||||||||||
terminal.r = terminal.r.wrapping_add(1); | ||||||||||
let cin = terminal.buf[fresh0.wrapping_rem(INPUT_BUF as u32) as usize] as i32; | ||||||||||
|
||||||||||
// end-of-file | ||||||||||
if cin == ctrl('D') { | ||||||||||
if (n as u32) < target { | ||||||||||
// Save ^D for next time, to make sure | ||||||||||
// caller gets a 0-byte result. | ||||||||||
this.r = this.r.wrapping_sub(1) | ||||||||||
terminal.r = terminal.r.wrapping_sub(1) | ||||||||||
} | ||||||||||
break; | ||||||||||
} else { | ||||||||||
|
@@ -121,58 +104,104 @@ impl Console { | |||||||||
target.wrapping_sub(n as u32) as i32 | ||||||||||
} | ||||||||||
|
||||||||||
unsafe fn intr(this: &mut SleepablelockGuard<'_, Self>, mut cin: i32) { | ||||||||||
fn intr(&self, mut cin: i32) { | ||||||||||
let mut terminal = self.terminal.lock(); | ||||||||||
match cin { | ||||||||||
// Print process list. | ||||||||||
m if m == ctrl('P') => { | ||||||||||
m if m == ctrl('P') => unsafe { | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 해당 block만 unsafe 하다고 판단했습니다. 나머지 block은 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 block은 왜 unsafe한가요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||
kernel().procs.dump(); | ||||||||||
} | ||||||||||
}, | ||||||||||
|
||||||||||
// Kill line. | ||||||||||
m if m == ctrl('U') => { | ||||||||||
while this.e != this.w | ||||||||||
&& this.buf[this.e.wrapping_sub(1).wrapping_rem(INPUT_BUF as u32) as usize] | ||||||||||
while terminal.e != terminal.w | ||||||||||
&& terminal.buf | ||||||||||
[terminal.e.wrapping_sub(1).wrapping_rem(INPUT_BUF as u32) as usize] | ||||||||||
as i32 | ||||||||||
!= '\n' as i32 | ||||||||||
{ | ||||||||||
this.e = this.e.wrapping_sub(1); | ||||||||||
this.putc(BACKSPACE); | ||||||||||
terminal.e = terminal.e.wrapping_sub(1); | ||||||||||
self.putc(BACKSPACE); | ||||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
// Backspace | ||||||||||
m if m == ctrl('H') | '\x7f' as i32 => { | ||||||||||
if this.e != this.w { | ||||||||||
this.e = this.e.wrapping_sub(1); | ||||||||||
this.putc(BACKSPACE); | ||||||||||
if terminal.e != terminal.w { | ||||||||||
terminal.e = terminal.e.wrapping_sub(1); | ||||||||||
self.putc(BACKSPACE); | ||||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
_ => { | ||||||||||
if cin != 0 && this.e.wrapping_sub(this.r) < INPUT_BUF as u32 { | ||||||||||
if cin != 0 && terminal.e.wrapping_sub(terminal.r) < INPUT_BUF as u32 { | ||||||||||
cin = if cin == '\r' as i32 { '\n' as i32 } else { cin }; | ||||||||||
|
||||||||||
// Echo back to the user. | ||||||||||
this.putc(cin); | ||||||||||
self.putc(cin); | ||||||||||
|
||||||||||
// Store for consumption by consoleread(). | ||||||||||
let fresh1 = this.e; | ||||||||||
this.e = this.e.wrapping_add(1); | ||||||||||
this.buf[fresh1.wrapping_rem(INPUT_BUF as u32) as usize] = cin as u8; | ||||||||||
let fresh1 = terminal.e; | ||||||||||
terminal.e = terminal.e.wrapping_add(1); | ||||||||||
terminal.buf[fresh1.wrapping_rem(INPUT_BUF as u32) as usize] = cin as u8; | ||||||||||
if cin == '\n' as i32 | ||||||||||
|| cin == ctrl('D') | ||||||||||
|| this.e == this.r.wrapping_add(INPUT_BUF as u32) | ||||||||||
|| terminal.e == terminal.r.wrapping_add(INPUT_BUF as u32) | ||||||||||
{ | ||||||||||
// Wake up consoleread() if a whole line (or end-of-file) | ||||||||||
// has arrived. | ||||||||||
this.w = this.e; | ||||||||||
this.wakeup(); | ||||||||||
terminal.w = terminal.e; | ||||||||||
terminal.wakeup(); | ||||||||||
} | ||||||||||
} | ||||||||||
} | ||||||||||
} | ||||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
pub struct Terminal { | ||||||||||
coolofficials marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
buf: [u8; INPUT_BUF], | ||||||||||
|
||||||||||
/// Read index. | ||||||||||
r: u32, | ||||||||||
|
||||||||||
/// Write index. | ||||||||||
w: u32, | ||||||||||
|
||||||||||
/// Edit index. | ||||||||||
e: u32, | ||||||||||
} | ||||||||||
|
||||||||||
impl Terminal { | ||||||||||
pub const fn new() -> Self { | ||||||||||
Self { | ||||||||||
buf: [0; INPUT_BUF], | ||||||||||
r: 0, | ||||||||||
w: 0, | ||||||||||
e: 0, | ||||||||||
} | ||||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
pub struct Printer { | ||||||||||
_padding: u8, | ||||||||||
coolofficials marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
} | ||||||||||
|
||||||||||
impl Printer { | ||||||||||
pub const fn new() -> Self { | ||||||||||
Self { _padding: 0 } | ||||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
impl Write for Printer { | ||||||||||
fn write_str(&mut self, s: &str) -> fmt::Result { | ||||||||||
for c in s.bytes() { | ||||||||||
kernel().console.putc(c as _); | ||||||||||
coolofficials marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
} | ||||||||||
Ok(()) | ||||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
/// Console input and output, to the uart. | ||||||||||
/// Reads are line at a time. | ||||||||||
/// Implements special input characters: | ||||||||||
|
@@ -188,7 +217,9 @@ const fn ctrl(x: char) -> i32 { | |||||||||
x as i32 - '@' as i32 | ||||||||||
} | ||||||||||
|
||||||||||
pub unsafe fn consoleinit(devsw: &mut [Devsw; NDEV]) { | ||||||||||
pub fn consoleinit(devsw: &mut [Devsw; NDEV]) { | ||||||||||
kernel().console.uart.init(); | ||||||||||
coolofficials marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
// Connect read and write system calls | ||||||||||
// to consoleread and consolewrite. | ||||||||||
devsw[CONSOLE_IN_DEVSW] = Devsw { | ||||||||||
|
@@ -199,24 +230,21 @@ pub unsafe fn consoleinit(devsw: &mut [Devsw; NDEV]) { | |||||||||
|
||||||||||
/// User write()s to the console go here. | ||||||||||
unsafe fn consolewrite(src: UVAddr, n: i32) -> i32 { | ||||||||||
let mut console = kernel().console.lock(); | ||||||||||
console.write(src, n) | ||||||||||
kernel().console.write(src, n) | ||||||||||
} | ||||||||||
|
||||||||||
/// User read()s from the console go here. | ||||||||||
/// Copy (up to) a whole input line to dst. | ||||||||||
/// User_dist indicates whether dst is a user | ||||||||||
/// or kernel address. | ||||||||||
unsafe fn consoleread(dst: UVAddr, n: i32) -> i32 { | ||||||||||
let mut console = kernel().console.lock(); | ||||||||||
Console::read(&mut console, dst, n) | ||||||||||
kernel().console.read(dst, n) | ||||||||||
} | ||||||||||
|
||||||||||
/// The console input interrupt handler. | ||||||||||
/// uartintr() calls this for input character. | ||||||||||
/// Do erase/kill processing, append to CONS.buf, | ||||||||||
/// wake up consoleread() if a whole line has arrived. | ||||||||||
pub unsafe fn consoleintr(cin: i32) { | ||||||||||
let mut console = kernel().console.lock(); | ||||||||||
Console::intr(&mut console, cin); | ||||||||||
pub fn consoleintr(cin: i32) { | ||||||||||
kernel().console.intr(cin); | ||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,42 @@ | ||
/// maximum number of processes | ||
/// Maximum number of processes. | ||
pub const NPROC: usize = 64; | ||
|
||
/// maximum number of CPUs | ||
/// Maximum number of CPUs. | ||
pub const NCPU: usize = 8; | ||
|
||
/// open files per process | ||
/// Open files per process. | ||
pub const NOFILE: usize = 16; | ||
|
||
/// open files per system | ||
/// Open files per system. | ||
pub const NFILE: usize = 100; | ||
|
||
/// maximum number of active i-nodes | ||
/// Maximum number of active i-nodes. | ||
pub const NINODE: usize = 50; | ||
|
||
/// maximum major device number | ||
/// Maximum major device number. | ||
pub const NDEV: usize = 10; | ||
|
||
/// device number of file system root disk | ||
/// Device number of file system root disk. | ||
pub const ROOTDEV: i32 = 1; | ||
|
||
/// max exec arguments | ||
/// Max exec arguments. | ||
pub const MAXARG: usize = 32; | ||
|
||
/// max # of blocks any FS op writes | ||
/// Will be handled in #31 | ||
/// Max # of blocks any FS op writes. | ||
/// Will be handled in #31. | ||
pub const MAXOPBLOCKS: usize = 10; | ||
|
||
/// max data blocks in on-disk log | ||
/// Max data blocks in on-disk log. | ||
pub const LOGSIZE: usize = MAXOPBLOCKS * 3; | ||
|
||
/// size of disk block cache | ||
/// Size of disk block cache. | ||
pub const NBUF: usize = MAXOPBLOCKS * 3; | ||
|
||
/// size of file system in blocks | ||
/// Size of file system in blocks. | ||
pub const FSSIZE: usize = 1000; | ||
|
||
/// maximum file path name | ||
/// Maximum file path name. | ||
pub const MAXPATH: usize = 128; | ||
|
||
/// Maximum length of process name. | ||
pub const MAXPROCNAME: usize = 16; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
여전히 이게 &self인게 이해가 잘 안갑니다. 여러 thread가 동시에 putc를 부르면 어떻게 되나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
생각해봤는데, 명확히 어떤 문제가 생기는지 reasoning이 잘 안됩니다. 면담 때 이런 경우에 어떻게 reasoning 할 수 있는지 가르침을 청해도 될까요?
Uart::putc_sync는 interrupt disable을 통해 synchronization을 handling 중입니다.