Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 13 additions & 31 deletions include/heidi-kernel/gov_rule.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/* Resolved merge of gov_rule.h to keep P1 governor surface.
This file intentionally keeps a minimal, stable ApplyField ABI
(uint8_t) and the GovApplyMsg used by the process governor cherry-pick.
*/
#pragma once

#include <array>
Expand All @@ -22,13 +26,6 @@ enum class AckCode : uint8_t {
NACK_UNKNOWN_FIELD = 5,
NACK_QUEUE_FULL = 6,
NACK_PROCESS_DEAD = 7,
NACK_INVALID_GROUP = 8,
NACK_GROUP_CAPACITY = 9,
};

enum class GovVersion : uint8_t {
V1 = 1,
V2 = 2,
};

enum class ViolationAction : uint8_t {
Expand All @@ -42,13 +39,10 @@ struct CpuPolicy {
std::optional<std::string> affinity;
std::optional<int8_t> nice;
std::optional<uint8_t> max_pct;
std::optional<uint32_t> period_us;
std::optional<uint64_t> quota_us;
};

struct MemPolicy {
std::optional<uint64_t> max_bytes;
std::optional<uint64_t> high_bytes;
};

struct PidsPolicy {
Expand All @@ -62,21 +56,13 @@ struct RlimPolicy {
std::optional<uint64_t> core_hard;
};

struct TimeoutPolicy {
std::optional<uint32_t> apply_deadline_ms;
};

struct GovApplyMsg {
GovVersion version = GovVersion::V1;
int32_t pid = 0;
std::optional<std::string> group;
std::optional<ViolationAction> action;
std::optional<CpuPolicy> cpu;
std::optional<MemPolicy> mem;
std::optional<PidsPolicy> pids;
std::optional<RlimPolicy> rlim;
std::optional<int> oom_score_adj;
std::optional<TimeoutPolicy> timeouts;
};

struct ParseResult {
Expand All @@ -90,28 +76,24 @@ ParseResult parse_gov_apply(std::string_view payload);

std::string ack_to_string(AckCode code);

enum class ApplyField : uint16_t {
// Use a compact 8-bit bitmask for applied fields in the P1 API.
enum class ApplyField : uint8_t {
NONE = 0,
CPU_AFFINITY = 1 << 0,
CPU_NICE = 1 << 1,
CPU_MAX_PCT = 1 << 2,
CPU_PERIOD_US = 1 << 3,
MEM_MAX_BYTES = 1 << 4,
MEM_HIGH_BYTES = 1 << 5,
PIDS_MAX = 1 << 6,
RLIM_NOFILE = 1 << 7,
RLIM_CORE = 1 << 8,
OOM_SCORE_ADJ = 1 << 9,
GROUP = 1 << 10,
ACTION = 1 << 11,
TIMEOUT_APPLY_DEADLINE_MS = 1 << 12,
MEM_MAX_BYTES = 1 << 3,
PIDS_MAX = 1 << 4,
RLIM_NOFILE = 1 << 5,
RLIM_CORE = 1 << 6,
OOM_SCORE_ADJ = 1 << 7,
};

constexpr ApplyField operator|(ApplyField a, ApplyField b) {
return static_cast<ApplyField>(static_cast<uint16_t>(a) | static_cast<uint16_t>(b));
return static_cast<ApplyField>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
}
constexpr bool has_field(ApplyField fields, ApplyField field) {
return (static_cast<uint16_t>(fields) & static_cast<uint16_t>(field)) != 0;
return (static_cast<uint8_t>(fields) & static_cast<uint8_t>(field)) != 0;
}

} // namespace gov
Expand Down
80 changes: 4 additions & 76 deletions include/heidi-kernel/process_governor.h
Original file line number Diff line number Diff line change
@@ -1,68 +1,27 @@
#pragma once

#include "heidi-kernel/cgroup_driver.h"
#include "heidi-kernel/gov_rule.h"
#include "heidi-kernel/group_policy_store.h"

#include <atomic>
#include <cstdint>
#include <functional>
#include <memory>
#include <mutex>
#include <optional>
#include <queue>
#include <string>
#include <thread>
#include <unordered_map>
#include <vector>

namespace heidi {
namespace gov {

enum class GovEventType : uint8_t {
APPLY_SUCCESS = 0,
APPLY_FAILURE = 1,
PID_EXIT = 2,
PID_EVICTED = 3,
GROUP_EVICTED = 4,
PIDMAP_EVICTED = 5,
CGROUP_UNAVAILABLE = 6,
};

constexpr inline const char* gov_event_name(GovEventType e) {
switch (e) {
case GovEventType::APPLY_SUCCESS:
return "APPLY_SUCCESS";
case GovEventType::APPLY_FAILURE:
return "APPLY_FAILURE";
case GovEventType::PID_EXIT:
return "PID_EXIT";
case GovEventType::PID_EVICTED:
return "PID_EVICTED";
case GovEventType::GROUP_EVICTED:
return "GROUP_EVICTED";
case GovEventType::PIDMAP_EVICTED:
return "PIDMAP_EVICTED";
case GovEventType::CGROUP_UNAVAILABLE:
return "CGROUP_UNAVAILABLE";
}
return "UNKNOWN";
}

struct ApplyResult {
bool success = false;
int err = 0;
std::string error_detail;
ApplyField applied_fields = ApplyField::NONE;
};

struct PidHandle {
int pidfd = -1;
pid_t pid = 0;
uint64_t start_time_ns = 0;
uint64_t last_seen_ns = 0;
bool using_pidfd = false;
};

class ProcessGovernor {
public:
ProcessGovernor();
Expand All @@ -80,66 +39,35 @@ class ProcessGovernor {
struct Stats {
uint64_t messages_processed = 0;
uint64_t messages_failed = 0;
uint64_t messages_dropped = 0;
uint64_t last_err = 0;
std::string last_err_detail;
size_t rules_count = 0;
size_t tracked_pids = 0;
uint64_t pid_exit_events = 0;
uint64_t evicted_events = 0;
uint64_t group_evictions = 0;
uint64_t pidmap_evictions = 0;
uint64_t cgroup_unavailable_events = 0;
};
Stats get_stats() const;

void
set_event_callback(std::function<void(uint8_t event_type, const GovApplyMsg& msg, int err)> cb) {
event_callback_ = std::move(cb);
}

private:
void apply_loop();
void epoll_loop();

ApplyResult apply_rules(int32_t pid, const GovApplyMsg& msg);
ApplyResult apply_group_policy(int32_t pid, const GovApplyMsg& msg);
ApplyResult apply_cgroup_policy(int32_t pid, const GroupPolicy& group_policy);

ApplyResult apply_affinity(int32_t pid, const std::string& affinity);
ApplyResult apply_nice(int32_t pid, int8_t nice);
ApplyResult apply_rlimit(int32_t pid, const RlimPolicy& rlim);
ApplyResult apply_oom_score_adj(int32_t pid, int oom_score_adj);

bool track_pid(int32_t pid);
void untrack_pid(int32_t pid);
void cleanup_dead_pids();
bool is_process_alive(int32_t pid);

static constexpr size_t kQueueCapacity = 256;
static constexpr size_t kMaxTrackedPids = 4096;
static constexpr int kEpollMaxEvents = 64;
static constexpr size_t kMaxRules = 1024;

std::queue<GovApplyMsg> ingress_queue_;
mutable std::mutex queue_mutex_;
std::atomic<bool> running_{false};
std::thread apply_thread_;
std::thread epoll_thread_;
int epoll_fd_ = -1;

struct TrackedRule {
GovApplyMsg msg;
PidHandle handle;
};
std::unordered_map<int32_t, TrackedRule> rules_;
std::unordered_map<int32_t, GovApplyMsg> rules_;
mutable std::mutex rules_mutex_;

std::function<void(uint8_t event_type, const GovApplyMsg& msg, int err)> event_callback_;

GroupPolicyStore group_store_;
CgroupDriver cgroup_driver_;
uint64_t last_cgroup_unavailable_ns_ = 0;
static constexpr uint64_t kCgroupUnavailableRateLimitNs = 1000000000ULL;

Stats stats_;
};

Expand Down
2 changes: 1 addition & 1 deletion src/governor/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ target_link_libraries(heidi-kernel-governor
heidi-kernel-lib
)

target_compile_options(heidi-kernel-governor PRIVATE -Wall -Wextra -Wpedantic)
target_compile_options(heidi-kernel-governor PRIVATE -Wall -Wextra -Wpedantic)
Loading
Loading