2#include "pedigree/kernel/LockGuard.h"
3#include "pedigree/kernel/process/Scheduler.h"
4#include "pedigree/kernel/process/TerminationDeferral.h"
5#include "pedigree/kernel/process/Thread.h"
6#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
7#include "pedigree/kernel/processor/Processor.h"
8#include "pedigree/kernel/processor/ProcessorInformation.h"
9#include "pedigree/kernel/syscallError.h"
13#include "PosixProcess.h"
14#include "PosixSubsystem.h"
15#include "ResolvedPath.h"
16#include "accounting-record.h"
17#include "file-syscalls.h"
18#include "modules/system/console/Console.h"
19#include "modules/system/vfs/VFS.h"
20#include "process-accounting.h"
33 m_File->decreaseRefCount(
true);
34 m_File->releaseVfsReference();
39 bool prepare(
File* file) {
40 if (!Process::currentFilesystemCredentials(m_Credentials))
42 if (!
VFS::instance().pinFilesystem(file->getFilesystem(), m_Filesystem) ||
46 file->increaseRefCount(
true);
53 const uint64_t written =
54 m_File->append(
sizeof(record),
reinterpret_cast<uintptr_t
>(&record), offset);
55 if (written !=
sizeof(record)) {
58 if (!(m_Dropped++ % 64))
59 WARNING(
"Process accounting could not append a complete record");
65 File* m_File =
nullptr;
73struct AccountingResult {
74 AccountingResult(
int result)
76 error(result < 0 ?
Processor::information().getCurrentThread()->getErrno() : 0) {}
81AccountingResult configure(
const char* path) {
84 if (process->getEffectiveUserId() != 0) {
85 SYSCALL_ERROR(NotEnoughPermissions);
92 if (result != PosixSubsystem::UserStringSuccess) {
93 syscallError(result == PosixSubsystem::UserStringBadAddress ? Error::BadAddress
94 : Error::NameTooLong);
97 if (!copied.length()) {
98 SYSCALL_ERROR(DoesNotExist);
101 normalisePath(normalised, copied.cstr());
106 SYSCALL_ERROR(DoesNotExist);
110 SYSCALL_ERROR(PermissionDenied);
114 SYSCALL_ERROR(ReadOnlyFilesystem);
120 if (!prepared || !prepared.get()->prepare(file)) {
121 SYSCALL_ERROR(OutOfMemory);
129 retired = pedigree_std::move(accountingFile);
130 accountingFile = pedigree_std::move(prepared);
150int posix_acct(
const char* path) {
151 const AccountingResult result = configure(path);
152 syscallError(result.error);
158#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
159 record.version |= 128;
161 const auto credentials = process.snapshotCredentials();
162 record.uid = credentials.ruid;
163 record.gid = credentials.rgid;
165 record.parentPid = parentId(process);
166 const uint64_t birth = lifetime.birth / Time::Multiplier::Second;
167 record.birthSeconds = birth > UINT32_MAX ? UINT32_MAX :
static_cast<uint32_t
>(birth);
168 const uint64_t now = Time::getTicks();
169 record.elapsedFloat = PosixAccounting::floatBits(
170 (now > lifetime.started ? now - lifetime.started : 0) / PosixAccounting::TickNanoseconds);
172 PosixAccounting::compressed(process.
getUserTime() / PosixAccounting::TickNanoseconds);
174 PosixAccounting::compressed(process.getKernelTime() / PosixAccounting::TickNanoseconds);
175 record.memory = PosixAccounting::compressed(lifetime.virtualKilobytes);
178 File* terminal = process.acquireCtty(terminalLease);
179 if (terminal && ConsoleManager::instance().isConsole(terminal)) {
180 const size_t number =
static_cast<ConsoleFile*
>(terminal)->getConsoleNumber();
182 record.terminal =
static_cast<uint16_t
>(0x8800 | number);
186 if (record.exitStatus & 0x7f)
187 record.flags |= AXSIG;
188 if (lifetime.forked && !process.hasExecCommitted())
189 record.flags |= AFORK;
192 for (
size_t i = 0; i < description.length(); ++i) {
193 if (description[i] ==
'/')
196 for (
size_t i = 0; i <
sizeof(record.command) - 1 && start + i < description.length(); ++i)
197 record.command[i] = description[start + i];
202 accountingFile.get()->append(record);
204 syscallError(previousError);
207void posix_stop_accounting() {
211 retired = pedigree_std::move(accountingFile);
215void PosixProcess::snapshotAccountingMemory() {
217 const ssize_t pages = getVirtualPageCount();
219 m_AccountingLifetime.virtualKilobytes =
220 pages > 0 ?
static_cast<uint64_t
>(pages) * kilobytesPerPage : 0;
virtual bool retainVfsReference()
bool supportsRegularFileOperations()
static constexpr size_t getPageSize() PURE
static UserStringResult copyUserString(const char *userString, String ©, size_t maxLength)
size_t getUserspaceId() const
LargeStaticString & description()
Time::Timestamp getUserTime() const
static ProcessorInformation & information()
static Scheduler & instance()
static bool checkAccess(File *pFile, bool bRead, bool bWrite, bool bExecute)