-
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
Fix WaitChannel's API #349
Conversation
kernel-rs/src/proc.rs
Outdated
let p: *mut Proc = myproc(); | ||
/// # Safety | ||
/// | ||
/// Make sure `lk` is the only lock we currently hold. |
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.
이게 아니면 어떻게 되나요?
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.
저도 아직 확실하지는 않지만, 일단은 xv6에서 사용하던 invariant인것 같습니다.
일단, sleep()
내부에서 sched()
을 부르게 되는데, sched()
함수에 있는 주석에는
/// Switch to scheduler. Must hold only p->lock
/// and have changed proc->state. Saves and restores
/// interrupt_enabled because interrupt_enabled is a property of this
/// kernel thread, not this CPU. It should
/// be proc->interrupt_enabled and proc->noff, but that would
/// break in the few places where a lock is held but
/// there's no process.
이라고 나와있어서 이걸 반영한겁니다.
다만, 이건 좀 더 알아보겠습니다!
EDIT: 일단 xv6책을 보면 의도적으로 이런 invariant을 넣어놓은 것 같긴 한데, 이유는 안 나와있는 것 같네요. 제 생각에는 deadlock을 좀 더 쉽게 방지하기 위한 장치 중 하나인 것 같습니다.
Now that sleep holds p->lock and no others, it can put the process to sleep by recording the
sleep channel, changing the process state to SLEEPING, and calling sched (kernel/proc.c:564-567).
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.
이 조건을 만족하지 않고 sleep
을 호출하면 memory safety 에 영향을 주나요? 말씀하신 내용대로면 deadlock 이 문제인데 이것은 safety 와 상관없는 것 같습니다.
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.
이 조건을 만족하지 않고 sleep 을 호출하면 memory safety 에 영향을 주나요? 말씀하신 내용대로면 deadlock 이 문제인데 이것은 safety 와 상관없는 것 같습니다.
sched()
와 달리 scheduler()
에서는 저런 조건이 없는 걸 보면 딱히 그런건 아닌 것 같습니다. 그러면 unsafe fn sleep()
-> fn sleep()
으로 바꿀까요? (참고로, sleep()
을 call하기 전에는 항상 Cpu->proc
이 non-null이여야 한다는 추가적인 safety 조건이 있기는 한데, 이거는 #258 와 관련해서 나중에 해결해야될 문제 같습니다.)
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.
네 말씀하신 대로 Proc
refactoring 을 전제하면 이 함수는 safe하다고 말할 수 있어 보입니다. sleep
은 safe function 으로 바꾸어 주시고, 그 때문에 생기는 unsafe block 에 safety argument 를 추가해 주세요.
|
kernel-rs/src/proc.rs
Outdated
let p: *mut Proc = myproc(); | ||
/// # Safety | ||
/// | ||
/// Make sure `lk` is the only lock we currently hold. |
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.
이 조건을 만족하지 않고 sleep
을 호출하면 memory safety 에 영향을 주나요? 말씀하신 내용대로면 deadlock 이 문제인데 이것은 safety 와 상관없는 것 같습니다.
3b9bcc8
to
ddecffe
Compare
이 PR은 @efenniht 님이 리뷰해주시고 r+ 해주시면 감사하겠습니다. |
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.
전반적으로 safety argument 에 관련된 comment를 추가해 주시길 부탁드립니다. 🙏
kernel-rs/src/proc.rs
Outdated
let p: *mut Proc = myproc(); | ||
/// # Safety | ||
/// | ||
/// Make sure `lk` is the only lock we currently hold. |
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.
네 말씀하신 대로 Proc
refactoring 을 전제하면 이 함수는 safe하다고 말할 수 있어 보입니다. sleep
은 safe function 으로 바꾸어 주시고, 그 때문에 생기는 unsafe block 에 safety argument 를 추가해 주세요.
kernel-rs/src/proc.rs
Outdated
/// You should manually prove the correctness when directly accessing | ||
/// the inner `RawSpinlock` instead of using the lock's API. |
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.
실제로 어떤 걸 증명해야 하는 지 설명해주셨으면 합니다:
get_raw
로 얻은RawSpinlock
을release
하면, 다시acquire
하기 전 까지는self
에 접근하면 안 됨.
그리고 나서 이 함수를 사용하는 지점에서 해당 조건을 만족함을 주석으로 설명해 주세요.
|
bors r+ |
349: Fix WaitChannel's API r=efenniht a=travis1829 #241 작업을 하기 전에 먼저 `WaitChannel`의 지저분한 부분을 조금 다듬어봤습니다. * 기존에는 `WaitChannel`에 대해서 sleep을 하기 위해서는 `SpinlockGuard`는 `sleep()`로, `SleepablelockGuard`는 `sleep_sleepable()`로, 그리고 `SpinlockProtected`는 `sleep_raw()`로 **여러가지로 API가 나눠져있는 걸 하나로 합쳤습니다.** * 이를 위해, `Guard`라는 trait을 추가했습니다. (현재 `SpinlockGuard`, `SpinlockProtectedGuard`, `SleepablelockGuard`이 이걸 impl합니다.) * 다만, 별개로, **현재 `SleepablelockGuard::sleep()`이 `unsafe`이 아닌데, 이래도 괜찮은지 잘 모르겠습니다.** * 먼저, `WaitChannel::sleep()`이 `unsafe`한 이유는 `guard.sched()`을 call할때는 항상 `p->lock`이외에는 어떠한 RawSpinlock도 acquire한 상태여선 안되기 때문입니다. (`guard.sched()`내에서도 `assert_eq!((*kernel().mycpu()).noff, 1, "sched locks");`로 이걸 확인합니다). 그러나 `SleepablelockGuard::sleep()`은 내부에서 `WaitChannel::sleep()`을 사용하는데도 unsafe이 아닙니다. Co-authored-by: travis1829 <[email protected]>
Build failed: |
a46a91c
to
dcfd735
Compare
bors r+ |
Build succeeded: |
#241 작업을 하기 전에 먼저
WaitChannel
의 지저분한 부분을 조금 다듬어봤습니다.WaitChannel
에 대해서 sleep을 하기 위해서는SpinlockGuard
는sleep()
로,SleepablelockGuard
는sleep_sleepable()
로, 그리고SpinlockProtected
는sleep_raw()
로 여러가지로 API가 나눠져있는 걸 하나로 합쳤습니다.Guard
라는 trait을 추가했습니다. (현재SpinlockGuard
,SpinlockProtectedGuard
,SleepablelockGuard
이 이걸 impl합니다.)SleepablelockGuard::sleep()
이unsafe
이 아닌데, 이래도 괜찮은지 잘 모르겠습니다.WaitChannel::sleep()
이unsafe
한 이유는guard.sched()
을 call할때는 항상p->lock
이외에는 어떠한 RawSpinlock도 acquire한 상태여선 안되기 때문입니다. (guard.sched()
내에서도assert_eq!((*kernel().mycpu()).noff, 1, "sched locks");
로 이걸 확인합니다). 그러나SleepablelockGuard::sleep()
은 내부에서WaitChannel::sleep()
을 사용하는데도 unsafe이 아닙니다.