浏览代码

Wrap buffer data in spinning_top::Spinlock

This is a stepping stone / first attempt at making it possible to mutate
underlying buffer data, which requires getting access to data within the
Arc. While totally not ideal to be using a spinlock here, it works for
now and allows us to get writes to buffer fields working.

We've got a few ideas on how to improve this in the future, but for now I
think this is fine.
Isaac Woods 3 年之前
父节点
当前提交
6a610dc1d8
共有 5 个文件被更改,包括 51 次插入27 次删除
  1. 1 0
      aml/Cargo.toml
  2. 2 1
      aml/src/resource.rs
  3. 12 6
      aml/src/term_object.rs
  4. 29 15
      aml/src/type2.rs
  5. 7 5
      aml/src/value.rs

+ 1 - 0
aml/Cargo.toml

@@ -13,3 +13,4 @@ edition = "2018"
 log = "0.4"
 bit_field = "0.10"
 byteorder = { version = "1", default-features = false }
+spinning_top = "0.2.4"

+ 2 - 1
aml/src/resource.rs

@@ -22,7 +22,8 @@ pub enum Resource {
 pub fn resource_descriptor_list(descriptor: &AmlValue) -> Result<Vec<Resource>, AmlError> {
     if let AmlValue::Buffer(bytes) = descriptor {
         let mut descriptors = Vec::new();
-        let mut bytes = bytes.as_slice();
+        let mut buffer_data = bytes.lock();
+        let mut bytes = buffer_data.as_slice();
 
         while bytes.len() > 0 {
             let (descriptor, remaining_bytes) = resource_descriptor(bytes)?;

+ 12 - 6
aml/src/term_object.rs

@@ -193,7 +193,8 @@ where
             "DefCreateBitField",
             term_arg().then(term_arg()).then(name_string()).map_with_context(
                 |((source, index), name), context| {
-                    let source_data: Arc<Vec<u8>> = try_with_context!(context, source.as_buffer(context)).clone();
+                    let source_data: Arc<spinning_top::Spinlock<Vec<u8>>> =
+                        try_with_context!(context, source.as_buffer(context)).clone();
                     let index = try_with_context!(context, index.as_integer(context));
 
                     try_with_context!(
@@ -227,7 +228,8 @@ where
             "DefCreateByteField",
             term_arg().then(term_arg()).then(name_string()).map_with_context(
                 |((source, index), name), context| {
-                    let source_data: Arc<Vec<u8>> = try_with_context!(context, source.as_buffer(context)).clone();
+                    let source_data: Arc<spinning_top::Spinlock<Vec<u8>>> =
+                        try_with_context!(context, source.as_buffer(context)).clone();
                     let index = try_with_context!(context, index.as_integer(context));
 
                     try_with_context!(
@@ -261,7 +263,8 @@ where
             "DefCreateWordField",
             term_arg().then(term_arg()).then(name_string()).map_with_context(
                 |((source, index), name), context| {
-                    let source_data: Arc<Vec<u8>> = try_with_context!(context, source.as_buffer(context)).clone();
+                    let source_data: Arc<spinning_top::Spinlock<Vec<u8>>> =
+                        try_with_context!(context, source.as_buffer(context)).clone();
                     let index = try_with_context!(context, index.as_integer(context));
 
                     try_with_context!(
@@ -295,7 +298,8 @@ where
             "DefCreateDWordField",
             term_arg().then(term_arg()).then(name_string()).map_with_context(
                 |((source, index), name), context| {
-                    let source_data: Arc<Vec<u8>> = try_with_context!(context, source.as_buffer(context)).clone();
+                    let source_data: Arc<spinning_top::Spinlock<Vec<u8>>> =
+                        try_with_context!(context, source.as_buffer(context)).clone();
                     let index = try_with_context!(context, index.as_integer(context));
 
                     try_with_context!(
@@ -329,7 +333,8 @@ where
             "DefCreateQWordField",
             term_arg().then(term_arg()).then(name_string()).map_with_context(
                 |((source, index), name), context| {
-                    let source_data: Arc<Vec<u8>> = try_with_context!(context, source.as_buffer(context)).clone();
+                    let source_data: Arc<spinning_top::Spinlock<Vec<u8>>> =
+                        try_with_context!(context, source.as_buffer(context)).clone();
                     let index = try_with_context!(context, index.as_integer(context));
 
                     try_with_context!(
@@ -364,7 +369,8 @@ where
             "DefCreateField",
             term_arg().then(term_arg()).then(term_arg()).then(name_string()).map_with_context(
                 |(((source, index), num_bits), name), context| {
-                    let source_data: Arc<Vec<u8>> = try_with_context!(context, source.as_buffer(context)).clone();
+                    let source_data: Arc<spinning_top::Spinlock<Vec<u8>>> =
+                        try_with_context!(context, source.as_buffer(context)).clone();
                     let index = try_with_context!(context, index.as_integer(context));
                     let num_bits = try_with_context!(context, num_bits.as_integer(context));
 

+ 29 - 15
aml/src/type2.rs

@@ -154,7 +154,7 @@ where
                 })
             }),
         ))
-        .map(|((), buffer)| Ok(AmlValue::Buffer(Arc::new(buffer))))
+        .map(|((), buffer)| Ok(AmlValue::Buffer(Arc::new(spinning_top::Spinlock::new(buffer)))))
 }
 
 pub fn def_concat<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
@@ -178,12 +178,12 @@ where
                         buffer.extend_from_slice(&left.to_le_bytes());
                         buffer.extend_from_slice(&right.to_le_bytes());
 
-                        AmlValue::Buffer(Arc::new(buffer))
+                        AmlValue::Buffer(Arc::new(spinning_top::Spinlock::new(buffer)))
                     }
                     AmlValue::Buffer(left) => {
-                        let mut new = left.deref().clone();
-                        new.extend(try_with_context!(context, right.as_buffer(context)).iter());
-                        AmlValue::Buffer(Arc::new(new))
+                        let mut new: Vec<u8> = left.lock().deref().clone();
+                        new.extend(try_with_context!(context, right.as_buffer(context)).lock().iter());
+                        AmlValue::Buffer(Arc::new(spinning_top::Spinlock::new(new)))
                     }
                     AmlValue::String(left) => {
                         let right = match right.as_concat_type() {
@@ -220,7 +220,10 @@ where
                 let left = try_with_context!(context, left.as_buffer(context));
                 let right = try_with_context!(context, right.as_buffer(context));
 
-                if left.len() == 1 || right.len() == 1 {
+                let left_len = left.lock().len();
+                let right_len = right.lock().len();
+
+                if left_len == 1 || right_len == 1 {
                     return (Err(Propagate::Err(AmlError::ResourceDescriptorTooShort)), context);
                 }
 
@@ -233,9 +236,15 @@ where
                  */
                 let result = {
                     let mut result =
-                        Vec::with_capacity(left.len().saturating_sub(2) + right.len().saturating_sub(2) + 2);
-                    result.extend_from_slice(if left.len() == 0 { &[] } else { &left[..(left.len() - 2)] });
-                    result.extend_from_slice(if right.len() == 0 { &[] } else { &right[..(right.len() - 2)] });
+                        Vec::with_capacity(left_len.saturating_sub(2) + right_len.saturating_sub(2) + 2);
+                    let left_contents = left.lock();
+                    let right_contents = right.lock();
+                    result.extend_from_slice(if left_len == 0 { &[] } else { &left_contents[..(left_len - 2)] });
+                    result.extend_from_slice(if right_len == 0 {
+                        &[]
+                    } else {
+                        &right_contents[..(right_len - 2)]
+                    });
 
                     /*
                      * Construct a new end tag, including a new checksum:
@@ -250,7 +259,7 @@ where
                         result.iter().fold(0u8, |checksum, byte| checksum.wrapping_add(*byte)).wrapping_neg(),
                     );
 
-                    AmlValue::Buffer(Arc::new(result))
+                    AmlValue::Buffer(Arc::new(spinning_top::Spinlock::new(result)))
                 };
 
                 try_with_context!(context, context.store(target, result.clone()));
@@ -464,12 +473,17 @@ where
                         context,
                         match source {
                             AmlValue::Buffer(bytes) => {
-                                if index >= bytes.len() {
-                                    Ok(AmlValue::Buffer(Arc::new(vec![])))
-                                } else if (index + length) >= bytes.len() {
-                                    Ok(AmlValue::Buffer(Arc::new(bytes[index..].to_vec())))
+                                let foo = bytes.lock();
+                                if index >= foo.len() {
+                                    Ok(AmlValue::Buffer(Arc::new(spinning_top::Spinlock::new(vec![]))))
+                                } else if (index + length) >= foo.len() {
+                                    Ok(AmlValue::Buffer(Arc::new(spinning_top::Spinlock::new(
+                                        foo[index..].to_vec(),
+                                    ))))
                                 } else {
-                                    Ok(AmlValue::Buffer(Arc::new(bytes[index..(index + length)].to_vec())))
+                                    Ok(AmlValue::Buffer(Arc::new(spinning_top::Spinlock::new(
+                                        foo[index..(index + length)].to_vec(),
+                                    ))))
                                 }
                             }
                             /*

+ 7 - 5
aml/src/value.rs

@@ -6,6 +6,7 @@ use alloc::{
 };
 use bit_field::BitField;
 use core::{cmp, fmt, fmt::Debug};
+use spinning_top::Spinlock;
 
 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
 pub enum RegionSpace {
@@ -197,9 +198,9 @@ pub enum AmlValue {
         flags: MethodFlags,
         code: MethodCode,
     },
-    Buffer(Arc<Vec<u8>>),
+    Buffer(Arc<Spinlock<Vec<u8>>>),
     BufferField {
-        buffer_data: Arc<Vec<u8>>,
+        buffer_data: Arc<Spinlock<Vec<u8>>>,
         /// In bits.
         offset: u64,
         /// In bits.
@@ -283,7 +284,8 @@ impl AmlValue {
                  *
                  * XXX: Buffers with length `0` appear in real tables, so we return `0` for them.
                  */
-                let bytes = if bytes.len() > 8 { &bytes[0..8] } else { bytes };
+                let bytes = bytes.lock();
+                let bytes = if bytes.len() > 8 { &bytes[0..8] } else { &bytes[..] };
 
                 Ok(bytes.iter().rev().fold(0: u64, |mut i, &popped| {
                     i <<= 8;
@@ -302,7 +304,7 @@ impl AmlValue {
         }
     }
 
-    pub fn as_buffer(&self, context: &AmlContext) -> Result<Arc<Vec<u8>>, AmlError> {
+    pub fn as_buffer(&self, context: &AmlContext) -> Result<Arc<Spinlock<Vec<u8>>>, AmlError> {
         match self {
             AmlValue::Buffer(ref bytes) => Ok(bytes.clone()),
             // TODO: implement conversion of String and Integer to Buffer
@@ -513,7 +515,7 @@ impl AmlValue {
 
         match self_inner.type_of() {
             AmlType::Integer => Ok(self.as_integer(context)?.cmp(&other.as_integer(context)?)),
-            AmlType::Buffer => Ok(self.as_buffer(context)?.cmp(&other.as_buffer(context)?)),
+            AmlType::Buffer => Ok(self.as_buffer(context)?.lock().cmp(&other.as_buffer(context)?.lock())),
             AmlType::String => Ok(self.as_string(context)?.cmp(&other.as_string(context)?)),
             typ => Err(AmlError::TypeCannotBeCompared(typ)),
         }