GCC Code Coverage Report


Directory: Os/
File: Linux/Cpu.cpp
Date: 2026-09-03 21:15:10
Exec Total Coverage
Lines: 0 48 0.0%
Functions: 0 4 0.0%
Branches: 0 32 0.0%

Line Branch Exec Source
1 // ======================================================================
2 // \title Os/Linux/Cpu.cpp
3 // \brief Linux implementation for Os::Cpu
4 // ======================================================================
5 #include <unistd.h>
6 #include <Fw/Types/Assert.hpp>
7 #include <Fw/Types/StringUtils.hpp>
8 #include <Os/File.hpp>
9 #include <Os/Linux/Cpu.hpp>
10 #include <cstring>
11 namespace Os {
12 namespace Linux {
13 namespace Cpu {
14
15 // Proc FS /proc/stat file format example:
16 //
17 // cpu 270288 1598 88660 8470416 15185 9775 2990 867 0 0
18 // cpu0 67462 108 22104 2118172 3779 2540 648 287 0 0
19 // cpu1 74237 650 24059 2109680 2995 2447 667 93 0 0
20 // cpu2 69388 630 22033 2115177 4428 2424 649 378 0 0
21 // cpu3 59199 209 20462 2127387 3981 2363 1024 108 0 0
22 // ...
23
24 // Needed format, and compliant with kernel < 2.5
25 enum ProcCpuMeasures { CPU_NUMBER = 0, USER = 1, NICE = 2, SYSTEM = 3, IDLE = 4, MAX_CPU_TICK_TYPES = 8 };
26
27 using ProcCpuData = FwSizeType[ProcCpuMeasures::MAX_CPU_TICK_TYPES];
28 constexpr FwSizeType LINE_SIZE = 255; // log10(max(U64)) * 11 fields (kernel 2.6.33) = 220. Round to 256 - 1 (\0)
29
30 CpuInterface::Status getCpuData(FwSizeType cpu_index, ProcCpuData data) {
31 Os::File file;
32 // Open the procfs file
33 constexpr char PROC_STAT_PATH[] = "/proc/stat";
34 if (file.open(PROC_STAT_PATH, Os::File::Mode::OPEN_READ) != Os::File::Status::OP_OK) {
35 return CpuInterface::Status::ERROR;
36 }
37 char proc_stat_line[LINE_SIZE + 1];
38 // File starts with cpu line, then individual CPUs.
39 const FwSizeType line_count = cpu_index + 2;
40 for (FwSizeType i = 0; i < line_count; i++) {
41 FwSizeType read_size = sizeof proc_stat_line - 1;
42 Os::File::Status file_status =
43 file.readline(reinterpret_cast<U8*>(proc_stat_line), read_size, Os::File::WaitType::NO_WAIT);
44 if (file_status != Os::File::Status::OP_OK) {
45 return CpuInterface::Status::ERROR;
46 }
47 proc_stat_line[read_size] = '\0'; // Null terminate, read_size is at most LINE_SIZE
48 // Make sure we've not strayed passed the cpu section
49 if (::strncmp(proc_stat_line, "cpu", 3) != 0) {
50 return CpuInterface::Status::ERROR;
51 }
52 }
53 char* token_start = proc_stat_line + 3; // Length of "cpu"
54 for (FwSizeType i = 0; i < ProcCpuMeasures::MAX_CPU_TICK_TYPES; i++) {
55 FwSizeType token = 0;
56 Fw::StringUtils::StringToNumberStatus status = Fw::StringUtils::string_to_number(
57 token_start,
58 static_cast<FwSizeType>(sizeof proc_stat_line) - static_cast<FwSizeType>(token_start - proc_stat_line),
59 token, &token_start);
60 // Check conversion success
61 if (status != Fw::StringUtils::StringToNumberStatus::SUCCESSFUL_CONVERSION) {
62 return CpuInterface::Status::ERROR;
63 }
64 data[i] = token;
65 // Check cpu index is correct
66 if (i == ProcCpuMeasures::CPU_NUMBER and data[i] != cpu_index) {
67 return CpuInterface::Status::ERROR;
68 }
69 }
70 return CpuInterface::Status::OP_OK;
71 }
72
73 CpuInterface::Status LinuxCpu::_getCount(FwSizeType& cpu_count) {
74 long cpus = sysconf(_SC_NPROCESSORS_ONLN);
75 if ((cpus > 0) && (static_cast<FwSizeType>(cpus) < std::numeric_limits<FwSizeType>::max())) {
76 cpu_count = static_cast<FwSizeType>(cpus);
77 return Status::OP_OK;
78 }
79 cpu_count = 0;
80 return Status::ERROR;
81 }
82
83 CpuInterface::Status LinuxCpu::_getTicks(Os::Cpu::Ticks& ticks, FwSizeType cpu_index) {
84 FwSizeType count = 0;
85 CpuInterface::Status status = this->_getCount(count);
86 if (status != CpuInterface::Status::OP_OK) {
87 return status;
88 } else if (cpu_index >= count) {
89 return CpuInterface::Status::ERROR;
90 }
91 ProcCpuData cpu_data = {0, 0, 0, 0, 0, 0, 0, 0};
92 status = getCpuData(cpu_index, cpu_data);
93 ticks.used = cpu_data[ProcCpuMeasures::USER] + cpu_data[ProcCpuMeasures::NICE] + cpu_data[ProcCpuMeasures::SYSTEM];
94 ticks.total = ticks.used + cpu_data[ProcCpuMeasures::IDLE];
95
96 return status;
97 }
98
99 CpuHandle* LinuxCpu::getHandle() {
100 return &this->m_handle;
101 }
102
103 } // namespace Cpu
104 } // namespace Linux
105 } // namespace Os
106