Nothing to see here, move along
1use crate::cap::object::{NotificationData, ObjectData, ObjectTag};
2use crate::cap::pool::POOL;
3use crate::cap::table::{CapRef, Rights};
4use crate::ipc::IpcOutcome;
5use crate::ipc::notification;
6use crate::proc::{PROCESSES, ProcessState};
7
8fn alloc_notification() -> (crate::types::ObjectId, crate::types::Generation, CapRef) {
9 let (id, generation) = POOL
10 .lock()
11 .allocate(ObjectData::Notification(NotificationData::new()))
12 .expect("alloc notification");
13 let cap = CapRef::new(ObjectTag::Notification, id, Rights::ALL, generation);
14 (id, generation, cap)
15}
16
17crate::kernel_test!(
18 fn signal_sets_word_bits() {
19 let (id, generation, cap) = alloc_notification();
20 let mut ptable = PROCESSES.lock();
21 notification::do_signal(&cap, 0x0F, &mut ptable).expect("signal");
22
23 let mut pool = POOL.lock();
24 let notif = pool
25 .get_mut(id, generation)
26 .unwrap()
27 .as_notification_mut()
28 .unwrap();
29 assert!(notif.word == 0x0F, "word should have bits set");
30 drop(pool);
31 drop(ptable);
32 let _ = POOL.lock().dec_ref(id, generation);
33 }
34);
35
36crate::kernel_test!(
37 fn signal_accumulates_bits() {
38 let (id, generation, cap) = alloc_notification();
39 let mut ptable = PROCESSES.lock();
40 notification::do_signal(&cap, 0x01, &mut ptable).expect("signal 1");
41 notification::do_signal(&cap, 0x02, &mut ptable).expect("signal 2");
42
43 let mut pool = POOL.lock();
44 let notif = pool
45 .get_mut(id, generation)
46 .unwrap()
47 .as_notification_mut()
48 .unwrap();
49 assert!(notif.word == 0x03, "bits should accumulate via OR");
50 drop(pool);
51 drop(ptable);
52 let _ = POOL.lock().dec_ref(id, generation);
53 }
54);
55
56crate::kernel_test!(
57 fn poll_returns_word_and_clears() {
58 let (id, generation, cap) = alloc_notification();
59 {
60 let mut pool = POOL.lock();
61 pool.get_mut(id, generation)
62 .unwrap()
63 .as_notification_mut()
64 .unwrap()
65 .word = 0xFF;
66 }
67 let val = notification::do_poll(&cap).expect("poll");
68 assert!(val == 0xFF, "poll should return accumulated word");
69
70 let val2 = notification::do_poll(&cap).expect("poll again");
71 assert!(val2 == 0, "second poll should return 0 after clear");
72
73 let _ = POOL.lock().dec_ref(id, generation);
74 }
75);
76
77crate::kernel_test!(
78 fn wait_with_pending_returns_immediately() {
79 let (id, generation, cap) = alloc_notification();
80 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
81 let mut ptable = PROCESSES.lock();
82
83 let created = ptable.allocate(&mut allocator).expect("alloc");
84 ptable.start(created).expect("start");
85 let pid = created.pid();
86 ptable[pid]
87 .transition_to(ProcessState::Running)
88 .expect("-> Running");
89
90 {
91 let mut pool = POOL.lock();
92 pool.get_mut(id, generation)
93 .unwrap()
94 .as_notification_mut()
95 .unwrap()
96 .word = 0xAB;
97 }
98
99 let result = notification::do_wait(&cap, pid, &mut ptable).expect("wait");
100 match result {
101 IpcOutcome::Done(bits) => assert!(bits == 0xAB, "should return pending word"),
102 IpcOutcome::Blocked => panic!("should not block when word is pending"),
103 }
104
105 ptable.destroy(pid, &mut allocator);
106 let _ = POOL.lock().dec_ref(id, generation);
107 }
108);
109
110crate::kernel_test!(
111 fn wait_without_pending_blocks() {
112 let (id, generation, cap) = alloc_notification();
113 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
114 let mut ptable = PROCESSES.lock();
115
116 let created = ptable.allocate(&mut allocator).expect("alloc");
117 ptable.start(created).expect("start");
118 let pid = created.pid();
119 ptable[pid]
120 .transition_to(ProcessState::Running)
121 .expect("-> Running");
122
123 let result = notification::do_wait(&cap, pid, &mut ptable).expect("wait");
124 match result {
125 IpcOutcome::Blocked => {
126 assert!(
127 ptable[pid].state() == ProcessState::Blocked,
128 "process should be Blocked"
129 );
130 }
131 IpcOutcome::Done(_) => panic!("should block when no word pending"),
132 }
133
134 ptable.destroy(pid, &mut allocator);
135 let _ = POOL.lock().dec_ref(id, generation);
136 }
137);
138
139crate::kernel_test!(
140 fn signal_wakes_blocked_waiter() {
141 let (id, generation, cap) = alloc_notification();
142 let mut allocator = crate::mem::phys::BitmapFrameAllocator;
143 let mut ptable = PROCESSES.lock();
144
145 let created = ptable.allocate(&mut allocator).expect("alloc");
146 ptable.start(created).expect("start");
147 let pid = created.pid();
148 ptable[pid]
149 .transition_to(ProcessState::Running)
150 .expect("-> Running");
151
152 let result = notification::do_wait(&cap, pid, &mut ptable).expect("wait");
153 assert!(matches!(result, IpcOutcome::Blocked));
154
155 notification::do_signal(&cap, 0xDEAD, &mut ptable).expect("signal");
156
157 assert!(
158 ptable[pid].state() == ProcessState::Ready,
159 "waiter should be unblocked after signal"
160 );
161 assert!(
162 ptable[pid].saved_context.rdx == 0xDEAD,
163 "waiter's rdx should hold the signaled word"
164 );
165 assert!(
166 ptable[pid].saved_context.rax == 0,
167 "waiter's rax should be 0 (success)"
168 );
169
170 ptable.destroy(pid, &mut allocator);
171 let _ = POOL.lock().dec_ref(id, generation);
172 }
173);
174
175crate::kernel_test!(
176 fn poll_on_empty_returns_zero() {
177 let (id, generation, cap) = alloc_notification();
178 let val = notification::do_poll(&cap).expect("poll");
179 assert!(val == 0, "poll on fresh notification should return 0");
180 let _ = POOL.lock().dec_ref(id, generation);
181 }
182);