20 #include "pedigree/kernel/Log.h" 21 #include <PosixSubsystem.h> 23 #include "pedigree/kernel/process/PerProcessorScheduler.h" 24 #include "pedigree/kernel/process/Scheduler.h" 25 #include "pedigree/kernel/process/SignalEvent.h" 26 #include "pedigree/kernel/process/Thread.h" 27 #include "pedigree/kernel/process/Uninterruptible.h" 28 #include "pedigree/kernel/processor/PhysicalMemoryManager.h" 29 #include "pedigree/kernel/processor/Processor.h" 30 #include "pedigree/kernel/processor/state.h" 31 #include "pedigree/kernel/processor/types.h" 32 #include "pedigree/kernel/syscallError.h" 34 #include "pedigree/kernel/LockGuard.h" 36 #include "pedigree/kernel/utilities/Tree.h" 38 #include "pedigree/kernel/utilities/assert.h" 40 #include "FileDescriptor.h" 41 #include "PosixProcess.h" 44 #include "modules/system/linker/DynamicLinker.h" 45 #include "modules/system/vfs/File.h" 46 #include "modules/system/vfs/LockedFile.h" 48 #include "modules/system/vfs/Symlink.h" 49 #include "modules/system/vfs/VFS.h" 50 #include "pedigree/kernel/linker/Elf.h" 52 #include "file-syscalls.h" 58 extern char __posix_compat_vsyscall_base;
60 #define POSIX_VSYSCALL_ADDRESS 0xffffffffff600000 73 extern void pedigree_init_sigret();
74 extern void pedigree_init_pthreads();
76 ProcessGroupManager::ProcessGroupManager() : m_GroupIds()
81 ProcessGroupManager::~ProcessGroupManager()
87 size_t bit = m_GroupIds.getFirstClear();
94 if (m_GroupIds.test(gid))
96 PS_NOTICE(
"ProcessGroupManager: setGroupId called on a group ID that " 104 return m_GroupIds.test(gid);
109 m_GroupIds.clear(gid);
113 :
Subsystem(s), m_SignalHandlers(), m_SignalHandlersLock(), m_FdMap(),
114 m_NextFd(s.m_NextFd), m_FdLock(), m_FdBitmap(), m_LastFd(0),
115 m_FreeCount(s.m_FreeCount), m_AltSigStack(), m_SyncObjects(),
m_Threads(),
116 m_ThreadWaiters(), m_NextThreadWaiter(1)
127 size_t key = it.key();
128 void *value = it.value();
133 new SignalHandler(*reinterpret_cast<SignalHandler *>(value));
144 void *key = it.key();
150 m_NextThreadWaiter = s.m_NextThreadWaiter;
192 "PosixSubsystem object freed when a thread is still running?");
225 delete reinterpret_cast<Mutex *
>(p->pObject);
227 delete reinterpret_cast<Semaphore *
>(p->pObject);
319 #ifdef POSIX_NO_EFAULT 325 #ifdef VERBOSE_KERNEL 327 "PosixSubsystem::checkAddress(" <<
Hex << addr <<
", " <<
Dec << extent
328 <<
", " <<
Hex << flags <<
")");
334 #ifdef VERBOSE_KERNEL 335 PS_NOTICE(
" -> zero extent, address is sane.");
340 uintptr_t aa =
reinterpret_cast<uintptr_t
>(__builtin_return_address(0));
341 #ifdef VERBOSE_KERNEL 342 PS_NOTICE(
" -> ret: " << aa);
349 #ifdef VERBOSE_KERNEL 350 PS_NOTICE(
" -> outside of user address area.");
358 #ifdef VERBOSE_KERNEL 359 PS_NOTICE(
" -> inside memory map.");
367 void *pAddr =
reinterpret_cast<void *
>(addr + i);
370 #ifdef VERBOSE_KERNEL 371 PS_NOTICE(
" -> page " <<
Hex << pAddr <<
" is not mapped.");
376 if (flags & SafeWrite)
379 physical_uintptr_t phys = 0;
385 #ifdef VERBOSE_KERNEL 386 PS_NOTICE(
" -> not writeable.");
393 #ifdef VERBOSE_KERNEL 394 PS_NOTICE(
" -> mapped and available.");
405 "PosixSubsystem::exit(" <<
Dec << pProcess->
getId() <<
", code=" << code
407 pProcess->markTerminating();
436 while (pBlockingThread)
439 pBlockingThread = pBlockingThread->getBlockingThread();
448 delete pProcess->getLinker();
453 if (pProcess->
getType() == Process::Posix)
489 if (pParent && pParent->getSubsystem())
500 " -> file lookup LRU cache had " 507 FATAL(
"PosixSubsystem::exit() running after Process::kill()!");
515 if (pProcess->
getType() != Process::Posix)
517 ERROR(
"PosixSubsystem::kill called with a non-POSIX process!");
542 PS_NOTICE(
"PosixSubsystem - killing " << pThread->
getParent()->
getId());
559 "PosixSubsystem::threadException -> " 567 PS_NOTICE(
" (Page fault)");
572 PS_NOTICE(
" (Invalid opcode)");
576 case GeneralProtectionFault:
577 PS_NOTICE(
" (General Fault)");
582 PS_NOTICE(
" (Division by zero)");
587 PS_NOTICE(
" (FPU error)");
591 case SpecialFpuError:
592 PS_NOTICE(
" (FPU error - special)");
597 PS_NOTICE(
" (Attempt to read from terminal by non-foreground " 603 PS_NOTICE(
" (Output to terminal by non-foreground process)");
608 PS_NOTICE(
" (Continuing a stopped process)");
613 PS_NOTICE(
" (Stopping a process)");
618 PS_NOTICE(
" (Interrupting a process)");
623 PS_NOTICE(
" (Requesting quit)");
628 PS_NOTICE(
" (Child status changed)");
633 PS_NOTICE(
" (Pipe broken)");
638 PS_NOTICE(
" (Unknown)");
641 "Unknown exception type in threadException - POSIX subsystem");
651 "PosixSubsystem::sendSignal #" << signal <<
" -> pid:tid " <<
Dec 653 << pThread->
getId());
656 if (pProcess->getType() != Process::Posix)
659 "PosixSubsystem::threadException called with a non-POSIX process!");
669 ERROR(
"Unknown signal in sendSignal - POSIX subsystem");
680 WARNING(
"PosixSubsystem::sendSignal dropping signal as a previous " 681 "generation has not delivered yet.");
691 if (pCurrentThread == pThread)
709 "No event configured for signal #" << signal
710 <<
", silently dropping!");
776 size_t ret = m_NextFd++;
842 size_t newFd = it.key();
861 bool bOnlyCloExec,
size_t iFirst,
size_t iLast)
875 bool bAllToBeFreed = ((iFirst == 0 && iLast == ~0UL) && !bOnlyCloExec);
882 size_t Fd = it.key();
887 if (!(Fd >= iFirst && Fd <= iLast))
892 if (!(pFd->
fdflags & FD_CLOEXEC))
906 fdsToRemove.
pushBack(reinterpret_cast<void *>(Fd));
924 it != fdsToRemove.
end(); it++)
971 if (thread->pThread != pThread)
983 bool PosixSubsystem::checkAccess(
991 File *pFile, uintptr_t mappedAddress, uintptr_t &newAddress,
992 uintptr_t &finalAddress,
bool &relocated)
994 PS_NOTICE(
"PosixSubsystem::loadElf(" << pFile->
getName() <<
")");
1002 if ((pHeader->ident[1] !=
'E') || (pHeader->ident[2] !=
'L') ||
1003 (pHeader->ident[3] !=
'F') || (pHeader->ident[0] != 127))
1008 size_t phnum = pHeader->phnum;
1011 mappedAddress + pHeader->phoff);
1014 uintptr_t startAddress = ~0U;
1015 uintptr_t unalignedStartAddress = 0;
1016 uintptr_t endAddress = 0;
1017 for (
size_t i = 0; i < phnum; ++i)
1019 if (phdrs[i].type != PT_LOAD)
1024 if (phdrs[i].vaddr < startAddress)
1026 startAddress = phdrs[i].vaddr;
1029 uintptr_t maybeEndAddress = phdrs[i].vaddr + phdrs[i].memsz;
1030 if (maybeEndAddress > endAddress)
1032 endAddress = maybeEndAddress;
1038 unalignedStartAddress = startAddress;
1039 startAddress &= ~(pageSz - 1);
1040 if (endAddress & (pageSz - 1))
1042 endAddress = (endAddress + pageSz) & ~(pageSz - 1);
1046 bool bRelocated =
false;
1047 if (pHeader->type == ET_REL || pHeader->type == ET_DYN)
1049 if (!pProcess->getDynamicSpaceAllocator().allocate(
1050 endAddress - startAddress, newAddress))
1051 if (!pProcess->getSpaceAllocator().allocate(
1052 endAddress - startAddress, newAddress))
1056 unalignedStartAddress = newAddress + (startAddress & (pageSz - 1));
1057 startAddress = newAddress;
1059 newAddress = unalignedStartAddress;
1065 if (!pProcess->getDynamicSpaceAllocator().allocateSpecific(
1066 startAddress, endAddress - startAddress))
1067 if (!pProcess->getSpaceAllocator().allocateSpecific(
1068 startAddress, endAddress - startAddress))
1071 newAddress = unalignedStartAddress;
1074 finalAddress = startAddress + (endAddress - startAddress);
1077 for (
size_t i = 0; i < phnum; ++i)
1079 if (phdrs[i].type != PT_LOAD)
1084 uintptr_t base = phdrs[i].vaddr;
1087 base += startAddress;
1089 uintptr_t unalignedBase = base;
1090 if (base & (pageSz - 1))
1092 base &= ~(pageSz - 1);
1095 uintptr_t offset = phdrs[i].offset;
1096 if (offset & (pageSz - 1))
1098 offset &= ~(pageSz - 1);
1104 size_t length = phdrs[i].memsz + (unalignedBase & (pageSz - 1));
1105 if (length & (pageSz - 1))
1107 length = (length + pageSz) & ~(pageSz - 1);
1112 if (phdrs[i].flags & PF_X)
1114 perms |= MemoryMappedObject::Exec;
1116 if (phdrs[i].flags & PF_R)
1118 perms |= MemoryMappedObject::Read;
1120 if (phdrs[i].flags & PF_W)
1122 perms |= MemoryMappedObject::Write;
1126 pFile->
getName() <<
" PHDR[" << i <<
"]: @" <<
Hex << base <<
" -> " 1129 pFile, base, length, perms, offset);
1132 ERROR(
"PosixSubsystem::loadElf: failed to map PT_LOAD section");
1136 if (phdrs[i].memsz > phdrs[i].filesz)
1138 uintptr_t end = unalignedBase + phdrs[i].memsz;
1139 uintptr_t zeroStart = unalignedBase + phdrs[i].filesz;
1140 if (zeroStart & (pageSz - 1))
1142 size_t numBytes = pageSz - (zeroStart & (pageSz - 1));
1143 if ((zeroStart + numBytes) > end)
1145 numBytes = end - zeroStart;
1147 ByteSet(reinterpret_cast<void *>(zeroStart), 0, numBytes);
1148 zeroStart += numBytes;
1151 if (zeroStart < end)
1155 zeroStart, end - zeroStart, perms);
1156 if (!pAnonymousRegion)
1158 ERROR(
"PosixSubsystem::loadElf: failed to map anonymous " 1159 "pages for filesz/memsz mismatch");
1171 if (workingDir ==
nullptr)
1174 workingDir = m_pProcess->
getCwd();
1177 bool mountAwareAbi =
getAbi() != PosixSubsystem::LinuxAbi;
1182 if (mountAwareAbi || (path[0] !=
'/'))
1190 File *target =
nullptr;
1213 #define STACK_PUSH(stack, value) *--stack = value 1214 #define STACK_PUSH2(stack, value1, value2) \ 1215 STACK_PUSH(stack, value1); \ 1216 STACK_PUSH(stack, value2) 1217 #define STACK_PUSH_COPY(stack, value, length) \ 1218 stack = adjust_pointer(stack, -(length)); \ 1219 MemoryCopy(stack, value, length) 1220 #define STACK_PUSH_STRING(stack, str, length) \ 1221 stack = adjust_pointer(stack, -(length)); \ 1222 StringCopyN(reinterpret_cast<char *>(stack), str, length) 1223 #define STACK_PUSH_ZEROES(stack, length) \ 1224 stack = adjust_pointer(stack, -(length)); \ 1225 ByteSet(stack, 0, length) 1226 #define STACK_ALIGN(stack, to) \ 1227 STACK_PUSH_ZEROES( \ 1229 (to) - ((to) - (reinterpret_cast<uintptr_t>(stack) & ((to) -1)))) 1234 return invoke(name, argv, env, 0);
1239 SyscallState &state)
1241 return invoke(name, argv, env, &state);
1247 PS_NOTICE(
"Attempting to parse shebang in " << pFile->
getFullPath());
1252 bool bSearchDone =
false;
1254 while (!bSearchDone)
1258 pFile->
read(offset, 128, reinterpret_cast<uintptr_t>(buff));
1266 char *newline =
const_cast<char *
>(StringFind(buff,
'\n'));
1272 fileContents +=
String(buff);
1283 if (!fileContents.startswith(
"#!"))
1285 PS_NOTICE(
"no shebang found");
1290 fileContents.lchomp();
1291 fileContents.lchomp();
1295 if (!additionalArgv.
count())
1298 PS_NOTICE(
"split didn't find anything");
1305 if (normalisePath(invokePath, static_cast<const char *>(newTarget)))
1308 newTarget = invokePath;
1312 File *pNewTarget = findFileWithAbiFallbacks(newTarget);
1316 PS_NOTICE(
"target not found");
1317 SYSCALL_ERROR(DoesNotExist);
1323 while (additionalArgv.
count())
1328 pOutFile = pNewTarget;
1333 static File *traverseForInvoke(
File *pFile)
1342 PS_NOTICE(
"PosixSubsystem::invoke: symlink traversal failed");
1343 SYSCALL_ERROR(DoesNotExist);
1350 PS_NOTICE(
"PosixSubsystem::invoke: target is a directory");
1351 SYSCALL_ERROR(IsADirectory);
1360 SyscallState *state)
1363 String originalName(name);
1366 File *originalFile = findFileWithAbiFallbacks(originalName);
1370 "PosixSubsystem::invoke: could not find file '" << originalName <<
"'");
1371 SYSCALL_ERROR(DoesNotExist);
1375 return invoke(originalFile, originalName, argv, env, state);
1382 return invoke(originalFile, originalName, argv, env, 0);
1389 return invoke(originalFile, originalName, argv, env, &state);
1396 PS_NOTICE(
"PosixSubsystem::invoke(" << originalName <<
")");
1410 PS_NOTICE(
"invoke attempted with multiple threads in this process");
1414 originalFile = traverseForInvoke(originalFile);
1421 uint8_t validateBuffer[128];
1423 originalFile->
read(0, 128, reinterpret_cast<uintptr_t>(validateBuffer));
1425 Elf *validElf =
new Elf();
1426 if (!validElf->
validate(validateBuffer, nBytes))
1429 "PosixSubsystem::invoke: '" 1430 << originalFile->
getName() <<
"' is not an ELF binary, looking for shebang...");
1432 File *shebangFile = 0;
1436 "PosixSubsystem::invoke: failed to parse shebang line in '" 1437 << originalFile->
getName() <<
"'");
1445 originalFile = shebangFile;
1448 originalFile = traverseForInvoke(originalFile);
1463 File *interpreterFile = 0;
1466 for (
int sig = 0; sig < 32; sig++)
1472 pProcess->setLinker(pLinker);
1476 interpreterFile = findFileWithAbiFallbacks(interpreter);
1477 interpreterFile = traverseForInvoke(interpreterFile);
1478 if (!interpreterFile)
1481 "PosixSubsystem::invoke: could not find interpreter '" 1482 << interpreter <<
"'");
1483 SYSCALL_ERROR(ExecFormatError);
1491 interpreterFile = originalFile;
1497 pProcess->setLinker(pLinker);
1519 uintptr_t originalBase = 0, interpreterBase = 0;
1521 MemoryMappedObject::Write |
1522 MemoryMappedObject::Exec;
1524 originalFile, originalBase, originalFile->getSize(), perms);
1527 PS_NOTICE(
"PosixSubsystem::invoke: failed to map target");
1528 SYSCALL_ERROR(OutOfMemory);
1533 interpreterFile, interpreterBase, interpreterFile->getSize(), perms);
1536 PS_NOTICE(
"PosixSubsystem::invoke: failed to map interpreter");
1538 SYSCALL_ERROR(OutOfMemory);
1543 uintptr_t originalLoadedAddress = 0;
1544 uintptr_t originalFinalAddress = 0;
1545 bool originalRelocated =
false;
1547 originalFile, originalBase, originalLoadedAddress,
1548 originalFinalAddress, originalRelocated))
1551 PS_NOTICE(
"PosixSubsystem::invoke: failed to load target");
1552 SYSCALL_ERROR(ExecFormatError);
1557 uintptr_t interpreterLoadedAddress = 0;
1558 uintptr_t interpreterFinalAddress = 0;
1559 bool interpreterRelocated =
false;
1561 interpreterFile, interpreterBase, interpreterLoadedAddress,
1562 interpreterFinalAddress, interpreterRelocated))
1565 PS_NOTICE(
"PosixSubsystem::invoke: failed to load interpreter");
1566 SYSCALL_ERROR(ExecFormatError);
1571 uintptr_t originalEntryPoint = 0, interpreterEntryPoint = 0;
1573 reinterpret_cast<uint8_t *>(originalBase), originalFile->getSize(),
1574 originalEntryPoint);
1576 reinterpret_cast<uint8_t *>(interpreterBase),
1577 interpreterFile->getSize(), interpreterEntryPoint);
1579 if (originalRelocated)
1581 originalEntryPoint += originalLoadedAddress;
1583 if (interpreterRelocated)
1585 interpreterEntryPoint += interpreterLoadedAddress;
1594 pProcess->resetCounts();
1601 if (pProcess->
getType() == Process::Posix)
1605 p->setSavedUserId(p->getEffectiveUserId());
1606 p->setSavedGroupId(p->getEffectiveGroupId());
1611 MemoryMappedObject::Write |
1612 MemoryMappedObject::Exec;
1613 uintptr_t vdsoAddress = 0;
1619 PS_NOTICE(
"PosixSubsystem::invoke: failed to map VDSO");
1625 reinterpret_cast<void *>(vdsoAddress), __vdso_so, __vdso_so_len);
1631 vdsoPerms & ~MemoryMappedObject::Write);
1636 reinterpret_cast<void *>(POSIX_VSYSCALL_ADDRESS)))
1638 physical_uintptr_t vsyscallBase = 0;
1639 size_t vsyscallFlags = 0;
1641 &__posix_compat_vsyscall_base, vsyscallBase, vsyscallFlags);
1643 vsyscallBase, reinterpret_cast<void *>(POSIX_VSYSCALL_ADDRESS),
1650 uintptr_t *loaderStack =
reinterpret_cast<uintptr_t *
>(stack->getTop());
1653 STACK_PUSH(loaderStack, 0);
1656 STACK_ALIGN(loaderStack, 16);
1659 char **envs =
new char *[env.
count()];
1661 for (
size_t i = 0; i < env.
count(); ++i)
1665 loaderStack, static_cast<const char *>(str), str.length() + 1);
1666 PS_NOTICE(
"env[" << envc <<
"]: " << str);
1667 envs[envc++] =
reinterpret_cast<char *
>(loaderStack);
1671 STACK_ALIGN(loaderStack, 16);
1673 char **argvs =
new char *[argv.
count()];
1675 for (
size_t i = 0; i < argv.
count(); ++i)
1679 loaderStack, static_cast<const char *>(str), str.length() + 1);
1680 PS_NOTICE(
"argv[" << argc <<
"]: " << str);
1681 argvs[argc++] =
reinterpret_cast<char *
>(loaderStack);
1685 STACK_ALIGN(loaderStack, 16);
1688 STACK_PUSH_STRING(loaderStack,
"x86_64", 7);
1689 void *platform = loaderStack;
1691 STACK_PUSH_STRING(loaderStack, originalName, originalName.length() + 1);
1692 void *execfn = loaderStack;
1695 STACK_ALIGN(loaderStack, 16);
1698 STACK_PUSH_ZEROES(loaderStack, 16);
1699 void *random = loaderStack;
1702 if (((argc + envc) % 2) == 0)
1704 STACK_PUSH_ZEROES(loaderStack, 8);
1708 STACK_PUSH2(loaderStack, 0, 0);
1710 loaderStack, reinterpret_cast<uintptr_t>(platform), 15);
1712 loaderStack, reinterpret_cast<uintptr_t>(random), 25);
1713 STACK_PUSH2(loaderStack, 0, 23);
1714 STACK_PUSH2(loaderStack, pProcess->
getUserId(), 14);
1715 STACK_PUSH2(loaderStack, pProcess->getGroupId(), 13);
1716 STACK_PUSH2(loaderStack, pProcess->getEffectiveUserId(), 12);
1717 STACK_PUSH2(loaderStack, pProcess->getEffectiveGroupId(), 11);
1719 loaderStack, reinterpret_cast<uintptr_t>(execfn), 31);
1724 STACK_PUSH2(loaderStack, 0, 32);
1725 STACK_PUSH2(loaderStack, vdsoAddress, 33);
1729 STACK_PUSH2(loaderStack, originalEntryPoint, 9);
1730 STACK_PUSH2(loaderStack, interpreterLoadedAddress, 7);
1733 STACK_PUSH2(loaderStack, originalHeader->phnum, 5);
1734 STACK_PUSH2(loaderStack, originalHeader->phentsize, 4);
1736 loaderStack, originalLoadedAddress + originalHeader->phoff,
1740 STACK_PUSH(loaderStack, 0);
1741 for (
size_t i = 0; i < envc; ++i)
1743 STACK_PUSH(loaderStack, reinterpret_cast<uintptr_t>(envs[i]));
1747 STACK_PUSH(loaderStack, 0);
1748 for (ssize_t i = argc - 1; i >= 0; --i)
1750 STACK_PUSH(loaderStack, reinterpret_cast<uintptr_t>(argvs[i]));
1754 STACK_PUSH(loaderStack, argc);
1760 pInterpreter = pOriginal = 0;
1763 pedigree_init_sigret();
1774 reinterpret_cast<Thread::ThreadStartFunc>(interpreterEntryPoint), 0,
1784 ByteSet(&s, 0,
sizeof(s));
1785 pThread->
state() = s;
1788 for (
int sig = 0; sig < 32; sig++)
1796 0, interpreterEntryPoint, reinterpret_cast<uintptr_t>(loaderStack));
void store(const K &key, const T &object)
virtual bool kill(KillReason killReason, Thread *pThread)
virtual ~PosixSubsystem()
File * find(const String &path, File *pStartNode=0)
void pushBack(const T &value)
static size_t getPageSize() PURE
Tree< size_t, PosixThreadKey * > m_ThreadData
void popState(bool clean=true)
Iterator erase(Iterator &Iter)
Thread * m_pAcquiredThread
virtual void getMapping(void *virtualAddress, physical_uintptr_t &physicalAddress, size_t &flags)=0
void freeFd(size_t fdNum)
A vector / dynamic array.
virtual bool invoke(const char *name, Vector< String > &argv, Vector< String > &env)
Tree< size_t, FileDescriptor * > m_FdMap
int followLink(char *pBuffer, size_t bufLen)
MemoryMappedObject * mapAnon(uintptr_t &address, size_t length, MemoryMappedObject::Permissions perms)
virtual uintptr_t getUserStart() const =0
ExtensibleBitmap m_FdBitmap
virtual bool isMapped(void *virtualAddress)=0
bool copyDescriptors(PosixSubsystem *pSubsystem)
static const size_t Execute
virtual uintptr_t getUserReservedStart() const =0
void freeMultipleFds(bool bOnlyCloExec=false, size_t iFirst=0, size_t iLast=-1)
virtual int64_t getUserId() const
size_t getStateLevel() const
Tree< size_t, PosixThread * > m_Threads
void setUnwindState(UnwindType ut)
bool acquire(bool recurse=false, bool safe=true)
Tree< void *, Semaphore * > m_ThreadWaiters
Filesystem * lookupFilesystem(const String &alias)
virtual uintptr_t getKernelStart() const =0
virtual void threadException(Thread *pThread, ExceptionType eType)
void free(T address, T length, bool merge=true)
static ProcessorInformation & information()
void addFileDescriptor(size_t fd, FileDescriptor *pFd)
static void switchAddressSpace(VirtualAddressSpace &AddressSpace)
void setGroupId(size_t gid)
File * file
Our open file pointer.
bool test(size_t n) const
void unmap(MemoryMappedObject *pObj)
Tree< size_t, SignalHandler * > m_SignalHandlers
Tree< size_t, PosixSyncObject * > m_SyncObjects
size_t setPermissions(uintptr_t base, size_t length, MemoryMappedObject::Permissions perms)
bool hasEvent(Event *pEvent)
static bool checkAddress(uintptr_t addr, size_t extent, size_t flags)
Vector< Thread * > m_Threads
static bool extractEntryPoint(uint8_t *pBuffer, size_t length, uintptr_t &entry)
static const size_t Write
bool sendEvent(Event *pEvent)
void insert(const K &key, const E &value)
SignalHandler * getSignalHandler(size_t sig)
void exit(int code) NORETURN
Memory-mapped file interface.
void allocateFd(size_t fdNum)
MemoryAllocator & getDynamicSpaceAllocator()
LruCache< String, File * > m_FindFileCache
LRU cache for file lookups. Many usage patterns involve something like a stat() immediately followed ...
SignalEvent * pEvent
Event for the signal handler.
virtual String getFullPath(bool bWithLabel=true)
void setExitStatus(int code)
static void jumpUser(volatile uintptr_t *pLock, uintptr_t address, uintptr_t stack, uintptr_t p1=0, uintptr_t p2=0, uintptr_t p3=0, uintptr_t p4=0) NORETURN
static MemoryMapManager & instance()
void recordTime(bool bUserspace)
static Scheduler & instance()
virtual uintptr_t getDynamicEnd() const
static void setInterrupts(bool bEnable)
MemoryMappedObject * mapFile(File *pFile, uintptr_t &address, size_t length, MemoryMappedObject::Permissions perms, size_t offset=0, bool bCopyOnWrite=true)
virtual uintptr_t getDynamicStart() const
virtual uint64_t read(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true) final
static Symlink * fromFile(File *pF)
Thread * getThread(size_t n)
Process * getParent() const
void pushFront(const T &value)
List< PosixProcess * > Members
UnlikelyLock m_SignalHandlersLock
void setSignalHandler(size_t sig, SignalHandler *handler)
virtual void threadRemoved(Thread *pThread)
VirtualAddressSpace * getAddressSpace()
bool parseShebang(File *pFile, File *&outFile, Vector< String > &argv)
int fdflags
File descriptor flags (fcntl)
void returnGroupId(size_t gid)
LargeStaticString & description()
virtual ProcessType getType()
virtual void revertToKernelAddressSpace()=0
bool loadElf(File *pFile, uintptr_t mappedAddress, uintptr_t &newAddress, uintptr_t &finalAddress, bool &relocated)
FileDescriptor * getFileDescriptor(size_t fd)
virtual bool isDirectory()
bool validate(uint8_t *pBuffer, size_t length)
void remove(const K &key)
virtual void sendSignal(Thread *pThread, int signal, bool yield=true)
An iterator applicable for many data structures.
bool tryAcquire(size_t n=1)
bool checkInterpreter(File *pFile, String &actualFilename)
virtual void acquire()
Acquire full mutual exclusion for all Subsystem resources.
bool get(const K &key, T &object)
virtual File * findFile(const String &path, File *workingDir)
E lookup(const K &key) const
bool isGroupIdValid(size_t gid) const
static bool checkAccess(File *pFile, bool bRead, bool bWrite, bool bExecute)
static const size_t CopyOnWrite
MemoryAllocator & getSpaceAllocator()
Implements a Radix Tree, a kind of Trie with compressed keys.
virtual void threadException(Thread *pThread, ExceptionType eType)
virtual File * getRoot() const =0