starnix_core/power/
wakeup_count.rs1use crate::power::SuspendResumeManager;
6use crate::task::{
7 CurrentTask, EventHandler, SignalHandler, SignalHandlerInner, WaitCanceler, Waiter,
8};
9use crate::vfs::buffers::{InputBuffer, OutputBuffer};
10use crate::vfs::pseudo::simple_file::{SimpleFileNode, parse_unsigned_file, serialize_for_file};
11use crate::vfs::{FileObject, FileOps, FsNodeOps, fileops_impl_noop_sync, fileops_impl_seekless};
12use starnix_uapi::error;
13use starnix_uapi::errors::Errno;
14use starnix_uapi::vfs::FdEvents;
15use std::sync::Arc;
16
17pub struct PowerWakeupCountFile {
25 suspend_resume_manager: Arc<SuspendResumeManager>,
26 blocking_event: zx::EventPair,
27}
28
29impl PowerWakeupCountFile {
30 pub fn new_node(suspend_resume_manager: Arc<SuspendResumeManager>) -> impl FsNodeOps {
31 SimpleFileNode::new(move |_| {
32 Ok(Self {
33 suspend_resume_manager: suspend_resume_manager.clone(),
34 blocking_event: suspend_resume_manager.duplicate_lock_event(),
35 })
36 })
37 }
38}
39
40impl FileOps for PowerWakeupCountFile {
41 fileops_impl_seekless!();
42 fileops_impl_noop_sync!();
43
44 fn write(
45 &self,
46 _file: &FileObject,
47 _current_task: &CurrentTask,
48 _offset: usize,
49 data: &mut dyn InputBuffer,
50 ) -> Result<usize, Errno> {
51 let data = data.read_all()?;
52 let expected_count: u64 = parse_unsigned_file(&data)?;
53 let real_count = self.suspend_resume_manager.total_wakeup_events();
54 if expected_count != real_count {
55 return error!(EINVAL);
56 }
57 Ok(data.len())
58 }
59
60 fn read(
61 &self,
62 file: &FileObject,
63 current_task: &CurrentTask,
64 offset: usize,
65 data: &mut dyn OutputBuffer,
66 ) -> Result<usize, Errno> {
67 file.blocking_op(current_task, FdEvents::POLLIN | FdEvents::POLLHUP, None, || {
68 if !self.suspend_resume_manager.lock().can_suspend() {
69 return error!(EAGAIN);
70 }
71 let wakeup_count = self.suspend_resume_manager.total_wakeup_events();
72 let content = serialize_for_file(wakeup_count);
73 if offset >= content.len() {
74 return Ok(0);
75 }
76 data.write(&content[offset..])
77 })
78 }
79
80 fn wait_async(
81 &self,
82 _file: &FileObject,
83 _current_task: &CurrentTask,
84 waiter: &Waiter,
85 events: FdEvents,
86 handler: EventHandler,
87 ) -> Option<WaitCanceler> {
88 if events.contains(FdEvents::POLLIN) {
89 let signal_handler = SignalHandler {
90 inner: SignalHandlerInner::ZxHandle(|_signals| FdEvents::POLLIN),
91 event_handler: handler,
92 err_code: None,
93 };
94 return Some(WaitCanceler::new_port(
95 waiter
96 .wake_on_zircon_signals(
97 &self.blocking_event,
98 zx::Signals::USER_0,
99 signal_handler,
100 )
101 .expect("Failed to wait on zircon signals"),
102 ));
103 }
104 None
105 }
106
107 fn query_events(
108 &self,
109 _file: &FileObject,
110 _current_task: &CurrentTask,
111 ) -> Result<FdEvents, Errno> {
112 let mut events = FdEvents::POLLOUT;
113 if self.suspend_resume_manager.lock().can_suspend() {
114 events |= FdEvents::POLLIN;
115 }
116 Ok(events)
117 }
118}