mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-04-27 08:43:40 -07:00
Design for the protection mutator context module.
Copied from Perforce Change: 187360 ServerID: perforce.ravenbrook.com
This commit is contained in:
parent
dc314c2100
commit
8fc70f9b4a
5 changed files with 46 additions and 71 deletions
|
|
@ -80,6 +80,7 @@ poolmrg_ Manual Rank Guardian pool class
|
|||
poolmv_ Manual Variable pool class
|
||||
poolmvt_ Manual Variable Temporal pool class
|
||||
poolmvff_ Manual Variable First-Fit pool class
|
||||
prmc_ Protection mutator context
|
||||
prot_ Memory protection
|
||||
protan_ ANSI implementation of protection module
|
||||
protli_ Linux implementation of protection module
|
||||
|
|
@ -154,6 +155,7 @@ writef_ The WriteF function
|
|||
.. _poolmv: poolmv
|
||||
.. _poolmvt: poolmvt
|
||||
.. _poolmvff: poolmvff
|
||||
.. _prmc: prmc
|
||||
.. _prot: prot
|
||||
.. _protan: protan
|
||||
.. _protli: protli
|
||||
|
|
|
|||
|
|
@ -53,34 +53,6 @@ _`.if.sync`: ``ProtSync()`` is called to ensure that the actual
|
|||
protection of each segment (as determined by the OS) is in accordance
|
||||
with the segments's ``pm`` field.
|
||||
|
||||
``typedef struct MutatorFaultContextStruct *MutatorFaultContext``
|
||||
|
||||
_`.if.context-type`: This abstract type is implemented by the
|
||||
protection module (impl.c.prot*). It represents the continuation of
|
||||
the mutator which is restored after a mutator fault has been handled.
|
||||
The functions ``ProtCanStepInstruction()`` (`.if.canstep`_ below) and
|
||||
``ProtStepInstruction()`` (`.if.step`_ below) inspect and manipulate
|
||||
the context.
|
||||
|
||||
``Bool ProtCanStepInstruction(MutatorFaultContext context)``
|
||||
|
||||
_`.if.canstep`: Examines the context to determine whether the
|
||||
protection module can single-step the instruction which is causing the
|
||||
fault. Should return ``TRUE`` if and only if the instruction can be
|
||||
single-stepped (that is, ``ProtStepInstruction()`` can be called).
|
||||
|
||||
``Bool Res ProtStepInstruction(MutatorFaultContext context)``
|
||||
|
||||
_`.if.step`: Single-steps the instruction which is causing the fault.
|
||||
This function should only be called if ``ProtCanStepInstruction()``
|
||||
applied to the context returned ``TRUE``. It should return
|
||||
``ResUNIMPL`` if the instruction cannot be single-stepped. It should
|
||||
return ``ResOK`` if the instruction is single-stepped.
|
||||
|
||||
The mutator context will be updated by the emulation/execution of the
|
||||
instruction such that resuming the mutator will not cause the
|
||||
instruction which was causing the fault to be executed.
|
||||
|
||||
|
||||
Document History
|
||||
----------------
|
||||
|
|
@ -91,6 +63,11 @@ Document History
|
|||
|
||||
- 2013-05-23 GDR_ Converted to reStructuredText.
|
||||
|
||||
- 2014-10-23 GDR_ Move protection mutator context interface to
|
||||
design.mps.prmc_.
|
||||
|
||||
.. _design.mps.prmc: prmc
|
||||
|
||||
.. _RB: http://www.ravenbrook.com/consultants/rb/
|
||||
.. _GDR: http://www.ravenbrook.com/consultants/gdr/
|
||||
|
||||
|
|
|
|||
|
|
@ -15,8 +15,7 @@ Thread manager
|
|||
Introduction
|
||||
------------
|
||||
|
||||
_`.intro`: This document describes the design of the thread manager
|
||||
module.
|
||||
_`.intro`: This is the design of the thread manager module.
|
||||
|
||||
_`.readership`: Any MPS developer.
|
||||
|
||||
|
|
@ -76,56 +75,65 @@ Interface
|
|||
|
||||
``typedef struct mps_thr_s *Thread``
|
||||
|
||||
The type of threads. It is a pointer to an opaque structure, which
|
||||
must be defined by the implementation.
|
||||
_`.if.thread`: The type of threads. It is a pointer to an opaque
|
||||
structure, which must be defined by the implementation.
|
||||
|
||||
``Bool ThreadCheck(Thread thread)``
|
||||
|
||||
The check function for threads. See design.mps.check_.
|
||||
_`.if.check`: The check function for threads. See design.mps.check_.
|
||||
|
||||
.. _design.mps.check: check
|
||||
|
||||
``Bool ThreadCheckSimple(Thread thread)``
|
||||
|
||||
A thread-safe check function for threads, for use by
|
||||
``mps_thread_dereg()``. It can't use ``AVER(TESTT(Thread, thread))``,
|
||||
as recommended by design.mps.sig.check.arg.unlocked_, since ``Thread``
|
||||
is an opaque type.
|
||||
_`.if.check.simple`: A thread-safe check function for threads, for use
|
||||
by ``mps_thread_dereg()``. It can't use ``AVER(TESTT(Thread,
|
||||
thread))``, as recommended by design.mps.sig.check.arg.unlocked_,
|
||||
since ``Thread`` is an opaque type.
|
||||
|
||||
.. _design.mps.sig.check.arg.unlocked: sig#check.arg.unlocked
|
||||
|
||||
``Arena ThreadArena(Thread thread)``
|
||||
|
||||
Return the arena that the thread is registered with. Must be
|
||||
thread-safe as it is necessarily called before taking the arena lock.
|
||||
_`.if.arena`: Return the arena that the thread is registered with.
|
||||
Must be thread-safe as it needs to be called by ``mps_thread_dereg()``
|
||||
before taking the arena lock.
|
||||
|
||||
``Res ThreadRegister(Thread *threadReturn, Arena arena)``
|
||||
|
||||
Register the current thread with the arena, allocating a new
|
||||
``*threadReturn`` to point to it.
|
||||
_`.if.register`: Register the current thread with the arena,
|
||||
allocating a new ``Thread`` object. If successful, update
|
||||
``*threadReturn`` to point to the new thread and return ``ResOK``.
|
||||
Otherwise, return a result code indicating the cause of the error.
|
||||
|
||||
``void ThreadDeregister(Thread thread, Arena arena)``
|
||||
|
||||
Remove ``thread`` from the list of threads managed by the arena and
|
||||
free it.
|
||||
_`.if.deregister`: Remove ``thread`` from the list of threads managed
|
||||
by the arena and free it.
|
||||
|
||||
``void ThreadRingSuspend(Ring threadRing)``
|
||||
|
||||
Suspend all the threads on ``threadRing``, except for the current
|
||||
thread.
|
||||
_`.if.ring.suspend`: Suspend all the threads on ``threadRing``, except
|
||||
for the current thread.
|
||||
|
||||
``void ThreadRingResume(Ring threadRing)``
|
||||
|
||||
Resume all the threads on ``threadRing``.
|
||||
_`.if.ring.resume`: Resume all the threads on ``threadRing``.
|
||||
|
||||
``Thread ThreadRingThread(Ring threadRing)``
|
||||
|
||||
Return the thread that owns an element of the thread ring.
|
||||
_`.if.ring.thread`: Return the thread that owns the given element of
|
||||
the thread ring.
|
||||
|
||||
``Res ThreadScan(ScanState ss, Thread thread, void *stackBot)``
|
||||
|
||||
Scan the stacks and root registers of ``thread``, treating each value
|
||||
found as an ambiguous reference.
|
||||
_`.if.scan`: Scan the stacks and root registers of ``thread``,
|
||||
treating each value found as an ambiguous reference. ``stackBot``
|
||||
points to the "bottom" of the thread's stack---this is the value that
|
||||
was supplied by the client program when it called
|
||||
``mps_root_create_reg()``. In the common case, where the stack grows
|
||||
downwards, ``stackBot`` is actually the highest stack address. Return
|
||||
``ResOK`` if successful, another result code otherwise.
|
||||
|
||||
|
||||
Implementations
|
||||
|
|
@ -193,12 +201,7 @@ the thread is current.
|
|||
_`.impl.ix.scan.suspended`: ``PThreadextSuspend()`` records the
|
||||
context of each suspended thread, and ``ThreadRingSuspend()`` stores
|
||||
this in the ``Thread`` structure, so that is available by the time
|
||||
``ThreadScan()`` is called. The thread's registers are dumped into a
|
||||
``ucontext_t`` structure and fixed in memory. The stack pointer is
|
||||
obtained from ``ucontext_t.uc_mcontext.mc_esp`` (FreeBSD on IA-32),
|
||||
``uc_mcontext.gregs[REG_ESP]`` (Linux on IA-32),
|
||||
``ucontext_t.uc_mcontext.mc_rsp`` (FreeBSD on x86-64), or
|
||||
``uc_mcontext.gregs[REG_RSP]`` (Linux on x86-64).
|
||||
``ThreadScan()`` is called.
|
||||
|
||||
|
||||
Windows implementation
|
||||
|
|
@ -245,10 +248,7 @@ values which were in the saved registers on entry to the MPS.
|
|||
|
||||
_`.impl.w3.scan.suspended`: Otherwise, ``ThreadScan()`` calls
|
||||
|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
|
||||
stack is scanned.
|
||||
pointer.
|
||||
|
||||
|
||||
OS X implementation
|
||||
|
|
@ -284,10 +284,6 @@ 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_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
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ Design
|
|||
land
|
||||
lock
|
||||
nailboard
|
||||
prmc
|
||||
range
|
||||
ring
|
||||
sig
|
||||
|
|
|
|||
|
|
@ -77,15 +77,14 @@ usable.
|
|||
|
||||
#. The **protection mutator context** module figures out what the
|
||||
:term:`mutator` was doing when it caused a :term:`protection
|
||||
fault`, or when a thread was suspended, so that its
|
||||
:term:`registers` and :term:`control stack` can be scanned, and so
|
||||
that access to a protected region of memory can be emulated as
|
||||
described at :ref:`pool-awl-barrier`.
|
||||
fault`, so that access to a protected region of memory can be
|
||||
handled, or when a thread was suspended, so that its
|
||||
:term:`registers` and :term:`control stack` can be scanned.
|
||||
|
||||
See :ref:`design-prot` for the design, and ``prot.h`` for the
|
||||
interface. There are eight implementations, a typical example being
|
||||
``prmci3w3.c`` for Windows on IA-32. There is a generic
|
||||
implementation in ``prmcan.c``, which can't provide this feature.
|
||||
See :ref:`design-prmc` for the design, and ``prot.h`` for the
|
||||
interface. There are implementations on Unix, Windows, and OS X for
|
||||
IA-32 and x86-64. There is a generic implementation in
|
||||
``prmcan.c``, which can't provide these features.
|
||||
|
||||
#. The **stack probe** module checks that there is enough space on the
|
||||
:term:`control stack` for the MPS to complete any operation that it
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue