/// <summary> /// Explicitly frees this end of the channel. /// /// Since both threads on the channel could try to do this simultaneously, /// we use the ref counting on the underlying endpoints to let the last /// free operation (the one pulling the ref count to 0) to free the associated /// event. /// </summary> public unsafe static void Free(Allocation * /*EndpointCore* opt(ExHeap)!*/ endpoint) { // Use unchecked GetData here, since this may be called from the // cleanup threading running in the kernel. EndpointCore *ep = ((EndpointCore *)Allocation.GetDataUnchecked(endpoint)); if (ep->deliveryHandle != DeliveryHandle.Zero) { if (DeliveryHandle.Free(ep->deliveryHandle)) { Interlocked.Decrement(ref openChannelCount); } } else { // was never connected, just free this endpoint AutoResetEventHandle areHandle = ep->cachedMessageEvent; SharedHeap.KernelSharedHeap.Free(endpoint, SharedHeap.CurrentProcessSharedHeap.EndpointPeerOwnerId); if (areHandle.id != UIntPtr.Zero) { Process.kernelProcess.ReleaseHandle(areHandle.id); } } }
/// <summary> /// The peer thread might try this too, so we use the ref count of the /// underlying memory to allow only the last freeer to also free the /// associated auto-reset event handle. Make sure to grab the handle /// before freeing the endpoint. /// </summary> unsafe private static bool TryFreeResources( Allocation * /*EndpointCore*/ endpoint, SharedHeap.AllocationOwnerId ownerId) { EndpointCore *epData = (EndpointCore *)Allocation.GetDataUnchecked(endpoint); AutoResetEventHandle areHandle = epData->GetAreHandle(); DeliveryHandle dh = epData->dImpHandle; int channelId = epData->ChannelId; bool lastRefGone = SharedHeap.KernelSharedHeap.Free(endpoint, ownerId); if (lastRefGone) { if (dh != DeliveryHandle.Zero) { DeliveryHandle.Dispose(dh); } if (areHandle.id != UIntPtr.Zero) { Process.kernelProcess.ReleaseHandle(areHandle.id); } } return(lastRefGone); }
public static int GetPeerProcessID(ref EndpointCore ep) { if (ep.peerStateValid) { EndpointCore *peer = (EndpointCore *)SharedHeapService.GetData(ep.cachedPeer); return(peer->cachedOwnerProcessId); } else { return(GetPeerProcessIDABI(ref ep)); } }
public static bool PeerClosed(ref EndpointCore ep) { if (ep.cachedPeer != null) { EndpointCore *peer = (EndpointCore *)SharedHeapService.GetData(ep.cachedPeer); return(peer->cachedClosed); } else { return(PeerClosedABI(ref ep)); } }
internal static DeliveryImpl AllocationEndpointDeliveryImplUnchecked( Allocation * /*EndpointCore* opt(ExHeap)!*/ endpoint) { EndpointCore *ep = (EndpointCore *)Allocation.GetDataUnchecked(endpoint); if (ep == null) { return(null); } else { return(ep->EndpointDeliveryImpl); } }
/// <summary> /// Performs the initialization of the core part of each endpoint and cross links /// them to form a channel. Uses the given delivery mechanism. /// </summary> public static void Connect( Allocation * /*EndpointCore* opt(ExHeap)!*/ imp, Allocation * /*EndpointCore* opt(ExHeap)!*/ exp, Allocation * /*EndpointCore* opt(ExHeap)!*/ securityEp, string deliveryImplType) { if (imp == null || exp == null) { throw new ApplicationException("Connect called with null endpoints"); } EndpointCore *impData = (EndpointCore *)Allocation.GetData(imp); EndpointCore *expData = (EndpointCore *)Allocation.GetData(exp); if (impData == null || expData == null) { throw new ApplicationException("SharedHeap.GetData return null"); } Tracing.Log(Tracing.Debug, "connect {0:x8} and {1:x8}", (UIntPtr)imp, (UIntPtr)exp); if (!(DeliveryHandle.Create(deliveryImplType, imp, out impData->deliveryHandle) && DeliveryHandle.Create(deliveryImplType, exp, out expData->deliveryHandle))) { throw new EndpointCoreException( "Error trying to create EndpointCore using \"" + deliveryImplType + "\" delivery implementation"); } #if false DebugStub.Print("imp handle {0,8:x} exp handle {1,8:x}\n", __arglist((uint)impData->deliveryHandle.id, (uint)expData->deliveryHandle.id)); #endif DeliveryImpl impDi = impData->EndpointDeliveryImpl; DeliveryImpl expDi = expData->EndpointDeliveryImpl; VTable.Assert(impDi != null && expDi != null); impDi.Connect(expDi, securityEp); // keep track of how many channels are open Interlocked.Increment(ref openChannelCount); #if CHANNEL_COUNT PerfCounters.IncrementChannelsCreated(); #endif Monitoring.Log(Monitoring.Provider.EndpointCore, (ushort)EndpointCoreEvent.Connect, 0, (uint)expData->ChannelId, 0, 0, 0, 0); }
// requires alloc's owner unlocked private unsafe void EndpointVisit(SharedHeap.Allocation *alloc) { // TODO: support PAGING #if !PAGING EndpointCore *epData = (EndpointCore *) // Currently use unchecked access here, since the shared heap // walker does not run in the same process as the data. SharedHeap.Allocation.GetDataUnchecked(alloc); if (!epData->Closed()) { epData->Dispose(); } EndpointCore.Free(alloc); #endif //PAGING }
//////////////////////////////////////////////////////////////////// // Class Methods // internal DeliveryImpl(Allocation * /*EndpointCore* opt(ExHeap)!*/ ep) { this.endpointAlloc = ep; this.endpoint = ((EndpointCore *)Allocation.GetData(ep)); // set default values (shadow cached values in EndpointCore if necessary) setMessageEvent(new AutoResetEventHandle( Process.kernelProcess.AllocateHandle(new AutoResetEvent(false)))); endpoint->CollectionEvent = new AutoResetEventHandle(); endpoint->SetCachedPeer(null); // set as null by default ProcessId = Thread.CurrentProcess.ProcessId; ChannelId = 0; // zero initially, corrected in connect Marshall = false; // false by default Closed = true; // opened in connect principalHandle = new PrincipalHandle(Thread.CurrentProcess.Principal.Val); delegationState = DelegationState.None; receiveCount = 0; }