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