From dc314c2100a97f1e9220ba5ed821ebdf2a006ceb Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 22 Oct 2014 22:44:13 +0100 Subject: [PATCH] Merge vman design into vm; add designs for vmix and vmw3. Link to POSIX and Windows documentation from thread-manager design. Copied from Perforce Change: 187357 ServerID: perforce.ravenbrook.com --- mps/design/index.txt | 1 - mps/design/thread-manager.txt | 61 ++++++++++++++------- mps/design/vm.txt | 87 ++++++++++++++++++++++++++++++ mps/manual/source/design/index.rst | 1 - 4 files changed, 130 insertions(+), 20 deletions(-) diff --git a/mps/design/index.txt b/mps/design/index.txt index 6144f5707b7..b95def3a359 100644 --- a/mps/design/index.txt +++ b/mps/design/index.txt @@ -180,7 +180,6 @@ writef_ The WriteF function .. _version-library: version-library .. _version: version .. _vm: vm -.. _vman: vman .. _vmo1: vmo1 .. _vmso: vmso .. _writef: writef diff --git a/mps/design/thread-manager.txt b/mps/design/thread-manager.txt index 21443f01108..81ed57b507f 100644 --- a/mps/design/thread-manager.txt +++ b/mps/design/thread-manager.txt @@ -164,7 +164,10 @@ design.mps.pthreadext_. _`.impl.ix.multi`: Supports multiple threads. _`.impl.ix.register`: ``ThreadRegister()`` records the thread id -the current thread by calling ``pthread_self()``. +the current thread by calling |pthread_self|_. + +.. |pthread_self| replace:: ``pthread_self()`` +.. _pthread_self: http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_self.html _`.impl.ix.register.multi`: Multiply-registered threads are handled specially by the POSIX thread extensions. See @@ -210,27 +213,38 @@ information for the current thread: - A ``HANDLE`` to the process, with access flags ``THREAD_SUSPEND_RESUME`` and ``THREAD_GET_CONTEXT``. This handle - is needed as parameter to ``SuspendThread()`` and - ``ResumeThread()``. - - The result of ``GetCurrentThreadId()``, so that the current thread + is needed as parameter to |SuspendThread|_ and + |ResumeThread|_. + + - The result of |GetCurrentThreadId|_, so that the current thread may be identified in the ring of threads. +.. |SuspendThread| replace:: ``SuspendThread()`` +.. _SuspendThread: http://msdn.microsoft.com/en-us/library/windows/desktop/ms686345.aspx +.. |ResumeThread| replace:: ``ResumeThread()`` +.. _ResumeThread: http://msdn.microsoft.com/en-us/library/windows/desktop/ms685086.aspx +.. |GetCurrentThreadId| replace:: ``GetCurrentThreadId()`` +.. _GetCurrentThreadId: http://msdn.microsoft.com/en-us/library/windows/desktop/ms683183.aspx + _`.impl.w3.register.multi`: There is no need for any special treatment of multiple threads, because Windows maintains a suspend count that is -incremented on ``SuspendThread()`` and decremented on -``ResumeThread()``. +incremented on |SuspendThread|_ and decremented on +|ResumeThread|_. -_`.impl.w3.suspend`: ``ThreadRingSuspend()`` calls ``SuspendThread()``. +_`.impl.w3.suspend`: ``ThreadRingSuspend()`` calls |SuspendThread|_. -_`.impl.w3.resume`: ``ThreadRingResume()`` calls ``ResumeThread()``. +_`.impl.w3.resume`: ``ThreadRingResume()`` calls |ResumeThread|_. _`.impl.w3.scan.current`: ``ThreadScan()`` calls ``StackScan()`` if -the thread is current. This is because ``GetThreadContext()`` doesn't +the thread is current. This is because |GetThreadContext|_ doesn't work on the current thread: the context would not necessarily have the values which were in the saved registers on entry to the MPS. +.. |GetThreadContext| replace:: ``GetThreadContext()`` +.. _GetThreadContext: http://msdn.microsoft.com/en-us/library/windows/desktop/ms679362.aspx + _`.impl.w3.scan.suspended`: Otherwise, ``ThreadScan()`` calls -``GetThreadContext()`` to get the root registers and the stack +|GetThreadContext|_ to get the root registers and the stack pointer. The thread's registers are dumped into a ``CONTEXT`` structure and fixed in memory. The stack pointer is obtained from ``CONTEXT.Rsp`` (on IA-32) or ``CONTEXT.Rsp`` (on x86-64) and then the @@ -245,28 +259,39 @@ _`.impl.xc`: In ``thxc.c``. _`.impl.xc.multi`: Supports multiple threads. _`.impl.xc.register`: ``ThreadRegister()`` records the Mach port of -the current thread by calling ``mach_thread_self()``. +the current thread by calling |mach_thread_self|_. + +.. |mach_thread_self| replace:: ``mach_thread_self()`` +.. _mach_thread_self: http://www.gnu.org/software/hurd/gnumach-doc/Thread-Information.html _`.impl.xc.register.multi`: There is no need for any special treatment of multiple threads, because Mach maintains a suspend count that is -incremented on ``thread_suspend()`` and decremented on -``thread_resume()``. +incremented on |thread_suspend|_ and decremented on +|thread_resume|_. + +.. |thread_suspend| replace:: ``thread_suspend()`` +.. _thread_suspend: http://www.gnu.org/software/hurd/gnumach-doc/Thread-Execution.html +.. |thread_resume| replace:: ``thread_resume()`` +.. _thread_resume: http://www.gnu.org/software/hurd/gnumach-doc/Thread-Execution.html _`.impl.xc.suspend`: ``ThreadRingSuspend()`` calls -``thread_suspend()``. +|thread_suspend|_. -_`.impl.xc.resume`: ``ThreadRingResume()`` calls ``thread_resume()``. +_`.impl.xc.resume`: ``ThreadRingResume()`` calls |thread_resume|_. _`.impl.xc.scan.current`: ``ThreadScan()`` calls ``StackScan()`` if the thread is current. _`.impl.xc.scan.suspended`: Otherwise, ``ThreadScan()`` calls -``thread_get_state()`` to get the root registers and the stack -pointer. The thread's registers are dumped into a ``THREAD_STATE_S`` -structure and fixed in memory. The stack pointer is obtained from +|thread_get_state|_ to get the root registers and the stack pointer. +The thread's registers are dumped into a ``THREAD_STATE_S`` structure +and fixed in memory. The stack pointer is obtained from ``THREAD_STATE_S.__esp`` (on IA-32) or ``THREAD_STATE_S.__rsp`` (on x86-64) and then the stack is scanned. +.. |thread_get_state| replace:: ``thread_get_state()`` +.. _thread_get_state: http://www.gnu.org/software/hurd/gnumach-doc/Thread-Execution.html + Document History ---------------- diff --git a/mps/design/vm.txt b/mps/design/vm.txt index ea7dba7dad9..8efb4338c42 100644 --- a/mps/design/vm.txt +++ b/mps/design/vm.txt @@ -229,6 +229,93 @@ mapped into memory by the VM. _`.if.copy`: Copy the VM descriptor from ``src`` to ``dest``. +Implementations +--------------- + + +Generic implementation +...................... + +_`.impl.an`: In ``vman.c``. + +_`.impl.an.page.size`: The generic VM uses a fake page size, given by +the constant ``VMAN_PAGE_SIZE`` in ``config.h``. + +_`.impl.an.reserve`: Address space is "reserved" by calling +``malloc()``. + +_`.impl.an.release`: Address space is "released" by calling +``free()``. + +_`.impl.an.map`: Mapping (and unmapping) just fills the mapped region +with copies of ``VMJunkBYTE`` to emulate the erasure of freshly mapped +pages by virtual memory systems. + + +POSIX implementation +.................... + +_`.impl.ix`: In ``vmix.c``. + +_`.impl.ix.page.size`: The page size is given by ``getpagesize()``. + +_`.impl.ix.reserve`: Address space is reserved by calling |mmap|_, +passing ``PROT_NONE`` and ``MAP_PRIVATE | MAP_ANON``. + +.. |mmap| replace:: ``mmap()`` +.. _mmap: http://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html + +_`.impl.ix.anon.trans`: Note that ``MAP_ANON`` ("map anonymous +memory not associated with any specific file") is an extension to +POSIX, but it is supported by FreeBSD, Linux, and OS X. A work-around +that was formerly used on systems lacking ``MAP_ANON`` was to map +the file ``/dev/zero``. + +_`.impl.ix.release`: Address space is released by calling |munmap|_. + +.. |munmap| replace:: ``munmap()`` +.. _munmap: http://pubs.opengroup.org/onlinepubs/9699919799/functions/munmap.html + +_`.impl.ix.map`: Address space is mapped to main memory by calling +|mmap|_, passing ``PROT_READ | PROT_WRITE | PROT_EXEC`` and +``MAP_ANON | MAP_PRIVATE | MAP_FIXED``. + +_`.impl.ix.unmap`: Address space is unmapped from main memory by +calling |mmap|_, passing ``PROT_NONE`` and ``MAP_ANON | MAP_PRIVATE | +MAP_FIXED``. + + +Windows implementation +...................... + +_`.impl.w3`: In ``vmw3.c``. + +_`.impl.w3.page.size`: The page size is retrieved by calling +|GetSystemInfo|_ and consulting ``SYSTEMINFO.dwPageSize``. + +.. |GetSystemInfo| replace:: ``GetSystemInfo()`` +.. _GetSystemInfo: http://msdn.microsoft.com/en-gb/library/windows/desktop/ms724381.aspx + +_`.impl.w3.reserve`: Address space is reserved by calling +|VirtualAlloc|_, passing ``PAGE_NOACCESS``. + +.. |VirtualAlloc| replace:: ``VirtualAlloc()`` +.. _VirtualAlloc: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366887.aspx + +_`.impl.w3.release`: Address space is released by calling +|VirtualFree|_, passing ``MEM_RELEASE``. + +.. |VirtualFree| replace:: ``VirtualFree()`` +.. _VirtualFree: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366892.aspx + +_`.impl.w3.map`: Address space is mapped to main memory by calling +|VirtualAlloc|_, passing ``MEM_COMMIT`` and +``PAGE_EXECUTE_READWRITE``. + +_`.impl.w3.unmap`: Address space is unmapped from main memory by +calling |VirtualFree|_, passing ``MEM_DECOMMIT``. + + Testing ------- diff --git a/mps/manual/source/design/index.rst b/mps/manual/source/design/index.rst index 6db472df738..d208e4de101 100644 --- a/mps/manual/source/design/index.rst +++ b/mps/manual/source/design/index.rst @@ -28,4 +28,3 @@ Design thread-manager type vm - vman