]> git.lttng.org Git - lttng-tools.git/commitdiff
common: Add helper to get max possible CPU count
authorKienan Stewart <kstewart@efficios.com>
Wed, 13 Nov 2024 19:53:03 +0000 (14:53 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Tue, 3 Dec 2024 18:35:02 +0000 (13:35 -0500)
`get_max_possible_cpu_id()` is adapted from lttng-ust[1].

[1]: https://github.com/lttng/lttng-ust/blob/c0de10a2dab6d5cc6568e12c0ad3b97d85e0dc6b/src/common/smp.c#L197

Change-Id: I2697be51b21dad424c74d7397c1e6649ca7456bb
Signed-off-by: Kienan Stewart <kstewart@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
src/common/defaults.hpp
src/common/exception.hpp
src/common/utils.cpp
src/common/utils.hpp

index 8ca8bc02665ff2d3380e8251705a637fde5f324a..a0c218622187c0e5ceab26e2548808d6bfbceed6 100644 (file)
  */
 #define DEFAULT_ROTATE_PENDING_TIMER CONFIG_DEFAULT_ROTATE_PENDING_TIMER
 
+#define DEFAULT_LINUX_POSSIBLE_CPU_PATH "/sys/devices/system/cpu/possible"
+#define DEFAULT_LINUX_POSSIBLE_CPU_MASK_LENGTH 4096
+
 /*
  * Returns the default subbuf size.
  *
index 1d53e6402ee06c16461d742ac99420ccf01fd777..08afbb920b159635ecc9b617e0c76bd999024125 100644 (file)
 #include <string>
 #include <system_error>
 
+/*
+ * Indicate internal functions for which the caller should check exceptions
+ * that may be thrown.
+ *
+ * As the project is transitioning from C-style error return codes towards
+ * exception-based error handling in C++, this may be applied to function
+ * declarations alert users to the use of the different error-handling mechanism.
+ */
+#define LTTNG_MAY_THROW noexcept(false)
+
 #define LTTNG_SOURCE_LOCATION() lttng::source_location(__FILE__, __func__, __LINE__)
 
 #define LTTNG_THROW_CTL(msg, error_code) \
index 701a9f275b4a44568a74ca025b25719c80bc31bd..b1478c80a11990e143388bd118d6e228dd0b758f 100644 (file)
 #include <common/compat/getenv.hpp>
 #include <common/compat/string.hpp>
 #include <common/dynamic-buffer.hpp>
+#include <common/exception.hpp>
+#include <common/file-descriptor.hpp>
 #include <common/format.hpp>
 #include <common/readwrite.hpp>
 #include <common/runas.hpp>
+#include <common/scope-exit.hpp>
 #include <common/string-utils/c-string-view.hpp>
 #include <common/string-utils/format.hpp>
 
@@ -1384,3 +1387,85 @@ int utils_parse_unsigned_long_long(const char *str, unsigned long long *value)
 end:
        return ret;
 }
+
+/*
+ * Get the highest CPU id from a CPU mask.
+ *
+ * Returns the highest CPU id from the mask or throws an exception on error.
+ */
+namespace {
+unsigned int get_max_possible_cpu_id() LTTNG_MAY_THROW
+{
+       constexpr unsigned int cpu_mask_buffer_length{ DEFAULT_LINUX_POSSIBLE_CPU_MASK_LENGTH };
+       std::array<uint8_t, cpu_mask_buffer_length> possible_cpu_mask{};
+       static int max_possible_cpu_id{ 0 };
+       size_t possible_cpu_mask_len{ 0 };
+       unsigned long cpu_index{ 0 };
+       int i{};
+
+       if (max_possible_cpu_id != 0) {
+               return max_possible_cpu_id;
+       }
+
+       auto possible_cpu_mask_fd = [] {
+               int raw_handle = open(DEFAULT_LINUX_POSSIBLE_CPU_PATH, O_RDONLY);
+               if (raw_handle < 0) {
+                       LTTNG_THROW_POSIX(
+                               lttng::format("Failed to open possible CPU file, path='{}'",
+                                             DEFAULT_LINUX_POSSIBLE_CPU_PATH),
+                               errno);
+               }
+               return lttng::file_descriptor(raw_handle);
+       }();
+
+       const ssize_t bytes_read =
+               read(possible_cpu_mask_fd.fd(), possible_cpu_mask.data(), cpu_mask_buffer_length);
+       if (bytes_read == cpu_mask_buffer_length) {
+               uint8_t next{};
+               if (read(possible_cpu_mask_fd.fd(), &next, 1) != 0) {
+                       LTTNG_THROW_ERROR(lttng::format(
+                               "Possible CPU mask length exceeds maximum configured size: path='{}', max_size={}",
+                               DEFAULT_LINUX_POSSIBLE_CPU_PATH,
+                               cpu_mask_buffer_length));
+               }
+       }
+
+       possible_cpu_mask_len = (size_t) bytes_read;
+       if (possible_cpu_mask_len < 1) {
+               LTTNG_THROW_ERROR(lttng::format("0 bytes read from possible cpu file path={}",
+                                               DEFAULT_LINUX_POSSIBLE_CPU_PATH));
+       }
+
+       /* Start from the end to read the last CPU index. */
+       i = possible_cpu_mask_len;
+       for (auto iter = possible_cpu_mask.crbegin(); iter != possible_cpu_mask.crend(); iter++) {
+               /* Break when we hit the first separator. */
+               if ((possible_cpu_mask[i] == ',') || (possible_cpu_mask[i] == '-')) {
+                       i++;
+                       break;
+               }
+               i--;
+       }
+
+       cpu_index = strtoul((const char *) &possible_cpu_mask.data()[i],
+                           (char **) &possible_cpu_mask.data()[possible_cpu_mask_len],
+                           10);
+       if ((i != possible_cpu_mask_len) && (cpu_index < INT_MAX)) {
+               max_possible_cpu_id = (unsigned int) cpu_index;
+               return max_possible_cpu_id;
+       }
+
+       LTTNG_THROW_ERROR("Unable to determine maximum possible CPU id");
+       return 0;
+}
+} /* namespace */
+
+/*
+ * Return the count of possible CPUs on the system.
+ *
+ * Throws an error on failure.
+ */
+unsigned int utils_get_cpu_count() LTTNG_MAY_THROW
+{
+       return get_max_possible_cpu_id() + 1;
+}
index a15aa02a7d89f1995e483b93eaf28f8bdbf9f1cc..0d9f59afe8a929b1d5af477e9f1c57093320d251 100644 (file)
@@ -9,6 +9,7 @@
 #define _COMMON_UTILS_H
 
 #include <common/compat/directory-handle.hpp>
+#include <common/exception.hpp>
 
 #include <lttng/lttng-error.h>
 
@@ -60,6 +61,9 @@ int utils_get_memory_total(uint64_t *value);
 int utils_change_working_directory(const char *path);
 enum lttng_error_code utils_user_id_from_name(const char *user_name, uid_t *user_id);
 enum lttng_error_code utils_group_id_from_name(const char *group_name, gid_t *group_id);
+unsigned int utils_get_cpu_count() LTTNG_MAY_THROW;
+enum lttng_error_code utils_check_enough_available_memory(uint64_t num_bytes,
+                                                         uint64_t *bytes_available);
 
 /*
  * Parse `str` as an unsigned long long value.
This page took 0.032384 seconds and 4 git commands to generate.