GCC Code Coverage Report


Directory: ./
File: Os/Linux/Cpu.cpp
Date: 2026-09-03 22:12:29
Exec Total Coverage
Lines: 36 47 76.6%
Functions: 3 4 75.0%
Branches: 22 32 68.8%

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 940 CpuInterface::Status getCpuData(FwSizeType cpu_index, ProcCpuData data) {
31
1/1
✓ Branch 1 taken 940 times.
940 Os::File file;
32 // Open the procfs file
33 940 constexpr char PROC_STAT_PATH[] = "/proc/stat";
34
2/3
✓ Branch 1 taken 940 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 940 times.
940 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 940 const FwSizeType line_count = cpu_index + 2;
40
2/2
✓ Branch 0 taken 3290 times.
✓ Branch 1 taken 940 times.
4230 for (FwSizeType i = 0; i < line_count; i++) {
41 3290 FwSizeType read_size = sizeof proc_stat_line - 1;
42 Os::File::Status file_status =
43
1/1
✓ Branch 1 taken 3290 times.
3290 file.readline(reinterpret_cast<U8*>(proc_stat_line), read_size, Os::File::WaitType::NO_WAIT);
44
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3290 times.
3290 if (file_status != Os::File::Status::OP_OK) {
45 return CpuInterface::Status::ERROR;
46 }
47 3290 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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3290 times.
3290 if (::strncmp(proc_stat_line, "cpu", 3) != 0) {
50 return CpuInterface::Status::ERROR;
51 }
52 }
53 940 char* token_start = proc_stat_line + 3; // Length of "cpu"
54
2/2
✓ Branch 0 taken 7520 times.
✓ Branch 1 taken 940 times.
8460 for (FwSizeType i = 0; i < ProcCpuMeasures::MAX_CPU_TICK_TYPES; i++) {
55 7520 FwSizeType token = 0;
56 15040 Fw::StringUtils::StringToNumberStatus status = Fw::StringUtils::string_to_number(
57 token_start,
58
1/1
✓ Branch 1 taken 7520 times.
7520 static_cast<FwSizeType>(sizeof proc_stat_line) - static_cast<FwSizeType>(token_start - proc_stat_line),
59 token, &token_start);
60 // Check conversion success
61
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7520 times.
7520 if (status != Fw::StringUtils::StringToNumberStatus::SUCCESSFUL_CONVERSION) {
62 return CpuInterface::Status::ERROR;
63 }
64 7520 data[i] = token;
65 // Check cpu index is correct
66
3/4
✓ Branch 0 taken 940 times.
✓ Branch 1 taken 6580 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 940 times.
7520 if (i == ProcCpuMeasures::CPU_NUMBER and data[i] != cpu_index) {
67 return CpuInterface::Status::ERROR;
68 }
69 }
70 940 return CpuInterface::Status::OP_OK;
71 940 }
72
73 941 CpuInterface::Status LinuxCpu::_getCount(FwSizeType& cpu_count) {
74 941 long cpus = sysconf(_SC_NPROCESSORS_ONLN);
75
3/6
✓ Branch 0 taken 941 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 941 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 941 times.
✗ Branch 6 not taken.
941 if ((cpus > 0) && (static_cast<FwSizeType>(cpus) < std::numeric_limits<FwSizeType>::max())) {
76 941 cpu_count = static_cast<FwSizeType>(cpus);
77 941 return Status::OP_OK;
78 }
79 cpu_count = 0;
80 return Status::ERROR;
81 }
82
83 940 CpuInterface::Status LinuxCpu::_getTicks(Os::Cpu::Ticks& ticks, FwSizeType cpu_index) {
84 940 FwSizeType count = 0;
85
1/1
✓ Branch 1 taken 940 times.
940 CpuInterface::Status status = this->_getCount(count);
86
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 940 times.
940 if (status != CpuInterface::Status::OP_OK) {
87 return status;
88
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 940 times.
940 } else if (cpu_index >= count) {
89 return CpuInterface::Status::ERROR;
90 }
91 940 ProcCpuData cpu_data = {0, 0, 0, 0, 0, 0, 0, 0};
92
1/1
✓ Branch 1 taken 940 times.
940 status = getCpuData(cpu_index, cpu_data);
93 940 ticks.used = cpu_data[ProcCpuMeasures::USER] + cpu_data[ProcCpuMeasures::NICE] + cpu_data[ProcCpuMeasures::SYSTEM];
94 940 ticks.total = ticks.used + cpu_data[ProcCpuMeasures::IDLE];
95
96 940 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