15de0a3e9SWalter Erquinigo //===-- Procfs.cpp --------------------------------------------------------===//
25de0a3e9SWalter Erquinigo //
35de0a3e9SWalter Erquinigo // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45de0a3e9SWalter Erquinigo // See https://llvm.org/LICENSE.txt for license information.
55de0a3e9SWalter Erquinigo // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65de0a3e9SWalter Erquinigo //
75de0a3e9SWalter Erquinigo //===----------------------------------------------------------------------===//
85de0a3e9SWalter Erquinigo 
95de0a3e9SWalter Erquinigo #include "Procfs.h"
105de0a3e9SWalter Erquinigo 
115de0a3e9SWalter Erquinigo #include "lldb/Host/linux/Support.h"
125de0a3e9SWalter Erquinigo #include "llvm/Support/MemoryBuffer.h"
135de0a3e9SWalter Erquinigo 
141f49714dSWalter Erquinigo using namespace lldb;
155de0a3e9SWalter Erquinigo using namespace lldb_private;
165de0a3e9SWalter Erquinigo using namespace process_linux;
175de0a3e9SWalter Erquinigo using namespace llvm;
185de0a3e9SWalter Erquinigo 
GetProcfsCpuInfo()195de0a3e9SWalter Erquinigo Expected<ArrayRef<uint8_t>> lldb_private::process_linux::GetProcfsCpuInfo() {
205de0a3e9SWalter Erquinigo   static Optional<std::vector<uint8_t>> cpu_info;
215de0a3e9SWalter Erquinigo   if (!cpu_info) {
225de0a3e9SWalter Erquinigo     auto buffer_or_error = errorOrToExpected(getProcFile("cpuinfo"));
235de0a3e9SWalter Erquinigo     if (!buffer_or_error)
245de0a3e9SWalter Erquinigo       return buffer_or_error.takeError();
255de0a3e9SWalter Erquinigo     MemoryBuffer &buffer = **buffer_or_error;
265de0a3e9SWalter Erquinigo     cpu_info = std::vector<uint8_t>(
275de0a3e9SWalter Erquinigo         reinterpret_cast<const uint8_t *>(buffer.getBufferStart()),
285de0a3e9SWalter Erquinigo         reinterpret_cast<const uint8_t *>(buffer.getBufferEnd()));
295de0a3e9SWalter Erquinigo   }
305de0a3e9SWalter Erquinigo   return *cpu_info;
315de0a3e9SWalter Erquinigo }
325de0a3e9SWalter Erquinigo 
33*6a5355e8SWalter Erquinigo Expected<std::vector<cpu_id_t>>
GetAvailableLogicalCoreIDs(StringRef cpuinfo)345de0a3e9SWalter Erquinigo lldb_private::process_linux::GetAvailableLogicalCoreIDs(StringRef cpuinfo) {
355de0a3e9SWalter Erquinigo   SmallVector<StringRef, 8> lines;
365de0a3e9SWalter Erquinigo   cpuinfo.split(lines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
37*6a5355e8SWalter Erquinigo   std::vector<cpu_id_t> logical_cores;
385de0a3e9SWalter Erquinigo 
395de0a3e9SWalter Erquinigo   for (StringRef line : lines) {
405de0a3e9SWalter Erquinigo     std::pair<StringRef, StringRef> key_value = line.split(':');
415de0a3e9SWalter Erquinigo     auto key = key_value.first.trim();
425de0a3e9SWalter Erquinigo     auto val = key_value.second.trim();
435de0a3e9SWalter Erquinigo     if (key == "processor") {
44*6a5355e8SWalter Erquinigo       cpu_id_t processor;
455de0a3e9SWalter Erquinigo       if (val.getAsInteger(10, processor))
465de0a3e9SWalter Erquinigo         return createStringError(
475de0a3e9SWalter Erquinigo             inconvertibleErrorCode(),
485de0a3e9SWalter Erquinigo             "Failed parsing the /proc/cpuinfo line entry: %s", line.data());
495de0a3e9SWalter Erquinigo       logical_cores.push_back(processor);
505de0a3e9SWalter Erquinigo     }
515de0a3e9SWalter Erquinigo   }
525de0a3e9SWalter Erquinigo   return logical_cores;
535de0a3e9SWalter Erquinigo }
545de0a3e9SWalter Erquinigo 
55*6a5355e8SWalter Erquinigo llvm::Expected<llvm::ArrayRef<cpu_id_t>>
GetAvailableLogicalCoreIDs()565de0a3e9SWalter Erquinigo lldb_private::process_linux::GetAvailableLogicalCoreIDs() {
57*6a5355e8SWalter Erquinigo   static Optional<std::vector<cpu_id_t>> logical_cores_ids;
585de0a3e9SWalter Erquinigo   if (!logical_cores_ids) {
595de0a3e9SWalter Erquinigo     // We find the actual list of core ids by parsing /proc/cpuinfo
605de0a3e9SWalter Erquinigo     Expected<ArrayRef<uint8_t>> cpuinfo = GetProcfsCpuInfo();
615de0a3e9SWalter Erquinigo     if (!cpuinfo)
625de0a3e9SWalter Erquinigo       return cpuinfo.takeError();
635de0a3e9SWalter Erquinigo 
64*6a5355e8SWalter Erquinigo     Expected<std::vector<cpu_id_t>> cpu_ids = GetAvailableLogicalCoreIDs(
651f49714dSWalter Erquinigo         StringRef(reinterpret_cast<const char *>(cpuinfo->data())));
66*6a5355e8SWalter Erquinigo     if (!cpu_ids)
67*6a5355e8SWalter Erquinigo       return cpu_ids.takeError();
685de0a3e9SWalter Erquinigo 
69*6a5355e8SWalter Erquinigo     logical_cores_ids.emplace(std::move(*cpu_ids));
705de0a3e9SWalter Erquinigo   }
715de0a3e9SWalter Erquinigo   return *logical_cores_ids;
725de0a3e9SWalter Erquinigo }
73