Skip to content
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 #365] Fix TODOs in pipe.rs #362

Merged
6 commits merged into from
Jan 29, 2021
Merged

[Closes #365] Fix TODOs in pipe.rs #362

6 commits merged into from
Jan 29, 2021

Conversation

travis1829
Copy link
Collaborator

@travis1829 travis1829 commented Jan 27, 2021

Closes #365

@travis1829 travis1829 requested review from jeehoonkang and removed request for jeehoonkang January 27, 2021 06:51
@travis1829 travis1829 changed the title Add Pipe::Drop [Closes #365] Add Pipe::Drop Jan 27, 2021
kernel-rs/src/pipe.rs Outdated Show resolved Hide resolved
kernel-rs/src/pipe.rs Outdated Show resolved Hide resolved
kernel-rs/src/pipe.rs Outdated Show resolved Hide resolved
kernel-rs/src/pipe.rs Outdated Show resolved Hide resolved
@travis1829
Copy link
Collaborator Author

travis1829 commented Jan 27, 2021

  • ptr: *mut Pipe -> ptr: NonNull<Pipe>
  • AllocatedPipe&mut self가 아니라 self를 받도록 바꿨습니다. AllocatedPipe::Drop은 없앴습니다. (Drop을 제대로 구현하려면 같은 값을 저장하는 readable/writable 변수를 File에도 저장하고 AllocatedPipe에도 중복해서 저장해야 합니다.)
  • myproc() refactoring #354 를 고려하여 일단은 Pipe::read()Pipe::write()의 unsafe를 없앴습니다. myproc()부분을 제외하면, caller()가 추가로 고려해야 되는 사항은 딱히 없는 것으로 보입니다.

  • 다만, 추가로 AllocatedPipe을 없애는게 어떨지 제안해봅니다.
    • 현재는 xv6의 Pipe이 rv6의 030fea5 에서 PipeInner, Pipe, AllocatedPipe 3가지로 나뉘어졌습니다. 여기서, PipeInnerPipe는 한개씩만 만들어지지만, AllocatedPipe만 두개가 만들어집니다. (하나는 read, 하나는 write). 또한 API의 경우도 Pipe꺼를 써야하는 경우와 AllocatedPipe을 써야하는 경우로 뒤섞여있습니다.
    • 차라리 PipeInner는 하나만 만들어지고 Pipe이 두개 만들어지도록 바꾸는게 나을 것 같습니다. 다만, 이러려면 Pipe::inner의 type을 Spinlock<PipeInner> -> *const Spinlock<PipeInner>로 바꿔야합니다. 또, PipeWaitChannel들을 inner안으로 넣어야 합니다. (어차피 WaitChannel을 access할때는 항상 Spinlock을 lock()한 상태이니, 추가로 lock()을 할 필요는 없습니다.)

@travis1829 travis1829 requested a review from Medowhill January 27, 2021 12:52
}
}

impl AllocatedPipe {
pub fn alloc() -> Result<(RcFile<'static>, RcFile<'static>), ()> {
let page = kernel().alloc().ok_or(())?;
let ptr = page.into_usize() as *mut Pipe;
let mut ptr = NonNull::new(page.into_usize() as *mut Pipe).expect("AllocatedPipe alloc");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Page의 invariant에 따라 page.into_usize() as *mut Pipe가 non-null이라는 보장이 있으므로 new_unchecked를 사용해서 run-time check를 줄이는 것도 괜찮아 보입니다.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

앞으로 NonNull 을 많이 사용하게 된다면 Page::into_non_null_ptr 같은 걸 만드는 것도 좋겠습니다. (https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.as_non_null_ptr)

!inner.readopen && !inner.writeopen
}
}

/// # Safety
///
/// `ptr` always refers to a `Pipe`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이와 동시에 Page를 가리킨다는 것도 명시되어 있어야 close의 안전성이 완전히 설명될 것 같습니다.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

코드를 더 보다 보니 위 조건을 추가해도 여전히 충분하지 않은 것 같습니다. AllocatedPipe::close에서 페이지를 free하면 같은 주소를 가리키던 다른 AllocatedPipe의 invariant가 깨질 수 있습니다. 물론 Pipe::close의 결과가 true일 때만 free하며, Pipe::close의 결과가 true라는 조건이 같은 주소를 가리키는 다른 AllocatedPipe가 존재하지 않는다는 사실을 보장하므로 구현은 안전한 것이 맞습니다.

AllocatedPipe의 invariant에 "ptr이 가리키는 Piperead_waitchannelwrite_waitchannel 중 하나가 false라면 자기 자신이 아닌 다른 AllocatedPipe가 존재하지 않는다"는(또는 이와 유사한 형태의) 조건이 추가로 있어야 할 것 같습니다.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

반영했습니다!

@Medowhill
Copy link
Collaborator

  • 차라리 PipeInner는 하나만 만들어지고 Pipe이 두개 만들어지도록 바꾸는게 나을 것 같습니다. 다만, 이러려면 Pipe::inner의 type을 Spinlock<PipeInner> -> *const Spinlock<PipeInner>로 바꿔야합니다. 또, PipeWaitChannel들을 inner안으로 넣어야 합니다. (어차피 WaitChannel을 access할때는 항상 Spinlock을 lock()한 상태이니, 추가로 lock()을 할 필요는 없습니다.)

저는 특별한 의견은 없습니다. 지금 상태도 크게 나쁘지는 않은 것 같은데, 바꿔서 더 간단해질 수 있다면 바꾸는 것도 좋다고 생각합니다.

@efenniht
Copy link
Collaborator

WaitChannel::sleep&mut LockGuard 를 필요로 하므로 WaitChannelSpinlock 안에 있으면 안될 것 같습니다.

@travis1829
Copy link
Collaborator Author

WaitChannel::sleep 이 &mut LockGuard 를 필요로 하므로 WaitChannel 이 Spinlock 안에 있으면 안될 것 같습니다.

그렇네요. 간단한 부분을 제가 놓쳤네요. 말씀해주셔서 감사합니다!

kernel-rs/src/pipe.rs Outdated Show resolved Hide resolved
}
}

impl AllocatedPipe {
pub fn alloc() -> Result<(RcFile<'static>, RcFile<'static>), ()> {
let page = kernel().alloc().ok_or(())?;
let ptr = page.into_usize() as *mut Pipe;
let mut ptr = NonNull::new(page.into_usize() as *mut Pipe).expect("AllocatedPipe alloc");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

앞으로 NonNull 을 많이 사용하게 된다면 Page::into_non_null_ptr 같은 걸 만드는 것도 좋겠습니다. (https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.as_non_null_ptr)

@travis1829
Copy link
Collaborator Author

travis1829 commented Jan 28, 2021

@travis1829 travis1829 changed the title [Closes #365] Add Pipe::Drop [Closes #365] Fix TODOs in pipe.rs Jan 28, 2021
@travis1829 travis1829 requested a review from Medowhill January 29, 2021 08:34
@Medowhill
Copy link
Collaborator

bors r+

ghost pushed a commit that referenced this pull request Jan 29, 2021
362: [Closes #365] Fix TODOs in pipe.rs r=Medowhill a=travis1829

Closes #365 
* #356 에서의 변경사항 중 `Pin` API와 관련없는 내용만 따로 빼서 새롭게 PR을 만들었습니다. (주로 `Pipe`에 대한 변경사항입니다.)
* `Pipe`의 `Drop` trait을 추가했고 `Copy`, `Clone` trait을 없앴습니다.
* 추가로, `Pipe::copy`가 `unsafe`일 필요가 없는 것 같아서 없앴습니다. (혹시 `unsafe`이여야하는 이유가 있다면 말씀해주세요.)
* kernel.rs에 있던 주석을 일부 지웠습니다. (#356 (comment))

Co-authored-by: travis1829 <[email protected]>
@ghost
Copy link

ghost commented Jan 29, 2021

Build failed:

@Medowhill
Copy link
Collaborator

bors retry

ghost pushed a commit that referenced this pull request Jan 29, 2021
362: [Closes #365] Fix TODOs in pipe.rs r=Medowhill a=travis1829

Closes #365 
* #356 에서의 변경사항 중 `Pin` API와 관련없는 내용만 따로 빼서 새롭게 PR을 만들었습니다. (주로 `Pipe`에 대한 변경사항입니다.)
* `Pipe`의 `Drop` trait을 추가했고 `Copy`, `Clone` trait을 없앴습니다.
* 추가로, `Pipe::copy`가 `unsafe`일 필요가 없는 것 같아서 없앴습니다. (혹시 `unsafe`이여야하는 이유가 있다면 말씀해주세요.)
* kernel.rs에 있던 주석을 일부 지웠습니다. (#356 (comment))

Co-authored-by: travis1829 <[email protected]>
@ghost
Copy link

ghost commented Jan 29, 2021

Build failed:

@Medowhill
Copy link
Collaborator

bors retry

@ghost
Copy link

ghost commented Jan 29, 2021

Build succeeded:

@ghost ghost merged commit df05e46 into kaist-cp:riscv Jan 29, 2021
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

AllocatedPipe::close(): use Drop & use self
3 participants