ZXFoundation™ 26h2
Loading...
Searching...
No Matches
types.cxxm
1/// SPDX-License-Identifier: Apache-2.0
2/// @file zxfoundation/scoms/scoms_types.cxxm
3/// @brief SCOMS — Scalable Object Management System — core types.
4
5export module zxfoundation.scoms.kobject.types;
6import zxfoundation.base.types;
7import zxfoundation.base.typestate;
8import std;
9
10export {
11
12namespace zxfoundation::scoms::kobject {
13
14 using base::lifecycle_state;
15 using std::atomic;
16 using std::memory_order;
17
18 /// @brief value for an unassigned kernel-object id.
19 inline constexpr u32 KOBJECT_ID_INVALID = ~0U;
20
21 /// @brief Discriminates the concrete type behind a kobject pointer.
22 enum class kobject_type : u8 {
23 none = 0,
24 domain = 1,
25 gate = 2,
26 portal = 3,
27 vm_region = 4,
28 io_binding = 5,
29 capability = 6,
30 strand = 7,
31 irq_desc = 8,
32 memory_resource = 9,
33 memory_extent = 10,
34 memory_folio = 11,
35 page = 12,
36 storage = 13,
37 grant = 14,
38 mapping = 15,
39 address_space = 16,
40 page_table = 17,
41 key = 18,
42 endpoint = 19,
43 message = 20,
44 kmem_cache = 21,
45 policy_server = 22,
46 service_entry = 23,
47 device_binding = 24,
48 dataset_extent = 25,
49 };
50
51 /// @brief ASCII name for each kobject type (debug/printk).
52 [[nodiscard]] constexpr auto kobject_type_name(kobject::kobject_type t) noexcept
53 -> std::string_view
54 {
55 switch (t) {
56 case kobject::kobject_type::none: return "none";
57 case kobject::kobject_type::domain: return "domain";
58 case kobject::kobject_type::gate: return "gate";
59 case kobject::kobject_type::portal: return "portal";
60 case kobject::kobject_type::vm_region: return "vm_region";
61 case kobject::kobject_type::io_binding: return "io_binding";
62 case kobject::kobject_type::capability: return "capability";
63 case kobject::kobject_type::strand: return "strand";
64 case kobject::kobject_type::irq_desc: return "irq_desc";
65 case kobject::kobject_type::memory_resource: return "memory_resource";
66 case kobject::kobject_type::memory_extent: return "memory_extent";
67 case kobject::kobject_type::memory_folio: return "memory_folio";
68 case kobject::kobject_type::page: return "page";
69 case kobject::kobject_type::storage: return "storage";
70 case kobject::kobject_type::grant: return "grant";
71 case kobject::kobject_type::mapping: return "mapping";
72 case kobject::kobject_type::address_space: return "address_space";
73 case kobject::kobject_type::page_table: return "page_table";
74 case kobject::kobject_type::key: return "key";
75 case kobject::kobject_type::endpoint: return "endpoint";
76 case kobject::kobject_type::message: return "message";
77 case kobject::kobject_type::kmem_cache: return "kmem_cache";
78 case kobject::kobject_type::policy_server: return "policy_server";
79 case kobject::kobject_type::service_entry: return "service_entry";
80 case kobject::kobject_type::device_binding: return "device_binding";
81 case kobject::kobject_type::dataset_extent: return "dataset_extent";
82 default: return "unknown";
83 }
84 }
85
86 /// @brief Saturating atomic reference count.
87 struct kref {
88 atomic<u32> count{1};
89
90 /// @brief Acquire a reference only while the object remains live.
91 /// @return False when the last owner already released the object.
92 [[nodiscard]] auto try_get() noexcept -> bool {
93 u32 current = count.load(memory_order::acquire);
94 for (;;) {
95 if (current == 0U) return false;
96 if (current >= 0x7FFF'FFFEU) [[unlikely]] __builtin_trap();
97 if (count.compare_exchange_weak(
98 current, static_cast<u32>(current + 1U),
99 memory_order::acq_rel, memory_order::acquire)) {
100 return true;
101 }
102 }
103 }
104
105 /// @brief Decrement the reference count.
106 /// @return true if this was the LAST reference (count hit 0).
107 [[nodiscard]] auto put() noexcept -> bool {
108 const u32 prev = count.fetch_sub(1U, memory_order::release);
109 if (prev == 0U) [[unlikely]] {
110 __builtin_trap();
111 }
112 if (prev == 1U) {
113 atomic<u32> fence_dummy{0};
114 discard_value fence_dummy.load(memory_order::acquire);
115 return true;
116 }
117 return false;
118 }
119
120 /// @brief Read the current count (advisory — racy by definition).
121 [[nodiscard]] auto read() const noexcept -> u32 {
122 return count.load(memory_order::relaxed);
123 }
124
125 /// @brief Check if exactly one reference remains.
126 [[nodiscard]] auto is_one() const noexcept -> bool {
127 return count.load(memory_order::acquire) == 1U;
128 }
129 };
130
131 static_assert(sizeof(kref) == 4, "kref must be exactly 4 bytes");
132
133} // namespace zxfoundation::scoms
134
135} // end export