Skip to content
Draft
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
17 changes: 17 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ score_log = { git = "https://github.com/eclipse-score/baselibs_rust.git", tag =
score_testing_macros = { git = "https://github.com/eclipse-score/baselibs_rust.git", tag = "v0.0.4" }
stdout_logger = { git = "https://github.com/eclipse-score/baselibs_rust.git", tag = "v0.0.4" }
containers = { git = "https://github.com/eclipse-score/baselibs_rust.git", tag = "v0.0.4" }
thread = { git = "https://github.com/eclipse-score/baselibs_rust.git", rev = "237f7fb228168f114bfcdf5dcb94cebcf0f8f7e8"}

[workspace.lints.clippy]
std_instead_of_core = "warn"
Expand Down
6 changes: 6 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@ pip.parse(
use_repo(pip, "pip_score_venv_test")

bazel_dep(name = "score_baselibs_rust", version = "0.1.0")
git_override(
module_name = "score_baselibs_rust",
commit = "237f7fb228168f114bfcdf5dcb94cebcf0f8f7e8",
remote = "https://github.com/eclipse-score/baselibs_rust.git",
)

bazel_dep(name = "score_baselibs", version = "0.2.4")
bazel_dep(name = "score_logging", version = "0.1.0")

Expand Down
2 changes: 0 additions & 2 deletions MODULE.bazel.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/health_monitoring_lib/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ load("@score_baselibs//:bazel/unit_tests.bzl", "cc_gtest_unit_test")

COMMON_DEPS = [
"@score_baselibs_rust//src/containers:containers",
"@score_baselibs_rust//src/thread:thread",
"@score_baselibs_rust//src/log/score_log:score_log",
"//src/launch_manager_daemon/health_monitor_lib/rust_bindings:monitor_rs",
]
Expand All @@ -31,11 +32,13 @@ CC_SOURCES = [
"cpp/heartbeat_monitor.cpp",
"cpp/logic_monitor.cpp",
"cpp/health_monitor.cpp",
"cpp/thread.cpp",
]

CC_HDRS = [
"cpp/include/score/hm/common.h",
"cpp/include/score/hm/tag.h",
"cpp/include/score/hm/thread.h",
"cpp/include/score/hm/deadline/deadline_monitor.h",
"cpp/include/score/hm/heartbeat/heartbeat_monitor.h",
"cpp/include/score/hm/logic/logic_monitor.h",
Expand Down
1 change: 1 addition & 0 deletions src/health_monitoring_lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ path = "rust/lib.rs"
workspace = true

[dependencies]
thread.workspace = true
score_log.workspace = true
score_testing_macros.workspace = true
containers.workspace = true
Expand Down
21 changes: 19 additions & 2 deletions src/health_monitoring_lib/cpp/health_monitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ FFICode health_monitor_builder_destroy(FFIHandle health_monitor_builder_handle);
FFICode health_monitor_builder_build(FFIHandle health_monitor_builder_handle,
uint32_t supervisor_cycle_ms,
uint32_t internal_cycle_ms,
FFIHandle thread_parameters_handle,
FFIHandle* health_monitor_handle_out);
FFICode health_monitor_builder_add_deadline_monitor(FFIHandle health_monitor_builder_handle,
const MonitorTag* monitor_tag,
Expand Down Expand Up @@ -125,17 +126,33 @@ HealthMonitorBuilder HealthMonitorBuilder::with_supervisor_api_cycle(std::chrono
return std::move(*this);
}

HealthMonitorBuilder HealthMonitorBuilder::thread_parameters(score::hm::ThreadParameters&& thread_parameters) &&
{
thread_parameters_ = std::move(thread_parameters);
return std::move(*this);
}

score::cpp::expected<HealthMonitor, Error> HealthMonitorBuilder::build() &&
{
auto health_monitor_builder_handle = health_monitor_builder_handle_.drop_by_rust();
SCORE_LANGUAGE_FUTURECPP_PRECONDITION(health_monitor_builder_handle.has_value());

uint32_t supervisor_duration_ms = static_cast<uint32_t>(supervisor_api_cycle_duration_.count());
uint32_t internal_duration_ms = static_cast<uint32_t>(internal_processing_cycle_duration_.count());
FFIHandle thread_parameters_handle{nullptr};
if (thread_parameters_.has_value())
{
auto rust_handle{thread_parameters_.value().drop_by_rust()};
SCORE_LANGUAGE_FUTURECPP_ASSERT(rust_handle.has_value());
thread_parameters_handle = rust_handle.value();
}

FFIHandle health_monitor_handle{nullptr};
auto result{health_monitor_builder_build(
health_monitor_builder_handle.value(), supervisor_duration_ms, internal_duration_ms, &health_monitor_handle)};
auto result{health_monitor_builder_build(health_monitor_builder_handle.value(),
supervisor_duration_ms,
internal_duration_ms,
thread_parameters_handle,
&health_monitor_handle)};
if (result != kSuccess)
{
return score::cpp::unexpected(static_cast<Error>(result));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <score/hm/heartbeat/heartbeat_monitor.h>
#include <score/hm/logic/logic_monitor.h>
#include <score/hm/tag.h>
#include <score/hm/thread.h>

namespace score::hm
{
Expand Down Expand Up @@ -59,6 +60,9 @@ class HealthMonitorBuilder final
/// This duration determines how often the health monitor checks deadlines.
HealthMonitorBuilder with_internal_processing_cycle(std::chrono::milliseconds cycle_duration) &&;

/// Sets the monitoring thread parameters.
HealthMonitorBuilder thread_parameters(score::hm::ThreadParameters&& thread_parameters) &&;

/// Build a new `HealthMonitor` instance based on provided parameters.
score::cpp::expected<HealthMonitor, Error> build() &&;

Expand All @@ -67,6 +71,7 @@ class HealthMonitorBuilder final

std::chrono::milliseconds supervisor_api_cycle_duration_;
std::chrono::milliseconds internal_processing_cycle_duration_;
std::optional<ThreadParameters> thread_parameters_;
};

class HealthMonitor final
Expand Down
91 changes: 91 additions & 0 deletions src/health_monitoring_lib/cpp/include/score/hm/thread.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/********************************************************************************
* Copyright (c) 2026 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/
#ifndef SCORE_HM_THREAD_H
#define SCORE_HM_THREAD_H

#include "common.h"
#include <cstdint>
#include <vector>

namespace score::hm
{

class HealthMonitorBuilder;

/// Scheduler policy.
enum class SchedulerPolicy : int32_t
{
Other,
Fifo,
RoundRobin,
};

/// Get min thread priority for given policy.
int32_t scheduler_policy_priority_min(SchedulerPolicy scheduler_policy);

/// Get max thread priority for given policy.
int32_t scheduler_policy_priority_max(SchedulerPolicy scheduler_policy);

class SchedulerParameters final
{
public:
/// Create a new `SchedulerParameters`.
/// Priority must be in allowed range for the scheduler policy.
SchedulerParameters(SchedulerPolicy policy, int32_t priority);

/// Scheduler policy.
SchedulerPolicy policy() const;

/// Thread priority.
int32_t priority() const;

private:
SchedulerPolicy policy_;
int32_t priority_;
};

/// Thread parameters.
class ThreadParameters final : public internal::RustDroppable<ThreadParameters>
{
public:
/// Create a new `ThreadParameters` containing default values.
ThreadParameters();

/// Scheduler parameters, including scheduler policy and thread priority.
ThreadParameters scheduler_parameters(SchedulerParameters scheduler_parameters) &&;

/// Set thread affinity - array of CPU core IDs that the thread can run on.
ThreadParameters affinity(const std::vector<size_t>& affinity) &&;

/// Set stack size.
ThreadParameters stack_size(size_t stack_size) &&;

protected:
std::optional<internal::FFIHandle> _drop_by_rust_impl()
{
return thread_parameters_handle_.drop_by_rust();
}

private:
internal::DroppableFFIHandle thread_parameters_handle_;

// Allow to hide `drop_by_rust` implementation.
friend class internal::RustDroppable<ThreadParameters>;

// Allow `HealthMonitorBuilder` to access `drop_by_rust` implementation.
friend class score::hm::HealthMonitorBuilder;
};

} // namespace score::hm

#endif // SCORE_HM_THREAD_H
4 changes: 4 additions & 0 deletions src/health_monitoring_lib/cpp/tests/health_monitor_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,16 @@ TEST_F(HealthMonitorTest, TestName)
auto logic_monitor_builder =
logic::LogicMonitorBuilder{from_state}.add_state(from_state, std::vector{to_state}).add_state(to_state, {});

// Thread parameters.
auto thread_parameters{ThreadParameters().affinity(std::vector<size_t>{0})};

auto hmon_result{HealthMonitorBuilder()
.add_deadline_monitor(deadline_monitor_tag, std::move(deadline_monitor_builder))
.add_heartbeat_monitor(heartbeat_monitor_tag, std::move(heartbeat_monitor_builder))
.add_logic_monitor(logic_monitor_tag, std::move(logic_monitor_builder))
.with_internal_processing_cycle(std::chrono::milliseconds(50))
.with_supervisor_api_cycle(std::chrono::milliseconds(50))
.thread_parameters(std::move(thread_parameters))
.build()};
EXPECT_TRUE(hmon_result.has_value());
auto hm{std::move(hmon_result.value())};
Expand Down
120 changes: 120 additions & 0 deletions src/health_monitoring_lib/cpp/thread.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/********************************************************************************
* Copyright (c) 2026 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

#include "score/hm/thread.h"
#include <score/assert.hpp>

namespace
{
extern "C" {

using namespace score::hm;
using namespace score::hm::internal;

// Functions below must match functions defined in `crate::thread_ffi`.

FFICode scheduler_policy_priority_min(SchedulerPolicy scheduler_policy, int32_t* priority_out);
FFICode scheduler_policy_priority_max(SchedulerPolicy scheduler_policy, int32_t* priority_out);
FFICode thread_parameters_create(FFIHandle* thread_parameters_handle_out);
FFICode thread_parameters_destroy(FFIHandle thread_parameters_handle);
FFICode thread_parameters_scheduler_parameters(FFIHandle thread_parameters_handle,
SchedulerParameters scheduler_parameters);
FFICode thread_parameters_affinity(FFIHandle thread_parameters_handle, const size_t* affinity, size_t num_affinity);
FFICode thread_parameters_stack_size(FFIHandle thread_parameters_handle, size_t stack_size);
Comment on lines +26 to +33
}

FFIHandle thread_parameters_create_wrapper()
{
FFIHandle handle{nullptr};
auto result{thread_parameters_create(&handle)};
SCORE_LANGUAGE_FUTURECPP_ASSERT(result == kSuccess);
return handle;
}
} // namespace

namespace score::hm
{

int32_t scheduler_policy_priority_min(SchedulerPolicy scheduler_policy)
{
int32_t priority{0};
auto result{::scheduler_policy_priority_min(scheduler_policy, &priority)};
SCORE_LANGUAGE_FUTURECPP_ASSERT(result == kSuccess);
return priority;
}

int32_t scheduler_policy_priority_max(SchedulerPolicy scheduler_policy)
{
int32_t priority{0};
auto result{::scheduler_policy_priority_max(scheduler_policy, &priority)};
SCORE_LANGUAGE_FUTURECPP_ASSERT(result == kSuccess);
return priority;
}

SchedulerParameters::SchedulerParameters(SchedulerPolicy policy, int32_t priority)
: policy_{policy}, priority_{priority}
{
auto min{scheduler_policy_priority_min(policy)};
auto max{scheduler_policy_priority_max(policy)};
SCORE_LANGUAGE_FUTURECPP_ASSERT(priority >= min && priority <= max);
}

SchedulerPolicy SchedulerParameters::policy() const
{
return policy_;
}

int32_t SchedulerParameters::priority() const
{
return priority_;
}

ThreadParameters::ThreadParameters()
: thread_parameters_handle_{thread_parameters_create_wrapper(), &thread_parameters_destroy}
{
}

ThreadParameters ThreadParameters::scheduler_parameters(SchedulerParameters scheduler_parameters) &&
{
auto rust_handle{thread_parameters_handle_.as_rust_handle()};
SCORE_LANGUAGE_FUTURECPP_PRECONDITION(rust_handle.has_value());

auto result{thread_parameters_scheduler_parameters(rust_handle.value(), scheduler_parameters)};
SCORE_LANGUAGE_FUTURECPP_ASSERT(result == kSuccess);

return std::move(*this);
}

ThreadParameters ThreadParameters::affinity(const std::vector<size_t>& affinity) &&
{
auto rust_handle{thread_parameters_handle_.as_rust_handle()};
SCORE_LANGUAGE_FUTURECPP_PRECONDITION(rust_handle.has_value());

auto result{thread_parameters_affinity(rust_handle.value(), affinity.data(), affinity.size())};
SCORE_LANGUAGE_FUTURECPP_ASSERT(result == kSuccess);

return std::move(*this);
}

ThreadParameters ThreadParameters::stack_size(size_t stack_size) &&
{
auto rust_handle{thread_parameters_handle_.as_rust_handle()};
SCORE_LANGUAGE_FUTURECPP_PRECONDITION(rust_handle.has_value());

auto result{thread_parameters_stack_size(rust_handle.value(), stack_size)};
SCORE_LANGUAGE_FUTURECPP_ASSERT(result == kSuccess);

return std::move(*this);
}

} // namespace score::hm
Loading
Loading