strat9_kernel/memory/
cow.rs1use crate::{
22 memory::{
23 frame::{frame_flags, get_meta, PhysFrame},
24 ownership_table, release_owned_block, resolve_handle, BlockHandle, OwnerError,
25 RemoveRefResult,
26 },
27 sync::SpinLock,
28};
29
30static COW_LOCK: SpinLock<()> = SpinLock::new(());
31
32#[inline]
34fn frame_meta(frame: PhysFrame) -> &'static crate::memory::frame::FrameMeta {
35 get_meta(frame.start_address)
36}
37
38#[inline]
40fn handle_meta(handle: BlockHandle) -> &'static crate::memory::frame::FrameMeta {
41 get_meta(handle.base)
42}
43
44pub fn handle_inc_ref(handle: BlockHandle) -> Result<u32, OwnerError> {
46 ownership_table().pin(handle)
47}
48
49pub fn handle_dec_ref(handle: BlockHandle) {
51 match ownership_table().unpin(handle) {
52 Ok(RemoveRefResult::Freed(block)) => release_owned_block(block),
53 Ok(RemoveRefResult::NowExclusive { .. })
54 | Ok(RemoveRefResult::StillPinned { .. })
55 | Ok(RemoveRefResult::StillShared { .. }) => {}
56 Err(error) => {
57 log::warn!(
58 "memory: failed to unpin shared handle {:#x}/{}: {:?}",
59 handle.base.as_u64(),
60 handle.order,
61 error
62 );
63 }
64 }
65}
66
67pub fn handle_get_refcount(handle: BlockHandle) -> u32 {
69 ownership_table()
70 .refcount(handle)
71 .unwrap_or_else(|| handle_meta(handle).get_refcount())
72}
73
74pub fn handle_init_ref(handle: BlockHandle) {
76 let meta = handle_meta(handle);
77 meta.set_order(handle.order);
78 meta.set_refcount(1);
79}
80
81pub fn frame_inc_ref(frame: PhysFrame) -> Result<u32, OwnerError> {
83 handle_inc_ref(resolve_handle(frame.start_address))
84}
85
86pub fn frame_dec_ref(frame: PhysFrame) {
88 handle_dec_ref(resolve_handle(frame.start_address));
89}
90
91pub fn frame_get_refcount(frame: PhysFrame) -> u32 {
93 handle_get_refcount(resolve_handle(frame.start_address))
94}
95
96pub fn frame_set_cow(frame: PhysFrame) {
98 let _lock = COW_LOCK.lock();
99 let meta = frame_meta(frame);
100 let flags = meta.get_flags() | frame_flags::COW;
101 meta.set_flags(flags);
102}
103
104pub fn frame_clear_cow(frame: PhysFrame) {
106 let _lock = COW_LOCK.lock();
107 let meta = frame_meta(frame);
108 let flags = meta.get_flags() & !frame_flags::COW;
109 meta.set_flags(flags);
110}
111
112pub fn frame_is_cow(frame: PhysFrame) -> bool {
114 frame_meta(frame).is_cow()
115}
116
117pub fn frame_set_dll(frame: PhysFrame) {
119 let _lock = COW_LOCK.lock();
120 let meta = frame_meta(frame);
121 let flags = meta.get_flags() | frame_flags::DLL;
122 meta.set_flags(flags);
123}
124
125pub fn frame_is_dll(frame: PhysFrame) -> bool {
127 frame_meta(frame).is_dll()
128}