16 if (!count || count > (~
size_t(0) - (SlotSize - 1)) / SlotSize) {
19 const size_t bytes = count * SlotSize + SlotSize - 1;
21 m_Storage =
new (std::nothrow) uint8_t[bytes];
23 m_Storage =
new uint8_t[bytes];
29 const uintptr_t aligned =
30 (
reinterpret_cast<uintptr_t
>(m_Storage) + SlotSize - 1) & ~uintptr_t(SlotSize - 1);
31 m_Slots =
reinterpret_cast<uint8_t*
>(aligned);
33 for (
size_t cpu = 0; cpu < m_Count; ++cpu) {
34 new (slot(cpu))
Slot{};
47 Slot* current = slot(cpu);
48 Time::Timestamp* value = mode == CpuTimeMode::User ? ¤t->user : ¤t->kernel;
49#if X64 && !HOSTED && !UTILITY_LINUX
52 asm volatile(
"addq %1, %0" :
"+m"(*value) :
"r"(elapsed) :
"cc");
54 __atomic_fetch_add(value, elapsed, __ATOMIC_RELAXED);
59 Time::Timestamp total(CpuTimeMode mode)
const {
60 Time::Timestamp result = 0;
61 for (
size_t cpu = 0; cpu < m_Count; ++cpu) {
62 const Slot* current = slot(cpu);
63 const Time::Timestamp* value = mode == CpuTimeMode::User ? ¤t->user : ¤t->kernel;
64 result += __atomic_load_n(value, __ATOMIC_ACQUIRE);
70 static constexpr size_t SlotSize = 64;
71 struct alignas(SlotSize)
Slot {
73 Time::Timestamp kernel;
74 uint8_t padding[SlotSize - 2 *
sizeof(Time::Timestamp)];
76 static_assert(
sizeof(
Slot) == SlotSize &&
alignof(
Slot) == SlotSize,
77 "CPU accounting slots must occupy separate aligned cache lines");
80 return reinterpret_cast<Slot*
>(m_Slots + cpu * SlotSize);