LoadState.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Levin on August 8, 1983 1:43 pm
Paul Rovner and Andrew Birrell on July 7, 1983 2:00 pm
Russ Atkinson (RRA) February 1, 1985 4:59:34 pm PST
Doug Wyatt, February 27, 1985 10:07:01 am PST
Each loadstate is organized as a set of configurations, ordered by the time of their loading. Each configuration consists of an unordered set of modules.
DIRECTORY
BcdDefs USING [BcdBase, ModuleIndex, MTIndex, NullModule],
PrincOps USING [GlobalFrameHandle, EPIndex, ControlLink],
SafeStorage USING [nullType, Type];
LoadState: DEFINITIONS
= BEGIN
Types
Handle: TYPE = REF Object;
Object: TYPE;
Access: TYPE = {shared, exclusive};
ConfigID: TYPE[1];
nullConfig: READONLY ConfigID;
ModuleIndex: TYPE = BcdDefs.ModuleIndex;
nullModule: ModuleIndex = BcdDefs.NullModule;
Note that, at present, a ModuleIndex is not completely opaque. The client of this interface is assumed to understand something about the format of BCDs; in particular, the field BcdDefs.MTRecord.gfi corresponds directly to a ModuleIndex as used in this interface. This should not be confused with an MTIndex, which is a relative pointer to an MTRecord.
BcdBase: TYPE = BcdDefs.BcdBase;
Type: TYPE = SafeStorage.Type;
nullType: Type = SafeStorage.nullType;
GlobalFrameHandle: TYPE = PrincOps.GlobalFrameHandle;
CopiesList: TYPE = LIST OF GlobalFrameHandle;
Loadstate Instances
This interface is capable of handling multiple loadstates. The variable "local", below, identifies the loadstate for the local world. Other loadstates may be created (by means not defined in the interface) that refer to remote worlds.
local: READONLY Handle;
Synchronization
Acquire: PROC [loadState: Handle, access: Access ← shared];
The client must invoke Acquire before calling any other procedures in this interface. When it returns, the requested access has been granted to the specified loadstate.
Release: PROC [loadState: Handle, commit: BOOLTRUE];
Release must be called when the client has finished with the loadstate. If the loadState was acquired with exclusive access, the "commit" parameter determines whether the changes made to configurations added via NewConfig (see below) since Acquire was called are retained (commit = TRUE) or discarded (commit = FALSE). If the loadState was acquired with shared access, the commit parameter is ignored.
Interrogation Procedures
These procedures do not alter the loadstate and therefore can be invoked after acquiring the loadstate with "shared" access. Note that these procedures never need to look inside a BcdBase in order to perform their functions.
ConfigInfo: PROC [loadState: Handle, config: ConfigID] RETURNS [bcd: BcdBase, ref: REF ANY];
GetChangeCount: PROC [loadState: LoadState.Handle] RETURNS [INT];
ModuleInfo: PROC [loadState: Handle, config: ConfigID, module: ModuleIndex]
RETURNS [
gfh: GlobalFrameHandle,
mti: BcdDefs.MTIndex,
type: Type,
copies: CopiesList -- NIL if no copies exist
];
GlobalFrameToModule: PROC [loadState: Handle, gfh: GlobalFrameHandle]
RETURNS [config: ConfigID, module: ModuleIndex];
GlobalFrameToType: PROC [loadState: Handle, gfh: GlobalFrameHandle]
RETURNS [type: Type] = INLINE {
config: ConfigID;
module: ModuleIndex;
[config, module] ← GlobalFrameToModule[loadState, gfh];
RETURN[ModuleInfo[loadState, config, module].type]
};
ModuleToGlobalFrame: PROC [loadState: Handle, config: ConfigID, module: ModuleIndex]
RETURNS [gfh: GlobalFrameHandle] = INLINE {
RETURN[ModuleInfo[loadState, config, module].gfh]
};
BuildProcDescUsingModule: PROC [
loadState: Handle, config: ConfigID, module: ModuleIndex, ep: PrincOps.EPIndex]
RETURNS [PrincOps.ControlLink];
Note: there is a difference (temporary until the wonderful world of 32-bit ControlLinks) in the result of BuildProcDesc between local and remote loadstates. In the local case, a fully usable ControlLink is returned. In the remote case, a ControlLink with relative gfi (to be relocated by adding gfh.gfi) is returned. This difference obtains because we can't dereference GFH in the remote case.
BuildProcDescUsingGlobalFrame: PROC [
loadState: Handle, gfh: GlobalFrameHandle, ep: NAT]
RETURNS [PrincOps.ControlLink];
Note that 'ep' is a full entry point index, not the abbreviated PrincOps.EPIndex that appears in procedure descriptors. This procedure simply constructs the requested descriptor; it doesn't ensure that the result actually corresponds to an extant procedure.
Modification Procedures
These procedures alter the loadstate and therefore can be invoked only after acquiring the loadstate with "exclusive" access. These procedures assume they can access the relevant BCD.
LoadStateFull: ERROR;
Raised by NewConfig and CopyNew.
NewConfig: PROC [loadState: Handle, bcd: BcdBase, ref: REF ANY] RETURNS [ConfigID];
This procedure is intended to be called by the loader when it instantiates a new configuration. The 'ref' parameter is treated as an opaque quantity that the client can recover using ConfigInfo. Before relinquishing its exclusive access to the loadState, the loader is expected to call SetGlobalFrame and SetType for each module in the configuration. Note that the enumerators, below, cannot be used to drive these calls. LoadStateFull will be raised if there is no room to add the new configuration.
SetGlobalFrame: PROC [
loadState: Handle, config: ConfigID, module: ModuleIndex, gfh: GlobalFrameHandle];
This procedure should be called precisely once for each module.
SetType: PROC [loadState: Handle, gfh: GlobalFrameHandle, type: Type];
This procedure should be called precisely once for each module.
CopyNew: PROC [loadState: Handle, old: PROGRAM] RETURNS [new: PROGRAM];
This procedure creates a new instance of the specified module, retaining all of its import bindings. LoadStateFull will be raised if there is no room in the loadstate for this module. The language construct NEW[program] is equivalent to LoadState.local.CopyNew[program].
UnNew: UNSAFE PROC [loadState: Handle, program: PROGRAM];
This procedure performs the inverse of CopyNew, removing the specified PROGRAM from the loadstate. The program must have been obtained by a call of CopyNew.
SelfDestruct: UNSAFE PROC;
This procedure is equivalent to LoadState.local.UnNew[invoker's module] followed by a return to the invoker of the invoker. The invoker must have been created by a call of CopyNew. Since the invoker's module is destroyed by this call, the invoker's invoker must not be in the same module.
Enumerators
All enumerators take a "proc" argument that returns a Boolean. The enumeration continues as long as the procedure returns FALSE and stops as soon as it returns TRUE. The enumerators never alter the loadstate and therefore may be invoked after acquiring it with "shared" access. However, if the "proc" passed to the enumerator alters the loadstate, "exclusive" access is required.
EnumerationOrder: TYPE = {newestFirst, oldestFirst};
EnumerateConfigs: PROC [
loadState: Handle,
order: EnumerationOrder,
proc: PROC [ConfigID] RETURNS [--stop:--BOOL]]
RETURNS [config: ConfigID];
The return value is the one passed to "proc" when it returned TRUE, or, if "proc" returned FALSE for all invocations, "config" is "nullConfig".
EnumerateModulesInConfig: PROC [
loadState: Handle,
config: ConfigID,
proc: PROC [ModuleIndex] RETURNS [--stop:--BOOL]]
RETURNS [module: ModuleIndex, gfh: GlobalFrameHandle];
The return value is the one passed to "proc" when it returned TRUE, or, if "proc" returned FALSE for all invocations, "module" is "nullModule". "proc" will be called only for those modules in "config" that have been entered into the loadState using SetGlobalFrame, above.
EnumerateAllModules: PROC [
loadState: Handle,
order: EnumerationOrder,
proc: PROC [ConfigID, ModuleIndex] RETURNS [--stop:--BOOL]]
RETURNS [config: ConfigID, module: ModuleIndex];
The return values are those passed to "proc" when it returned TRUE, or, if "proc" returned FALSE for all invocations, "config" is "nullConfig" and "module" is "nullModule". "proc" will be called only for those modules in "config" that have been entered into the loadState using SetGlobalFrame, above.
END.