The Pedigree Project  0.1
PosixProcess.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "PosixProcess.h"
21 #include "ProcFs.h"
22 
23 #include "modules/system/vfs/VFS.h"
24 #include "pedigree/kernel/utilities/utility.h"
25 
26 #include <signal.h>
27 
28 ProcessGroup::~ProcessGroup()
29 {
30  // Remove all processes in the list from this group
32  it != Members.end(); ++it)
33  {
34  if (*it)
35  {
36  (*it)->setGroupMembership(PosixProcess::NoGroup);
37  (*it)->setProcessGroup(0, false);
38  }
39  }
40 
41  ProcessGroupManager::instance().returnGroupId(processGroupId);
42 
43  // All have been removed, update our list accordingly
44  Members.clear();
45 }
46 
47 PosixProcess::PosixProcess()
48  : Process(), m_pSession(0), m_pProcessGroup(0), m_GroupMembership(NoGroup),
49  m_Mask(0), m_RealIntervalTimer(this, IntervalTimer::Hardware),
50  m_VirtualIntervalTimer(this, IntervalTimer::Virtual),
51  m_ProfileIntervalTimer(this, IntervalTimer::Profile), m_Uid(0), m_Gid(0),
52  m_Euid(0), m_Egid(0), m_Suid(0), m_Sgid(0), m_SupplementalIds()
53 {
54  registerProcess();
55 }
56 
58 PosixProcess::PosixProcess(Process *pParent, bool bCopyOnWrite)
59  : Process(pParent, bCopyOnWrite), m_pSession(0), m_pProcessGroup(0),
60  m_GroupMembership(NoGroup), m_Mask(0),
61  m_RealIntervalTimer(this, IntervalTimer::Hardware),
62  m_VirtualIntervalTimer(this, IntervalTimer::Virtual),
63  m_ProfileIntervalTimer(this, IntervalTimer::Profile)
64 {
65  if (pParent->getType() == Posix)
66  {
67  PosixProcess *pPosixParent = static_cast<PosixProcess *>(pParent);
68  m_pSession = pPosixParent->m_pSession;
69  setProcessGroup(pPosixParent->getProcessGroup());
70  if (m_pProcessGroup)
71  {
72  setGroupMembership(Member);
73  }
74 
75  // Child inherits parent's mask.
76  m_Mask = pPosixParent->getMask();
77 
78  m_SupplementalIds.clear();
79  pPosixParent->getSupplementalGroupIds(m_SupplementalIds);
80  m_Suid = pPosixParent->getSavedUserId();
81  m_Sgid = pPosixParent->getSavedGroupId();
82  }
83 
84  m_Uid = pParent->getUserId();
85  m_Gid = pParent->getGroupId();
86  m_Euid = pParent->getEffectiveUserId();
87  m_Egid = pParent->getEffectiveGroupId();
88  m_Suid = -1;
89  m_Sgid = -1;
90 
91  registerProcess();
92 }
93 
94 PosixProcess::~PosixProcess()
95 {
96  unregisterProcess();
97 }
98 
99 void PosixProcess::setProcessGroup(
100  ProcessGroup *newGroup, bool bRemoveFromGroup)
101 {
102  // Remove ourselves from our existing group.
103  if (m_pProcessGroup && bRemoveFromGroup)
104  {
106  m_pProcessGroup->Members.begin();
107  it != m_pProcessGroup->Members.end();)
108  {
109  if ((*it) == this)
110  {
111  it = m_pProcessGroup->Members.erase(it);
112  }
113  else
114  ++it;
115  }
116  }
117 
118  // Now join the real group.
119  m_pProcessGroup = newGroup;
120  if (m_pProcessGroup)
121  {
122  m_pProcessGroup->Members.pushBack(this);
123  ProcessGroupManager::instance().setGroupId(
124  m_pProcessGroup->processGroupId);
125  }
126 }
127 
128 ProcessGroup *PosixProcess::getProcessGroup() const
129 {
130  return m_pProcessGroup;
131 }
132 
133 void PosixProcess::setGroupMembership(Membership type)
134 {
135  m_GroupMembership = type;
136 }
137 
138 PosixProcess::Membership PosixProcess::getGroupMembership() const
139 {
140  return m_GroupMembership;
141 }
142 
143 PosixSession *PosixProcess::getSession() const
144 {
145  return m_pSession;
146 }
147 
148 void PosixProcess::setSession(PosixSession *p)
149 {
150  m_pSession = p;
151 }
152 
154 {
155  return Posix;
156 }
157 
158 void PosixProcess::setMask(uint32_t mask)
159 {
160  m_Mask = mask;
161 }
162 
163 uint32_t PosixProcess::getMask() const
164 {
165  return m_Mask;
166 }
167 
168 const PosixProcess::RobustListData &PosixProcess::getRobustList() const
169 {
170  return m_RobustListData;
171 }
172 
173 void PosixProcess::setRobustList(const RobustListData &data)
174 {
175  m_RobustListData = data;
176 }
177 
178 void PosixProcess::registerProcess()
179 {
181  if (!pFs)
182  {
183  return;
184  }
185 
186  ProcFs *pProcFs = static_cast<ProcFs *>(pFs);
187  pProcFs->addProcess(this);
188 }
189 
190 void PosixProcess::unregisterProcess()
191 {
193  if (!pFs)
194  {
195  return;
196  }
197 
198  ProcFs *pProcFs = static_cast<ProcFs *>(pFs);
199  pProcFs->removeProcess(this);
200 }
201 
202 IntervalTimer &PosixProcess::getRealIntervalTimer()
203 {
204  return m_RealIntervalTimer;
205 }
206 
207 IntervalTimer &PosixProcess::getVirtualIntervalTimer()
208 {
209  return m_VirtualIntervalTimer;
210 }
211 
212 IntervalTimer &PosixProcess::getProfileIntervalTimer()
213 {
214  return m_ProfileIntervalTimer;
215 }
216 
218  Time::Timestamp user, Time::Timestamp system)
219 {
220  m_VirtualIntervalTimer.adjustValue(-user);
221  m_ProfileIntervalTimer.adjustValue(-(user + system));
222 }
223 
225 {
226  // Cancel all timers.
227  m_RealIntervalTimer.setIntervalAndValue(0, 0);
228  m_VirtualIntervalTimer.setIntervalAndValue(0, 0);
229  m_ProfileIntervalTimer.setIntervalAndValue(0, 0);
230 }
231 
233  : m_Process(pProcess), m_Mode(mode), m_Value(0), m_Interval(0),
234  m_Lock(false), m_Armed(false)
235 {
236  if (m_Mode == Hardware)
237  {
238  Timer *t = Machine::instance().getTimer();
239  if (t)
240  {
241  t->registerHandler(this);
242  }
243  }
244 }
245 
246 IntervalTimer::~IntervalTimer()
247 {
248  if (m_Mode == Hardware)
249  {
250  Timer *t = Machine::instance().getTimer();
251  if (t)
252  {
253  t->unregisterHandler(this);
254  }
255  }
256 }
257 
259  Time::Timestamp interval, Time::Timestamp *prevInterval)
260 {
261  LockGuard<Spinlock> guard(m_Lock);
262 
263  if (prevInterval)
264  {
265  *prevInterval = m_Interval;
266  }
267  m_Interval = interval;
268 }
269 
271  Time::Timestamp value, Time::Timestamp *prevValue)
272 {
273  LockGuard<Spinlock> guard(m_Lock);
274 
275  if (prevValue)
276  {
277  *prevValue = m_Value;
278  }
279  m_Value = value;
280  m_Armed = m_Value > 0;
281 }
282 
284  Time::Timestamp interval, Time::Timestamp value,
285  Time::Timestamp *prevInterval, Time::Timestamp *prevValue)
286 {
287  LockGuard<Spinlock> guard(m_Lock);
288 
289  if (prevInterval)
290  {
291  *prevInterval = m_Interval;
292  }
293 
294  if (prevValue)
295  {
296  *prevValue = m_Value;
297  }
298 
299  m_Interval = interval;
300  m_Value = value;
301  m_Armed = m_Value > 0;
302 }
303 
304 void IntervalTimer::getIntervalAndValue(
305  Time::Timestamp &interval, Time::Timestamp &value)
306 {
307  LockGuard<Spinlock> guard(m_Lock);
308 
309  interval = m_Interval;
310  value = m_Value;
311 }
312 
313 void IntervalTimer::adjustValue(int64_t adjustment)
314 {
315  bool needsSignal = false;
316  {
317  LockGuard<Spinlock> guard(m_Lock);
318 
319  // Fixup in case of potential underflow
320  if ((adjustment < 0) &&
321  (static_cast<uint64_t>(adjustment * -1) > m_Value))
322  {
323  m_Value = 0;
324  }
325  else
326  {
327  m_Value += adjustment;
328  }
329 
330  if (m_Armed && !m_Value)
331  {
332  m_Value = m_Interval;
333  m_Armed = m_Value > 0;
334 
335  needsSignal = true;
336  }
337  }
338 
339  if (needsSignal)
340  {
341  signal();
342  }
343 }
344 
345 Time::Timestamp IntervalTimer::getInterval() const
346 {
347  return m_Interval;
348 }
349 
350 Time::Timestamp IntervalTimer::getValue() const
351 {
352  return m_Value;
353 }
354 
355 void IntervalTimer::timer(uint64_t delta, InterruptState &state)
356 {
357  if (m_Mode != Hardware)
358  {
359  return;
360  }
361 
362  bool needsSignal = false;
363  {
364  LockGuard<Spinlock> guard(m_Lock);
365 
366  if (!m_Armed)
367  {
368  // Disarmed - ignore the timer event.
369  return;
370  }
371 
372  if (m_Value < delta)
373  {
374  m_Value = m_Interval;
375  m_Armed = m_Value > 0;
376 
377  needsSignal = true;
378  }
379  else
380  {
381  m_Value -= delta;
382  }
383  }
384 
385  if (needsSignal)
386  {
387  signal();
388  }
389 }
390 
392 {
393  int signal = -1;
394  switch (m_Mode)
395  {
396  case Hardware:
397  signal = SIGALRM;
398  break;
399  case Virtual:
400  signal = SIGVTALRM;
401  break;
402  case Profile:
403  signal = SIGPROF;
404  break;
405  }
406 
408  PosixSubsystem *pSubsystem =
409  static_cast<PosixSubsystem *>(m_Process->getSubsystem());
410 
411  // Don't yield in the middle of the timer handler
412  pSubsystem->sendSignal(m_Process->getThread(0), signal, false);
413 }
414 
415 int64_t PosixProcess::getUserId() const
416 {
417  return m_Uid;
418 }
419 
420 int64_t PosixProcess::getGroupId() const
421 {
422  return m_Gid;
423 }
424 
425 int64_t PosixProcess::getEffectiveUserId() const
426 {
427  return m_Euid;
428 }
429 
430 int64_t PosixProcess::getEffectiveGroupId() const
431 {
432  return m_Egid;
433 }
434 
435 void PosixProcess::getSupplementalGroupIds(Vector<int64_t> &vec) const
436 {
437  for (auto it : m_SupplementalIds)
438  {
439  vec.pushBack(it);
440  }
441 }
442 
443 void PosixProcess::setUserId(int64_t id)
444 {
445  m_Uid = id;
446 }
447 
448 void PosixProcess::setGroupId(int64_t id)
449 {
450  m_Gid = id;
451 }
452 
453 void PosixProcess::setEffectiveUserId(int64_t id)
454 {
455  m_Euid = id;
456 }
457 
458 void PosixProcess::setEffectiveGroupId(int64_t id)
459 {
460  m_Egid = id;
461 }
462 
463 void PosixProcess::setSupplementalGroupIds(const Vector<int64_t> &vec)
464 {
465  m_SupplementalIds.clear();
466  m_SupplementalIds.reserve(vec.size(), false);
467 
468  for (auto it : vec)
469  {
470  m_SupplementalIds.pushBack(it);
471  }
472 }
473 
474 int64_t PosixProcess::getSavedUserId() const
475 {
476  return m_Suid;
477 }
478 
479 int64_t PosixProcess::getSavedGroupId() const
480 {
481  return m_Sgid;
482 }
483 
484 void PosixProcess::setSavedUserId(int64_t id)
485 {
486  m_Suid = id;
487 }
488 
489 void PosixProcess::setSavedGroupId(int64_t id)
490 {
491  m_Sgid = id;
492 }
ProcessType
Definition: Process.h:61
void clear()
Definition: List.h:386
void pushBack(const T &value)
Definition: Vector.h:270
void pushBack(const T &value)
Definition: List.h:232
Spinlock m_Lock
Definition: Process.h:512
virtual ProcessType getType()
void setInterval(Time::Timestamp interval, Time::Timestamp *prevInterval=nullptr)
Definition: ProcFs.h:192
Iterator erase(Iterator &Iter)
Definition: List.h:343
void removeProcess(PosixProcess *proc)
Definition: ProcFs.cc:582
virtual Timer * getTimer()=0
CPU time in user and system.
Definition: PosixProcess.h:84
virtual int64_t getUserId() const
Definition: Process.cc:320
virtual int64_t getUserId() const
Definition: String.h:49
Filesystem * lookupFilesystem(const String &alias)
Definition: VFS.cc:221
static VFS & instance()
Definition: VFS.cc:56
void setGroupId(size_t gid)
void setTimerValue(Time::Timestamp value, Time::Timestamp *prevValue=nullptr)
Set the current value of the timer.
virtual void processTerminated()
IntervalTimer(PosixProcess *pProcess, Mode mode=Hardware)
Definition: List.h:64
virtual void reportTimesUpdated(Time::Timestamp user, Time::Timestamp system)
Iterator begin()
Definition: List.h:123
virtual void timer(uint64_t delta, InterruptState &state)
size_t size() const
Definition: Vector.h:258
int processGroupId
Definition: PosixProcess.h:58
Thread * getThread(size_t n)
Definition: Process.cc:225
CPU time in user mode only.
Definition: PosixProcess.h:82
List< PosixProcess * > Members
Definition: PosixProcess.h:67
void setIntervalAndValue(Time::Timestamp interval, Time::Timestamp value, Time::Timestamp *prevInterval=nullptr, Time::Timestamp *prevValue=nullptr)
Set both interval and value atomically.
void returnGroupId(size_t gid)
virtual ProcessType getType()
Definition: Process.h:259
void adjustValue(int64_t adjustment)
Adjust the current value directly.
virtual void sendSignal(Thread *pThread, int signal, bool yield=true)
Hardware-backed timer (wall time).
Definition: PosixProcess.h:80
void clear(bool freeMem=false)
Definition: Vector.h:337
Iterator end()
Definition: List.h:135
void addProcess(PosixProcess *proc)
Definition: ProcFs.cc:555