20#include "PosixProcess.h"
21#include "pedigree/kernel/process/Scheduler.h"
22#include "pedigree/kernel/utilities/utility.h"
26#include "IntervalTimerState.h"
28#include "TerminalControl.h"
29#include "modules/system/vfs/VFS.h"
31PosixProcess::PosixProcess()
32 :
Process(DeferredPublication(), Posix),
33 m_AccountingLifetime(false),
35 m_pProcessGroup(nullptr),
36 m_GroupPrevious(nullptr),
38 m_ExecCommitted(false),
39 m_GroupMembership(NoGroup),
46 m_bRegistered(false) {
47 initializeJobControl(
nullptr);
48 publishCredentialReadCache();
49 enableTimeAccountingReports(0);
53PosixProcess::PosixProcess(
Process* pParent,
bool bCopyOnWrite,
54 FilesystemContextMode filesystemContext,
bool emptyAddressSpace)
57 m_AccountingLifetime(true),
59 m_pProcessGroup(nullptr),
60 m_GroupPrevious(nullptr),
62 m_ExecCommitted(false),
63 m_GroupMembership(NoGroup),
70 m_bRegistered(false) {
71 initializeJobControl(pParent);
74 if (pParent->getType() == Posix) {
78 m_Mask = pPosixParent->getMask();
80 m_Credentials = pPosixParent->snapshotCredentials();
83 if (pParent->snapshotFilesystemCredentials(
nullptr, inherited)) {
84 m_Credentials.ruid = m_Credentials.euid = m_Credentials.suid = inherited.uid;
85 m_Credentials.rgid = m_Credentials.egid = m_Credentials.sgid = inherited.gid;
86 m_Credentials.groupCount = inherited.groupCount;
87 for (
size_t i = 0; i < inherited.groupCount; ++i)
88 m_Credentials.groups[i] = inherited.groups[i];
91 publishCredentialReadCache();
94void PosixProcess::publishCredentialReadCache() {
95 __atomic_store_n(&m_RealUserId, m_Credentials.ruid, __ATOMIC_RELEASE);
98PosixProcess::~PosixProcess() {
107 assert(jobControlReady());
112void PosixProcess::setMask(uint32_t mask) {
116uint32_t PosixProcess::getMask()
const {
120void PosixProcess::registerProcess() {
121 ProcFs::publishProcess(
this);
122 m_bRegistered =
true;
123 if (!pidNamespaceReady()) {
124 ThreadLease recipient;
126 getSubsystem()->
kill(Subsystem::Unknown, recipient.get());
131void PosixProcess::unregisterProcess() {
133 ProcFs::unpublishProcess(
this);
134 m_bRegistered =
false;
139 return m_RealIntervalTimer;
143 return m_VirtualIntervalTimer;
147 return m_ProfileIntervalTimer;
157 m_RealIntervalTimer.
disarm();
158 m_VirtualIntervalTimer.
disarm();
159 m_ProfileIntervalTimer.
disarm();
160 posix_account_process_exit(*
this, m_AccountingLifetime);
161 TerminalControl::processTerminated(*
this);
165 : m_Process(pProcess),
173 m_LastTotal = absoluteTotal();
176 if (t && t->registerHandler(
this)) {
179 ERROR(
"IntervalTimer could not register its hardware callback");
184IntervalTimer::~IntervalTimer() {
186 if (!m_pTimer->unregisterHandler(
this)) {
187 FATAL(
"IntervalTimer could not drain its hardware callback");
194 bool needsSignal =
false;
197 needsSignal = advanceTimeLocked(absoluteTotal());
200 *prevInterval = m_Interval;
202 m_Interval = interval;
211 bool needsSignal =
false;
214 needsSignal = advanceTimeLocked(absoluteTotal());
217 *prevValue = m_Value;
220 setArmedLocked(m_Value > 0);
229 Time::Timestamp* prevInterval, Time::Timestamp* prevValue) {
230 bool needsSignal =
false;
233 needsSignal = advanceTimeLocked(absoluteTotal());
236 *prevInterval = m_Interval;
240 *prevValue = m_Value;
243 m_Interval = interval;
245 setArmedLocked(m_Value > 0);
255 const Time::Timestamp current = absoluteTotal();
256 if (current > m_LastTotal) {
257 m_LastTotal = current;
261 setArmedLocked(
false);
265void IntervalTimer::getIntervalAndValue(Time::Timestamp& interval, Time::Timestamp& value) {
266 bool needsSignal =
false;
269 needsSignal = advanceTimeLocked(absoluteTotal());
271 interval = m_Interval;
285 bool needsSignal =
false;
288 needsSignal = advanceTimeLocked(absoluteTotal);
296Time::Timestamp IntervalTimer::absoluteTotal()
const {
298 return Time::getTicks();
304 return m_Process->
getUserTime() + m_Process->getKernelTime();
309bool IntervalTimer::advanceTimeLocked(Time::Timestamp absoluteTotal) {
311 PosixIntervalTimerState::consumeAbsolute(m_Value, m_Interval, m_Armed, m_LastTotal,
313 m_Value = result.timer.value;
314 setArmedLocked(result.timer.armed);
315 m_LastTotal = result.baseline;
316 return result.timer.expired;
319void IntervalTimer::armHardwareLocked() {
323 const Time::Timestamp maximum = Time::Infinity - 1;
324 const Time::Timestamp deadline =
325 !m_Armed ? 0 : (m_Value > maximum - m_LastTotal ? maximum : m_LastTotal + m_Value);
327 FATAL(
"IntervalTimer could not arm its hardware callback");
331void IntervalTimer::setArmedLocked(
bool armed) {
332 if (m_Armed == armed) {
341Time::Timestamp IntervalTimer::getInterval()
const {
345Time::Timestamp IntervalTimer::getValue()
const {
355 bool needsSignal =
false;
364 needsSignal = advanceTimeLocked(absoluteTotal());
395 if (!pSubsystem || !targetAcquired) {
IntervalTimer(PosixProcess *pProcess, Mode mode=Hardware)
void setInterval(Time::Timestamp interval, Time::Timestamp *prevInterval=nullptr)
@ Virtual
CPU time in user mode only.
@ Hardware
Hardware-backed timer (wall time).
@ Profile
CPU time in user and system.
void setTimerValue(Time::Timestamp value, Time::Timestamp *prevValue=nullptr)
Set the current value of the timer.
void consumeCpuTime(Time::Timestamp absoluteTotal)
virtual void timer(uint64_t delta)
void setIntervalAndValue(Time::Timestamp interval, Time::Timestamp value, Time::Timestamp *prevInterval=nullptr, Time::Timestamp *prevValue=nullptr)
Set both interval and value atomically.
virtual Timer * getTimer()=0
virtual void processTerminated()
virtual void reportTimesUpdated(Time::Timestamp userTotal, Time::Timestamp total)
virtual void sendSignal(Thread *pThread, int signal, bool yield=true, bool processDirected=false)
MUST_USE_RESULT bool acquireProcessSignalThread(ThreadLease &lease)
Time::Timestamp getUserTime() const
void prepareForDestruction()
void setTimeAccountingReportInterest(size_t interest, bool enabled)
void enableTimeAccountingReports(size_t initialInterest=~size_t(0))
static Scheduler & instance()
virtual bool kill(KillReason killReason, Thread *pThread=0)=0
virtual bool supportsDeadlines() const
virtual bool armHandler(TimerHandler *, uint64_t)