xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Process/Linux/Procfs.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1*f6aab3d8Srobert //===-- Procfs.cpp --------------------------------------------------------===//
2*f6aab3d8Srobert //
3*f6aab3d8Srobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*f6aab3d8Srobert // See https://llvm.org/LICENSE.txt for license information.
5*f6aab3d8Srobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*f6aab3d8Srobert //
7*f6aab3d8Srobert //===----------------------------------------------------------------------===//
8*f6aab3d8Srobert 
9*f6aab3d8Srobert #include "Procfs.h"
10*f6aab3d8Srobert #include "lldb/Host/linux/Support.h"
11*f6aab3d8Srobert #include "llvm/Support/MemoryBuffer.h"
12*f6aab3d8Srobert #include "llvm/Support/Threading.h"
13*f6aab3d8Srobert #include <optional>
14*f6aab3d8Srobert 
15*f6aab3d8Srobert using namespace lldb;
16*f6aab3d8Srobert using namespace lldb_private;
17*f6aab3d8Srobert using namespace process_linux;
18*f6aab3d8Srobert using namespace llvm;
19*f6aab3d8Srobert 
GetProcfsCpuInfo()20*f6aab3d8Srobert Expected<ArrayRef<uint8_t>> lldb_private::process_linux::GetProcfsCpuInfo() {
21*f6aab3d8Srobert   static ErrorOr<std::unique_ptr<MemoryBuffer>> cpu_info_or_err =
22*f6aab3d8Srobert       getProcFile("cpuinfo");
23*f6aab3d8Srobert 
24*f6aab3d8Srobert   if (!*cpu_info_or_err)
25*f6aab3d8Srobert     cpu_info_or_err.getError();
26*f6aab3d8Srobert 
27*f6aab3d8Srobert   MemoryBuffer &buffer = **cpu_info_or_err;
28*f6aab3d8Srobert   return arrayRefFromStringRef(buffer.getBuffer());
29*f6aab3d8Srobert }
30*f6aab3d8Srobert 
31*f6aab3d8Srobert Expected<std::vector<cpu_id_t>>
GetAvailableLogicalCoreIDs(StringRef cpuinfo)32*f6aab3d8Srobert lldb_private::process_linux::GetAvailableLogicalCoreIDs(StringRef cpuinfo) {
33*f6aab3d8Srobert   SmallVector<StringRef, 8> lines;
34*f6aab3d8Srobert   cpuinfo.split(lines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
35*f6aab3d8Srobert   std::vector<cpu_id_t> logical_cores;
36*f6aab3d8Srobert 
37*f6aab3d8Srobert   for (StringRef line : lines) {
38*f6aab3d8Srobert     std::pair<StringRef, StringRef> key_value = line.split(':');
39*f6aab3d8Srobert     auto key = key_value.first.trim();
40*f6aab3d8Srobert     auto val = key_value.second.trim();
41*f6aab3d8Srobert     if (key == "processor") {
42*f6aab3d8Srobert       cpu_id_t processor;
43*f6aab3d8Srobert       if (val.getAsInteger(10, processor))
44*f6aab3d8Srobert         return createStringError(
45*f6aab3d8Srobert             inconvertibleErrorCode(),
46*f6aab3d8Srobert             "Failed parsing the /proc/cpuinfo line entry: %s", line.data());
47*f6aab3d8Srobert       logical_cores.push_back(processor);
48*f6aab3d8Srobert     }
49*f6aab3d8Srobert   }
50*f6aab3d8Srobert   return logical_cores;
51*f6aab3d8Srobert }
52*f6aab3d8Srobert 
53*f6aab3d8Srobert llvm::Expected<llvm::ArrayRef<cpu_id_t>>
GetAvailableLogicalCoreIDs()54*f6aab3d8Srobert lldb_private::process_linux::GetAvailableLogicalCoreIDs() {
55*f6aab3d8Srobert   static std::optional<std::vector<cpu_id_t>> logical_cores_ids;
56*f6aab3d8Srobert   if (!logical_cores_ids) {
57*f6aab3d8Srobert     // We find the actual list of core ids by parsing /proc/cpuinfo
58*f6aab3d8Srobert     Expected<ArrayRef<uint8_t>> cpuinfo = GetProcfsCpuInfo();
59*f6aab3d8Srobert     if (!cpuinfo)
60*f6aab3d8Srobert       return cpuinfo.takeError();
61*f6aab3d8Srobert 
62*f6aab3d8Srobert     Expected<std::vector<cpu_id_t>> cpu_ids = GetAvailableLogicalCoreIDs(
63*f6aab3d8Srobert         StringRef(reinterpret_cast<const char *>(cpuinfo->data())));
64*f6aab3d8Srobert     if (!cpu_ids)
65*f6aab3d8Srobert       return cpu_ids.takeError();
66*f6aab3d8Srobert 
67*f6aab3d8Srobert     logical_cores_ids.emplace(std::move(*cpu_ids));
68*f6aab3d8Srobert   }
69*f6aab3d8Srobert   return *logical_cores_ids;
70*f6aab3d8Srobert }
71