Skip to content

Commit 68c240a

Browse files
committed
Implement Wait, Signal, and Reset opcodes for event synchronization
1 parent 806093c commit 68c240a

File tree

2 files changed

+104
-10
lines changed

2 files changed

+104
-10
lines changed

src/aml/mod.rs

Lines changed: 100 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,12 @@ use alloc::{
3737
vec::Vec,
3838
};
3939
use bit_field::BitField;
40-
use core::{mem, slice, str::FromStr, sync::atomic::Ordering};
40+
use core::{
41+
mem,
42+
slice,
43+
str::FromStr,
44+
sync::atomic::{AtomicU64, Ordering},
45+
};
4146
use log::{info, trace, warn};
4247
use namespace::{AmlName, Namespace, NamespaceLevelKind};
4348
use object::{
@@ -464,6 +469,91 @@ where
464469
context.contribute_arg(Argument::Object(result));
465470
context.retire_op(op);
466471
}
472+
Opcode::Reset => {
473+
let [Argument::Object(sync_object)] = &op.arguments[..] else {
474+
panic!();
475+
};
476+
let sync_object = sync_object.clone().unwrap_reference();
477+
478+
if let Object::Event(ref counter) = *sync_object {
479+
counter.store(0, Ordering::Release);
480+
} else {
481+
return Err(AmlError::InvalidOperationOnObject {
482+
op: Operation::ResetEvent,
483+
typ: sync_object.typ(),
484+
});
485+
}
486+
}
487+
Opcode::Signal => {
488+
let [Argument::Object(sync_object)] = &op.arguments[..] else {
489+
panic!();
490+
};
491+
let sync_object = sync_object.clone().unwrap_reference();
492+
493+
if let Object::Event(ref counter) = *sync_object {
494+
counter.fetch_add(1, Ordering::AcqRel);
495+
} else {
496+
return Err(AmlError::InvalidOperationOnObject {
497+
op: Operation::SignalEvent,
498+
typ: sync_object.typ(),
499+
});
500+
}
501+
}
502+
Opcode::Wait => {
503+
let [Argument::Object(sync_object), Argument::Object(timeout)] = &op.arguments[..] else {
504+
panic!();
505+
};
506+
let sync_object = sync_object.clone().unwrap_reference();
507+
let timeout = u64::min(timeout.as_integer()?, 0xffff);
508+
509+
if let Object::Event(ref counter) = *sync_object {
510+
/*
511+
* `Wait` returns a non-zero value if a timeout occurs and the event
512+
* was not signaled, and zero if it was. Timeout is specified in
513+
* milliseconds, should relinquish processor control (we use
514+
* `Handler::sleep` to do so) and a value of `0xffff` specifies that
515+
* the operation should wait indefinitely.
516+
*/
517+
let mut remaining_sleep = timeout;
518+
let mut timed_out = true;
519+
520+
'signaled: while remaining_sleep > 0 {
521+
loop {
522+
/*
523+
* Try to decrement the counter. If it's zero after a load, we
524+
* haven't been signalled and should wait for a bit. If it's
525+
* non-zero, we were signalled and should stop waiting.
526+
*/
527+
let value = counter.load(Ordering::Acquire);
528+
if value == 0 {
529+
break;
530+
}
531+
if counter
532+
.compare_exchange(value, value - 1, Ordering::AcqRel, Ordering::Acquire)
533+
.is_ok()
534+
{
535+
timed_out = false;
536+
break 'signaled;
537+
}
538+
}
539+
540+
let to_sleep = u64::min(timeout, 10);
541+
if timeout < 0xffff {
542+
remaining_sleep -= to_sleep
543+
}
544+
self.handler.sleep(to_sleep);
545+
}
546+
547+
context.contribute_arg(Argument::Object(
548+
Object::Integer(if timed_out { u64::MAX } else { 0 }).wrap(),
549+
));
550+
} else {
551+
return Err(AmlError::InvalidOperationOnObject {
552+
op: Operation::WaitEvent,
553+
typ: sync_object.typ(),
554+
});
555+
}
556+
}
467557
Opcode::FromBCD => self.do_from_bcd(&mut context, op)?,
468558
Opcode::ToBCD => self.do_to_bcd(&mut context, op)?,
469559
Opcode::Name => {
@@ -1150,17 +1240,17 @@ where
11501240
let name = context.namestring()?;
11511241

11521242
let name = name.resolve(&context.current_scope)?;
1153-
self.namespace.lock().insert(name, Object::Event.wrap())?;
1243+
self.namespace.lock().insert(name, Object::Event(Arc::new(AtomicU64::new(0))).wrap())?;
11541244
}
11551245
Opcode::LoadTable => todo!(),
11561246
Opcode::Load => todo!(),
11571247
Opcode::Stall => context.start_in_flight_op(OpInFlight::new(Opcode::Stall, 1)),
11581248
Opcode::Sleep => context.start_in_flight_op(OpInFlight::new(Opcode::Sleep, 1)),
11591249
Opcode::Acquire => context.start_in_flight_op(OpInFlight::new(opcode, 1)),
11601250
Opcode::Release => context.start_in_flight_op(OpInFlight::new(opcode, 1)),
1161-
Opcode::Signal => todo!(),
1162-
Opcode::Wait => todo!(),
1163-
Opcode::Reset => todo!(),
1251+
Opcode::Signal => context.start_in_flight_op(OpInFlight::new(opcode, 1)),
1252+
Opcode::Wait => context.start_in_flight_op(OpInFlight::new(opcode, 2)),
1253+
Opcode::Reset => context.start_in_flight_op(OpInFlight::new(opcode, 1)),
11641254
Opcode::Notify => todo!(),
11651255
Opcode::FromBCD | Opcode::ToBCD => context.start_in_flight_op(OpInFlight::new(opcode, 2)),
11661256
Opcode::Revision => {
@@ -1944,7 +2034,7 @@ where
19442034
Object::Buffer(bytes) => String::from_utf8_lossy(bytes).into_owned(),
19452035
Object::BufferField { .. } => "[Buffer Field]".to_string(),
19462036
Object::Device => "[Device]".to_string(),
1947-
Object::Event => "[Event]".to_string(),
2037+
Object::Event(_) => "[Event]".to_string(),
19482038
Object::FieldUnit(_) => "[Field]".to_string(),
19492039
Object::Integer(value) => value.to_string(),
19502040
Object::Method { .. } | Object::NativeMethod { .. } => "[Control Method]".to_string(),
@@ -3033,6 +3123,10 @@ pub enum Operation {
30333123
LogicalOp,
30343124
DecodePrt,
30353125
ParseResource,
3126+
3127+
ResetEvent,
3128+
SignalEvent,
3129+
WaitEvent,
30363130
}
30373131

30383132
#[derive(Clone, PartialEq, Debug)]

src/aml/object.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::aml::{AmlError, Handle, Operation, op_region::OpRegion};
22
use alloc::{borrow::Cow, string::String, sync::Arc, vec::Vec};
33
use bit_field::BitField;
4-
use core::{cell::UnsafeCell, fmt, ops};
4+
use core::{cell::UnsafeCell, fmt, ops, sync::atomic::AtomicU64};
55

66
type NativeMethod = dyn Fn(&[WrappedObject]) -> Result<WrappedObject, AmlError>;
77

@@ -11,7 +11,7 @@ pub enum Object {
1111
Buffer(Vec<u8>),
1212
BufferField { buffer: WrappedObject, offset: usize, length: usize },
1313
Device,
14-
Event,
14+
Event(Arc<AtomicU64>),
1515
FieldUnit(FieldUnit),
1616
Integer(u64),
1717
Method { code: Vec<u8>, flags: MethodFlags },
@@ -48,7 +48,7 @@ impl fmt::Display for Object {
4848
write!(f, "BufferField {{ offset: {offset}, length: {length} }}")
4949
}
5050
Object::Device => write!(f, "Device"),
51-
Object::Event => write!(f, "Event"),
51+
Object::Event(counter) => write!(f, "Event({counter:?})"),
5252
// TODO: include fields
5353
Object::FieldUnit(_) => write!(f, "FieldUnit"),
5454
Object::Integer(value) => write!(f, "Integer({value})"),
@@ -263,7 +263,7 @@ impl Object {
263263
Object::Buffer(_) => ObjectType::Buffer,
264264
Object::BufferField { .. } => ObjectType::BufferField,
265265
Object::Device => ObjectType::Device,
266-
Object::Event => ObjectType::Event,
266+
Object::Event(_) => ObjectType::Event,
267267
Object::FieldUnit(_) => ObjectType::FieldUnit,
268268
Object::Integer(_) => ObjectType::Integer,
269269
Object::Method { .. } => ObjectType::Method,

0 commit comments

Comments
 (0)