From 3e7e6831b13239fef8ee6c7b63c956d47f9d23d7 Mon Sep 17 00:00:00 2001 From: Philip Date: Mon, 12 Nov 2018 13:56:24 +0100 Subject: [PATCH] #163 changes to how memory spaces are created and managed in preparation for moving process management into userspace --- kernel/arch/x86/x32/context.c | 6 +- kernel/arch/x86/x32/memory/virtualmemory.c | 2 +- kernel/arch/x86/x64/context.c | 6 +- kernel/arch/x86/x64/memory/virtualmemory.c | 2 +- kernel/handle.c | 6 +- kernel/include/handle.h | 1 + kernel/include/memoryspace.h | 75 ++++---- kernel/include/threading.h | 24 +-- kernel/memoryspace.c | 113 ++++++------ kernel/process/loaders/pe.c | 9 +- kernel/threading.c | 97 ++++++----- librt/include/os/buffer.h | 92 +++++----- librt/libc/os/driver/acsupport.c | 51 +++--- librt/libc/os/file.c | 4 +- services/sessionmanager/process/process.c | 193 +++++++++++++++++++++ services/sessionmanager/process/process.h | 46 ++--- 16 files changed, 460 insertions(+), 267 deletions(-) create mode 100644 services/sessionmanager/process/process.c diff --git a/kernel/arch/x86/x32/context.c b/kernel/arch/x86/x32/context.c index a88b723c8..5577955eb 100644 --- a/kernel/arch/x86/x32/context.c +++ b/kernel/arch/x86/x32/context.c @@ -77,11 +77,7 @@ ContextCreate( ExtraSegment = GDT_EXTRA_SEGMENT + 0x03; // Now select the correct run-mode segments - if (THREADING_RUNMODE(ThreadFlags) == THREADING_DRIVERMODE) { - CodeSegment = GDT_PCODE_SEGMENT + 0x03; - StackSegment = DataSegment = GDT_PDATA_SEGMENT + 0x03; - } - else if (THREADING_RUNMODE(ThreadFlags) == THREADING_USERMODE) { + if (THREADING_RUNMODE(ThreadFlags) == THREADING_USERMODE) { CodeSegment = GDT_UCODE_SEGMENT + 0x03; StackSegment = DataSegment = GDT_UDATA_SEGMENT + 0x03; } diff --git a/kernel/arch/x86/x32/memory/virtualmemory.c b/kernel/arch/x86/x32/memory/virtualmemory.c index baba7193b..d25d1cbca 100644 --- a/kernel/arch/x86/x32/memory/virtualmemory.c +++ b/kernel/arch/x86/x32/memory/virtualmemory.c @@ -275,7 +275,7 @@ CloneVirtualSpace( // Create new resources for the happy new parent :-) if (MemorySpaceParent == NULL) { MemorySpace->Data[MEMORY_SPACE_IOMAP] = (uintptr_t)kmalloc(GDT_IOMAP_SIZE); - if (MemorySpace->Flags & (MEMORY_SPACE_APPLICATION | MEMORY_SPACE_SERVICE)) { + if (MemorySpace->Flags & MEMORY_SPACE_APPLICATION) { memset((void*)MemorySpace->Data[MEMORY_SPACE_IOMAP], 0xFF, GDT_IOMAP_SIZE); } else { diff --git a/kernel/arch/x86/x64/context.c b/kernel/arch/x86/x64/context.c index a029810b2..b0c82d75e 100644 --- a/kernel/arch/x86/x64/context.c +++ b/kernel/arch/x86/x64/context.c @@ -81,11 +81,7 @@ ContextCreate( ExtraSegment = GDT_EXTRA_SEGMENT + 0x03; // Now select the correct run-mode segments - if (THREADING_RUNMODE(ThreadFlags) == THREADING_DRIVERMODE) { - CodeSegment = GDT_UCODE_SEGMENT + 0x03; - StackSegment = DataSegment = GDT_UDATA_SEGMENT + 0x03; - } - else if (THREADING_RUNMODE(ThreadFlags) == THREADING_USERMODE) { + if (THREADING_RUNMODE(ThreadFlags) == THREADING_USERMODE) { CodeSegment = GDT_UCODE_SEGMENT + 0x03; StackSegment = DataSegment = GDT_UDATA_SEGMENT + 0x03; } diff --git a/kernel/arch/x86/x64/memory/virtualmemory.c b/kernel/arch/x86/x64/memory/virtualmemory.c index c3c842b88..f15a36df1 100644 --- a/kernel/arch/x86/x64/memory/virtualmemory.c +++ b/kernel/arch/x86/x64/memory/virtualmemory.c @@ -404,7 +404,7 @@ CloneVirtualSpace( // Create new resources for the happy new parent :-) if (MemorySpaceParent == NULL) { MemorySpace->Data[MEMORY_SPACE_IOMAP] = (uintptr_t)kmalloc(GDT_IOMAP_SIZE); - if (MemorySpace->Flags & (MEMORY_SPACE_APPLICATION | MEMORY_SPACE_SERVICE)) { + if (MemorySpace->Flags & MEMORY_SPACE_APPLICATION) { memset((void*)MemorySpace->Data[MEMORY_SPACE_IOMAP], 0xFF, GDT_IOMAP_SIZE); } else { diff --git a/kernel/handle.c b/kernel/handle.c index 48eeb4586..834d20e26 100644 --- a/kernel/handle.c +++ b/kernel/handle.c @@ -34,12 +34,14 @@ // Include all the systems that we have to cleanup #include #include +#include static Collection_t SystemHandles = COLLECTION_INIT(KeyId); static _Atomic(UUId_t) IdGenerator = 1; static HandleDestructorFn HandleDestructors[HandleTypeCount] = { DestroyMemoryBuffer, - DestroyProcess + DestroyProcess, + DestroySystemMemorySpace }; /* CreateHandle @@ -89,7 +91,7 @@ AcquireHandle( PreviousReferences = atomic_fetch_add(&Instance->References, 1); if (PreviousReferences == 0) { - // Special case, to fix race-conditioning. If the reference + // Special case, to prevent race-conditioning. If the reference // count ever reach 0 this was called on cleanup. return NULL; } diff --git a/kernel/include/handle.h b/kernel/include/handle.h index 989896321..2600eb456 100644 --- a/kernel/include/handle.h +++ b/kernel/include/handle.h @@ -30,6 +30,7 @@ typedef enum _SystemHandleType { HandleTypeMemoryBuffer = 0, HandleTypeProcess, + HandleTypeMemorySpace, HandleTypeCount } SystemHandleType_t; diff --git a/kernel/include/memoryspace.h b/kernel/include/memoryspace.h index 9fbbda3c6..b5d01e058 100644 --- a/kernel/include/memoryspace.h +++ b/kernel/include/memoryspace.h @@ -25,7 +25,6 @@ #define __MEMORY_SPACE_INTERFACE__ #include -#include /* SystemMemorySpace Definitions * Definitions, bit definitions and magic constants for memory spaces */ @@ -35,7 +34,6 @@ * Definitions, bit definitions and magic constants for memory spaces */ #define MEMORY_SPACE_INHERIT 0x00000001 #define MEMORY_SPACE_APPLICATION 0x00000002 -#define MEMORY_SPACE_SERVICE 0x00000004 /* SystemMemorySpace (Spaces) Definitions * Definitions, bit definitions and magic constants for memory spaces */ @@ -64,16 +62,11 @@ #define MAPPING_LEGACY 0x80000000 // (Virtual) Mapping is for legacy memory devices #define MAPPING_VMODE_MASK 0xF0000000 -/* SystemMemorySpace - * Represents a virtual memory space that can be used with MMIO - * functionality on the architecture. */ typedef struct _SystemMemorySpace { - CriticalSection_t SyncObject; - UUId_t Id; - _Atomic(int) References; Flags_t Flags; uintptr_t Data[MEMORY_DATACOUNT]; struct _SystemMemorySpace* Parent; + UUId_t ParentHandle; //blockmap spaces[max-spaces] } SystemMemorySpace_t; @@ -82,28 +75,28 @@ typedef struct _SystemMemorySpace { * system memory space which is the default space the cpu should use for kernel operation. */ KERNELAPI OsStatus_t KERNELABI InitializeSystemMemorySpace( - _In_ SystemMemorySpace_t* SystemMemorySpace); + _In_ SystemMemorySpace_t* SystemMemorySpace); /* CreateSystemMemorySpace * Initialize a new memory space, depending on what user is requesting we * might recycle a already existing address space */ -KERNELAPI SystemMemorySpace_t* KERNELABI +KERNELAPI OsStatus_t KERNELABI CreateSystemMemorySpace( - _In_ Flags_t Flags); + _In_ Flags_t Flags, + _Out_ UUId_t* Handle); -/* ReleaseSystemMemorySpace - * Destroy and release all resources related to an address space, - * only if there is no more references */ +/* DestroySystemMemorySpace + * Callback invoked by the handle system when references on a process reaches zero */ KERNELAPI OsStatus_t KERNELABI -ReleaseSystemMemorySpace( - _In_ SystemMemorySpace_t* SystemMemorySpace); +DestroySystemMemorySpace( + _In_ void* Resource); /* SwitchSystemMemorySpace * Switches the current address space out with the the address space provided * for the current cpu */ KERNELAPI OsStatus_t KERNELABI SwitchSystemMemorySpace( - _In_ SystemMemorySpace_t* SystemMemorySpace); + _In_ SystemMemorySpace_t* SystemMemorySpace); /* GetCurrentSystemMemorySpace * Returns the current address space if there is no active threads or threading @@ -117,17 +110,23 @@ GetCurrentSystemMemorySpace(void); KERNELAPI SystemMemorySpace_t* KERNELABI GetDomainSystemMemorySpace(void); +/* GetCurrentSystemMemorySpaceHandle + * Returns the current address space if there is no active threads or threading + * is not setup it returns the kernel address space */ +KERNELAPI UUId_t KERNELABI +GetCurrentSystemMemorySpaceHandle(void); + /* ChangeSystemMemorySpaceProtection * Changes the protection parameters for the given memory region. * The region must already be mapped and the size will be rounded up * to a multiple of the page-size. */ KERNELAPI OsStatus_t KERNELABI ChangeSystemMemorySpaceProtection( - _In_ SystemMemorySpace_t* SystemMemorySpace, - _InOut_Opt_ VirtualAddress_t VirtualAddress, - _In_ size_t Size, - _In_ Flags_t Flags, - _Out_ Flags_t* PreviousFlags); + _In_ SystemMemorySpace_t* SystemMemorySpace, + _InOut_Opt_ VirtualAddress_t VirtualAddress, + _In_ size_t Size, + _In_ Flags_t Flags, + _Out_ Flags_t* PreviousFlags); /* CreateSystemMemorySpaceMapping * Maps the given virtual address into the given address space @@ -135,33 +134,33 @@ ChangeSystemMemorySpaceProtection( * It returns the start address of the allocated physical region */ KERNELAPI OsStatus_t KERNELABI CreateSystemMemorySpaceMapping( - _In_ SystemMemorySpace_t* SystemMemorySpace, - _InOut_Opt_ PhysicalAddress_t* PhysicalAddress, - _InOut_Opt_ VirtualAddress_t* VirtualAddress, - _In_ size_t Size, - _In_ Flags_t Flags, - _In_ uintptr_t Mask); + _In_ SystemMemorySpace_t* SystemMemorySpace, + _InOut_Opt_ PhysicalAddress_t* PhysicalAddress, + _InOut_Opt_ VirtualAddress_t* VirtualAddress, + _In_ size_t Size, + _In_ Flags_t Flags, + _In_ uintptr_t Mask); /* CloneSystemMemorySpaceMapping * Clones a region of memory mappings into the address space provided. The new mapping * will automatically be marked PERSISTANT and PROVIDED. */ KERNELAPI OsStatus_t KERNELABI CloneSystemMemorySpaceMapping( - _In_ SystemMemorySpace_t* SourceSpace, - _In_ SystemMemorySpace_t* DestinationSpace, - _In_ VirtualAddress_t SourceAddress, - _InOut_Opt_ VirtualAddress_t* DestinationAddress, - _In_ size_t Size, - _In_ Flags_t Flags, - _In_ uintptr_t Mask); + _In_ SystemMemorySpace_t* SourceSpace, + _In_ SystemMemorySpace_t* DestinationSpace, + _In_ VirtualAddress_t SourceAddress, + _InOut_Opt_ VirtualAddress_t* DestinationAddress, + _In_ size_t Size, + _In_ Flags_t Flags, + _In_ uintptr_t Mask); /* RemoveSystemMemoryMapping * Unmaps a virtual memory region from an address space */ KERNELAPI OsStatus_t KERNELABI RemoveSystemMemoryMapping( - _In_ SystemMemorySpace_t* SystemMemorySpace, - _In_ VirtualAddress_t Address, - _In_ size_t Size); + _In_ SystemMemorySpace_t* SystemMemorySpace, + _In_ VirtualAddress_t Address, + _In_ size_t Size); /* GetSystemMemoryMapping * Retrieves a physical mapping from an address space determined diff --git a/kernel/include/threading.h b/kernel/include/threading.h index 0f119c3ff..302c8f737 100644 --- a/kernel/include/threading.h +++ b/kernel/include/threading.h @@ -56,12 +56,11 @@ typedef void(*ThreadEntry_t)(void*); * runtime mode, which is either: * 0 => Kernel * 1 => User - * 2 => Driver + * 2 => Reserved * 3 => Reserved * Bit 3: If it's currently in switch-mode */ #define THREADING_KERNELMODE 0x00000000 #define THREADING_USERMODE 0x00000001 -#define THREADING_DRIVERMODE 0x00000002 #define THREADING_SWITCHMODE 0x00000004 #define THREADING_MODEMASK 0x00000003 #define THREADING_RUNMODE(Flags) (Flags & THREADING_MODEMASK) @@ -100,6 +99,7 @@ typedef struct _MCoreThread { SystemPipe_t* Pipe; SystemMemorySpace_t* MemorySpace; + UUId_t MemorySpaceHandle; ThreadEntry_t Function; void* Arguments; @@ -135,15 +135,17 @@ ThreadingInitialize(void); KERNELAPI OsStatus_t KERNELABI ThreadingEnable(void); -/* ThreadingCreateThread - * Creates a new thread with the given paramaters and it is immediately - * queued up for execution. */ -KERNELAPI UUId_t KERNELABI -ThreadingCreateThread( - _In_ const char* Name, - _In_ ThreadEntry_t Function, - _In_ void* Arguments, - _In_ Flags_t Flags); +/* CreateThread + * Creates a new thread that will execute the given function as soon as possible. The + * thread can be supplied with arguments, mode and a custom memory space. */ +KERNELAPI OsStatus_t KERNELABI +CreateThread( + _In_ const char* Name, + _In_ ThreadEntry_t Function, + _In_ void* Arguments, + _In_ Flags_t Flags, + _In_ UUId_t MemorySpaceHandle, + _Out_ UUId_t* Handle); /* ThreadingTerminateThread * Marks the thread with the given id for finished, and it will be cleaned up diff --git a/kernel/memoryspace.c b/kernel/memoryspace.c index 1f8a1de03..4d4b97dd3 100644 --- a/kernel/memoryspace.c +++ b/kernel/memoryspace.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -47,102 +48,87 @@ extern OsStatus_t SetVirtualPageMapping(SystemMemorySpace_t*, PhysicalAddress_ extern OsStatus_t ClearVirtualPageMapping(SystemMemorySpace_t*, VirtualAddress_t); extern void SynchronizePageRegion(SystemMemorySpace_t*, uintptr_t, size_t); -// Global static storage -static _Atomic(int) AddressSpaceIdGenerator = ATOMIC_VAR_INIT(1); - /* InitializeSystemMemorySpace * Initializes the system memory space. This initializes a static version of the * system memory space which is the default space the cpu should use for kernel operation. */ OsStatus_t InitializeSystemMemorySpace( - _In_ SystemMemorySpace_t* SystemMemorySpace) + _In_ SystemMemorySpace_t* SystemMemorySpace) { - // Setup reference and lock - SystemMemorySpace->Parent = NULL; - SystemMemorySpace->Id = atomic_fetch_add(&AddressSpaceIdGenerator, 1); - CriticalSectionConstruct(&SystemMemorySpace->SyncObject, CRITICALSECTION_REENTRANCY); - atomic_store(&SystemMemorySpace->References, 1); - - // Let the architecture initialize further + SystemMemorySpace->Parent = NULL; + SystemMemorySpace->ParentHandle = UUID_INVALID; return InitializeVirtualSpace(SystemMemorySpace); } /* CreateSystemMemorySpace * Initialize a new memory space, depending on what user is requesting we * might recycle a already existing address space */ -SystemMemorySpace_t* +OsStatus_t CreateSystemMemorySpace( - _In_ Flags_t Flags) + _In_ Flags_t Flags, + _Out_ UUId_t* Handle) { - SystemMemorySpace_t *MemorySpace = NULL; - int i; - // If we want to create a new kernel address // space we instead want to re-use the current // If kernel is specified, ignore rest if (Flags == MEMORY_SPACE_INHERIT) { // Inheritance is a bit different, we re-use again // but instead of reusing the kernel, we reuse the current - MemorySpace = GetCurrentSystemMemorySpace(); - atomic_fetch_add(&MemorySpace->References, 1); + *Handle = GetCurrentSystemMemorySpaceHandle(); } - else if (Flags & (MEMORY_SPACE_APPLICATION | MEMORY_SPACE_SERVICE)) { - // Allocate a new address space - MemorySpace = (SystemMemorySpace_t*)kmalloc(sizeof(SystemMemorySpace_t)); + else if (Flags & MEMORY_SPACE_APPLICATION) { + SystemMemorySpace_t* MemorySpace = (SystemMemorySpace_t*)kmalloc(sizeof(SystemMemorySpace_t)); memset((void*)MemorySpace, 0, sizeof(SystemMemorySpace_t)); - MemorySpace->Id = atomic_fetch_add(&AddressSpaceIdGenerator, 1); - MemorySpace->Flags = Flags; - MemorySpace->References = 1; - CriticalSectionConstruct(&MemorySpace->SyncObject, CRITICALSECTION_REENTRANCY); + MemorySpace->Flags = Flags; + MemorySpace->ParentHandle = UUID_INVALID; // Parent must be the upper-most instance of the address-space // of the process. Only to the point of not having kernel as parent if (Flags & MEMORY_SPACE_INHERIT) { - MemorySpace->Parent = (GetCurrentSystemMemorySpace()->Parent != NULL) ? - GetCurrentSystemMemorySpace()->Parent : GetCurrentSystemMemorySpace(); - if (MemorySpace->Parent == GetDomainSystemMemorySpace()) { - MemorySpace->Parent = NULL; - } - } + SystemMemorySpace_t* Parent = GetCurrentSystemMemorySpace(); + int i; + if (Parent != GetDomainSystemMemorySpace()) { + if (Parent->ParentHandle != UUID_INVALID) { + MemorySpace->Parent = Parent->Parent; + MemorySpace->ParentHandle = Parent->ParentHandle; + } + else { + MemorySpace->Parent = Parent; + MemorySpace->ParentHandle = GetCurrentSystemMemorySpaceHandle(); + } - // If we have a parent, both add a new reference to the parent - // and also copy all its members. - if (MemorySpace->Parent != NULL) { - atomic_fetch_add(&MemorySpace->Parent->References, 1); - for (i = 0; i < MEMORY_DATACOUNT; i++) { - MemorySpace->Data[i] = MemorySpace->Parent->Data[i]; + // Add a reference and copy data + AcquireHandle(MemorySpace->ParentHandle); + for (i = 0; i < MEMORY_DATACOUNT; i++) { + MemorySpace->Data[i] = MemorySpace->Parent->Data[i]; + } } } CloneVirtualSpace(MemorySpace->Parent, MemorySpace, (Flags & MEMORY_SPACE_INHERIT) ? 1 : 0); + *Handle = CreateHandle(HandleTypeMemorySpace, 0, MemorySpace); } else { FATAL(FATAL_SCOPE_KERNEL, "Invalid flags parsed in CreateSystemMemorySpace 0x%x", Flags); } - return MemorySpace; + return OsSuccess; } -/* ReleaseSystemMemorySpace - * Destroy and release all resources related to an address space, - * only if there is no more references */ +/* DestroySystemMemorySpace + * Callback invoked by the handle system when references on a process reaches zero */ OsStatus_t -ReleaseSystemMemorySpace( - _In_ SystemMemorySpace_t* SystemMemorySpace) +DestroySystemMemorySpace( + _In_ void* Resource) { - // Acquire lock on the address space - int References = atomic_fetch_sub(&SystemMemorySpace->References, 1) - 1; - - // In case that was the last reference cleanup the address space otherwise - // just unlock - if (References == 0) { - if (SystemMemorySpace->Flags & (MEMORY_SPACE_APPLICATION | MEMORY_SPACE_SERVICE)) { - DestroyVirtualSpace(SystemMemorySpace); - } - kfree(SystemMemorySpace); + SystemMemorySpace_t* MemorySpace = (SystemMemorySpace_t*)Resource; + if (MemorySpace->Flags & MEMORY_SPACE_APPLICATION) { + DestroyVirtualSpace(MemorySpace); } - - // Reduce a reference to our parent as-well if we have one - return (SystemMemorySpace->Parent == NULL) ? OsSuccess : ReleaseSystemMemorySpace(SystemMemorySpace->Parent); + if (MemorySpace->ParentHandle != UUID_INVALID) { + DestroyHandle(MemorySpace->ParentHandle); + } + kfree(MemorySpace); + return OsSuccess; } /* SwitchSystemMemorySpace @@ -174,6 +160,21 @@ GetCurrentSystemMemorySpace(void) } } +/* GetCurrentSystemMemorySpaceHandle + * Returns the current address space if there is no active threads or threading + * is not setup it returns the kernel address space */ +UUId_t +GetCurrentSystemMemorySpaceHandle(void) +{ + MCoreThread_t* CurrentThread = ThreadingGetCurrentThread(CpuGetCurrentId()); + if (CurrentThread == NULL) { + return UUID_INVALID; + } + else { + return CurrentThread->MemorySpaceHandle; + } +} + /* GetDomainSystemMemorySpace * Retrieves the system's current copy of its memory space. If domains are active it will * be for the current domain, if system is uma-mode it's the machine wide. */ diff --git a/kernel/process/loaders/pe.c b/kernel/process/loaders/pe.c index 933a122af..291f1fd44 100644 --- a/kernel/process/loaders/pe.c +++ b/kernel/process/loaders/pe.c @@ -44,8 +44,8 @@ __EXTERN CriticalSection_t LoaderLock; * of a PE executable */ uint32_t PeCalculateChecksum( - _In_ uint8_t* Data, - _In_ size_t DataLength, + _In_ uint8_t* Data, + _In_ size_t DataLength, _In_ size_t PeChkSumOffset) { // Variables @@ -79,7 +79,7 @@ PeCalculateChecksum( * validation. Returns either PE_INVALID or PE_VALID */ int PeValidate( - _In_ uint8_t* Buffer, + _In_ uint8_t* Buffer, _In_ size_t Length) { PeOptionalHeader_t *OptHeader = NULL; @@ -643,8 +643,7 @@ PeResolveFunction( _In_ MCorePeFile_t* Library, _In_ const char* Function) { - // Variables - MCorePeExportFunction_t *Exports = Library->ExportedFunctions; + MCorePeExportFunction_t* Exports = Library->ExportedFunctions; if (Exports != NULL) { for (int i = 0; i < Library->NumberOfExportedFunctions; i++) { if (Exports[i].Name != NULL && !strcmp(Exports[i].Name, Function)) { diff --git a/kernel/threading.c b/kernel/threading.c index 936b04b20..3bd79eed6 100644 --- a/kernel/threading.c +++ b/kernel/threading.c @@ -75,7 +75,8 @@ ThreadingEnable(void) COLLECTION_NODE_INIT(&Thread->CollectionHeader, Key); // Initialize arch-dependant members - Thread->MemorySpace = GetCurrentSystemMemorySpace(); + Thread->MemorySpace = GetCurrentSystemMemorySpace(); + Thread->MemorySpaceHandle = GetCurrentSystemMemorySpaceHandle(); if (ThreadingRegister(Thread) != OsSuccess) { ERROR("Failed to register thread with system. Threading is not enabled."); CpuHalt(); @@ -107,34 +108,36 @@ ThreadingEntryPoint(void) for (;;); } -/* ThreadingCreateThread - * Creates a new thread with the given paramaters and it is immediately - * queued up for execution. */ -UUId_t -ThreadingCreateThread( - _In_ const char* Name, - _In_ ThreadEntry_t Function, - _In_ void* Arguments, - _In_ Flags_t Flags) +/* CreateThread + * Creates a new thread that will execute the given function as soon as possible. The + * thread can be supplied with arguments, mode and a custom memory space. */ +OsStatus_t +CreateThread( + _In_ const char* Name, + _In_ ThreadEntry_t Function, + _In_ void* Arguments, + _In_ Flags_t Flags, + _In_ UUId_t MemorySpaceHandle, + _Out_ UUId_t* Handle) { - MCoreThread_t* Thread; - MCoreThread_t* Parent; - UUId_t Cpu; - char NameBuffer[16]; - DataKey_t Key; + MCoreThread_t* Thread; + MCoreThread_t* Parent; + UUId_t CoreId; + char NameBuffer[16]; + DataKey_t Key; - TRACE("ThreadingCreateThread(%s, 0x%x)", Name, Flags); + TRACE("CreateThread(%s, 0x%x)", Name, Flags); Key.Value.Id = atomic_fetch_add(&GlbThreadId, 1); - Cpu = CpuGetCurrentId(); - Parent = ThreadingGetCurrentThread(Cpu); + CoreId = CpuGetCurrentId(); + Parent = ThreadingGetCurrentThread(CoreId); Thread = (MCoreThread_t*)kmalloc(sizeof(MCoreThread_t)); memset(Thread, 0, sizeof(MCoreThread_t)); if (ThreadingRegister(Thread) != OsSuccess) { ERROR("Failed to register a new thread with system."); kfree(Thread); - return UUID_INVALID; + return OsError; } // Sanitize name, if NULL generate a new thread name of format 'Thread X' @@ -166,32 +169,43 @@ ThreadingCreateThread( Thread->SignalQueue = CollectionCreate(KeyInteger); Thread->ActiveSignal.Signal = -1; - // Flag-Special-Case - // If it's NOT a kernel thread - // we specify transition-mode - if (THREADING_RUNMODE(Flags) != THREADING_KERNELMODE && !(Flags & THREADING_INHERIT)) { - Thread->Flags |= THREADING_SWITCHMODE; - } + // Is a memory space given to us that we should run in? Determine run mode automatically + if (MemorySpaceHandle != UUID_INVALID) { + SystemMemorySpace_t* MemorySpace = (SystemMemorySpace_t*)LookupHandle(MemorySpaceHandle); + if (MemorySpace == NULL) { + return OsDoesNotExist; + } - // Flag-Special-Case - // Determine the address space we want - // to initialize for this thread - if (THREADING_RUNMODE(Flags) == THREADING_KERNELMODE) { - Thread->MemorySpace = CreateSystemMemorySpace(MEMORY_SPACE_INHERIT); + if (MemorySpace->Flags & MEMORY_SPACE_APPLICATION) { + Thread->Flags |= THREADING_USERMODE; + } + Thread->MemorySpace = MemorySpace; + Thread->MemorySpaceHandle = MemorySpaceHandle; + AcquireHandle(MemorySpaceHandle); } else { - Flags_t ASFlags = 0; + Flags_t MemorySpaceFlags = 0; + if (THREADING_RUNMODE(Flags) != THREADING_KERNELMODE && !(Flags & THREADING_INHERIT)) { + Thread->Flags |= THREADING_SWITCHMODE; + } - if (THREADING_RUNMODE(Flags) == THREADING_DRIVERMODE) { - ASFlags |= MEMORY_SPACE_SERVICE; + if (THREADING_RUNMODE(Flags) == THREADING_KERNELMODE) { + MemorySpaceFlags = MEMORY_SPACE_INHERIT; } else { - ASFlags |= MEMORY_SPACE_APPLICATION; + if (THREADING_RUNMODE(Flags) == THREADING_USERMODE) { + MemorySpaceFlags |= MEMORY_SPACE_APPLICATION; + } + if (Flags & THREADING_INHERIT) { + MemorySpaceFlags |= MEMORY_SPACE_INHERIT; + } } - if (Flags & THREADING_INHERIT) { - ASFlags |= MEMORY_SPACE_INHERIT; + + if (CreateSystemMemorySpace(MemorySpaceFlags, &Thread->MemorySpaceHandle) != OsSuccess) { + ERROR("Failed to create memory space for thread"); + return OsError; } - Thread->MemorySpace = CreateSystemMemorySpace(ASFlags); + Thread->MemorySpace = (SystemMemorySpace_t*)LookupHandle(Thread->MemorySpaceHandle); } // Create context's neccessary @@ -204,7 +218,8 @@ ThreadingCreateThread( } CollectionAppend(&Threads, &Thread->CollectionHeader); SchedulerThreadQueue(Thread, 0); - return Thread->Id; + *Handle = Thread->Id; + return OsSuccess; } /* ThreadingCleanupThread @@ -235,9 +250,13 @@ ThreadingCleanupThread( kfree(Thread->Contexts[i]); } } - ReleaseSystemMemorySpace(Thread->MemorySpace); DestroySystemPipe(Thread->Pipe); + // Remove a reference to the memory space if not root + if (Thread->MemorySpaceHandle != UUID_INVALID) { + DestroyHandle(Thread->MemorySpaceHandle); + } + // Remove a reference to the process if (Thread->ProcessHandle != UUID_INVALID) { DestroyHandle(Thread->ProcessHandle); diff --git a/librt/include/os/buffer.h b/librt/include/os/buffer.h index 7263574cf..a3779ac44 100644 --- a/librt/include/os/buffer.h +++ b/librt/include/os/buffer.h @@ -21,8 +21,8 @@ * and functionality, refer to the individual things for descriptions */ -#ifndef _BUFFER_INTERFACE_H_ -#define _BUFFER_INTERFACE_H_ +#ifndef __BUFFER_INTERFACE__ +#define __BUFFER_INTERFACE__ #include @@ -30,112 +30,100 @@ // Contains information about a dma buffer for use with transfers, // shared memory or hardware interaction. typedef struct _DmaBuffer { - UUId_t Handle; - uintptr_t Address; - uintptr_t Dma; - size_t Capacity; - size_t Position; + UUId_t Handle; + uintptr_t Address; + uintptr_t Dma; + size_t Capacity; + size_t Position; } DmaBuffer_t; _CODE_BEGIN /* CreateBuffer * Creates a new buffer either from an existing handle (Length will be ignored), * or creates a new buffer with the given length if FromHandle == UUID_INVALID. */ -CRTDECL( -DmaBuffer_t*, +CRTDECL(DmaBuffer_t*, CreateBuffer( - _In_ UUId_t FromHandle, - _In_ size_t Length)); + _In_ UUId_t FromHandle, + _In_ size_t Length)); /* DestroyBuffer * Destroys the given buffer object and release resources * allocated with the CreateBuffer function */ -CRTDECL( -OsStatus_t, +CRTDECL(OsStatus_t, DestroyBuffer( - _In_ DmaBuffer_t* BufferObject)); + _In_ DmaBuffer_t* BufferObject)); /* ZeroBuffer * Clears the entire buffer and resets the internal indices */ -CRTDECL( -OsStatus_t, +CRTDECL(OsStatus_t, ZeroBuffer( - _In_ DmaBuffer_t* BufferObject)); + _In_ DmaBuffer_t* BufferObject)); /* SeekBuffer * Seeks the current write/read marker to a specified point * in the buffer */ -CRTDECL( -OsStatus_t, +CRTDECL(OsStatus_t, SeekBuffer( - _In_ DmaBuffer_t* BufferObject, - _In_ size_t Position)); + _In_ DmaBuffer_t* BufferObject, + _In_ size_t Position)); /* ReadBuffer * Reads into the given user-buffer from the given buffer-object. * It performs indexed reads, so the read will be from the current position */ -CRTDECL( -OsStatus_t, +CRTDECL(OsStatus_t, ReadBuffer( - _In_ DmaBuffer_t* BufferObject, - _Out_ const void* Buffer, - _In_ size_t BytesToRead, - _Out_Opt_ size_t* BytesRead)); + _In_ DmaBuffer_t* BufferObject, + _Out_ const void* Buffer, + _In_ size_t BytesToRead, + _Out_Opt_ size_t* BytesRead)); /* WriteBuffer * Writes into the allocated buffer-object from the given user-buffer. * It performs indexed writes, so the next write will be appended to the current position */ -CRTDECL( -OsStatus_t, +CRTDECL(OsStatus_t, WriteBuffer( - _In_ DmaBuffer_t* BufferObject, - _In_ const void* Buffer, - _In_ size_t BytesToWrite, - _Out_Opt_ size_t* BytesWritten)); + _In_ DmaBuffer_t* BufferObject, + _In_ const void* Buffer, + _In_ size_t BytesToWrite, + _Out_Opt_ size_t* BytesWritten)); /* CombineBuffer * Writes into the destination from the given * source buffer, make sure the position in both buffers are correct. * The number of bytes transferred is set as output */ -CRTDECL( -OsStatus_t, +CRTDECL(OsStatus_t, CombineBuffer( - _In_ DmaBuffer_t* Destination, - _In_ DmaBuffer_t* Source, - _In_ size_t BytesToTransfer, - _Out_Opt_ size_t* BytesTransferred)); + _In_ DmaBuffer_t* Destination, + _In_ DmaBuffer_t* Source, + _In_ size_t BytesToTransfer, + _Out_Opt_ size_t* BytesTransferred)); /* GetBufferHandle * Retrieves the handle of the dma buffer for other processes to use. */ -CRTDECL( -UUId_t, +CRTDECL(UUId_t, GetBufferHandle( - _In_ DmaBuffer_t* BufferObject)); + _In_ DmaBuffer_t* BufferObject)); /* GetBufferSize * Retrieves the size of the dma buffer. This might vary from the length given in * creation of the buffer as it may change it for performance reasons. */ -CRTDECL( -size_t, +CRTDECL(size_t, GetBufferSize( - _In_ DmaBuffer_t* BufferObject)); + _In_ DmaBuffer_t* BufferObject)); /* GetBufferDma * Retrieves the dma address of the memory buffer. This address cannot be used * for accessing memory, but instead is a pointer to the physical memory. */ -CRTDECL( -uintptr_t, +CRTDECL(uintptr_t, GetBufferDma( - _In_ DmaBuffer_t* BufferObject)); + _In_ DmaBuffer_t* BufferObject)); /* GetBufferDataPointer * Retrieves the data pointer to the physical memory. This can be used to access * the physical memory as this pointer is mapped to the dma. */ -CRTDECL( -void*, +CRTDECL(void*, GetBufferDataPointer( - _In_ DmaBuffer_t* BufferObject)); - + _In_ DmaBuffer_t* BufferObject)); _CODE_END #endif //!_BUFFER_INTERFACE_H_ diff --git a/librt/libc/os/driver/acsupport.c b/librt/libc/os/driver/acsupport.c index 1316f55b4..91036ba94 100644 --- a/librt/libc/os/driver/acsupport.c +++ b/librt/libc/os/driver/acsupport.c @@ -21,13 +21,8 @@ * and functionality, refer to the individual things for descriptions */ -/* Includes - * - System */ #include #include - -/* Includes - * - Library */ #include /* AcpiQueryStatus @@ -36,7 +31,7 @@ OsStatus_t AcpiQueryStatus( AcpiDescriptor_t *AcpiDescriptor) { - return Syscall_AcpiQuery(AcpiDescriptor); + return Syscall_AcpiQuery(AcpiDescriptor); } /* AcpiQueryTable @@ -45,26 +40,26 @@ AcpiQueryStatus( * the buffer is automatically allocated, and should be cleaned up afterwards */ OsStatus_t AcpiQueryTable(const char *Signature, ACPI_TABLE_HEADER **Table) { - /* We need this temporary storage */ - ACPI_TABLE_HEADER Header; - OsStatus_t Result; + /* We need this temporary storage */ + ACPI_TABLE_HEADER Header; + OsStatus_t Result; - /* Now query for the header information - * so we know what we should allocate */ - Result = Syscall_AcpiGetHeader(Signature, &Header); + /* Now query for the header information + * so we know what we should allocate */ + Result = Syscall_AcpiGetHeader(Signature, &Header); - /* Sanitize the result */ - if (Result != OsSuccess) { - return Result; - } + /* Sanitize the result */ + if (Result != OsSuccess) { + return Result; + } - /* Ok, now we can allocate a buffer able to contain - * the entire table information */ - *Table = (ACPI_TABLE_HEADER*)malloc(Header.Length); + /* Ok, now we can allocate a buffer able to contain + * the entire table information */ + *Table = (ACPI_TABLE_HEADER*)malloc(Header.Length); - /* And finally, we can query for the entirety of - * the requested table! */ - return Syscall_AcpiGetTable(Signature, *Table); + /* And finally, we can query for the entirety of + * the requested table! */ + return Syscall_AcpiGetTable(Signature, *Table); } /* AcpiQueryInterrupt @@ -75,12 +70,12 @@ OsStatus_t AcpiQueryInterrupt( DevInfo_t Bus, DevInfo_t Device, int Pin, - int* Interrupt, + int* Interrupt, Flags_t* AcpiConform) { - // Validate the pointers - if (Interrupt == NULL || AcpiConform == NULL) { - return OsError; - } - return Syscall_AcpiQueryInterrupt(Bus, Device, Pin, Interrupt, AcpiConform); + // Validate the pointers + if (Interrupt == NULL || AcpiConform == NULL) { + return OsError; + } + return Syscall_AcpiQueryInterrupt(Bus, Device, Pin, Interrupt, AcpiConform); } diff --git a/librt/libc/os/file.c b/librt/libc/os/file.c index bd63d82c3..8ef347f7d 100644 --- a/librt/libc/os/file.c +++ b/librt/libc/os/file.c @@ -1,6 +1,6 @@ /* MollenOS * - * Copyright 2011 - 2017, Philip Meulengracht + * Copyright 2017, Philip Meulengracht * * This program is free software : you can redistribute it and / or modify * it under the terms of the GNU General Public License as published by @@ -21,8 +21,6 @@ * and functionality, refer to the individual things for descriptions */ -/* Includes - * - System */ #include #include #include diff --git a/services/sessionmanager/process/process.c b/services/sessionmanager/process/process.c new file mode 100644 index 000000000..790788cd4 --- /dev/null +++ b/services/sessionmanager/process/process.c @@ -0,0 +1,193 @@ +/* MollenOS + * + * Copyright 2018, Philip Meulengracht + * + * This program is free software : you can redistribute it and / or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation ? , either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.If not, see . + * + * + * MollenOS Service - Session Manager + * - Contains the implementation of the session-manager which keeps track + * of all users and their running applications. + */ + +#include "process.h" +#include +#include +#include +#include + +typedef struct _SessionProcessPackage { + SessionProcess_t* Process; + uint8_t* FileBuffer; + size_t FileBufferLength; +} SessionProcessPackage_t; + +/* LoadFile + * Utility function to load a file into memory. The file is cached if it fits into memory and + * we can find a space for it to improve respawnability of processes and libraries. */ +OsStatus_t +LoadFile( + _In_ const char* Path, + _Out_ char** FullPath, + _Out_ void** Data, + _Out_ size_t* Length) +{ + FileSystemCode_t FsCode; + UUId_t fHandle; + DmaBuffer_t* TransferBuffer; + LargeInteger_t QueriedSize = { { 0 } }; + void* fBuffer = NULL; + size_t fRead = 0, fIndex = 0; + size_t fSize = 0; + + // Open the file as read-only + FsCode = OpenFile(Path, 0, __FILE_READ_ACCESS, &fHandle); + if (FsCode != FsOk) { + ERROR("Invalid path given: %s", Path); + return OsError; + } + + if (GetFileSize(fHandle, &QueriedSize.u.LowPart, NULL) != OsSuccess) { + ERROR("Failed to retrieve the file size"); + CloseFile(fHandle); + return OsError; + } + + if (FullPath != NULL) { + *FullPath = (char*)malloc(_MAXPATH); + memset((void*)*FullPath, 0, _MAXPATH); + if (GetFilePath(fHandle, *FullPath, _MAXPATH) != OsSuccess) { + ERROR("Failed to query file handle for full path"); + kfree((void*)*FullPath); + CloseFile(fHandle); + return OsError; + } + } + + fSize = (size_t)QueriedSize.QuadPart; + if (fSize != 0) { + TransferBuffer = CreateBuffer(UUID_INVALID, fSize); + if (TransferBuffer == NULL) { + ERROR("Failed to create a memory buffer"); + CloseFile(fHandle); + return OsError; + } + + fBuffer = malloc(fSize); + if (fBuffer == NULL) { + ERROR("Failed to allocate resources for file-loading"); + CloseFile(fHandle); + return OsError; + } + + FsCode = ReadFile(fHandle, TransferBuffer->Handle, fSize, &fIndex, &fRead); + if (FsCode != FsOk) { + ERROR("Failed to read file, code %i", FsCode); + kfree(fBuffer); + CloseFile(fHandle); + return OsError; + } + memcpy(fBuffer, (const void*)TransferBuffer->Address, fRead); + DestroyBuffer(TransferBuffer); + } + CloseFile(fHandle); + *Data = fBuffer; + *Length = fSize; + return OsSuccess; +} + +/* HandleProcessStartupInformation + * Creates neccessary kernel copies of the process startup information, as well as + * validating the structure. */ +void +HandleProcessStartupInformation( + _In_ SessionProcess_t* Process, + _In_ ProcessStartupInformation_t* StartupInformation) +{ + char* ArgumentBuffer; + + // Handle startup information + if (StartupInformation->ArgumentPointer != NULL && StartupInformation->ArgumentLength != 0) { + ArgumentBuffer = (char*)kmalloc(MStringSize(Process->Path) + 1 + StartupInformation->ArgumentLength + 1); + + memcpy(ArgumentBuffer, MStringRaw(Process->Path), MStringSize(Process->Path)); + ArgumentBuffer[MStringSize(Process->Path)] = ' '; + + memcpy(ArgumentBuffer + MStringSize(Process->Path) + 1, + StartupInformation->ArgumentPointer, StartupInformation->ArgumentLength); + ArgumentBuffer[MStringSize(Process->Path) + 1 + StartupInformation->ArgumentLength] = '\0'; + + Process->StartupInformation.ArgumentPointer = ArgumentBuffer; + Process->StartupInformation.ArgumentLength = MStringSize(Process->Path) + 1 + StartupInformation->ArgumentLength + 1; + } + else { + ArgumentBuffer = (char*)kmalloc(MStringSize(Process->Path) + 1); + memcpy(ArgumentBuffer, MStringRaw(Process->Path), MStringSize(Process->Path) + 1); + + Process->StartupInformation.ArgumentPointer = ArgumentBuffer; + Process->StartupInformation.ArgumentLength = MStringSize(Process->Path) + 1; + } + + // Handle the inheritance block + if (StartupInformation->InheritanceBlockPointer != NULL && StartupInformation->InheritanceBlockLength != 0) { + void* InheritanceBlock = kmalloc(StartupInformation->InheritanceBlockLength); + memcpy(InheritanceBlock, StartupInformation->InheritanceBlockPointer, StartupInformation->InheritanceBlockLength); + Process->StartupInformation.InheritanceBlockPointer = InheritanceBlock; + Process->StartupInformation.InheritanceBlockLength = StartupInformation->InheritanceBlockLength; + } +} + +/* CreateProcess + * Spawns a new process, which can be configured through the parameters. */ +OsStatus_t +CreateProcess( + _In_ const char* Path, + _In_ ProcessStartupInformation_t* Parameters, + _Out_ UUId_t* Handle) +{ + SessionProcessPackage_t* Package; + SessionProcess_t* Process; + int Index; + UUId_t ThreadId; + + assert(Path != NULL); + assert(Handle != NULL); + + Process = (SessionProcess_t*)malloc(sizeof(SessionProcess_t)); + Package = (SessionProcessPackage_t*)malloc(sizeof(SessionProcessPackage_t)); + assert(Process != NULL); + assert(Package != NULL); + memset(Process, 0, sizeof(SessionProcess_t)); + + // Start out by trying to resolve the process path, otherwise just abort + if (LoadFile(Process, Package, Path) != OsSuccess) { + ERROR(" > failed to resolve process path"); + kfree(Process); + return OsDoesNotExist; + } + + // Split path, even if a / is not found + // it won't fail, since -1 + 1 = 0, so we just copy the entire string + Index = MStringFindReverse(Process->Path, '/', 0); + Process->WorkingDirectory = MStringSubString(Process->Path, 0, Index); + Process->BaseDirectory = MStringSubString(Process->Path, 0, Index); + Process->Name = MStringSubString(Process->Path, Index + 1, -1); + Package->ProcessHandle = CreateHandle(HandleTypeProcess, HandleSynchronize, Process); + HandleProcessStartupInformation(Process, StartupInformation); + + *Handle = Package->ProcessHandle; + ThreadId = ThreadingCreateThread(MStringRaw(Process->Name), ProcessThreadEntry, Package, THREADING_USERMODE); + ThreadingDetachThread(ThreadId); + return OsSuccess; +} diff --git a/services/sessionmanager/process/process.h b/services/sessionmanager/process/process.h index 152ceae74..97ae6cdf7 100644 --- a/services/sessionmanager/process/process.h +++ b/services/sessionmanager/process/process.h @@ -25,26 +25,30 @@ #define __PROCESS_INTERFACE__ #include - -typedef struct _SystemProcess { - UUId_t MainThread; - UUId_t Id; - - const char* Name; - const char* Path; - UUId_t MemorySpace; - - // Below is everything related to - // the startup and the executable information - // that the Ash has - void* Executable; - uintptr_t NextLoadingAddress; - uint8_t* FileBuffer; - size_t FileBufferLength; - int Code; -} SystemProcess_t; - - - +#include + +typedef struct _SessionProcess { + UUId_t MainThread; + UUId_t Id; + + const char* Name; + const char* Path; + UUId_t MemorySpace; + ProcessStartupInformation_t StartupInformation; + + void* Executable; + uintptr_t NextLoadingAddress; + uint8_t* FileBuffer; + size_t FileBufferLength; + int Code; +} SessionProcess_t; + +/* CreateProcess + * Spawns a new process, which can be configured through the parameters. */ +OsStatus_t +CreateProcess( + _In_ const char* Path, + _In_ ProcessStartupInformation_t* Parameters, + _Out_ UUId_t* Handle); #endif //!__PROCESS_INTERFACE__