internal static bool ExchangeReadyForCoCo(bool value) { CoCoThread t = MixinThread(Thread.CurrentThread); bool result = t.readyForCoCo; t.readyForCoCo = value; return(result); }
internal static void ThreadStart(Thread t_) { if (inited) { lock (interlock) { CoCoThread t = MixinThread(t_); t.readyForCoCo = true; t.acknowledgedPhase = (int)phase; t.acknowledgedForwarding = forwarding; t.acknowledgedPinning = pinning; } } }
internal static void ClientHandshake() { if (inited) { if (fVerbose) { VTable.DebugPrint(" !! ClientHandshake: interlock at "); VTable.DebugPrint((ulong)Magic.addressOf(interlock)); VTable.DebugPrint("\n"); } if (fVerbose) { if (Magic.addressOf(interlock) != interlockAddr) { VTable.DebugPrint(" !! ClientHandshake seeing interlock at new address: "); VTable.DebugPrint((ulong)Magic.addressOf(interlock)); VTable.DebugPrint("\n"); } if (ToSpaceAsPtr(interlock) != forwardedInterlockAddr) { VTable.DebugPrint(" !! ClientHandshake seeing interlock at new FORWARDED address: "); VTable.DebugPrint((ulong)ToSpaceAsPtr(interlock)); VTable.DebugPrint("\n"); } } lock (interlock) { if (fVerbose) { interlockAddr = Magic.addressOf(interlock); forwardedInterlockAddr = ToSpaceAsPtr(interlock); } CoCoThread t = MixinThread(Thread.CurrentThread); if (phase != (Phase)t.acknowledgedPhase || forwarding != t.acknowledgedForwarding || pinning != t.acknowledgedPinning) { if (fDebug) { VTable.DebugPrint(" !! thread "); VTable.DebugPrint((ulong)Magic.addressOf(t)); VTable.DebugPrint(" doing ack\n"); } t.acknowledgedPhase = (int)phase; t.acknowledgedForwarding = forwarding; t.acknowledgedPinning = pinning; t.phaseVersion++; Monitor.PulseAll(interlock); } } } }
internal static UIntPtr PinDirect(UIntPtr baseAddr, UIntPtr address, Pinner pinner) { Object o = Magic.fromAddress(baseAddr); UIntPtr CoCoWord; bool waited = false; for (;;) { CoCoWord = MixinObject(o).preHeader.CoCoWord; if (IsSimple(CoCoWord) || IsForwarded(CoCoWord)) { break; } else if (IsCopying(CoCoWord)) { VTable.Assert(pinner == Pinner.Barrier); if (fCount) { if (!waited) { waited = true; numWaitPins++; } numPinWaits++; } // wait until it's copied lock (interlock) { CoCoThread t = MixinThread(Thread.CurrentThread); t.pinnedOut = true; Monitor.PulseAll(interlock); while (t.pinnedOut) { Monitor.Wait(interlock); } } // ok, now try again (by the time we get here the // object could already be in the process of being // copied agagin!) } else if (IsTagged(CoCoWord)) { CASCoCoWord(o, Simple(), CoCoWord); NotifyPin(baseAddr); } } // what does it mean to get here? the object cannot // be moved until the next pinning safepoint prior to // a transition out of Idle. VTable.Assert(IsSimple(CoCoWord) || IsForwarded(CoCoWord)); // correct address if (IsForwarded(CoCoWord)) { address -= baseAddr; address += ForwardPtr(CoCoWord); } return(address); }
internal static void ChangePhase(Phase phase_, bool forwarding_, bool pinning_) { if (fDebug) { VTable.DebugPrint(" --> CoCo going to "); switch (phase_) { case Phase.Idle: VTable.DebugPrint("Idle"); break; case Phase.Prep: VTable.DebugPrint("Prep"); break; case Phase.Copy: VTable.DebugPrint("Copy"); break; case Phase.Fixup: VTable.DebugPrint("Fixup"); break; default: VTable.NotReached(); break; } VTable.DebugPrint(" (with"); if (!forwarding_) { VTable.DebugPrint("out"); } VTable.DebugPrint(" forwarding, with"); if (!pinning_) { VTable.DebugPrint("out"); } VTable.DebugPrint(" pinning)\n"); } lock (interlock) { phase = phase_; forwarding = forwarding_ || forceForwarding; pinning = pinning_ || forcePinning; SetAllowFastPath(); isNotIdle = phase != Phase.Idle || forceNotIdle; CoCoThread t = MixinThread(Thread.CurrentThread); t.acknowledgedPhase = (int)phase; t.acknowledgedForwarding = forwarding; t.acknowledgedPinning = pinning; t.phaseVersion++; Monitor.PulseAll(interlock); for (;;) { bool needToWait = false; bool doPulseAll = false; for (int i = 0; i < Thread.threadTable.Length; ++i) { Thread t_ = Thread.threadTable[i]; if (t_ == null) { continue; } t = MixinThread(t_); if (Transitions.InDormantState(i) || !t.readyForCoCo || t.pinnedOut) { t.acknowledgedPhase = (int)phase; t.acknowledgedForwarding = forwarding; t.acknowledgedPinning = pinning; } if (t.pinnedOut && phase == Phase.Idle) { t.pinnedOut = false; doPulseAll = true; } if ((Phase)t.acknowledgedPhase != phase || t.acknowledgedForwarding != forwarding || t.acknowledgedPinning != pinning) { if (fDebug) { VTable.DebugPrint(" !! thread "); VTable.DebugPrint((ulong)Magic.addressOf(t)); VTable.DebugPrint(" not ack\n"); } needToWait = true; } } if (doPulseAll) { Monitor.PulseAll(interlock); } if (!needToWait) { break; } // REVIEW: make the timeout less than 500 ms Monitor.Wait(interlock, 500); } } }