Skip to content

Commit 9919050

Browse files
committed
Part of making extension callbacks part of the public MPS.
* Move type and macro declarations to the public header mps.h. * Move documentation to appropriate sections of manual. (cherry picked from commit b928fa2)
1 parent 179341b commit 9919050

3 files changed

Lines changed: 109 additions & 3 deletions

File tree

code/mps.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,13 @@ typedef mps_addr_t (*mps_fmt_isfwd_t)(mps_addr_t);
120120
typedef void (*mps_fmt_pad_t)(mps_addr_t, size_t);
121121
typedef mps_addr_t (*mps_fmt_class_t)(mps_addr_t);
122122

123+
/* Callbacks indicating that the arena has extended or contracted.
124+
* These are used to register chunks with RtlInstallFunctionTableCallback
125+
* <https://docs.microsoft.com/en-gb/windows/win32/api/winnt/nf-winnt-rtlinstallfunctiontablecallback>
126+
* so that the client can unwind the stack through functions in the arena.
127+
*/
128+
typedef void (*mps_arena_extended_t)(mps_arena_t, mps_addr_t, size_t);
129+
typedef void (*mps_arena_contracted_t)(mps_arena_t, mps_addr_t, size_t);
123130

124131
/* Keyword argument lists */
125132

@@ -171,6 +178,12 @@ extern const struct mps_key_s _mps_key_ARENA_SIZE;
171178
extern const struct mps_key_s _mps_key_ARENA_ZONED;
172179
#define MPS_KEY_ARENA_ZONED (&_mps_key_ARENA_ZONED)
173180
#define MPS_KEY_ARENA_ZONED_FIELD b
181+
extern const struct mps_key_s _mps_key_arena_extended;
182+
#define MPS_KEY_ARENA_EXTENDED (&_mps_key_arena_extended)
183+
#define MPS_KEY_ARENA_EXTENDED_FIELD fun
184+
extern const struct mps_key_s _mps_key_arena_contracted;
185+
#define MPS_KEY_ARENA_CONTRACTED (&_mps_key_arena_contracted)
186+
#define MPS_KEY_ARENA_CONTRACTED_FIELD fun
174187
extern const struct mps_key_s _mps_key_FORMAT;
175188
#define MPS_KEY_FORMAT (&_mps_key_FORMAT)
176189
#define MPS_KEY_FORMAT_FIELD format

manual/source/release.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ New features
4747
:ref:`topic-scanning-protocol`. This allows the client program to
4848
safely update references in the visited objects.
4949

50+
#. A :term:`virtual memory arena` can now be configured to call
51+
functions when it acquires a new chunk of :term:`address space`,
52+
and when it returns a chunk of address space to the operation
53+
system. This is intended to support dynamic function tables in
54+
Windows. See :ref:`topic-arena-extension`.
55+
5056

5157
Interface changes
5258
.................

manual/source/topic/arena.rst

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ Client arenas
139139
* :c:macro:`MPS_KEY_ARENA_SIZE` (type :c:type:`size_t`) is its
140140
size.
141141
142-
It also accepts three optional keyword arguments:
142+
It also accepts five optional keyword arguments:
143143
144144
* :c:macro:`MPS_KEY_COMMIT_LIMIT` (type :c:type:`size_t`) is
145145
the maximum amount of memory, in :term:`bytes (1)`, that the MPS
@@ -159,6 +159,17 @@ Client arenas
159159
may pause the :term:`client program` for. See
160160
:c:func:`mps_arena_pause_time_set` for details.
161161
162+
* :c:macro:`MPS_KEY_ARENA_EXTENDED` (type :c:type:`mps_fun_t`) is
163+
a function that will be called when the arena is *extended*:
164+
that is, when it acquires a new chunk of address space from the
165+
operating system. See :ref:`topic-arena-extension` for details.
166+
167+
* :c:macro:`MPS_KEY_ARENA_CONTRACTED` (type :c:type:`mps_fun_t`)
168+
is a function that will be called when the arena is
169+
*contracted*: that is, when it finishes with a chunk of address
170+
space and returns it to the operating system. See
171+
:ref:`topic-arena-extension` for details.
172+
162173
For example::
163174
164175
MPS_ARGS_BEGIN(args) {
@@ -983,8 +994,8 @@ Arena introspection and debugging
983994
from MPS-managed memory, then it may attempt to re-enter the
984995
MPS, which will fail as the MPS is not re-entrant.
985996
986-
.. |RtlInstallFunctionTableCallback| replace:: ``RtlInstallFunctionTableCallback()``
987-
.. _RtlInstallFunctionTableCallback: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680595(v=vs.85).aspx
997+
.. |RtlInstallFunctionTableCallback| replace:: :c:func:`RtlInstallFunctionTableCallback`
998+
.. _RtlInstallFunctionTableCallback: https://docs.microsoft.com/en-gb/windows/win32/api/winnt/nf-winnt-rtlinstallfunctiontablecallback
988999
9891000
If this happens, in order to allow the debugger to finish
9901001
decoding the call stack, the only remedy is to put the arena
@@ -1040,3 +1051,79 @@ Arena introspection and debugging
10401051
:c:func:`mps_addr_pool`, and to find out which :term:`object
10411052
format` describes the object at the address, use
10421053
:c:func:`mps_addr_fmt`.
1054+
1055+
1056+
.. index::
1057+
single: arena extension callbacks; introduction
1058+
single: extension callbacks; introduction
1059+
single: arena contraction callbacks; introduction
1060+
single: contraction callbacks; introduction
1061+
1062+
.. _topic-arena-extension:
1063+
1064+
Arena extension callbacks
1065+
-------------------------
1066+
1067+
There are situations in which the :term:`client program` needs to be
1068+
informed about the chunks of address space that an :term:`arena` is
1069+
managing. To support this, the MPS allows the client program to
1070+
specify two callback functions when creating a :term:`virtual memory
1071+
arena`: one function is called when the arena is *extended* (that is,
1072+
when it acquires a new chunk of address space from the operating
1073+
system), and the other when the arena is *contracted* (that is, when
1074+
it returns a chunk of address space to the operating system).
1075+
1076+
The use case that this feature is designed to support is debugging of
1077+
dynamically generated code in 64-bit Windows. Microsoft's
1078+
documentation for |RtlInstallFunctionTableCallback|_ says:
1079+
1080+
Function tables are used on 64-bit Windows to determine how to
1081+
unwind or walk the stack. These tables are usually generated by
1082+
the compiler and stored as part of the image. However,
1083+
applications must provide the function table for dynamically
1084+
generated code.
1085+
1086+
An application may install a dynamic function table by calling
1087+
|RtlInstallFunctionTableCallback|_, passing the region of memory in
1088+
which the dynamically generated functions can be found, and may later
1089+
delete the table by calling |RtlDeleteFunctionTable|_.
1090+
1091+
.. |RtlDeleteFunctionTable| replace:: :c:func:`RtlDeleteFunctionTable`
1092+
.. _RtlDeleteFunctionTable: https://docs.microsoft.com/en-gb/windows/win32/api/winnt/nf-winnt-rtldeletefunctiontable
1093+
1094+
So if the client program is storing dynamically generated functions in
1095+
MPS-managed memory, then it could define callback functions that
1096+
install and delete the function table callback for the dynamically
1097+
generated code, like this::
1098+
1099+
void arena_extended(mps_arena_t arena, void *base, size_t size)
1100+
{
1101+
RtlInstallFunctionTableCallback(...);
1102+
}
1103+
1104+
void arena_contracted(mps_arena_t arena, void *base, size_t size)
1105+
{
1106+
RtlDeleteFunctionTable(...);
1107+
}
1108+
1109+
and then pass these two functions using :term:`keyword arguments` to
1110+
:c:func:`mps_arena_create_k`::
1111+
1112+
MPS_ARGS_BEGIN(args) {
1113+
MPS_ARGS_ADD(args, MPS_KEY_ARENA_EXTENDED, (mps_fun_t)arena_extended);
1114+
MPS_ARGS_ADD(args, MPS_KEY_ARENA_CONTRACTED, (mps_fun_t)arena_contracted);
1115+
/* ... other keyword arguments ... */
1116+
res = mps_arena_create_k(&arena, mps_arena_class_vm(), args);
1117+
} MPS_ARGS_END(args);
1118+
1119+
The callback functions receive three arguments: ``arena`` (the arena
1120+
being extended or contracted), ``base`` (the base address of the chunk
1121+
of address space that has just been acquired from, or is about to be
1122+
returned to, the operating system), and ``size`` (the size of the
1123+
chunk, in bytes). They must not call any function in the MPS, and must
1124+
not access any memory managed by the MPS.
1125+
1126+
.. note::
1127+
1128+
Arena extension callbacks are only supported by :term:`virtual
1129+
memory arenas`.

0 commit comments

Comments
 (0)