The Pedigree Project 0.1
accounting-record.h
1/* Copyright (c) 2026, Pedigree Developers. */
2#ifndef POSIX_ACCOUNTING_RECORD_H
3#define POSIX_ACCOUNTING_RECORD_H
4
5#include <stddef.h>
6#include <stdint.h>
7
8namespace PosixAccounting {
9constexpr uint64_t TickNanoseconds = 10000000;
10
11struct Record {
12 uint8_t flags = 0;
13 uint8_t version = 3;
14 uint16_t terminal = 0;
15 uint32_t exitStatus = 0;
16 uint32_t uid = 0, gid = 0, pid = 0, parentPid = 0;
17 uint32_t birthSeconds = 0;
18 uint32_t elapsedFloat = 0;
19 uint16_t userTicks = 0, systemTicks = 0, memory = 0;
20 uint16_t io = 0, blocks = 0, minorFaults = 0, majorFaults = 0, swaps = 0;
21 char command[16] = {};
22};
23static_assert(sizeof(Record) == 64 && offsetof(Record, command) == 48,
24 "Linux acct_v3 record layout changed");
25
26inline uint16_t compressed(uint64_t value) {
27 // Choose the smallest base-eight exponent whose rounded mantissa fits.
28 for (unsigned exponent = 0; exponent != 8; ++exponent) {
29 const unsigned shift = exponent * 3;
30 const uint64_t unit = uint64_t(1) << shift;
31 uint64_t mantissa = value >> shift;
32 if (shift && (value & (unit - 1)) >= unit / 2)
33 ++mantissa;
34 if (mantissa <= 8191)
35 return static_cast<uint16_t>((exponent << 13) | mantissa);
36 }
37 return 0xffff;
38}
39
40inline uint32_t floatBits(uint64_t value) {
41 // Kernel code cannot use floating-point registers. The accounting ABI
42 // stores an integral AHZ count as an IEEE-754 binary32 value.
43 if (!value)
44 return 0;
45 unsigned top = 0;
46 for (uint64_t bits = value; bits >>= 1;)
47 ++top;
48 const uint32_t significand = top > 23 ? static_cast<uint32_t>(value >> (top - 23))
49 : static_cast<uint32_t>(value << (23 - top));
50 return ((top + 127) << 23) | (significand & 0x7fffff);
51}
52} // namespace PosixAccounting
53#endif