Moved lock manipulation into context
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user