/base/Kernel/Singularity/Channels/DeliveryImpl.cs
C# | 410 lines | 231 code | 62 blank | 117 comment | 18 complexity | 61c422168158250f7e1dce353e4b6566 MD5 | raw file
- ////////////////////////////////////////////////////////////////////////////////
- //
- // Microsoft Research Singularity
- //
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //
- // File: DeliveryImpl.cs
- //
- // Note: Abstract super-class of all channel delivery implementations
- //
-
- using System;
- using System.Runtime.CompilerServices;
- using Microsoft.Singularity;
- using Microsoft.Singularity.Memory;
- using Microsoft.Singularity.Security;
-
- namespace Microsoft.Singularity.Channels
- {
- using Microsoft.Singularity.V1.Types;
- using Microsoft.Singularity.V1.Security;
- using Microsoft.Singularity.V1.Services;
- using Microsoft.Singularity.V1.Threads;
- using Allocation = Microsoft.Singularity.Memory.SharedHeap.Allocation;
- using DelegationState = Microsoft.Singularity.Channels.EndpointCore.DelegationState;
- using System.Threading;
-
- [CLSCompliant(false)]
- public unsafe abstract class DeliveryImpl
- {
-
- ////////////////////////////////////////////////////////////////////
- // Class Fields
- //
-
- /// <summary>
- /// Allocation which holds the endpoint core associated with this
- /// delivery implementation
- /// </summary>
- protected Allocation* /*EndpointCore* opt(ExHeap)!*/ endpointAlloc;
-
- /// <summary>
- /// Endpoint core associated with this delivery implementation
- /// </summary>
- protected EndpointCore* endpoint;
-
- /// <summary>
- /// Handle to the owning Principal
- /// </summary>
- protected PrincipalHandle principalHandle;
-
- /// <summary>
- /// Delegation state to control delegation through the principal
- /// </summary>
- protected DelegationState delegationState;
-
- /// <summary>
- /// Contains the number of sends to this endpoint.
- /// </summary>
- protected int receiveCount;
-
- //
- // Shadow "trusted" shadow copies of the fields in endpointCore
- //
-
- /// <summary>
- /// Event on which sends are signaled to this endpoint.
- /// The handle is owned by the kernel, since the endpoint can move.
- /// The kernel deallocates the handle when the channel is deallocated.
- /// NOTE: stays valid until the entire channel gets collected.
- /// </summary>
- private AutoResetEventHandle shadowMessageEvent;
-
- /// <summary>
- /// Closed flag
- /// </summary>
- private bool shadowClosed;
-
- /// <summary>
- /// Contains the process id of the process currently owning this end of the
- /// channel.
- /// </summary>
- private int shadowProcessId;
-
- /// <summary>
- /// Contains the channelId (positive on the EXP endpoint, negative on the imp endpoint)
- /// </summary>
- private int shadowChannelId;
-
- /// <summary>
- /// Whether or not to marshall messages
- /// </summary>
- private bool shadowMarshall;
-
- ////////////////////////////////////////////////////////////////////
- // 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;
- }
-
- /// <summary>
- /// Closes this end of the channel and frees associated resources,
- /// EXCEPT the block of memory for this endpoint. It must be released
- /// by the caller. Sing# does this for the programmer.
- ///
- /// This runs in the kernel to avoid a race condition with Process.Stop
- /// </summary>
- internal bool Dispose()
- {
- if (this.Closed) {
- return false;
- }
-
- Close(); // mark our side closed before waking up peer
- NotifyPeer();
-
- 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;
-
- }
-
- /// <summary>
- /// Set this end to closed
- /// </summary>
- public abstract void Close();
-
- /// <summary>
- /// Notify the owner of this endpoint that a message is ready.
- /// Notifies the set owner if this endpoint is part of a set.
- /// </summary>
- public void Notify() {
- this.receiveCount++;
- Tracing.Log(Tracing.Debug, "Endpoint Notify");
-
- // NB: Cache the collection event to prevent
- // a race with the receiver.
- AutoResetEventHandle cached_collEvent = endpoint->CollectionEvent;
- if (cached_collEvent.id != UIntPtr.Zero) {
- AutoResetEventHandle.Set(cached_collEvent);
- }
-
- AutoResetEventHandle.Set(this.AreHandle);
- }
-
- private static SystemType EndpointCoreSystemType =
- typeof(Microsoft.Singularity.V1.Services.EndpointCore).GetSystemType();
-
- /// <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);
- }
- }
-
- internal void AcceptDelegation(DeliveryImpl expDi, DeliveryImpl epDi)
- {
- if (epDi.OwnerDelegationState == DelegationState.Mediated) {
- OwnerPrincipalHandle = epDi.OwnerPrincipalHandle;
- PeerPrincipalHandle = epDi.OwnerPrincipalHandle;
- }
- }
-
- internal void EnableDelegation(bool allowMediation)
- {
- if (allowMediation)
- OwnerDelegationState = DelegationState.ByMediation;
- else
- OwnerDelegationState = DelegationState.ByCapability;
- }
-
- //
- // Getters and setters for fields which are shadowed in EndpointCore
- //
-
- internal bool Closed
- {
- [NoHeapAllocation]
- get {
- return shadowClosed;
- }
- set {
- shadowClosed = value;
- endpoint->SetCachedClose(value);
- }
- }
-
- internal int ChannelId {
- [NoHeapAllocation]
- get {
- return shadowChannelId;
- }
- set {
- shadowChannelId = value;
- endpoint->SetCachedChannelId(value);
- }
- }
- internal int ProcessId {
- [NoHeapAllocation]
- get {
- return shadowProcessId;
- }
- set {
- shadowProcessId = value;
- endpoint->SetCachedProcessId(value);
- }
- }
- internal int ReceiveCount {
- [NoHeapAllocation]
- get {
- return receiveCount;
- }
- }
- internal bool Marshall {
- [NoHeapAllocation]
- get {
- return shadowMarshall;
- }
- set {
- shadowMarshall = value;
- endpoint->SetCachedMarshall(value);
- }
- }
-
- internal AutoResetEventHandle AreHandle {
- get {
- return shadowMessageEvent;
- }
- }
-
- internal SyncHandle MessageEvent {
- get {
- return shadowMessageEvent;
- }
- }
- public Allocation * /* EndpointCore */ EndpointAlloc {
- get {
- return endpointAlloc;
- }
- }
-
- private void setMessageEvent(AutoResetEventHandle value) {
- shadowMessageEvent = value;
- endpoint->SetCachedMessageEvent(value);
- }
-
- internal Allocation* Peer(out bool marshall) {
- marshall = Marshall;
- return Peer();
- }
-
- internal EndpointCore.DelegationState OwnerDelegationState {
- [NoHeapAllocation]
- get {
- return delegationState;
- }
- set {
- delegationState = value;
- }
- }
- internal PrincipalHandle OwnerPrincipalHandle {
- [NoHeapAllocation]
- get {
- return principalHandle;
- }
- set {
- principalHandle = value;
- }
- }
-
- //
- // abstract methods which must be defined by actual delivery implementations
- //
-
- internal abstract void Initialize(DeliveryImpl peerDi);
-
- /// <summary>
- /// Return the associated peer of this endpoint
- /// </summary>
- [NoHeapAllocation]
- public abstract Allocation* Peer();
-
- /// <summary>
- /// Move endpoint data to a new process
- /// </summary>
- internal abstract Allocation* MoveEndpoint(SharedHeap fromHeap,
- SharedHeap toHeap,
- Process newOwner);
-
- // <summary>
- // Move non endpoint data to a new process
- // </summary>
- //internal abstract Allocation* MoveNonEndpoint(SharedHeap fromHeap,
- // SharedHeap toHeap,
- // Process newOwner);
-
- /// <summary>
- /// Returns true if this delivery mechanism has been initialised and
- /// can be used for channel transport.
- /// </summary>
- internal abstract bool IsMechanismInitialized();
-
- /// <summary>
- /// Returns the name of the delivery implementation actually being used
- /// </summary>
- internal abstract string GetImplName();
-
- /// <summary>
- /// Notify the peer that a message is ready.
- /// </summary>
- internal abstract void NotifyPeer();
-
- /// <summary>
- /// Close peer endpoint.
- /// </summary>
- internal abstract bool ClosePeer();
-
- /// <summary>
- /// Is peer endpoint closed.
- /// </summary>
- internal abstract bool PeerClosed();
-
- internal abstract int PeerProcessId {
- [NoHeapAllocation]
- get;
- }
-
- internal abstract int PeerReceiveCount {
- [NoHeapAllocation]
- get;
- }
-
- internal abstract PrincipalHandle PeerPrincipalHandle {
- [NoHeapAllocation]
- get;
- set;
- }
-
- //methods used for structures that contain pointers greater than one level deep
- internal abstract void BeginUpdate(byte* basep, byte* source, int* tagAddress, int msgSize);
-
- unsafe internal abstract void MarshallPointer(byte* basep, byte** target, SystemType type, byte* parent, int offset);
- ///////////////////////////////////////////////////////////////////
- }
- }