/base/Kernel/Singularity/V1/Services/ChannelService.cs
C# | 420 lines | 238 code | 49 blank | 133 comment | 2 complexity | 6d79eabf0e4afb77dd7af8c8419cde15 MD5 | raw file
- ////////////////////////////////////////////////////////////////////////////////
- //
- // Microsoft Research Singularity - Singularity ABI Implementation
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //
- // File: EndpointCore.cs
- //
- // Note:
- //
-
- using System;
- using System.Threading;
- using System.Runtime.CompilerServices;
-
- using Microsoft.Singularity;
- using Microsoft.Singularity.Channels;
- using Microsoft.Singularity.Security;
-
- using Microsoft.Singularity.Memory;
- using Microsoft.Singularity.V1.Security;
- using Microsoft.Singularity.V1.Threads;
- using Microsoft.Singularity.V1.Types;
-
- namespace Microsoft.Singularity.V1.Services
- {
- using Allocation = SharedHeapService.Allocation;
- using EndpointCoreImplementation = Microsoft.Singularity.Channels.EndpointCore;
-
- [CLSCompliant(false)]
- public enum ChannelServiceEvent : ushort
- {
- TransferBlockOwnership = 1,
- TransferContentOwnership = 2,
- }
-
-
- [CLSCompliant(false)]
- unsafe public struct EndpointCore
- {
- ////////////////////////////////////////////////////////////////////
- // Fields
- ////////////////////////////////////////////////////////////////////
- //
- // NOTE: The fields specified here must match those in:
- // Kernel/Singularity/Channels/EndpointCore.cs
- // Kernel/Singularity/V1/Services/ChannelServices.cs
- // Libraries/Singuarity.V1/Services/ChannelServices.cs
-
- /// <summary>
- /// Handle to the actual message delivery mechanism
- /// </summary>
- private DeliveryHandle deliveryHandle;
-
- /// <summary>
- /// Event handle in case this endpoint is part of a collection
- /// </summary>
- private AutoResetEventHandle collectionEvent;
-
- //
- // These "cached" fields are directly accessable by user programs,
- // but are not trusted by the kernel (as they could be modified by untrusted
- // code). The kernel relies on the trusted shadow copies held in the
- // deliveryImpl object, but updates these fields to reflect any changes to user
- // apps.
- //
-
- /// <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 cachedMessageEvent;
-
- /// <summary>
- /// Closed flag
- /// </summary>
- private bool cachedClosed;
-
- /// <summary>
- /// Contains the process id of the process currently owning this end of the
- /// channel.
- /// </summary>
- private int cachedOwnerProcessId;
-
- /// <summary>
- /// Contains the channelId (positive on the EXP endpoint, negative on the imp endpoint)
- /// </summary>
- private int cachedChannelId;
-
- /// <summary>
- /// Whether to marshall or not
- /// </summary>
- private bool cachedMarshall;
-
- /// <summary>
- /// Points to the peer endpoint
- /// </summary>
- private Allocation* /*EndpointCore* opt(ExHeap)*/ cachedPeer;
-
- /// <summary>
- /// If true then the peer state can be queried directly from cachedPeer
- /// </summary>
- private bool peerStateValid;
-
- ////////////////////////////////////////////////////////////////////
- // Methods
- ////////////////////////////////////////////////////////////////////
-
-
- /// <summary>
- /// Used to allocate a channel endpoint. The size must be correctly computed by
- /// the trusted caller (currently trusted code NewChannel)
- /// </summary>
- [ExternalEntryPoint]
- 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;
- }
-
- /// <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.
- /// Returns true for success, false for failure.
- /// </summary>
- [ExternalEntryPoint]
- public static bool Dispose(ref EndpointCore endpoint)
- {
- fixed (EndpointCore* ep = &endpoint) {
- EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
- return epimp->Dispose();
- }
- }
-
- /// <summary>
- /// Deallocates this end of the channel. If other end is also
- /// deallocated, the entire channel is deallocated.
- /// </summary>
- [ExternalEntryPoint]
- public static void Free(Allocation* /* EndpointCore* opt(ExHeap) */ endpoint)
- {
- EndpointCoreImplementation.Free((SharedHeap.Allocation*)endpoint);
- }
-
- /// <summary>
- /// Performs the initialization of the core part of each endpoint and cross links
- /// them to form a channel.
- /// </summary>
-
- [ExternalEntryPoint]
- 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);
- }
-
- /// <summary>
- /// Indicates if this endpoint is closed
- /// </summary>
- [NoHeapAllocation]
- public static bool Closed(ref EndpointCore endpoint)
- {
- // kernel methods always access the shadowed copy in deliveryImpl
- // not the user accessable copy in EndpointCore
- fixed (EndpointCore* ep = &endpoint) {
- EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
- return epimp->Closed();
- }
- }
-
- /// <summary>
- /// Indicates if the peer endpoint is closed
- /// </summary>
- public static bool PeerClosed(ref EndpointCore ep)
- {
- // kernel methods always access the shadowed copy in deliveryImpl
- // not the user accessable copy in EndpointCore
- return PeerClosedABI(ref ep);
- }
-
- /// <summary>
- /// Indicates if the peer endpoint is closed (ABI call)
- /// </summary>
- [ExternalEntryPoint]
- public static bool PeerClosedABI(ref EndpointCore endpoint) {
- fixed (EndpointCore* ep = &endpoint) {
- EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
- return epimp->PeerClosed();
- }
- }
-
- /// <summary>
- /// Set this end to closed
- /// </summary>
- [ExternalEntryPoint]
- public static void Close(ref EndpointCore endpoint) {
- fixed (EndpointCore* ep = &endpoint) {
- EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
- epimp->Close();
- }
- }
-
- /// <summary>
- /// The endpoint to which this endpoint is connected.
- /// </summary>
- public static Allocation* /*EndpointCore* opt(ExHeap) */ GetPeer(ref EndpointCore ep,
- out bool marshall)
- {
- // kernel methods always access the shadowed copy in deliveryImpl
- // not the user accessable copy in EndpointCore
- return GetPeerABI(ref ep, out marshall);
- }
-
- [ExternalEntryPoint]
- public static Allocation* /*EndpointCore* opt(ExHeap) */ GetPeerABI(ref EndpointCore endpoint,
- out bool marshall)
- {
- fixed (EndpointCore* ep = &endpoint) {
- EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
- return (Allocation*) epimp->Peer(out marshall);
- }
- }
-
- /// <summary>
- /// The event to wait for messages on this endpoint. Used by Select.
- /// </summary>
- public static SyncHandle GetWaitHandle(ref EndpointCore endpoint)
- {
- // kernel methods always access the shadowed copy in deliveryImpl
- // not the user accessable copy in EndpointCore
- fixed (EndpointCore* ep = &endpoint) {
- EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
- return epimp->GetWaitHandle();
- }
- }
-
- /// <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>
- [ExternalEntryPoint]
- public static void NotifyPeer(ref EndpointCore endpoint) {
- fixed (EndpointCore* ep = &endpoint) {
- EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
- epimp->NotifyPeer();
- }
- }
-
- /// <summary>
- /// Wait for a message to arrive on this endpoint.
- /// </summary>
- public static void Wait(ref EndpointCore ep) {
- SyncHandle.WaitOne(GetWaitHandle(ref ep));
- }
-
- /// <summary>
- /// Transfer the given Allocation block to the target endpoint
- /// </summary>
- [ExternalEntryPoint]
- public static void TransferBlockOwnership(Allocation* ptr, ref EndpointCore target)
- {
- fixed (EndpointCore* ep = &target) {
- EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
- EndpointCoreImplementation.TransferBlockOwnership((SharedHeap.Allocation*)ptr, ref *epimp);
- }
- }
-
- /// <summary>
- /// Transfer any contents that needs to be adjusted from the transferee to the target
- /// endpoint. Currently, this means setting the ownerProcessId of the
- /// transferee to that of the target.
- /// </summary>
- [ExternalEntryPoint]
- public static void TransferContentOwnership(
- ref EndpointCore transferee,
- ref EndpointCore target)
- {
- fixed (EndpointCore* ep1 = &transferee, ep2 = &target) {
- EndpointCoreImplementation* epimp1 = (EndpointCoreImplementation*)ep1;
- EndpointCoreImplementation* epimp2 = (EndpointCoreImplementation*)ep2;
- EndpointCoreImplementation.TransferContentOwnership(ref *epimp1, ref *epimp2);
- }
- }
-
- [NoHeapAllocation]
- public static int GetChannelID(ref EndpointCore endpoint)
- {
- // kernel methods always access the shadowed copy in deliveryImpl
- // not the user accessable copy in EndpointCore
- fixed (EndpointCore* ep = &endpoint) {
- EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
- return epimp->ChannelId;
- }
- }
-
- [NoHeapAllocation]
- public static int GetOwnerProcessID(ref EndpointCore endpoint)
- {
- // kernel methods always access the shadowed copy in deliveryImpl
- // not the user accessable copy in EndpointCore
- fixed (EndpointCore* ep = &endpoint) {
- EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
- return epimp->ProcessId;
- }
- }
-
- [NoHeapAllocation]
- public static int GetPeerProcessID(ref EndpointCore ep)
- {
- // kernel methods always access the shadowed copy in deliveryImpl
- // not the user accessable copy in EndpointCore
- return GetPeerProcessIDABI(ref ep);
- }
-
- [ExternalEntryPoint]
- [NoHeapAllocation]
- public static int GetPeerProcessIDABI(ref EndpointCore endpoint)
- {
- fixed (EndpointCore* ep = &endpoint) {
- EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
- return epimp->PeerProcessId;
- }
- }
-
- [ExternalEntryPoint]
- 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);
- }
-
- [ExternalEntryPoint]
- public static void EnableDelegation(ref EndpointCore endpoint, bool allowMediation)
- {
- fixed (EndpointCore* ep = &endpoint) {
- EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
- epimp->EnableDelegation(allowMediation);
- }
- }
-
- [ExternalEntryPoint]
- [NoHeapAllocation]
- public static PrincipalHandle GetPeerPrincipalHandle(ref EndpointCore endpoint)
- {
- fixed (EndpointCore* ep = &endpoint) {
- EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
- return epimp->PeerPrincipalHandle;
- }
- }
-
-
- [ExternalEntryPoint]
- [NoHeapAllocation]
- public static PrincipalHandle GetOwnerPrincipalHandle(ref EndpointCore endpoint)
- {
- fixed (EndpointCore* ep = &endpoint) {
- EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
- return epimp->OwnerPrincipalHandle;
- }
- }
-
- /// <summary>
- /// Instruct the selectable object to signal events on the given AutoResetEvent
- /// rather than its normal event in order to aggregate signalling into a set.
- /// A selectable object need only support being part of a single collection at
- /// any point in time.
- /// </summary>
- public static void LinkIntoCollection(ref EndpointCore ep,
- AutoResetEventHandle ev) {
- ep.collectionEvent = ev;
- }
-
- /// <summary>
- /// Instruct the selectable object to stop signalling events on the given
- /// AutoResetEvent.
- /// </summary>
- public static void UnlinkFromCollection(ref EndpointCore ep,
- AutoResetEventHandle ev) {
- ep.collectionEvent = new AutoResetEventHandle();
- }
-
- [ExternalEntryPoint]
- unsafe public static void MarshallMessage(ref EndpointCore endpoint,
- byte* basep,
- byte* source,
- int* tagAddress,
- int msgSize)
- {
-
- fixed (EndpointCore* ep = &endpoint) {
- EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
- epimp->BeginUpdate(basep, source, tagAddress, msgSize);
- }
- }
-
- [ExternalEntryPoint]
- public static void MarshallPointer(ref EndpointCore endpoint, byte* basep, byte** target, SystemType type, byte* parent, int offset)
- {
- fixed (EndpointCore* ep = &endpoint)
- {
- EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
- epimp->MarshallPointer(basep, target, type, parent, offset);
- }
- }
- }
- }