ZXFoundation™ 26h2
Loading...
Searching...
No Matches
core.cxxm
1/// SPDX-License-Identifier: Apache-2.0
2/// @file lib/softirq.cxxm
3/// @brief Generic softirq framework
4
5export module lib.softirq.core;
6import zxfoundation.base.types;
7import lib.error;
8import std;
9
10export {
11
12namespace lib {
13
14 /// @brief Softirq vector identifier.
15 enum class softirq_vec : u8 {
16 hi = 0, ///< High-priority tasklets (legacy slot, reserved).
17 timer = 1, ///< Timer expiry release work.
18 net_tx = 2, ///< Network transmit (reserved for future net domain).
19 net_rx = 3, ///< Network receive (reserved for future net domain).
20 block = 4, ///< Block I/O completion (reserved).
21 irq_poll = 5, ///< IRQ poll softirq (reserved).
22 tasklet = 6, ///< Generic tasklet vector (reserved).
23 sched = 7, ///< Scheduler load-balancing softirq.
24 hrtimer = 8, ///< High-resolution timer softirq.
25 rcu = 9, ///< Read-Copy-Update grace-period advancement.
26 mutex_release = 10, ///< Slow-path mutex release.
27 nohz_idle = 11, ///< nohz idle balance kick.
28 numa = 12, ///< NUMA balancing hint.
29 _count ///< Sentinel: number of softirq vectors supported.
30 };
31
32 static_assert(static_cast<u32>(softirq_vec::_count) <= 32U,
33 "softirq vector count must fit the u32 pending bitmap");
34
35 /// @brief Convert a softirq vector to its bit position in the pending bitmap.
36 /// @param[in] v Softirq vector identifier.
37 /// @return Bit position (0..31).
38 [[nodiscard]] constexpr auto softirq_bit(softirq_vec v) noexcept -> u32 {
39 return 1U << static_cast<u32>(v);
40 }
41
42 /// @brief Convert a softirq vector to its dense index in the vector table.
43 /// @param[in] v Softirq vector identifier.
44 /// @return Dense index 0 .. N-1 where N is the number of supported vectors.
45 [[nodiscard]] constexpr auto softirq_index(softirq_vec v) noexcept -> u32 {
46 return static_cast<u32>(v);
47 }
48
49 /// @brief Maximum number of softirq vectors supported by the framework.
50 inline constexpr u32 NR_SOFTIRQS = static_cast<u32>(softirq_vec::_count);
51
52 /// @brief Function pointer type invoked by the softirq dispatcher.
53 /// @param[in] data Opaque context registered with @c open_softirq.
54 using softirq_fn = auto (*)(void* data) noexcept -> void;
55
56 /// @brief One entry in the global softirq vector table.
57 struct softirq_entry {
58 softirq_fn action{nullptr};
59 void* data{nullptr};
60 /// @brief Generation counter bumped on @c open_softirq, allowing callers
61 /// to detect re-registration of a vector slot (e.g. for diagnostics).
62 std::atomic<u32> generation{0U};
63 };
64
65 static_assert(sizeof(softirq_entry) <= 24U,
66 "softirq_entry must fit one cache line stride (no false sharing)");
67
68 /// @brief Per-CPU softirq execution state.
69 struct softirq_state {
70 /// @brief Bitmap of pending softirq vectors (one bit per @c softirq_vec).
71 std::atomic<u32> pending{0U};
72 /// @brief Snapshot of pending bits being processed right now in @c do_softirq.
73 u32 processing{0U};
74 /// @brief Recursive re-entry guard (a softirq may raise another softirq).
75 u32 nest{0U};
76 /// @brief Monotonic counter bumped every time @c do_softirq is entered.
77 u64 dispatch_count{0U};
78 /// @brief Monotonic counter bumped every time @c raise_softirq actually sets a bit.
79 u64 raise_count{0U};
80 };
81
82 /// @brief Reserved value for "no softirq vector" returns.
83 inline constexpr softirq_vec SOFTIRQ_VEC_NONE = static_cast<softirq_vec>(0xFFU);
84
85 /// @brief Register a handler for a softirq vector.
86 /// @param[in] v Softirq vector to register.
87 /// @param[in] action Callback invoked by @c do_softirq when @c v is pending.
88 /// @param[in] data Opaque caller context passed back to @c action.
89 /// @return Success when the slot was free, or @c kernel_error::already_locked
90 /// when the slot was already registered.
91 [[nodiscard]] auto open_softirq(
92 softirq_vec v,
93 softirq_fn action,
94 void* data
95 ) noexcept -> std::expected<void, lib::kernel_error>;
96
97 /// @brief Mark a softirq vector as pending on the current CPU.
98 /// @param[in] v Vector to raise.
99 auto raise_softirq(softirq_vec v) noexcept -> void;
100
101 /// @brief Mark a softirq vector as pending on a *remote* CPU.
102 /// @param[in] cpu Target CPU id (logical, not absolute).
103 /// @param[in] v Softirq vector to raise.
104 auto raise_softirq_on(u16 cpu, softirq_vec v) noexcept -> void;
105
106 /// @brief Test whether any softirq is pending on the current CPU.
107 /// @return True when at least one vector is pending and dispatchable.
108 [[nodiscard]] auto softirq_pending() noexcept -> bool;
109
110 /// @brief Drain all pending softirq vectors on the current CPU.
111 auto do_softirq() noexcept -> void;
112
113 /// @brief Clear a pending softirq vector without dispatching it.
114 /// @param[in] v Vector to clear.
115 /// @return True when a pending bit was cleared; false when no work was pending.
116 [[nodiscard]] auto softirq_clear(softirq_vec v) noexcept -> bool;
117
118 /// @brief Test whether a particular softirq vector is pending on this CPU.
119 /// @param[in] v Vector to test.
120 [[nodiscard]] auto softirq_test(softirq_vec v) noexcept -> bool;
121
122 /// @brief Read this CPU's softirq dispatch statistics (for diagnostics).
123 /// @return A pair (raise_count, dispatch_count).
124 [[nodiscard]] auto softirq_stats() noexcept -> std::pair<u64, u64>;
125
126 /// @brief Return the global vector-table entry for a softirq vector.
127 /// @param[in] v Vector to inspect.
128 /// @return Const reference to the registered entry (action may be nullptr
129 /// when the slot was never opened).
130 [[nodiscard]] auto softirq_entry_for(softirq_vec v) noexcept -> const softirq_entry&;
131
132} // namespace lib
133
134} // end export