Make rekillable consistent with unkillable
As for now, rekillable is an unsafe function, instead, it should behave just like unkillable by encapsulating unsafe code within an unsafe block. This patch does that and removes unsafe blocks that were encapsulating rekillable calls throughout rust's libs. Fixes #8232
This commit is contained in:
parent
9cd91c8cc4
commit
cd92d2c77f
2 changed files with 46 additions and 45 deletions
|
@ -135,9 +135,7 @@ impl<Q:Send> Sem<Q> {
|
||||||
do task::unkillable {
|
do task::unkillable {
|
||||||
do (|| {
|
do (|| {
|
||||||
self.acquire();
|
self.acquire();
|
||||||
unsafe {
|
do task::rekillable { blk() }
|
||||||
do task::rekillable { blk() }
|
|
||||||
}
|
|
||||||
}).finally {
|
}).finally {
|
||||||
self.release();
|
self.release();
|
||||||
}
|
}
|
||||||
|
@ -234,10 +232,8 @@ impl<'self> Condvar<'self> {
|
||||||
// signaller already sent -- I mean 'unconditionally' in contrast
|
// signaller already sent -- I mean 'unconditionally' in contrast
|
||||||
// with acquire().)
|
// with acquire().)
|
||||||
do (|| {
|
do (|| {
|
||||||
unsafe {
|
do task::rekillable {
|
||||||
do task::rekillable {
|
let _ = WaitEnd.take_unwrap().recv();
|
||||||
let _ = WaitEnd.take_unwrap().recv();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}).finally {
|
}).finally {
|
||||||
// Reacquire the condvar. Note this is back in the unkillable
|
// Reacquire the condvar. Note this is back in the unkillable
|
||||||
|
@ -516,14 +512,12 @@ impl RWLock {
|
||||||
* 'write' from other tasks will run concurrently with this one.
|
* 'write' from other tasks will run concurrently with this one.
|
||||||
*/
|
*/
|
||||||
pub fn write<U>(&self, blk: &fn() -> U) -> U {
|
pub fn write<U>(&self, blk: &fn() -> U) -> U {
|
||||||
unsafe {
|
do task::unkillable {
|
||||||
do task::unkillable {
|
(&self.order_lock).acquire();
|
||||||
(&self.order_lock).acquire();
|
do (&self.access_lock).access {
|
||||||
do (&self.access_lock).access {
|
(&self.order_lock).release();
|
||||||
(&self.order_lock).release();
|
do task::rekillable {
|
||||||
do task::rekillable {
|
blk()
|
||||||
blk()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -562,16 +556,14 @@ impl RWLock {
|
||||||
// which can't happen until T2 finishes the downgrade-read entirely.
|
// which can't happen until T2 finishes the downgrade-read entirely.
|
||||||
// The astute reader will also note that making waking writers use the
|
// The astute reader will also note that making waking writers use the
|
||||||
// order_lock is better for not starving readers.
|
// order_lock is better for not starving readers.
|
||||||
unsafe {
|
do task::unkillable {
|
||||||
do task::unkillable {
|
(&self.order_lock).acquire();
|
||||||
(&self.order_lock).acquire();
|
do (&self.access_lock).access_cond |cond| {
|
||||||
do (&self.access_lock).access_cond |cond| {
|
(&self.order_lock).release();
|
||||||
(&self.order_lock).release();
|
do task::rekillable {
|
||||||
do task::rekillable {
|
let opt_lock = Just(&self.order_lock);
|
||||||
let opt_lock = Just(&self.order_lock);
|
blk(&Condvar { sem: cond.sem, order: opt_lock,
|
||||||
blk(&Condvar { sem: cond.sem, order: opt_lock,
|
token: NonCopyable::new() })
|
||||||
token: NonCopyable::new() })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -606,10 +598,8 @@ impl RWLock {
|
||||||
(&self.access_lock).acquire();
|
(&self.access_lock).acquire();
|
||||||
(&self.order_lock).release();
|
(&self.order_lock).release();
|
||||||
do (|| {
|
do (|| {
|
||||||
unsafe {
|
do task::rekillable {
|
||||||
do task::rekillable {
|
blk(RWLockWriteMode { lock: self, token: NonCopyable::new() })
|
||||||
blk(RWLockWriteMode { lock: self, token: NonCopyable::new() })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}).finally {
|
}).finally {
|
||||||
let writer_or_last_reader;
|
let writer_or_last_reader;
|
||||||
|
|
|
@ -597,21 +597,34 @@ pub fn unkillable<U>(f: &fn() -> U) -> U {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The inverse of unkillable. Only ever to be used nested in unkillable().
|
/**
|
||||||
pub unsafe fn rekillable<U>(f: &fn() -> U) -> U {
|
* Makes killable a task marked as unkillable
|
||||||
|
*
|
||||||
|
* # Example
|
||||||
|
*
|
||||||
|
* ~~~
|
||||||
|
* do task::unkillable {
|
||||||
|
* do task::rekillable {
|
||||||
|
* // Task is killable
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
pub fn rekillable<U>(f: &fn() -> U) -> U {
|
||||||
use rt::task::Task;
|
use rt::task::Task;
|
||||||
|
|
||||||
if in_green_task_context() {
|
unsafe {
|
||||||
let t = Local::unsafe_borrow::<Task>();
|
if in_green_task_context() {
|
||||||
do (|| {
|
let t = Local::unsafe_borrow::<Task>();
|
||||||
(*t).death.allow_kill((*t).unwinder.unwinding);
|
do (|| {
|
||||||
|
(*t).death.allow_kill((*t).unwinder.unwinding);
|
||||||
|
f()
|
||||||
|
}).finally {
|
||||||
|
(*t).death.inhibit_kill((*t).unwinder.unwinding);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// FIXME(#3095): As in unkillable().
|
||||||
f()
|
f()
|
||||||
}).finally {
|
|
||||||
(*t).death.inhibit_kill((*t).unwinder.unwinding);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// FIXME(#3095): As in unkillable().
|
|
||||||
f()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -646,11 +659,9 @@ fn test_kill_rekillable_task() {
|
||||||
do run_in_newsched_task {
|
do run_in_newsched_task {
|
||||||
do task::try {
|
do task::try {
|
||||||
do task::unkillable {
|
do task::unkillable {
|
||||||
unsafe {
|
do task::rekillable {
|
||||||
do task::rekillable {
|
do task::spawn {
|
||||||
do task::spawn {
|
fail!();
|
||||||
fail!();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue