/// <summary> /// Generic copy (either from kernel or to kernel) /// Determines if the thing we are moving is an endpoint and copies it accordingly. /// </summary> public static Allocation *MoveData(SharedHeap fromHeap, SharedHeap toHeap, Process newOwner, Allocation *data) { if (data == null) { return(data); } if (!fromHeap.Validate(data)) { throw new ArgumentException("Bad argument. Not visible"); } // We can only transfer either into our out of the kernel's heap DebugStub.Assert(fromHeap == SharedHeap.KernelSharedHeap || toHeap == SharedHeap.KernelSharedHeap); if (SystemType.IsSubtype(data, EndpointCoreSystemType)) { // we have an endpoint DeliveryImpl di = EndpointCore.AllocationEndpointDeliveryImpl(data); return(di.MoveEndpoint(fromHeap, toHeap, newOwner)); } else { // we have a NON-endpoint // TODO FIX this! return(null); // MoveNonEndpoint(fromHeap, toHeap, newOwner, data); } }
/// <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); }
/// <summary> /// Performs the initialization of the core part of each endpoint and cross links /// them to form a channel. Uses the standard shared address space delivery /// mechanism. /// </summary> public static void Connect( Allocation * /*EndpointCore* opt(ExHeap)!*/ imp, Allocation * /*EndpointCore* opt(ExHeap)!*/ exp, Allocation * /*EndpointCore* opt(ExHeap)!*/ securityEp) { Connect(imp, exp, securityEp, SingleAddrSpaceDelivery.ImplName); }
/// <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> /// Used internally by the kernel to transfer an endpoint to a new owner /// /// Can be used to transfer ANY kind of shared heap data, not just endpoints. /// </summary> public static Allocation *MoveEndpoint(SharedHeap fromHeap, SharedHeap toHeap, Process newOwner, Allocation *ep) { return(DeliveryImpl.MoveData(fromHeap, toHeap, newOwner, ep)); }
/// <summary> /// Transfer any contents that needs to be adjusted from the transferee to the target /// endpoint. /// </summary> // TODO: change "ref EndpointCore" to "EndpointCore" public static void TransferContentOwnership( ref EndpointCore transferee, ref EndpointCore target) { // TODO MAKE THIS APROPRIATE TO BOTH SINGLE AND PAGED IMPLS DeliveryImpl transfereeDi = transferee.EndpointDeliveryImpl; // XXX BUG? BUG? BUG? // targetDi = transferee.EndpointDeliveryImpl // should be: // targetDi = target.EndpointDeliveryImpl DeliveryImpl targetDi = transferee.EndpointDeliveryImpl; VTable.Assert((transfereeDi != null) && (targetDi != null)); //Monitoring.Log(Monitoring.Provider.ChannelService, // (ushort)ChannelServiceEvent.TransferContentOwnership, 0, // (uint)transfereeDi.ProcessId, // (uint)targetDi.ProcessId, // (uint)transfereeDi.ChannelId, // (uint)targetDi.ChannelId, // (uint)targetDi.Peer.ChannelId); int toProcessId = targetDi.ProcessId; transfereeDi.ProcessId = toProcessId; DelegationState newstate = transfereeDi.OwnerDelegationState; transfereeDi.OwnerPrincipalHandle = TransferPrincipal(transfereeDi.OwnerPrincipalHandle, toProcessId, ref newstate); transfereeDi.OwnerDelegationState = newstate; Allocation *transfereePeerAllocation = transfereeDi.Peer(); // also transfer the peer allocation Allocation.SetOwnerProcessId(transfereePeerAllocation, toProcessId); }
public static unsafe void Truncate(Allocation *allocation, UIntPtr newLength) { SharedHeap.CurrentProcessSharedHeap.Truncate( (SharedHeap.Allocation *)allocation, newLength ); }
public static unsafe Allocation *Split(Allocation *allocation, UIntPtr offset) { return((Allocation *)SharedHeap.CurrentProcessSharedHeap.Split( (SharedHeap.Allocation *)allocation, SharedHeap.CurrentProcessSharedHeap.DataOwnerId, offset)); }
internal override void Connect(DeliveryImpl expDi, Allocation * /*EndpointCore* opt(ExHeap)!*/ securityEp) { base.Connect(expDi, securityEp); this.Initialize(expDi); expDi.Initialize(this); }
internal static unsafe void SetOwnerProcessId( Allocation *allocation, int newOwnerProcessId) { SharedHeap.Allocation.SetOwnerProcessId( (SharedHeap.Allocation *)allocation, newOwnerProcessId); }
internal static unsafe void SetType( Allocation *allocation, UIntPtr type) { SharedHeap.Allocation.SetType( (SharedHeap.Allocation *)allocation, type); }
public static void AcceptDelegation(Allocation * /*EndpointCore* opt(ExHeap)!*/ imp, Allocation * /*EndpointCore* opt(ExHeap)!*/ exp, Allocation * /*EndpointCore* opt(ExHeap)!*/ ep) { EndpointCoreImplementation.AcceptDelegation((SharedHeap.Allocation *)imp, (SharedHeap.Allocation *)exp, (SharedHeap.Allocation *)ep); }
public static unsafe void TransferTo( Allocation *allocation, AllocationOwnerId newOwner) { return(SharedHeap.TransferOwnership( (SharedHeap.Allocation *)allocation, SharedHeap.CurrentProcessSharedHeap.DataOwnerId, newOwner)); }
public static unsafe void TransferFrom( Allocation *allocation, AllocationOwnerId oldOwner) { return(SharedHeap.TransferOwnership( (SharedHeap.Allocation *)allocation, oldOwner, SharedHeap.CurrentProcessSharedHeap.DataOwnerId)); }
public static void Connect( Allocation * /*EndpointCore* opt(ExHeap)!*/ imp, Allocation * /*EndpointCore* opt(ExHeap)!*/ exp, Allocation * /*EndpointCore* opt(ExHeap) */ ep) { EndpointCoreImplementation.Connect((SharedHeap.Allocation *)imp, (SharedHeap.Allocation *)exp, (SharedHeap.Allocation *)ep); }
public static void TransferBlockOwnership(Allocation *ptr, ref EndpointCore target) { fixed(EndpointCore *ep = &target) { EndpointCoreImplementation *epimp = (EndpointCoreImplementation *)ep; EndpointCoreImplementation.TransferBlockOwnership((SharedHeap.Allocation *)ptr, ref *epimp); } }
public static unsafe Allocation *Share(Allocation *allocation, UIntPtr startOffset, UIntPtr endOffset) { return((Allocation *)SharedHeap.CurrentProcessSharedHeap.Share( (SharedHeap.Allocation *)allocation, SharedHeap.CurrentProcessSharedHeap.DataOwnerId, startOffset, endOffset)); }
internal override void Initialize(DeliveryImpl peerDi) { peerEp = SharedHeap.CurrentProcessSharedHeap.Share(peerDi.EndpointAlloc, SharedHeap.CurrentProcessSharedHeap.EndpointPeerOwnerId, (UIntPtr)0, Allocation.GetSize(peerDi.EndpointAlloc)); this.endpoint->SetCachedPeer(peerEp); this.endpoint->SetPeerStateValid(true); }
public static Allocation * //EndpointCore* opt(ExHeap)! Allocate(uint size, SystemType st) { Allocation *ep = (Allocation *)SharedHeap.CurrentProcessSharedHeap.Allocate( size, st.id, 0, SharedHeap.CurrentProcessSharedHeap.EndpointOwnerId); if (ep == null) { throw new ApplicationException("SharedHeap.Allocate returned null"); } return(ep); }
public static unsafe UIntPtr GetData(Allocation *allocation) { // CANNOT CHECK THE OWNER HERE UNLESS WE MAKE CURRENTPROCESS visible // to this compilation // // Check owner! // if (allocation->owner != Thread.CurrentProcess.ProcessId) { // DebugStub.Break(); // } return(allocation->data); }
public static void AcceptDelegation(Allocation * /*EndpointCore* opt(ExHeap)!*/ imp, Allocation * /*EndpointCore* opt(ExHeap)!*/ exp, Allocation * /*EndpointCore* opt(ExHeap)!*/ ep) { DeliveryImpl impDi = AllocationEndpointDeliveryImpl(imp); DeliveryImpl expDi = AllocationEndpointDeliveryImpl(exp); DeliveryImpl epDi = AllocationEndpointDeliveryImpl(ep); VTable.Assert((impDi != null && expDi != null && epDi != null)); VTable.Assert((impDi.GetType() == expDi.GetType()) && (impDi.GetType() == epDi.GetType())); impDi.AcceptDelegation(expDi, epDi); }
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); }
/// <summary> /// Transfer the given Allocation block to the target endpoint /// </summary> public static void TransferBlockOwnership(Allocation *ptr, ref EndpointCore target) { Allocation.SetOwnerProcessId(ptr, target.cachedOwnerProcessId); // TODO MAKE THIS APROPRIATE TO BOTH SINGLE AND PAGED IMPLS DeliveryImpl di = target.EndpointDeliveryImpl; VTable.Assert(di != null); //Monitoring.Log(Monitoring.Provider.ChannelService, // (ushort)ChannelServiceEvent.TransferBlockOwnership, 0, // (uint)di.ChannelId, // (uint)di.ProcessId, // 0, 0, 0); #if CHANNEL_COUNT IncreaseBytesSentCount((long)Allocation.GetSize(ptr)); #endif Allocation.SetOwnerProcessId(ptr, di.ProcessId); }
//////////////////////////////////////////////////////////////////// // 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; }
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); }
internal virtual void Connect(DeliveryImpl expDi, Allocation * /*EndpointCore* opt(ExHeap)!*/ securityEp) { // security principals are held in the delivery impl, not the endpoint core // since this allows them to be kept out of user memory in paging builds if (securityEp != null) { DeliveryImpl secImpl = EndpointCore.AllocationEndpointDeliveryImpl(securityEp); if (secImpl != null && secImpl.OwnerDelegationState == DelegationState.Mediated) { this.OwnerPrincipalHandle = secImpl.OwnerPrincipalHandle; } } int newChannelId = EndpointCore.GetNextChannelId(); this.ChannelId = -newChannelId; expDi.ChannelId = newChannelId; this.Closed = false; expDi.Closed = false; }
public static extern void AcceptDelegation(Allocation * /*EndpointCore* opt(ExHeap)!*/ imp, Allocation * /*EndpointCore* opt(ExHeap)!*/ exp, Allocation * /*EndpointCore* opt(ExHeap)!*/ ep);
public static void Free(Allocation * /* EndpointCore* opt(ExHeap) */ endpoint) { EndpointCoreImplementation.Free((SharedHeap.Allocation *)endpoint); }
public void SetCachedPeer(Allocation * /* EndpointCore */ peer) { cachedPeer = peer; }