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