MachImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Bob Hagmann October 7, 1988 2:18:45 pm PDT
Handle calls to Camelot from Cedar.
See CamelotImpl for a discussion of the mapping of parameters advertized in .defs files and the actual calling sequence as generated by MIG.
DIRECTORY
IO USING [int, PutFR1],
Mach,
Rope USING [Cat, Fetch, Length, ROPE];
MachImpl: CEDAR PROGRAM
IMPORTS IO, Mach, Rope
EXPORTS Mach
~ BEGIN
OPEN Mach;
MachCall: PUBLIC SIGNAL [errorCode: msgReturnT, explanation: Rope.ROPE] = CODE;
MachAnomaly: PUBLIC SIGNAL [explanation: Rope.ROPE] = CODE;
Exported task procedures
taskSelf: PUBLIC PROC RETURNS [targetTask: taskT] ~ {
get my task
innerTaskSelf: PROC RETURNS [XtargetTask: taskT] ~ TRUSTED MACHINE CODE {
"@task←self←"
};
targetTask ← innerTaskSelf[];
IF targetTask # 1 THEN ERROR;
};
taskNotify: PUBLIC PROC RETURNS [notifyPort: portT] ~ {
get my notify port (task←notify)
innerTaskNotify: PROC RETURNS [XnotifyPort: portT] ~ TRUSTED MACHINE CODE {
"@task←notify←"
};
notifyPort ← innerTaskNotify[];
IF notifyPort # 2 THEN ERROR;
};
taskData: PUBLIC PROC RETURNS [dataPort: portT] ~ {
get my data port (task�ta)
innerTaskData: PROC RETURNS [XdataPort: portT] ~ TRUSTED MACHINE CODE {
"@task�ta←"
};
dataPort ← innerTaskData[];
IF dataPort # 3 THEN ERROR;
};
Exported virtual memory procedures
vmAllocate: PUBLIC PROC [targetTask: vmTaskT, address: vmAddressT, size: vmSizeT, anywhere: BOOL,raiseSignal: BOOL] RETURNS [mappedAddress: vmAddressT ← 0, kernCode: kernReturnT ← -1] ~ TRUSTED {
Grab some VM.
innerVmAllocate: PROC [itargetTask: vmTaskT, iaddress: POINTER TO vmAddressT, isize: vmSizeT, ianywhere: BOOL] RETURNS [kernReturnT] ~ TRUSTED MACHINE CODE {
"<mach.h>vm𡤊llocate"
};
localAddress: vmAddressT ← address;
allocCode: kernReturnT ← -1;
allocCode ← innerVmAllocate[targetTask, @localAddress, size, anywhere];
IF raiseSignal AND allocCode # KernSuccess THEN SIGNAL Mach.MachCall[allocCode, Rope.Cat["vm𡤊llocate failed; code = ", IO.PutFR1["%g", IO.int[allocCode]]]];
RETURN[localAddress, allocCode];
};
vmAllocateWithPager: PUBLIC PROC [targetTask: vmTaskT, address: vmAddressT, size: vmSizeT, anywhere: BOOL, pagingObject: pagingObjectT, offset: vmOffsetT, raiseSignal: BOOL] RETURNS [mappedAddress: vmAddressT ← 0, kernCode: kernReturnT ← -1] ~ TRUSTED {
Map some externally backed memory into VM.
innerVmAllocateWithPager: PROC [itargetTask: vmTaskT, iaddress: POINTER TO vmAddressT, isize: vmSizeT, ianywhere: BOOL, ipagingObject: pagingObjectT, ioffset: vmOffsetT] RETURNS [kernReturnT] ~ TRUSTED MACHINE CODE {
"vm𡤊llocate←with←pager"
};
localAddress: vmAddressT ← address;
allocCode: kernReturnT ← -1;
allocCode ← innerVmAllocateWithPager[targetTask, @localAddress, size, anywhere, pagingObject, offset];
IF raiseSignal AND allocCode # KernSuccess THEN SIGNAL Mach.MachCall[allocCode, Rope.Cat["vm𡤊llocate←with←pager failed; code = ", IO.PutFR1["%g", IO.int[allocCode]]]];
RETURN[localAddress, allocCode];
};
vmDeallocate: PUBLIC PROC [targetTask: vmTaskT, address: vmAddressT, size: vmSizeT, raiseSignal: BOOL] RETURNS [kernCode: kernReturnT ← -1] ~ {
Unmap some externally backed memory into VM, whether externally backed or not.
innerVmDellocate: PROC [itargetTask: vmTaskT, iaddress: vmAddressT, isize: vmSizeT] RETURNS [kernReturnT] ~ TRUSTED MACHINE CODE {
"<mach.h>vm�llocate"
};
deallocCode: kernReturnT ← -1;
deallocCode ← innerVmDellocate[targetTask, address, size];
IF raiseSignal AND deallocCode # KernSuccess THEN SIGNAL Mach.MachCall[deallocCode, Rope.Cat["vm�llocate failed; code = ", IO.PutFR1["%g", IO.int[deallocCode]]]];
RETURN[deallocCode];
};
Exported message procedures
msgSend: PUBLIC PROC [header: REF msgHeaderT, option: msgOptionT, timeout: INT, raiseSignal: BOOL] RETURNS [msgCode: msgReturnT ← -1] ~ {
send a message
innerMsgSend: PROC [iheader: POINTER TO msgHeaderT, ioption: msgOptionT, itimeout: INT] RETURNS [msgReturnT] ~ TRUSTED MACHINE CODE {
"<mach.h>msg←send"
};
sendCode: msgReturnT ← SendErrorsStart;
sendCode ← innerMsgSend[LOOPHOLE[header], option, timeout];
IF raiseSignal AND sendCode # KernSuccess THEN SIGNAL Mach.MachCall[sendCode, Rope.Cat["msg←send failed; code = ", IO.PutFR1["%g", IO.int[sendCode]]]];
RETURN[sendCode];
};
msgReceive: PUBLIC PROC [header: REF msgHeaderT, option: msgOptionT, timeout: INT, raiseSignal: BOOL] RETURNS [msgCode: msgReturnT ← -1] ~ {
Receive a message.
Modifies the header!
innerMsgReceive: PROC [iheader: POINTER TO msgHeaderT, ioption: msgOptionT, itimeout: INT] RETURNS [msgReturnT] ~ TRUSTED MACHINE CODE {
"<mach.h>msg←receive"
};
rCode: msgReturnT ← SendErrorsStart;
rCode ← innerMsgReceive[LOOPHOLE[header], option, timeout];
IF raiseSignal AND rCode # KernSuccess THEN ERROR MachCall[rCode, Rope.Cat["msg←receive failed; code = ", IO.PutFR1["%g", IO.int[rCode]]]];
RETURN[rCode];
};
msgRPC: PUBLIC PROC [header: REF msgHeaderT, option: msgOptionT, rcvSize: INT, sendTimeout: INT, rcvTimeout: INT, raiseSignal: BOOL] RETURNS [msgCode: msgReturnT ← -1] ~ {
Receive a message.
Modifies the header!
innerMsgRPC: PROC [iheader: POINTER TO msgHeaderT, ioption: msgOptionT, ircvSize: INT, isendTimeout: INT, ircvTimeout: INT] RETURNS [msgReturnT]~ TRUSTED MACHINE CODE {
"<mach.h>msg←RPC"
};
rpcCode: msgReturnT ← RcvErrorsStart ;
rpcCode ← innerMsgRPC[LOOPHOLE[header], option, rcvSize, sendTimeout, rcvTimeout];
IF raiseSignal AND rpcCode # KernSuccess THEN ERROR MachCall[rpcCode, Rope.Cat["msg←RPC failed; code = ", IO.PutFR1["%g", IO.int[rpcCode]]]];
RETURN[rpcCode];
};
Exported port procedures
nameServerPort: PUBLIC PROC RETURNS [p: portT] ~ {
get my port to the name server (name←server←port)
innerPort: PROC RETURNS [XportT: portT] ~ TRUSTED MACHINE CODE {
"@name←server←port"
};
p ← innerPort[];
};
environmentPort: PUBLIC PROC RETURNS [p: portT] ~ {
get my port to the environment (environment←port)
innerPort: PROC RETURNS [XportT: portT] ~ TRUSTED MACHINE CODE {
"@environment←port"
};
p ← innerPort[];
};
servicePort: PUBLIC PROC RETURNS [p: portT] ~ {
get my port to the service port (service←port)
innerPort: PROC RETURNS [XportT: portT] ~ TRUSTED MACHINE CODE {
"@service←port"
};
p ← innerPort[];
};
MachPortsLookup: PUBLIC PROC [targetTask: taskT, raiseSignal: BOOL] RETURNS [intPortSet: portArrayT, intPortArrayCount: INT, kernCode: kernReturnT] ~ {
get my port to the service port (service←port)
xintPortArrayCount: POINTER TO INT;
innerMachPortsLookup: PROC [itargetTask: taskT, iintPortSet: portArrayT, iintPortArrayCount: POINTER TO INT] RETURNS [kernReturnT]~ TRUSTED MACHINE CODE {
"<mach.h>mach←ports←lookup"
};
TRUSTED {xintPortArrayCount ← @intPortArrayCount;};
kernCode ← innerMachPortsLookup[targetTask, intPortSet, xintPortArrayCount];
IF raiseSignal AND kernCode # KernSuccess THEN ERROR MachCall[kernCode, IO.PutFR1["mach←ports←lookup failed; code = %g", IO.int[kernCode]]];
};
portAllocate: PUBLIC PROC [targetTask: taskT, raiseSignal: BOOL] RETURNS [newPort: portT, kernCode: kernReturnT ← -1] ~ TRUSTED {
send a message
innerPortAllocate: PROC [itargetTask: taskT, inewPort: POINTER TO portT] RETURNS [kernReturnT] ~ TRUSTED MACHINE CODE {
"<mach.h>port𡤊llocate"
};
allocCode: kernReturnT ← -1 ;
allocCode ← innerPortAllocate[targetTask, @newPort];
IF raiseSignal AND allocCode # KernSuccess THEN ERROR MachCall[allocCode, Rope.Cat["port𡤊llocate failed; code = ", IO.PutFR1["%g", IO.int[allocCode]]]];
kernCodeallocCode;
};
portDeallocate: PUBLIC PROC [targetTask: taskT, localPort: portT, raiseSignal: BOOL] RETURNS [kernCode: kernReturnT ← -1] ~ {
Receive a message.
Modifies the header!
innerPortDeallocate: PROC [itargetTask: taskT, ilocalPort: portT] RETURNS [kernReturnT] ~ TRUSTED MACHINE CODE {
"<mach.h>port�llocate"
};
deallocCode: kernReturnT ← -1 ;
deallocCode ← innerPortDeallocate[targetTask, localPort];
IF raiseSignal AND deallocCode # KernSuccess THEN ERROR MachCall[deallocCode, Rope.Cat["port�llocate failed; code = ", IO.PutFR1["%g", IO.int[deallocCode]]]];
RETURN[deallocCode];
};
portRestrict: PUBLIC PROC [targetTask: taskT, port: portT, raiseSignal: BOOL] RETURNS [kernCode: kernReturnT ← -1] ~ {
restricts port so that msgReceive must be used the port number, not PortDefault
innerPortRestrict: PROC [itargetTask: taskT, iport: portT] RETURNS [kernReturnT] ~ TRUSTED MACHINE CODE {
"<mach.h>port←restrict"
};
kernCode ← innerPortRestrict[targetTask, port];
IF raiseSignal AND kernCode # KernSuccess THEN SIGNAL Mach.MachCall[kernCode, IO.PutFR1["port←restrict failed; code = %g", IO.int[kernCode]]];
};
portUnrestrict: PUBLIC PROC [targetTask: taskT, port: portT, raiseSignal: BOOL] RETURNS [kernCode: kernReturnT ← -1] ~ {
unrestricts port so that PortDefault to msgReceive can receive from this port
innerPortUnrestrict: PROC [itargetTask: taskT, iport: portT] RETURNS [kernReturnT] ~ TRUSTED MACHINE CODE {
"<mach.h>port←restrict"
};
kernCode ← innerPortUnrestrict[targetTask, port];
IF raiseSignal AND kernCode # KernSuccess THEN SIGNAL Mach.MachCall[kernCode, IO.PutFR1["port←unrestrict failed; code = %g", IO.int[kernCode]]];
};
Netname
netnameCheckIn: PUBLIC PROC [ServPort: portT, portName: Rope.ROPE, signature: portT, portId: portT, raiseSignal: BOOL] RETURNS [kernCode: kernReturnT] ~ {
"check in a name into the local name space"
innerNetnameCheckIn: PROC [wServPort: portT, wportName: POINTER TO Mach.netnameNameT, wsignature: portT, wportId: portT] RETURNS [kernReturnT] ~ TRUSTED MACHINE CODE {
"<servers/netname.h>netname𡤌heck←in"
};
portNameString: REF Mach.netnameNameT;
portNameString ← netnameNameTFromRope[portName];
kernCode ← innerNetnameCheckIn[ServPort, LOOPHOLE[portNameString], signature, portId];
IF raiseSignal AND kernCode # KernSuccess THEN SIGNAL Mach.MachCall[kernCode, IO.PutFR1["netname𡤌heck←in failed; code = %g", IO.int[kernCode]]];
};
netnameLookUp: PUBLIC PROC [ServPort: portT, hostName: Rope.ROPE, portName: Rope.ROPE, raiseSignal: BOOL] RETURNS [portId: portT, kernCode: kernReturnT] ~ TRUSTED {
"check in a name into the local name space"
innerNetnameLookUp: PROC [wServPort: portT, whostName: POINTER TO Mach.netnameNameT, wportName: POINTER TO Mach.netnameNameT, wportId: POINTER TO portT] RETURNS [kernReturnT] ~ TRUSTED MACHINE CODE {
"<servers/netname.h>netname←look←up"
};
portNameString: REF Mach.netnameNameT;
hostNameString: REF Mach.netnameNameT;
portNameString ← netnameNameTFromRope[portName];
hostNameString ← netnameNameTFromRope[hostName];
kernCode ← innerNetnameLookUp[ServPort, LOOPHOLE[hostNameString], LOOPHOLE[portNameString], @portId];
IF raiseSignal AND kernCode # KernSuccess THEN SIGNAL Mach.MachCall[kernCode, IO.PutFR1["netname←look←up failed; code = %g", IO.int[kernCode]]];
};
netnameCheckOut: PUBLIC PROC [ServPort: portT, portName: Rope.ROPE, signature: portT, raiseSignal: BOOL] RETURNS [kernCode: kernReturnT] ~ {
"check in a name into the local name space"
innerNetnameCheckOut: PROC [wServPort: portT, wportName: POINTER TO Mach.netnameNameT, wsignature: portT] RETURNS [kernReturnT] ~ TRUSTED MACHINE CODE {
"<servers/netname.h>netname𡤌heck←out"
};
portNameString: REF Mach.netnameNameT;
portNameString ← netnameNameTFromRope[portName];
kernCode ← innerNetnameCheckOut[ServPort, LOOPHOLE[portNameString], signature];
IF raiseSignal AND kernCode # KernSuccess THEN SIGNAL Mach.MachCall[kernCode, IO.PutFR1["netname𡤌heck←in failed; code = %g", IO.int[kernCode]]];
};
netnameNameTFromRope: PROC [name: Rope.ROPE] RETURNS [portNameString: REF Mach.netnameNameT] ~ {
pNSize: INT ← 0;
portNameString ← NEW[Mach.netnameNameT];
pNSize ← Rope.Length[name];
IF pNSize >= 80 THEN ERROR;
FOR index: INT IN [0..pNSize) DO
portNameString[index] ← Rope.Fetch[name, index];
ENDLOOP;
portNameString[pNSize] ← 0C;
};
Initialization
END.