From 84e59c626ecde3b2913d7fb0c9ecdfd88ece533a Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Tue, 18 Oct 2016 22:35:13 +0100 Subject: [PATCH] Bring design.mps.message up to date and move it from old to current. Copied from Perforce Change: 192625 ServerID: perforce.ravenbrook.com --- mps/code/mpmst.h | 4 +- mps/design/message.txt | 265 ++++++++++++++--------------- mps/design/poolmrg.txt | 4 +- mps/manual/source/design/index.rst | 1 + mps/manual/source/design/old.rst | 1 - 5 files changed, 136 insertions(+), 139 deletions(-) diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h index dd0ecd077fc..b8af18a8eb2 100644 --- a/mps/code/mpmst.h +++ b/mps/code/mpmst.h @@ -176,7 +176,7 @@ typedef struct MessageClassStruct { /* generic methods */ MessageDeleteMethod delete; /* terminates a message */ - /* methods specific to MessageTypeFinalization */ + /* methods specific to MessageTypeFINALIZATION */ MessageFinalizationRefMethod finalizationRef; /* methods specific to MessageTypeGC */ @@ -184,7 +184,7 @@ typedef struct MessageClassStruct { MessageGCCondemnedSizeMethod gcCondemnedSize; MessageGCNotCondemnedSizeMethod gcNotCondemnedSize; - /* methods specific to MessageTypeGCStart */ + /* methods specific to MessageTypeGCSTART */ MessageGCStartWhyMethod gcStartWhy; Sig endSig; /* */ diff --git a/mps/design/message.txt b/mps/design/message.txt index 1c5d4210914..d48069006da 100644 --- a/mps/design/message.txt +++ b/mps/design/message.txt @@ -6,7 +6,7 @@ Client message protocol :Tag: design.mps.message :Author: David Jones :Date: 1997-02-13 -:Status: incomplete document +:Status: complete document :Revision: $Id$ :Copyright: See `Copyright and License`_. :Index terms: @@ -18,24 +18,16 @@ Introduction ------------ _`.intro`: The client message protocol provides a means by which -clients can receive messages from the MPS asynchronously. Typical -messages may be low memory notification (or in general low utility), -finalization notification, soft-failure notification. There is a -general assumption that it should not be disastrous for the MPS client -to ignore messages, but that it is probably in the clients best -interest to not ignore messages. The justification for this is that -the MPS cannot force the MPS client to read and act on messages, so no -message should be critical. +clients can receive messages from the MPS. The motivating use case is +finalization notification (see design.mps.finalize_), but the +mechanism is also used for feedback about collections. -.. note:: - - Bogus, since we cannot force clients to check error codes either. - Pekka P. Pirinen, 1997-09-17. +.. _design.mps.finalize: finalize _`.contents`: This document describes the design of the external and internal interfaces and concludes with a sketch of an example design of an internal client. The example is that of implementing -finalization using ``PoolMRG``. +finalization using the MRG pool. _`.readership`: Any MPS developer. @@ -43,21 +35,58 @@ _`.readership`: Any MPS developer. Requirements ------------ -_`.req`: The client message protocol will be used for implementing -finalization (see design.mps.finalize_ and req.dylan.fun.final). It -will also be used for implementing the notification of various -conditions (possibly req.dylan.prot.consult is relevant here). +_`.req.synchronous`: The message protocol must be synchronous with the +client program: that is, the client program must be able to choose +when to collect and act on messages. Justification: [Boehm_2002]_ +shows that asynchronous finalization is impossible to implement +correctly. -.. _design.mps.finalize: finalize +_`.req.reliable`: Posting a message must be reliable: that is, it must +not fail for a dynamic reason such as running out memory to store the +message. Justification: messages can't be used to implement +finalization unless the messages can be delivered reliably. + +_`.req.extensible.types`: The message mechanism must be extensible +with new types of message in future versions of the MPS, without +breaking client programs that do not receive those types of message. + +_`.req.resources`: It follows from `.req.extensible.types`_ that +messages must not use resources unless the client program has +requested them (otherwise resources would leak in client programs that +have not been updated to handle new types of message). + +_`.req.extensible.fields`: It must be possible to add new fields to +existing types of message in future versions of the MPS, without +breaking client programs that do not receive those types of message. + + +Design +------ + +_`.sol.synchronous`: Messages are stored on a ring belonging to the +arena. An interface is provided that allows the client program to +collect messages from the ring at a time of its choosing. + +_`.sol.reliable`: The memory needed for the message is allocated at an +earlier point in time, when it possible to communicate an allocation +failure via a result code. In particular, space for a finalization +message is allocated when the client program calls ``mps_finalize()``, +and space for trace messages is allocated in the arena (there can be +at most one instance of each message per trace, and the maximum number +of traces is known statically). + +_`.sol.resources`: Messages are not posted unless they belong to a +type that has been enabled by the client program calling +``mps_message_enable()``. This means that message types that are not +understood by the client program are not posted and use no resources. + +_`.sol.extensible.fields`: Message fields are retrieved by calling +accessor functions. External interface ------------------ -_`.if.queue`: Messages are presented as a single queue per arena. -Various functions are provided to inspect the queue and inspect -messages in it (see below). - Functions ......... @@ -73,12 +102,7 @@ messages of a certain type. The queue of messages of a arena will contain only messages whose types have been enabled. Initially all message types are disabled. Effectively this function allows the client to declare to the MPS what message types the client -understands. The MPS does not generate any messages of a type that -hasn't been enabled. This allows the MPS to add new message types (in -subsequent releases of a memory manager) without confusing the client. -The client will only be receiving the messages if they have explicitly -enabled them (and the client presumably only enables message types -when they have written the code to handle them). +understands. _`.if.fun.disable`: ``mps_message_type_disable()`` disables the flow of messages of a certain type. The antidote to @@ -122,10 +146,10 @@ Types of messages _`.type`: The type governs the "shape" and meaning of the message. -_`.type.int`: Types themselves will just be a scalar quantity, an -integer. +_`.type.int`: A message type is an integer belonging to the +``MessageType`` enumeration. -_`.type.semantics`: A type indicates the semantics of the message. +_`.type.semantics`: A type indicates the semantics of the message. _`.type.semantics.interpret`: The semantics of a message are interpreted by the client by calling various accessor methods on the @@ -134,10 +158,8 @@ message. _`.type.accessor`: The type of a message governs which accessor methods are legal to apply to the message. -_`.type.example`: Some example types: - -_`.type.finalization`: There will be a finalization type. The type is -abstractly: ``FinalizationMessage(Ref)``. +_`.type.finalization`: There is a finalization type, +``MessageTypeFINALIZATION``. _`.type.finalization.semantics`: A finalization message indicates that an object has been discovered to be finalizable (see @@ -145,32 +167,14 @@ design.mps.poolmrg.def.final.object_ for a definition of finalizable). .. _design.mps.poolmrg.def.final.object: poolmrg#def.final.object -_`.type.finalization.ref`: There is an accessor to get the reference -of the finalization message (i.e. a reference to the object which is -finalizable) called ``mps_message_finalization_ref()``. +_`.type.finalization.ref`: The accessor function +``mps_message_finalization_ref()`` retrieves the reference to the +object which is finalizable. _`.type.finalization.ref.scan`: Note that the reference returned -should be stored in scanned memory. +must be stored in scanned memory. -Compatibility issues -.................... - -_`.compatibility`: The following issues affect future compatibility of -the interface: - -_`.compatibility.future.type-new`: Notice that message of a type that -the client doesn't understand are not placed on the queue, therefore -the MPS can introduce new types of message and existing client will -still function and will not leak resources. This has been achieved by -getting the client to declare the types that the client understands -(with ``mps_message_type_enable()``, `.if.fun.enable`_). - -_`.compatibility.future.type-extend`: The information available in a -message of a given type can be extended by providing more accessor -methods. Old clients won't get any of this information but that's -okay. - Internal interface ------------------ @@ -184,8 +188,6 @@ _`.message.type`: ``Message`` is the type of messages. _`.message.instance`: Messages are instances of Message Classes. -``typedef struct MessageStruct *MessageStruct`` - _`.message.concrete`: Concretely a message is represented by a ``MessageStruct``. A ``MessageStruct`` has the usual signature field (see design.mps.sig_). A ``MessageStruct`` has a type field which @@ -201,14 +203,14 @@ that specific type of message. _`.message.struct`: The structure is declared as follows:: - struct MessageStruct { - Sig sig; - MessageType type; - MessageClass class; - RingStruct node; + typedef struct mps_message_s { + Sig sig; /* */ + Arena arena; /* owning arena */ + MessageClass klass; /* Message Class Structure */ + Clock postedClock; /* mps_clock() at post time, or 0 */ + RingStruct queueRing; /* Message queue ring */ } MessageStruct; - ``typedef struct MessageClassStruct *MessageClass`` _`.class`: A message class is an encapsulation of methods. It @@ -239,22 +241,26 @@ _`.class.methods.generic`: The generic methods are as follows: _`.class.methods.specific`: The type specific methods are: _`.class.methods.specific.finalization`: Specific to -``MessageTypeFinalization``: +``MessageTypeFINALIZATION``: * ``finalizationRef`` -- returns a reference to the finalizable object represented by this message. -_`.class.methods.specific.collectionstats`: Specific to ``MessageTypeCollectionStats``: +_`.class.methods.specific.gc`: Specific to ``MessageTypeGC``: -* ``collectionStatsLiveSize`` -- returns the number of bytes (of - objects) that were condemned but survived. +* ``gcLiveSize`` -- returns the number of bytes (of objects) that were + condemned by the trace but survived. -* ``collectionStatsCondemnedSize`` -- returns the number of bytes - condemned in the collection. +* ``gcCondemnedSize`` -- returns the number of bytes condemned by the + trace. -* ``collectionStatsNotCondemnedSize`` -- returns the the number of - bytes (of objects) that are subject to a GC policy (that is, - collectable) but were not condemned in the collection. +* ``gcNotCondemnedSize`` -- returns the the number of bytes (of + objects) that are collectable but were not condemned by the trace. + +_`.class.methods.specific.gcstart`: Specific to ``MessageTypeGCSTART``: + +* ``gcStartWhy`` -- returns an English-language description of the + reason why the trace was started. _`.class.sig.double`: The ``MessageClassStruct`` has a signature field at both ends. This is so that if the ``MessageClassStruct`` changes @@ -266,24 +272,28 @@ signature) unless the static initializers are changed as well. _`.class.struct`: The structure is declared as follows:: typedef struct MessageClassStruct { - Sig sig; /* design.mps.sig */ + Sig sig; /* */ const char *name; /* Human readable Class name */ + MessageType type; /* Message Type */ + /* generic methods */ MessageDeleteMethod delete; /* terminates a message */ - /* methods specific to MessageTypeFinalization */ - MessageFinalizationRefMethod finalizationRef; + /* methods specific to MessageTypeFINALIZATION */ + MessageFinalizationRefMethod finalizationRef; - /* methods specific to MessageTypeCollectionStats */ - MessageCollectionStatsLiveSizeMethod collectionStatsLiveSize; - MessageCollectionStatsCondemnedSizeMethod collectionStatsCondemnedSize; - MessageCollectionStatsNotCondemnedSizeMethod collectionStatsNotCondemnedSize; + /* methods specific to MessageTypeGC */ + MessageGCLiveSizeMethod gcLiveSize; + MessageGCCondemnedSizeMethod gcCondemnedSize; + MessageGCNotCondemnedSizeMethod gcNotCondemnedSize; - Sig endSig; /* design.mps.message.class.sig.double */ + /* methods specific to MessageTypeGCSTART */ + MessageGCStartWhyMethod gcStartWhy; + + Sig endSig; /* */ } MessageClassStruct; - _`.space.queue`: The arena structure is augmented with a structure for managing for queue of pending messages. This is a ring in the ``ArenaStruct``:: @@ -299,7 +309,7 @@ managing for queue of pending messages. This is a ring in the Functions ......... -``void MessageInit(Arena arena, Message message, MessageClass class)`` +``void MessageInit(Arena arena, Message message, MessageClass klass, MessageType type)`` _`.fun.init`: Initializes the ``MessageStruct`` pointed to by ``message``. The caller of this function is expected to manage the @@ -315,12 +325,15 @@ store for the ``MessageStruct``. _`.fun.post`: Places a message on the queue of an arena. -_`.fun.post.precondition`: Prior to calling the function, the node -field of the message must be a singleton. After the call to the -function the message will be available for MPS client to access. After -the call to the function the message fields must not be manipulated -except from the message's class's method functions (that is, you -mustn't poke about with the node field in particular). +_`.fun.post.precondition`: Prior to calling the function, the +``queueRing`` field of the message must be a singleton +(design.mps.ring.def.singleton_). After the call to the function the +message will be available for MPS client to access. After the call to +the function the message fields must not be manipulated except from +the message's class's method functions (that is, you mustn't poke +about with the ``queueRing`` field in particular). + +.. _design.mps.ring.def.singleton: ring#def.singleton ``void MessageEmpty(Arena arena)`` @@ -336,51 +349,35 @@ the future. Message life cycle ------------------ -_`.life`: A message will be allocated by a client of the message -module, it will be initialised by calling ``MessageInit()``. The -client will eventually post the message on the external queue (in fact -most clients will create a message and then immediately post it). The -message module may then apply any of the methods to the message. The -message module will eventually destroy the message by applying the -``delete`` method to it. +_`.life.alloc`: Space for the message structure is allocated at the +earliest point in time when the MPS knows that the message might be +needed. + +_`.life.init`: The message structure is initialized by calling +``MessageInit()``. + +_`.life.post`: The message is posted on the arena's message queue by +calling ``MessagePost()``. + +_`.life.get`: The client program retrieves the message by calling ``mps_message_get()``. + +_`.life.discard`: The client program indicates that it is finished +with the message by calling ``mps_message_discard()``. + +_`.life.reuse`: The MPS may reuse the message structure, in which case +the lifecycle continues from `.life.post`_. + +_`.life.delete`: When the MPS no longer needs the message structure, +its ``delete`` method is called. -Examples --------- +References +---------- -Finalization -............ - -.. note:: - - Possibly out of date, see design.mps.finalize_ and - design.mps.poolmrg_ instead. David Jones, 1997-08-28. - - .. _design.mps.poolmrg: poolmrg - .. _design.mps.finalize: finalize - -This subsection is a sketch of how PoolMRG will use Messages for -finalization (see design.mps.poolmrg_). - -PoolMRG has guardians (see design.mps.poolmrg.guardian_). Guardians -are used to manage final references and detect when an object is -finalizable. - -.. _design.mps.poolmrg.guardian: poolmrg#guardian - -The link part of a guardian will include a ``MessageStruct``. - -The ``MessageStruct`` is allocated when the final reference is created -(which is when the referred to object is registered for finalization). -This avoids allocating at the time when the message gets posted (which -might be a tricky, undesirable, or impossible, time to allocate). - -PoolMRG has two queues: the entry queue, and the exit queue. The entry -queue will use a ring; the exit queue of MRG will simply be the -external message queue. - -The ``delete`` method frees both the link part and the reference part -of the guardian. +.. [Boehm_2002] Hans-J. Boehm. 2002. "`Destructors, Finalizers, and + Synchronization + `_". HP + Labs technical report HPL-2002-335. Document History @@ -407,7 +404,7 @@ Document History Copyright and License --------------------- -Copyright © 2013-2014 Ravenbrook Limited . +Copyright © 2013-2016 Ravenbrook Limited . All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options. diff --git a/mps/design/poolmrg.txt b/mps/design/poolmrg.txt index 9c8de7e092e..4e15d0b2867 100644 --- a/mps/design/poolmrg.txt +++ b/mps/design/poolmrg.txt @@ -148,7 +148,7 @@ MPS detects that objects are finalizable. _`.over.message`: ``PoolClassMRG`` implements a ``MessageClass`` (see design.mps.message_). All the messages are of one ``MessageType``. This -type is ``MessageTypeFinalization``. Messages are created when objects +type is ``MessageTypeFINALIZATION``. Messages are created when objects are discovered to be finalizable and destroyed when the MPS client has received the message. @@ -685,7 +685,7 @@ Document History Copyright and License --------------------- -Copyright © 2013-2014 Ravenbrook Limited . +Copyright © 2013-2016 Ravenbrook Limited . All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options. diff --git a/mps/manual/source/design/index.rst b/mps/manual/source/design/index.rst index 50ee20f2492..a02f6e837b3 100644 --- a/mps/manual/source/design/index.rst +++ b/mps/manual/source/design/index.rst @@ -24,6 +24,7 @@ Design keyword-arguments land lock + message nailboard prmc prot diff --git a/mps/manual/source/design/old.rst b/mps/manual/source/design/old.rst index 0a858394180..15ba7686f5e 100644 --- a/mps/manual/source/design/old.rst +++ b/mps/manual/source/design/old.rst @@ -28,7 +28,6 @@ Old design io lib locus - message message-gc object-debug pool