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