2018-09-21 22:34:42 -04:00
|
|
|
extern crate libc;
|
2018-11-06 23:04:26 -05:00
|
|
|
extern crate qadapt_macro;
|
2018-09-22 17:26:52 -04:00
|
|
|
extern crate spin;
|
2018-09-21 22:34:42 -04:00
|
|
|
|
2018-11-06 23:04:26 -05:00
|
|
|
// Re-export the proc macros to use by other code
|
|
|
|
pub use qadapt_macro::*;
|
|
|
|
|
2018-09-21 22:34:42 -04:00
|
|
|
use libc::c_void;
|
|
|
|
use libc::free;
|
|
|
|
use libc::malloc;
|
2018-11-10 01:30:39 -05:00
|
|
|
use spin::Mutex;
|
2018-11-05 21:58:33 -05:00
|
|
|
use std::alloc::Layout;
|
|
|
|
use std::alloc::GlobalAlloc;
|
2018-11-10 01:30:39 -05:00
|
|
|
use std::sync::RwLock;
|
|
|
|
use std::thread;
|
2018-09-21 22:34:42 -04:00
|
|
|
|
2018-11-10 01:30:39 -05:00
|
|
|
static THREAD_LOCAL_LOCK: Mutex<()> = Mutex::new(());
|
|
|
|
thread_local! {
|
|
|
|
static PROTECTION_LEVEL: RwLock<u32> = RwLock::new(0);
|
|
|
|
}
|
2018-09-23 12:37:07 -04:00
|
|
|
|
2018-11-05 21:58:33 -05:00
|
|
|
pub struct QADAPT;
|
2018-09-22 16:13:36 -04:00
|
|
|
|
2018-11-10 01:30:39 -05:00
|
|
|
pub fn enter_protected() {
|
|
|
|
if thread::panicking() {
|
|
|
|
return
|
2018-11-06 20:51:44 -05:00
|
|
|
}
|
|
|
|
|
2018-11-10 01:30:39 -05:00
|
|
|
PROTECTION_LEVEL.try_with(|v| {
|
|
|
|
*v.write().unwrap() += 1;
|
|
|
|
}).unwrap_or_else(|_e| ());
|
2018-09-21 22:34:42 -04:00
|
|
|
}
|
|
|
|
|
2018-11-10 01:30:39 -05:00
|
|
|
pub fn exit_protected() {
|
|
|
|
if thread::panicking() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
PROTECTION_LEVEL.try_with(|v| {
|
|
|
|
let val = { *v.read().unwrap() };
|
|
|
|
match val {
|
|
|
|
v if v == 0 => panic!("Attempt to exit protected too many times"),
|
|
|
|
_ => {
|
|
|
|
*v.write().unwrap() -= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}).unwrap_or_else(|_e| ());
|
2018-09-22 17:26:52 -04:00
|
|
|
}
|
|
|
|
|
2018-09-21 22:34:42 -04:00
|
|
|
unsafe impl GlobalAlloc for QADAPT {
|
|
|
|
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
2018-11-10 01:30:39 -05:00
|
|
|
// If we're attempting to allocate our PROTECTION_LEVEL thread local,
|
|
|
|
// just allow it through
|
|
|
|
if thread::panicking() || THREAD_LOCAL_LOCK.try_lock().is_none() {
|
|
|
|
return malloc(layout.size()) as *mut u8;
|
|
|
|
}
|
2018-11-05 21:58:33 -05:00
|
|
|
|
2018-11-10 01:30:39 -05:00
|
|
|
let protection_level: Result<u32, ()> = {
|
|
|
|
let _lock = THREAD_LOCAL_LOCK.lock();
|
|
|
|
PROTECTION_LEVEL.try_with(|v| *v.read().unwrap())
|
|
|
|
.or(Ok(0))
|
|
|
|
};
|
2018-11-05 21:58:33 -05:00
|
|
|
|
2018-11-10 01:30:39 -05:00
|
|
|
match protection_level {
|
|
|
|
Ok(v) if v == 0 => malloc(layout.size()) as *mut u8,
|
|
|
|
//Ok(v) => panic!("Unexpected allocation for size {}, protection level: {}", layout.size(), v),
|
|
|
|
Ok(v) => {
|
|
|
|
// Tripped a bad allocation, but make sure further allocation/deallocation during unwind
|
|
|
|
// doesn't have issues
|
|
|
|
PROTECTION_LEVEL.with(|v| *v.write().unwrap() = 0);
|
|
|
|
panic!("Unexpected allocation for size {}, protection level: {}", layout.size(), v)
|
|
|
|
}
|
|
|
|
Err(_) => {
|
|
|
|
// It shouldn't be possible to reach this point...
|
|
|
|
panic!("Unexpected error for fetching protection level")
|
|
|
|
}
|
2018-09-22 16:13:36 -04:00
|
|
|
}
|
2018-09-21 22:34:42 -04:00
|
|
|
}
|
|
|
|
|
2018-11-10 01:30:39 -05:00
|
|
|
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
|
|
|
if thread::panicking() || THREAD_LOCAL_LOCK.try_lock().is_none() {
|
|
|
|
return free(ptr as *mut c_void);
|
|
|
|
}
|
2018-09-22 17:26:52 -04:00
|
|
|
|
2018-11-10 01:30:39 -05:00
|
|
|
let protection_level: Result<u32, ()> = {
|
|
|
|
let _lock = THREAD_LOCAL_LOCK.lock();
|
|
|
|
PROTECTION_LEVEL.try_with(|v| *v.read().unwrap())
|
|
|
|
.or(Ok(0))
|
|
|
|
};
|
2018-09-22 17:26:52 -04:00
|
|
|
|
2018-11-10 01:30:39 -05:00
|
|
|
free(ptr as *mut c_void);
|
|
|
|
match protection_level {
|
|
|
|
Ok(v) if v > 0 => {
|
|
|
|
// Tripped a bad dealloc, but make sure further memory access during unwind
|
|
|
|
// doesn't have issues
|
|
|
|
PROTECTION_LEVEL.with(|v| *v.write().unwrap() = 0);
|
|
|
|
panic!("Unexpected deallocation for size {}, protection level: {}", layout.size(), v)
|
|
|
|
},
|
|
|
|
_ => ()
|
2018-09-23 12:37:07 -04:00
|
|
|
}
|
2018-09-21 22:34:42 -04:00
|
|
|
}
|
|
|
|
}
|