Moved lock manipulation into context

This commit is contained in:
Connor Wood
2017-07-29 12:39:08 +03:00
parent f25df99a41
commit ab98746879
3 changed files with 130 additions and 71 deletions

View File

@@ -30,7 +30,8 @@ pub struct AmlExecutionContext {
pub arg_vars: [AmlValue; 8],
pub state: ExecutionState,
pub namespace_delta: Vec<String>,
pub ctx_id: u64
pub ctx_id: u64,
pub sync_level: u8
}
impl AmlExecutionContext {
@@ -60,9 +61,118 @@ impl AmlExecutionContext {
AmlValue::Uninitialized],
state: ExecutionState::EXECUTING,
namespace_delta: vec!(),
ctx_id: id
ctx_id: id,
sync_level: 0
}
}
pub fn release_mutex(&mut self, mutex_ptr: AmlValue) -> Result<(), AmlError> {
let id = self.ctx_id;
let mut namespace_ptr = self.prelock();
let mut namespace = match *namespace_ptr {
Some(ref mut n) => n,
None => return Err(AmlError::AmlHardFatal)
};
let mutex_idx = match mutex_ptr {
AmlValue::String(ref s) => s.clone(),
AmlValue::ObjectReference(ref o) => match *o {
ObjectReference::Object(ref s) => s.clone(),
_ => return Err(AmlError::AmlValueError)
},
_ => return Err(AmlError::AmlValueError)
};
let mutex = match namespace.get(&mutex_idx) {
Some(s) => s.clone(),
None => return Err(AmlError::AmlValueError)
};
match mutex {
AmlValue::Mutex((sync_level, owner)) => {
if let Some(o) = owner {
if o == id {
if sync_level == self.sync_level {
namespace.insert(mutex_idx, AmlValue::Mutex((sync_level, None)));
return Ok(());
} else {
return Err(AmlError::AmlValueError);
}
} else {
return Err(AmlError::AmlHardFatal);
}
}
},
AmlValue::OperationRegion(ref region) => {
if let Some(o) = region.accessed_by {
if o == id {
let mut new_region = region.clone();
new_region.accessed_by = None;
namespace.insert(mutex_idx, AmlValue::OperationRegion(new_region));
return Ok(());
} else {
return Err(AmlError::AmlHardFatal);
}
}
},
_ => return Err(AmlError::AmlValueError)
}
Ok(())
}
pub fn acquire_mutex(&mut self, mutex_ptr: AmlValue, timeout: u16) -> Result<bool, AmlError> {
let id = self.ctx_id;
let mut namespace_ptr = self.prelock();
let mut namespace = match *namespace_ptr {
Some(ref mut n) => n,
None => return Err(AmlError::AmlHardFatal)
};
let mutex_idx = match mutex_ptr {
AmlValue::String(ref s) => s.clone(),
AmlValue::ObjectReference(ref o) => match *o {
ObjectReference::Object(ref s) => s.clone(),
_ => return Err(AmlError::AmlValueError)
},
_ => return Err(AmlError::AmlValueError)
};
let mutex = match namespace.get(&mutex_idx) {
Some(s) => s.clone(),
None => return Err(AmlError::AmlValueError)
};
match mutex {
AmlValue::Mutex((sync_level, owner)) => {
if owner == None {
if sync_level < self.sync_level {
return Err(AmlError::AmlValueError);
}
namespace.insert(mutex_idx, AmlValue::Mutex((sync_level, Some(id))));
self.sync_level = sync_level;
return Ok(true);
}
},
AmlValue::OperationRegion(ref o) => {
if o.accessed_by == None {
let mut new_region = o.clone();
new_region.accessed_by = Some(id);
namespace.insert(mutex_idx, AmlValue::OperationRegion(new_region));
return Ok(true);
}
},
_ => return Err(AmlError::AmlValueError)
}
Ok(false)
}
pub fn add_to_namespace(&mut self, name: String, value: AmlValue) -> Result<(), AmlError> {
let mut namespace = ACPI_TABLE.namespace.write();

View File

@@ -202,35 +202,8 @@ fn parse_def_release(data: &[u8],
parser_opcode_extended!(data, 0x27);
let obj = parse_super_name(&data[2..], ctx)?;
let mut namespace = ctx.prelock();
let mutex = ctx.get(obj.val.clone());
match mutex {
AmlValue::Mutex((sync_level, owner)) => {
if let Some(o) = owner {
if o == ctx.ctx_id {
ctx.modify(obj.val.clone(), AmlValue::Mutex((sync_level, None)));
} else {
return Err(AmlError::AmlHardFatal);
}
}
},
AmlValue::OperationRegion(ref region) => {
if let Some(o) = region.accessed_by {
if o == ctx.ctx_id {
let mut new_region = region.clone();
new_region.accessed_by = None;
ctx.modify(obj.val.clone(), AmlValue::OperationRegion(new_region));
} else {
return Err(AmlError::AmlHardFatal);
}
}
},
_ => return Err(AmlError::AmlValueError)
}
ctx.release_mutex(obj.val);
Ok(AmlParseType {
val: AmlValue::None,
len: 2 + obj.len

View File

@@ -328,50 +328,26 @@ fn parse_def_acquire(data: &[u8],
let (seconds, nanoseconds) = monotonic();
let starting_time_ns = nanoseconds + (seconds * 1000000000);
let id = ctx.ctx_id;
loop {
{
let mut namespace = ctx.prelock();
let mutex = ctx.get(obj.val.clone());
match mutex {
AmlValue::Mutex((sync_level, owner)) => {
if owner == None {
ctx.modify(obj.val.clone(), AmlValue::Mutex((sync_level, Some(id))));
return Ok(AmlParseType {
val: AmlValue::Integer(0),
len: 4 + obj.len
});
}
},
AmlValue::OperationRegion(ref o) => {
if o.accessed_by == None {
let mut new_region = o.clone();
new_region.accessed_by = Some(id);
ctx.modify(obj.val.clone(), AmlValue::OperationRegion(new_region));
return Ok(AmlParseType {
val: AmlValue::Integer(0),
len: 4 + obj.len
});
}
},
_ => return Err(AmlError::AmlValueError)
}
}
if timeout == 0xFFFF {
// TODO: Brief sleep here
} else {
let (seconds, nanoseconds) = monotonic();
let current_time_ns = nanoseconds + (seconds * 1000000000);
if current_time_ns - starting_time_ns > timeout as u64 * 1000000 {
match ctx.acquire_mutex(obj.val.clone(), timeout) {
Err(e) => return Err(e),
Ok(b) => if b {
return Ok(AmlParseType {
val: AmlValue::Integer(1),
val: AmlValue::Integer(0),
len: 4 + obj.len
});
} else if timeout == 0xFFFF {
// TODO: Brief sleep here
} else {
let (seconds, nanoseconds) = monotonic();
let current_time_ns = nanoseconds + (seconds * 1000000000);
if current_time_ns - starting_time_ns > timeout as u64 * 1000000 {
return Ok(AmlParseType {
val: AmlValue::Integer(1),
len: 4 + obj.len
});
}
}
}
}