/// <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); }
internal static void Dispose(Process process, DeliveryHandle handle) { Tracing.Log(Tracing.Debug, "DeliveryHandle.Dispose(id={0:x8})", handle.id); // // Releasing the handle will allow the deliveryImpl to be garbage- // collected // process.ReleaseHandle(handle.id); }
/// <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); }
public static bool Free(DeliveryHandle handle) { DeliveryImpl di = GetImpl(handle); // This is a pretty kludgy hack, but is necessary since static // methods can't be called on an object. switch (di.GetImplName()) { case SingleAddrSpaceDelivery.ImplName: return(SingleAddrSpaceDelivery.Free((SingleAddrSpaceDelivery)di)); #if PAGING // TODO paging #endif default: throw new DeliveryHandleException( "Free of unknown channel delivery implementation \"" + di.GetImplName() + "\" requested"); } }
public unsafe static bool Create( string implName, Allocation * /*EndpointCore* opt(ExHeap)!*/ endpoint, out DeliveryHandle handle) { DeliveryImpl deliveryImpl; switch (implName) { case SingleAddrSpaceDelivery.ImplName: deliveryImpl = new SingleAddrSpaceDelivery(endpoint); break; #if PAGING // TODO paging #endif default: throw new DeliveryHandleException( "Unknown channel delivery implementation \"" + implName + "\" requested"); } if (!deliveryImpl.IsMechanismInitialized()) { DebugStub.Print("Ack! IsMechInit returns false!\n"); DebugStub.Break(); handle = Zero; return(false); } handle = new DeliveryHandle( Process.kernelProcess.AllocateHandle(deliveryImpl)); #if false unsafe { DebugStub.WriteLine("DeliveryHandle.Create: got handle {0,8:x}\n", __arglist((uint)handle.id)); } #endif return(true); }
public static void Dispose(DeliveryHandle handle) { Dispose(Process.kernelProcess, handle); }
public static DeliveryImpl GetImpl(DeliveryHandle handle) { DeliveryImpl di = HandleTable.GetHandle(handle.id) as DeliveryImpl; return(di); }