DIRECTORY BufferDefs USING[ Buffer ], DebuggerFormat USING[ LabelChecksum ], DiskFace USING[ Label, Type ], PrincOps, Process USING[ EnableAborts ], PupDefs USING[ GetFreePupBuffer, GetPupAddress, GetPupContentsBytes, MsToTocks, PupBuffer, PupNameTrouble, PupPackageDestroy, PupPackageMake, PupSocket, PupSocketDestroy, PupSocketMake, ReturnFreePupBuffer, SetPupContentsWords ], PupTypes USING[ fillInSocketID, Pair, PupAddress, PupType ], Rope USING[ ROPE ], TeledebugProtocol, WorldVM USING[ ], WVMPrivate; WVMRemote: MONITOR IMPORTS DebuggerFormat, Process, PupDefs EXPORTS WorldVM, WVMPrivate = { Machine: PUBLIC TYPE = PupTypes.PupAddress; ReadRemoteCore: PUBLIC PROC[host: Machine, data: REF WVMPrivate.PageData, mempage: WVMPrivate.PageNumber] RETURNS[map: WVMPrivate.MapEntry, ok: BOOL] = { in: LONG POINTER TO TeledebugProtocol.CoreFetchAcknowledgement; out: LONG POINTER TO TeledebugProtocol.CoreFetchRequest; Lock[host]; DO ENABLE UNWIND => Unlock[]; p: PupDefs.PupBuffer _ PupDefs.GetFreePupBuffer[]; out _ LOOPHOLE[@p.pupWords]; out^ _ [page: mempage]; p _ SendAndReceive[p, TeledebugProtocol.coreFetchRequest, TeledebugProtocol.coreFetchRequestSize]; in _ LOOPHOLE[@p.pupWords]; IF PupWords[p] # TeledebugProtocol.coreFetchAcknowledgementSize OR WVMPrivate.PageNumber[in.page] # mempage THEN { PupDefs.ReturnFreePupBuffer[p]; LOOP }; data^ _ LOOPHOLE[in.data, WVMPrivate.PageData]; map.state.flags _ LOOPHOLE[in.flags, PrincOps.PageState].flags; PupDefs.ReturnFreePupBuffer[p]; ok _ LOOPHOLE[in.flags, PrincOps.PageState].flags#PrincOps.flagsVacant; EXIT ENDLOOP; Unlock[]; }; WriteRemoteCore: PUBLIC PROC[host: Machine, data: REF WVMPrivate.PageData, mempage: WVMPrivate.PageNumber, map: WVMPrivate.MapEntry] RETURNS[readOnly: BOOL] = { in: LONG POINTER TO TeledebugProtocol.CoreStoreAcknowledgement; out: LONG POINTER TO TeledebugProtocol.CoreStoreRequest; readOnly _ map.state.flags.readonly; IF NOT readOnly THEN map.state.flags.dirty _ TRUE; Lock[host]; DO ENABLE UNWIND => Unlock[]; p: PupDefs.PupBuffer _ PupDefs.GetFreePupBuffer[]; out _ LOOPHOLE[@p.pupWords]; out.page _ mempage; out.flags _ LOOPHOLE[map.state.flags]; LOOPHOLE[@out.data, LONG POINTER TO WVMPrivate.PageData]^ _ data^; p _ SendAndReceive[p, TeledebugProtocol.coreStoreRequest, TeledebugProtocol.coreStoreRequestSize]; in _ LOOPHOLE[@p.pupWords]; IF PupWords[p] # TeledebugProtocol.coreStoreAcknowledgementSize OR WVMPrivate.PageNumber[in.page] # mempage THEN { PupDefs.ReturnFreePupBuffer[p]; LOOP }; IF in.flags#LOOPHOLE[map.state.flags, WORD] THEN ERROR; PupDefs.ReturnFreePupBuffer[p]; EXIT; ENDLOOP; Unlock[]; }; ClientDiskTellsLies: ERROR = CODE; ReadRemoteDisk: PUBLIC PROC[host: Machine, data: REF WVMPrivate.PageData, addr: WVMPrivate.DiskAddress, label: LONG POINTER TO DiskFace.Label] = { in: LONG POINTER TO TeledebugProtocol.DiskFetchAcknowledgement; out: LONG POINTER TO TeledebugProtocol.DiskAddressSetRequest; Lock[host]; DO ENABLE UNWIND => Unlock[]; p: PupDefs.PupBuffer _ PupDefs.GetFreePupBuffer[]; out _ LOOPHOLE[@p.pupWords]; out^ _ [addr.diskPage + addr.offset, addr.deviceType, addr.deviceOrdinal]; p _ SendAndReceive[p, TeledebugProtocol.diskFetchRequest, TeledebugProtocol.diskAddressSetRequestSize]; IF PupWords[p] # TeledebugProtocol.diskFetchAcknowledgementSize THEN { PupDefs.ReturnFreePupBuffer[p]; LOOP }; in _ LOOPHOLE[@p.pupWords]; IF data # NIL THEN data^ _ LOOPHOLE[in.data, WVMPrivate.PageData]; label^ _ LOOPHOLE[in.label, DiskFace.Label]; PupDefs.ReturnFreePupBuffer[p]; IF addr.labelCheck # DebuggerFormat.LabelChecksum[label^, addr.offset] THEN ERROR ClientDiskTellsLies[]; EXIT ENDLOOP; Unlock[]; }; WriteRemoteDisk: PUBLIC PROC[host: Machine, data: REF WVMPrivate.PageData, addr: WVMPrivate.DiskAddress, label: LONG POINTER TO DiskFace.Label] = { p: PupDefs.PupBuffer; in: LONG POINTER TO TeledebugProtocol.DiskStoreAcknowledgement; out: LONG POINTER TO TeledebugProtocol.DiskStoreRequest; Lock[host]; DO ENABLE UNWIND => Unlock[]; SetDiskAddress[addr.deviceType, addr.deviceOrdinal, addr.diskPage + addr.offset]; p _ PupDefs.GetFreePupBuffer[]; out _ LOOPHOLE[@p.pupWords]; LOOPHOLE[@out.label, LONG POINTER TO DiskFace.Label]^ _ label^; LOOPHOLE[@out.data, LONG POINTER TO WVMPrivate.PageData]^ _ data^; p _ SendAndReceive[p, TeledebugProtocol.diskStoreRequest, TeledebugProtocol.diskStoreRequestSize]; IF PupWords[p] # TeledebugProtocol.diskStoreAcknowledgementSize THEN { PupDefs.ReturnFreePupBuffer[p]; LOOP }; in _ LOOPHOLE[@p.pupWords]; IF in.label = TeledebugProtocol.noLabel THEN ERROR ClientDiskTellsLies[]; PupDefs.ReturnFreePupBuffer[p]; EXIT ENDLOOP; Unlock[]; }; GoRemote: PUBLIC PROC[host: Machine] = { p: PupDefs.PupBuffer _ PupDefs.GetFreePupBuffer[]; Lock[host]; { ENABLE UNWIND => Unlock[]; p _ SendAndReceive[p, TeledebugProtocol.go, 0]; p.pupID _ IncPair[p.pupID]; Send[p, TeledebugProtocol.goReply, 0]; }; Unlock[]; }; SetDiskAddress: PROC [device: DiskFace.Type, deviceOrdinal: CARDINAL, page: LONG CARDINAL] = { in: LONG POINTER TO TeledebugProtocol.DiskAddressSetAcknowledgement; out: LONG POINTER TO TeledebugProtocol.DiskAddressSetRequest; DO p: PupDefs.PupBuffer _ PupDefs.GetFreePupBuffer[]; out _ LOOPHOLE[@p.pupWords]; out^ _ [page, device, deviceOrdinal]; p _ SendAndReceive[p, TeledebugProtocol.diskAddressSetRequest, TeledebugProtocol.diskAddressSetRequestSize]; in _ LOOPHOLE[@p.pupWords]; IF PupWords[p] # TeledebugProtocol.diskAddressSetAcknowledgementSize OR in^ # [page, device, deviceOrdinal] THEN { PupDefs.ReturnFreePupBuffer[p]; LOOP }; PupDefs.ReturnFreePupBuffer[p]; EXIT ENDLOOP; }; lastPupID: PupTypes.Pair _ [0, 0]; GetNextPupID: ENTRY PROC RETURNS [PupTypes.Pair] = INLINE { RETURN[lastPupID_IncPair[IncPair[lastPupID]]]; }; IncPair: PROC [id: PupTypes.Pair] RETURNS [PupTypes.Pair] = INLINE { OPEN id; RETURN [[a+(IF b=LAST[CARDINAL] THEN 1 ELSE 0), b+1]]; }; PupWords: PROC [p: PupDefs.PupBuffer] RETURNS [CARDINAL] = INLINE { w: CARDINAL = PupDefs.GetPupContentsBytes[p]; IF w MOD 2 # 0 THEN RETURN[LAST[CARDINAL]]; RETURN[w/2]; }; SendAndReceive: PROC [x: PupDefs.PupBuffer, t: PupTypes.PupType, words: CARDINAL] RETURNS [answer: PupDefs.PupBuffer] = { requeued: BOOL _ TRUE; done: CONDITION; MyRequeue: ENTRY PROC[BufferDefs.Buffer] = { requeued _ TRUE; NOTIFY done }; WaitRequeue: ENTRY PROC = { ENABLE UNWIND => NULL; UNTIL requeued DO WAIT done ENDLOOP }; x.requeueProcedure _ MyRequeue; x.pupID _ GetNextPupID[]; DO WaitRequeue[]; requeued _ FALSE; Send[x, t, words]; answer _ Receive[x.pupID ! ReceiveTimeout => LOOP]; EXIT ENDLOOP; WaitRequeue[]; PupDefs.ReturnFreePupBuffer[x]; }; Send: PROC [x: PupDefs.PupBuffer, t: PupTypes.PupType, words: CARDINAL] = { x.pupType _ t; PupDefs.SetPupContentsWords[x, words]; socket.put[x]; }; ReceiveTimeout: ERROR = CODE; getMeAPup: CONDITION; receivedPup: PupDefs.PupBuffer; wantPup: BOOL; Receive: ENTRY PROC[thisPupID: PupTypes.Pair] RETURNS [PupDefs.PupBuffer] = { ENABLE UNWIND => NULL; DO wantPup _ TRUE; receivedPup _ NIL; WAIT getMeAPup; IF receivedPup=NIL THEN RETURN WITH ERROR ReceiveTimeout; IF receivedPup.pupID = thisPupID THEN RETURN[receivedPup]; PupDefs.ReturnFreePupBuffer[receivedPup]; ENDLOOP; }; keepReceiving: BOOL; ReceiveProcess: PROC = { x: PupDefs.PupBuffer; Pass: ENTRY PROC = INLINE { IF wantPup THEN { wantPup _ FALSE; receivedPup _ x; NOTIFY getMeAPup } ELSE PupDefs.ReturnFreePupBuffer[x]; }; Notify: ENTRY PROC = INLINE {NOTIFY getMeAPup}; Like: PROC RETURNS [BOOL] = INLINE { RETURN [ x.source = remote AND x.dest = socket.getLocalAddress[] AND x.pupType = TeledebugProtocol.acknowledgement]; }; WHILE keepReceiving DO x _ socket.get[]; IF x = NIL THEN Notify[] -- timeout ELSE IF Like[] THEN Pass[] ELSE PupDefs.ReturnFreePupBuffer[x]; ENDLOOP; }; locked: BOOL _ FALSE; unlocked: CONDITION; socket: PupDefs.PupSocket; remote: PupTypes.PupAddress; Lock: ENTRY PROC[host: Machine] = { ENABLE UNWIND => NULL; WHILE locked DO WAIT unlocked ENDLOOP; locked _ TRUE; socket.setRemoteAddress[remote _ host]; }; Unlock: ENTRY PROC = { locked _ FALSE; NOTIFY unlocked }; LookupFailed: PUBLIC ERROR = CODE; LocateRemote: PUBLIC PROC [name: Rope.ROPE] RETURNS[ host: Machine ] = { host _ PupDefs.GetPupAddress[TeledebugProtocol.teleSwatSocket, name ! PupDefs.PupNameTrouble => ERROR LookupFailed[] ]; }; receiveProcess: PROCESS; StartTeledebugging: PROC = { PupDefs.PupPackageMake[]; Process.EnableAborts[@getMeAPup]; remote.net _ [0]; remote.host _ [0]; socket _ PupDefs.PupSocketMake[ local: PupTypes.fillInSocketID, remote: remote, ticks: PupDefs.MsToTocks[500] ]; keepReceiving _ TRUE; wantPup _ FALSE; receiveProcess _ FORK ReceiveProcess; Unlock[]; }; StopTeledebugging: PROC = { Lock[remote]; keepReceiving _ FALSE; JOIN receiveProcess; PupDefs.PupSocketDestroy[socket]; PupDefs.PupPackageDestroy[]; }; StartTeledebugging[]; }. ξWVMRemote.mesa - TeleDebug protocol Copyright c 1985 by Xerox Corporation. All rights reserved. Andrew Birrell July 29, 1983 3:56 pm Russ Atkinson, February 6, 1985 9:37:28 pm PST Public procedures Sending diskFetchRequest with diskAddressSetRequestSize causes a combined addressSet and diskFetch. (I didn't design it!) Actual packet transmission/reception! -- first level of screening (don't care about others) There is only one socket, protected by Lock/Unlock during remote calls -- Κ Φ˜codešœ#™#Kšœ Οmœ1™™>Kšœ:™:˜9K˜-—Kšžœ=˜?Kšžœ#žœ˜.Kšœžœ˜Kšžœžœžœ žœ˜BKšœ žœ˜,K˜KšžœD˜FKšžœžœ˜!Kšž˜—Kšžœ˜K˜ Kšœ˜K˜—šŸœžœžœžœ;žœžœžœ˜“K˜Kšœžœžœžœ,˜?Kšœžœžœžœ$˜8K˜ šžœžœžœ ˜K˜QK˜Kšœžœ˜Kšžœ žœžœžœ˜?Kšžœ žœžœžœ˜B˜9K˜(—Kšžœ=˜?Kšžœ#žœ˜.Kšœžœ˜Kšžœ&žœžœ˜IK˜Kšž˜—Kšžœ˜K˜ Kšœ˜K˜—šŸœžœžœ˜(K˜2K˜ šœ˜Kšžœžœ ˜K˜/K˜K˜&Kšœ˜—K˜ Kšœ˜K˜—š Ÿœžœ(žœžœžœ˜^Kšœžœžœžœ1˜DKšœžœžœžœ)˜=šžœ3˜5Kšœžœ˜K˜%˜>K˜-—Kšœžœ˜KšžœC˜EKšžœ$˜&Kšžœ#žœ˜.K˜Kšž˜—Kšžœ˜Kšœ˜K˜K˜—Kšœ(™(K˜K˜"K˜š Ÿ œžœžœžœžœ˜;Kšžœ+˜1K˜—šŸœžœžœžœ˜DKšžœ˜Kš žœžœžœžœžœžœ ˜6Kšœ˜K˜—š Ÿœžœžœžœžœ˜CKšœžœ"˜-Kš žœžœžœžœžœžœ˜+Kšžœ˜ Kšœ˜K˜—šŸœžœ4žœžœ ˜yKšœ žœžœ˜Kšœž œ˜šŸ œžœžœ˜*Kšœ žœžœ˜!—šŸ œžœžœ˜Kšœžœžœžœžœ žœžœžœ˜?—K˜K˜šžœžœ˜6Kšœ-žœ˜3Kšž˜—Kšžœ˜K˜.Kšœ˜K˜—šŸœžœ4žœ˜KK˜K˜&K˜Kšœ˜K˜—Kšœžœžœ˜Kšœ ž œ˜K˜Kšœ žœ˜K˜š Ÿœžœžœžœžœ˜MKšžœžœžœ˜šžœ žœ˜Kšœžœ˜Kšžœ ˜Kš žœ žœžœžœžœžœ˜9Kšžœžœžœ˜:K˜)—Kšžœ˜Kšœ˜K˜—Kšœžœ˜K˜šŸœžœ˜K˜šŸœžœžœžœ˜Kšžœ˜ Kšžœ žœžœ ˜;Kšžœ ˜$Kšœ˜—Kš Ÿœžœžœžœžœ ˜/š Ÿœžœžœžœžœ˜$Kšœ2™2šžœ˜Kšœžœ#ž˜;K˜/—Kšœ˜—šžœž˜K˜Kšžœž˜ Kšžœ Οc ˜Kšžœžœžœžœ ˜?—Kšžœ˜Kšœ˜K˜K˜K˜—KšœI™IK˜Kšœžœžœ˜Kšœ ž œ˜K˜K˜K˜K˜šŸœžœžœ˜#Kšžœžœžœ˜Kš žœžœžœ žœ žœ˜5K˜'Kšœ˜K˜—š Ÿœžœžœžœžœ ˜9K˜—Kšœžœžœžœ˜"K˜š Ÿ œžœžœ žœžœ˜HšœE˜EKšœžœ˜1—Kšœ˜K˜—Kšœžœ˜K˜šŸœžœ˜K˜K˜!K˜$˜K˜/K˜ —Kšœžœ žœ˜&Kšœžœ˜%K˜ Kšœ˜K˜—šŸœžœ˜K˜ Kšœžœžœ˜+K˜!K˜Kšœ˜K˜—K˜K˜Kšœ˜K˜K˜—…—"~/B