The Pedigree Project 0.1
PosixSubsystem.h
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#ifndef POSIX_SUBSYSTEM_H
21#define POSIX_SUBSYSTEM_H
22
23#include "pedigree/kernel/LockGuard.h"
24#include "pedigree/kernel/Spinlock.h"
25#include "pedigree/kernel/Subsystem.h"
26#include "pedigree/kernel/compiler.h"
27#include "pedigree/kernel/process/Completion.h"
28#include "pedigree/kernel/process/ConditionVariable.h"
29#include "pedigree/kernel/process/Mutex.h"
30#include "pedigree/kernel/process/Rcu.h"
31#include "pedigree/kernel/process/Semaphore.h"
32#include "pedigree/kernel/process/SignalEvent.h"
33#include "pedigree/kernel/processor/types.h"
34#include "pedigree/kernel/utilities/ExtensibleBitmap.h"
36#include "pedigree/kernel/utilities/SharedPointer.h"
37#include "pedigree/kernel/utilities/Tree.h"
39#include "pedigree/kernel/utilities/Vector.h"
40
41#include "ResolvedPath.h"
42#include "modules/subsys/posix/FileDescriptor.h"
43#include "modules/subsys/posix/PosixMemoryLockAccount.h"
44#include "modules/subsys/posix/logging.h"
45#include "modules/subsys/posix/queued-signal.h"
46#include "modules/subsys/posix/trace-context.h"
47#include "modules/subsys/posix/uts-namespace.h"
48#include "modules/system/vfs/Directory.h"
49
50class File;
51class Filesystem;
52class UnixSocket;
53class PosixSubsystem;
54class ProcessGroup;
55class String;
56
65 public:
66 DescriptorLease() : m_Descriptor() {}
67
68 DescriptorLease(DescriptorLease&& other) noexcept
69 : m_Descriptor(pedigree_std::move(other.m_Descriptor)) {}
70
71 DescriptorLease& operator=(DescriptorLease&& other) noexcept {
72 if (this != &other) {
73 m_Descriptor = pedigree_std::move(other.m_Descriptor);
74 }
75 return *this;
76 }
77
78 DescriptorLease(const DescriptorLease&) = delete;
79 DescriptorLease& operator=(const DescriptorLease&) = delete;
80
81 FileDescriptor* operator->() const {
82 return m_Descriptor.operator->();
83 }
84
85 FileDescriptor& operator*() const {
86 return *m_Descriptor;
87 }
88
89 explicit operator bool() const {
90 return static_cast<bool>(m_Descriptor);
91 }
92
93 void reset() {
94 m_Descriptor.reset();
95 }
96
97 private:
98 friend class PosixSubsystem;
99 friend bool acquireDescriptor(int fd, DescriptorLease& descriptor);
100 friend bool removeDescriptor(int fd, const DescriptorLease& descriptor);
101 friend size_t installDescriptor(FileDescriptor* descriptor, DescriptorLease& lease);
102
103 void retain(const SharedPointer<FileDescriptor>& descriptor) {
104 m_Descriptor = descriptor;
105 }
106
108};
109
110extern PosixSubsystem* getSubsystem();
111extern bool acquireDescriptor(int fd, DescriptorLease& descriptor);
112extern void addDescriptor(int fd, FileDescriptor* f);
113extern size_t installDescriptor(FileDescriptor* descriptor, DescriptorLease& lease);
114extern bool removeDescriptor(int fd, const DescriptorLease& descriptor);
115extern size_t getAvailableDescriptor();
116
117// Grabs a subsystem for use.
118#define GRAB_POSIX_SUBSYSTEM(returnValue) \
119 PosixSubsystem* pSubsystem = getSubsystem(); \
120 if (!pSubsystem) { \
121 return (returnValue); \
122 }
123#define GRAB_POSIX_SUBSYSTEM_NORET \
124 PosixSubsystem* pSubsystem = getSubsystem(); \
125 if (!pSubsystem) { \
126 return; \
127 }
128
133 public:
135 virtual ~ProcessGroupManager();
136
137 static ProcessGroupManager& instance() {
138 return m_Instance;
139 }
140
142 size_t allocateGroupId();
143
145 void setGroupId(size_t gid);
146
148 bool isGroupIdValid(size_t gid) const;
149
151 void returnGroupId(size_t gid);
152
154 void registerGroup(size_t gid, ProcessGroup* group);
155 void unregisterGroup(size_t gid, ProcessGroup* group);
156
158 ProcessGroup* findGroup(size_t gid) const;
159 ProcessGroup* findGroup(size_t gid, const UserspacePidNamespace* space) const;
160
163 return m_GroupLock;
164 }
165
166 private:
167 static ProcessGroupManager m_Instance;
172 ProcessGroup* m_Groups;
173
174 mutable Spinlock m_GroupLock;
175};
176
178class EXPORTED_PUBLIC PosixSubsystem : public Subsystem {
179 public:
180 enum class DescriptorDuplicationResult { Success, BadSource, TargetBusy };
181
183 static const size_t SafeRegion = 0x0; // Region check is always done.
184 static const size_t SafeRead = 0x1;
185 static const size_t SafeWrite = 0x2;
186 static const size_t SafeExecute = 0x4;
187
192 static constexpr size_t LinuxPrivateSignalFirst = 32;
193 static constexpr size_t MaximumSupportedSignal = 64;
194 static constexpr size_t SignalDispositionCount = MaximumSupportedSignal + 1;
195
197 enum Abi {
198 PosixAbi = 0,
199 LinuxAbi = 1,
200 };
201
204 : Subsystem(Posix),
205 m_SignalHandlers(),
206 m_SignalHandlersLock(),
207 m_AdvisoryOwner(AdvisoryOwner::Kind::Process),
208 m_FdMap(),
209 m_FdEntries(),
210 m_NextFd(0),
211 m_FdLock(),
212 m_FdBitmap(),
213 m_LastFd(0),
214 m_FreeCount(1),
215 m_SyncObjects(),
216 m_Threads(),
217 m_ThreadWaiters(),
218 m_NextThreadWaiter(0),
219 m_ImageMetadataLock(),
220 m_ExecutablePath(),
221 m_CommandLine(),
222 m_Abi(PosixAbi),
223 m_bAcquired(false),
224 m_pAcquiredThread(nullptr) {}
225
227 PosixSubsystem(PosixSubsystem& s, bool clearSignalHandlers = false);
228
231 : Subsystem(type),
232 m_SignalHandlers(),
233 m_SignalHandlersLock(),
234 m_AdvisoryOwner(AdvisoryOwner::Kind::Process),
235 m_FdMap(),
236 m_FdEntries(),
237 m_NextFd(0),
238 m_FdLock(),
239 m_FdBitmap(),
240 m_LastFd(0),
241 m_FreeCount(1),
242 m_SyncObjects(),
243 m_Threads(),
244 m_ThreadWaiters(),
245 m_NextThreadWaiter(0),
246 m_ImageMetadataLock(),
247 m_ExecutablePath(),
248 m_CommandLine(),
249 m_Abi(PosixAbi),
250 m_bAcquired(false),
251 m_pAcquiredThread(nullptr) {}
252
253 SharedPointer<PosixNamespaceContext> namespaceContext() const {
254 return m_Namespaces;
255 }
256
257 bool executablePath(String& result) const;
258 bool executablePath(FilesystemPathRef& result) const;
259 bool commandLine(Vector<String>& result) const;
260
261 PosixTraceContext& traceContext() {
262 return m_TraceContext;
263 }
264 bool tracePolicyAllowed() const {
265 return affinityPolicyAllowed() && m_Abi == LinuxAbi;
266 }
267 UserReturnResult userReturnCheckpoint(Thread&, UserReturnFrame&) override;
268 UserReturnEventResult userReturnEvent(Thread&, Event&, UserReturnFrame&) override;
269 bool traceException(Thread&, int& signal, InterruptState&, ExceptionType, uintptr_t, uintptr_t);
270 TraceStatus prepareTraceSignal(Thread&, int signal, int32_t pid, uint32_t uid,
271 bool inheritReservation, UniquePointer<SignalEvent>&);
272 bool publishTraceSignal(Thread&, UniquePointer<SignalEvent>&, SignalEvent* source);
273
275 virtual ~PosixSubsystem();
276
277 /* Acquire mutual exclusion on the PosixSubsystem. */
278 virtual void acquire();
279
281 virtual void release();
282
297 static bool checkAddress(uintptr_t addr, size_t extent, size_t flags);
298
305 static bool checkedUserBufferSize(size_t count, size_t elementSize, size_t& extent);
306
307 static constexpr size_t MaximumExecArgumentBytes = 131072;
308
314 static bool checkUserAddressRange(uintptr_t addr, size_t count, size_t elementSize,
315 size_t* extent = nullptr);
316
318 static bool checkUserBuffer(uintptr_t addr, size_t count, size_t elementSize, size_t flags,
319 size_t* extent = nullptr);
320
327 static bool copyFromUser(void* destination, const void* source, size_t count,
328 size_t elementSize = 1);
329
331 static bool copyToUser(void* destination, const void* source, size_t count,
332 size_t elementSize = 1);
333
337 static size_t readCachedFile(File& file, uint64_t offset, void* destination, size_t count);
338
339 enum UserStringResult { UserStringSuccess, UserStringBadAddress, UserStringTooLong };
340
342 static UserStringResult copyUserString(const char* userString, String& copy, size_t maxLength);
343
345 virtual bool kill(KillReason killReason, Thread* pThread);
346
348 virtual void threadException(Thread* pThread, ExceptionType eType,
349 InterruptState* pState = nullptr, uintptr_t faultAddress = 0,
350 uintptr_t errorCode = 0);
351
352 bool resolveUserPageFault(Thread& thread, InterruptState& state, uintptr_t faultAddress,
353 uintptr_t errorCode) override;
354
356 virtual void sendSignal(Thread* pThread, int signal, bool yield = true,
357 bool processDirected = false);
358
361 SignalHandler() : sig(255), pEvent(0), sigMask(0), flags(0), restorer(0), type(0) {}
362
364 : sig(s.sig),
365 pEvent(s.pEvent ? s.pEvent->cloneForDisposition() : nullptr),
366 sigMask(s.sigMask),
367 flags(s.flags),
368 restorer(s.restorer),
369 type(s.type) {}
370
372 if (pEvent) {
373 pEvent->retire();
374 }
375 }
376
377 SignalHandler& operator=(const SignalHandler& s) {
378 if (this == &s) {
379 return *this;
380 }
381
382 if (pEvent) {
383 pEvent->retire();
384 }
385
386 sig = s.sig;
387 pEvent = s.pEvent ? s.pEvent->cloneForDisposition() : nullptr;
388 sigMask = s.sigMask;
389 flags = s.flags;
390 restorer = s.restorer;
391 type = s.type;
392 return *this;
393 }
394
396 size_t sig;
397
400
402 uint64_t sigMask;
403
405 uint32_t flags;
406
408 uintptr_t restorer;
409
411 int type;
412 };
413
416 SignalDisposition() : handler(0), signalMask(0), flags(0), restorer(0), type(1) {}
417
418 uintptr_t handler;
419 uint64_t signalMask;
420 uint32_t flags;
421 uintptr_t restorer;
422 int type;
423 };
424
425 enum class SignalDeliveryResult { Unavailable, Ignored, Rejected, Queued, Full };
426
428 void setSignalHandler(size_t sig, SignalHandler* handler);
429
430 bool admitLegacyUserSignals();
431
432 // Affinity admission holds the VM operation gate through policy queuing.
433 bool affinityPolicyAllowed() const {
434 return m_CallbackSchedulingDomain != CallbackSchedulingDomain::LegacySignals;
435 }
436 void recordAffinityPolicyUse() {
437 m_CallbackSchedulingDomain = CallbackSchedulingDomain::Affinity;
438 }
439
444 void resetSignalHandlersForExec(Thread* thread,
445 SignalHandler* const handlers[SignalDispositionCount]);
446
448 bool getSignalDisposition(size_t sig, SignalDisposition& disposition, bool beginDelivery = false);
449
451 SignalDeliveryResult queueSignalDelivery(
452 Thread* target, size_t sig, uint32_t* flags = nullptr, int32_t signalCode = 0,
453 bool processDirected = false, uint64_t signalValue = 0,
455
456 void setProcess(Process* process) override;
457
459 VirtualAddressSpace* space = nullptr;
460 uint64_t generation = 0;
461 };
462 // Tokens own no memory. Retain the Process and an outer VM operation guard
463 // while using a snapshot, so an exec cannot replace its admitted image.
464 bool snapshotUserImage(UserImageToken& token) const;
465 bool matchesUserImage(const UserImageToken& token) const;
466 void invalidateUserImage();
467 bool publishUserImage(VirtualAddressSpace& space);
468
469 SharedPointer<PendingSignalContext> pendingSignalContext() {
470 return m_PendingSignals;
471 }
472 Mutex& pendingSignalLock() {
473 return m_PendingSignals->lock;
474 }
475 ConditionVariable& pendingSignalChanged() {
476 return m_PendingSignals->changed;
477 }
478
479 void retireDescriptor(FileDescriptor* descriptor);
480
481 AdvisoryOwner& advisoryOwner() {
482 return m_AdvisoryOwner;
483 }
484
485 PosixMemoryLockAccount& memoryLockAccount() {
486 return m_MemoryLockAccount;
487 }
488
491 if (sig > MaximumSupportedSignal) {
492 return nullptr;
493 }
494 m_SignalHandlersLock.enter();
495 SignalHandler* ret = m_SignalHandlers.lookup(sig);
496 m_SignalHandlersLock.leave();
497 return ret;
498 }
499
500 void exit(int code, ExitCause cause = ExitCause::Normal) NORETURN;
501
503 bool copyDescriptors(PosixSubsystem* pSubsystem);
504
506 size_t getFd(size_t minimum = 0);
507
509 void allocateFd(size_t fdNum);
510
513 void freeFd(size_t fdNum);
514
516 void freeMultipleFds(bool bOnlyCloExec = false, size_t iFirst = 0, size_t iLast = -1);
517
525 bool acquireFileDescriptor(size_t fd, DescriptorLease& descriptor);
526
528 bool acquireNextFileDescriptor(size_t minimum, size_t& fd, DescriptorLease& descriptor);
529
531 bool descriptorMatchesOpenDescription(size_t fd,
533
541 bool closeFileDescriptor(size_t fd, const DescriptorLease& descriptor);
542
544 void addFileDescriptor(size_t fd, FileDescriptor* pFd);
545
554 DescriptorDuplicationResult duplicateFileDescriptor(size_t source, size_t target,
555 bool closeOnExec);
556
562 size_t installFileDescriptor(FileDescriptor* descriptor, DescriptorLease& lease,
563 size_t minimum = 0);
564
571 public:
572 PosixSyncObject() : pObject(0), isMutex(false) {}
574
575 void* pObject;
576 bool isMutex;
577
578 private:
580 const PosixSyncObject& operator=(const PosixSyncObject&);
581 };
582
585 return m_SyncObjects.lookup(n);
586 }
587
589 void insertSyncObject(size_t n, PosixSyncObject* sem) {
590 PosixSyncObject* t = m_SyncObjects.lookup(n);
591 if (t) {
592 m_SyncObjects.remove(n);
593 delete t;
594 }
595
596 m_SyncObjects.insert(n, sem);
597 }
598
600 void removeSyncObject(size_t n) {
601 PosixSyncObject* t = m_SyncObjects.lookup(n);
602 if (t) {
603 m_SyncObjects.remove(n);
604 delete t;
605 }
606 }
607
611 void (*destructor)(void*);
612
614 void* buffer;
615 };
616
619 public:
621 : pThread(0),
622 isRunning(),
623 returnValue(0),
624 canReclaim(false),
625 isDetached(false),
626 m_ThreadData(),
627 m_ThreadKeys(),
628 lastDataKey(0),
629 nextDataKey(0) {}
630 ~PosixThread() {}
631
632 Thread* pThread;
633 Completion isRunning;
634 void* returnValue;
635
636 bool canReclaim;
637 bool isDetached;
638
643 ExtensibleBitmap m_ThreadKeys;
644
647 return m_ThreadData.lookup(key);
648 }
649
654 void removeThreadData(size_t key) {
655 m_ThreadData.remove(key);
656 }
657
662 bool addThreadData(size_t key, PosixThreadKey* info) {
663 if (m_ThreadData.lookup(key))
664 return false;
665 m_ThreadData.insert(key, info);
666 return true;
667 }
668
671
674
675 private:
676 PosixThread(const PosixThread&);
677 const PosixThread& operator=(const PosixThread&);
678 };
679
682 return m_Threads.lookup(n);
683 }
684
686 void insertThread(size_t n, PosixThread* thread) {
687 PosixThread* t = m_Threads.lookup(n);
688 if (t)
689 m_Threads.remove(n);
691 return m_Threads.insert(n, thread);
692 }
693
695 void removeThread(size_t n) {
696 m_Threads.remove(n);
697 }
698
701 return m_ThreadWaiters.lookup(n);
702 }
703
706 void* descriptor = reinterpret_cast<void*>(m_NextThreadWaiter++);
707 Semaphore* t = m_ThreadWaiters.lookup(descriptor);
708 if (t)
709 m_ThreadWaiters.remove(descriptor);
710 m_ThreadWaiters.insert(descriptor, waiter);
711 return descriptor;
712 }
713
715 void removeThreadWaiter(void* n) {
716 m_ThreadWaiters.remove(n);
717 }
718
719 bool checkAccess(const DescriptorLease& pFileDescriptor, bool bRead, bool bWrite,
720 bool bExecute) const;
721 uint64_t filesystemAccess(const FilesystemPathRef* ancestry, size_t count) const override;
722 bool filesystemConstrained() const override;
723 bool filesystemReparent(const FilesystemPathRef* source, size_t sourceCount,
724 const FilesystemPathRef* destination,
725 size_t destinationCount) const override;
726
728 virtual bool invoke(const char* name, Vector<String>& argv, Vector<String>& env);
729
731 virtual bool invoke(const char* name, Vector<String>& argv, Vector<String>& env,
732 SyscallState& state);
733
735 virtual bool invoke(File* originalFile, const String& originalName, Vector<String>& argv,
736 Vector<String>& env);
737
739 virtual bool invoke(File* originalFile, const String& originalName, Vector<String>& argv,
740 Vector<String>& env, SyscallState& state);
741
742 bool invoke(File* originalFile, const String& originalName, Vector<String>& argv,
743 Vector<String>& env, SyscallState& state, bool descriptorPathInaccessible);
744
745 bool invoke(const FilesystemPathRef& originalPath, const String& originalName,
746 Vector<String>& argv, Vector<String>& env, SyscallState& state,
747 bool descriptorPathInaccessible = false);
748
749 File* findFileRetained(const String& path, ResolvedPath& result,
750 const FilesystemPathRef& workingDir = FilesystemPathRef(),
751 bool followFinal = false);
752 File* followFile(ResolvedPath& selected);
753
755 Abi getAbi() const {
756 return m_Abi;
757 }
758
760 void setAbi(Abi which) {
761 m_Abi = which;
762 }
763
764 private:
765 struct ExecutableImage;
766 struct FdEntry;
767 static constexpr size_t FdBuckets = 16;
768
769 void acquireFdLock();
770 void publishFdEntry(size_t fd);
771 void publishFdEntries();
772
773 virtual void prepareThreadsForExec(Thread* owner);
774 virtual void preserveProcessSignalsForThreadExit(Thread* thread);
775 virtual void threadExiting(Thread* pThread);
776 void clearChildTid(Thread* thread);
777 virtual void threadRemoved(Thread* pThread);
778
780 bool prepareExecutable(File* pFile, ExecutableImage& image, bool isInterpreter);
781
783 bool loadElf(const ExecutableImage& image, uintptr_t& loadBias);
784
785 bool invoke(const char* name, Vector<String>& argv, Vector<String>& env, SyscallState* state);
786
788 bool invoke(File* originalFile, const String& originalName, Vector<String>& argv,
789 Vector<String>& env, SyscallState* state, bool descriptorPathInaccessible = false,
790 const FilesystemPathRef& originalPath = FilesystemPathRef());
791
793 bool parseShebang(File* pFile, String& interpreter, String& optionalArgument,
794 bool& hasOptionalArgument);
795
798 Tree<size_t, SignalHandler*> m_SignalHandlers;
799
802 enum class CallbackSchedulingDomain { Unrestricted, LegacySignals, Affinity };
803 CallbackSchedulingDomain m_CallbackSchedulingDomain = CallbackSchedulingDomain::Unrestricted;
805 AdvisoryOwner m_AdvisoryOwner;
806 PosixMemoryLockAccount m_MemoryLockAccount;
809 VirtualAddressSpace* m_UserImageSpace = nullptr;
810 uint64_t m_UserImageGeneration = 0;
811 bool m_UserImageActive = false;
812
818 RcuPointer<FdEntry> m_FdEntries[FdBuckets];
822 size_t m_NextFd;
835 size_t m_LastFd;
850 size_t m_NextThreadWaiter;
851 mutable Mutex m_ImageMetadataLock;
852 FilesystemPathRef m_ExecutablePath;
853 Vector<String> m_CommandLine;
854
860
865
870
875};
876
877#endif
Implements a Radix Tree, a kind of Trie with compressed keys.
Definition Event.h:49
Definition File.h:75
Definition Mutex.h:56
void removeThreadData(size_t key)
Tree< size_t, PosixThreadKey * > m_ThreadData
size_t lastDataKey
Last data key that was allocated (for the bitmap)
PosixThreadKey * getThreadData(size_t key)
size_t nextDataKey
Next data key available.
bool addThreadData(size_t key, PosixThreadKey *info)
Tree< size_t, PosixSyncObject * > m_SyncObjects
void setAbi(Abi which)
Tree< void *, Semaphore * > m_ThreadWaiters
void * insertThreadWaiter(Semaphore *waiter)
Thread * m_pAcquiredThread
void insertSyncObject(size_t n, PosixSyncObject *sem)
SignalHandler * getSignalHandler(size_t sig)
Abi getAbi() const
UnlikelyLock m_SignalHandlersLock
PosixSyncObject * getSyncObject(size_t n)
PosixThread * getThread(size_t n)
void removeSyncObject(size_t n)
void insertThread(size_t n, PosixThread *thread)
ExtensibleBitmap m_FdBitmap
PosixTraceContext m_TraceContext
void removeThread(size_t n)
PosixSubsystem(SubsystemType type)
Tree< size_t, SharedPointer< FileDescriptor > > m_FdMap
Tree< size_t, PosixThread * > m_Threads
Semaphore * getThreadWaiter(void *n)
void removeThreadWaiter(void *n)
bool isGroupIdValid(size_t gid) const
void returnGroupId(size_t gid)
void registerGroup(size_t gid, ProcessGroup *group)
ExtensibleBitmap m_GroupIds
void setGroupId(size_t gid)
ProcessGroup * findGroup(size_t gid) const
static SharedPointer< T > tryAllocate(Args...)
virtual SignalEvent * cloneForDisposition()
virtual void release()
Definition Subsystem.cc:29
virtual void preserveProcessSignalsForThreadExit(Thread *thread)
Definition Subsystem.h:183
virtual bool invoke(const char *name, Vector< String > &argv, Vector< String > &env)=0
virtual bool resolveUserPageFault(Thread &, InterruptState &, uintptr_t, uintptr_t)
Definition Subsystem.h:146
virtual bool kill(KillReason killReason, Thread *pThread=0)=0
virtual void threadExiting(Thread *pThread)
Definition Subsystem.h:186
virtual void setProcess(Process *p)
Definition Subsystem.h:156
virtual void prepareThreadsForExec(Thread *owner)
Definition Subsystem.h:180
virtual void acquire()
Acquire full mutual exclusion for all Subsystem resources.
Definition Subsystem.cc:25
virtual void threadRemoved(Thread *pThread)
Definition Subsystem.h:189
virtual void threadException(Thread *pThread, ExceptionType eType, InterruptState *pState=nullptr, uintptr_t faultAddress=0, uintptr_t errorCode=0)
Definition Subsystem.cc:33
A key/value dictionary.
Definition Tree.h:33
void remove(const K &key)
Definition Tree.h:301
E lookup(const K &key) const
Definition Tree.h:193
void insert(const K &key, const E &value)
Definition Tree.h:149
A vector / dynamic array.
Definition Vector.h:33
void * buffer
Buffer pointer.
int type
Type - 0 = normal, 1 = SIG_DFL, 2 = SIG_IGN.
SignalEvent * pEvent
Event for the signal handler.
uintptr_t restorer
Userspace restorer for Linux-compatible signal delivery.
uint64_t sigMask
Signal mask to set when this signal handler is called.
uint32_t flags
Signal handler flags.