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*f6aab3d8SrobertExpected<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*f6aab3d8Srobertlldb_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*f6aab3d8Srobertlldb_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