singrdk/base/Kernel/Singularity/Channels/EndpointCore.cs

678 lines
25 KiB
C#
Raw Normal View History

2008-03-05 09:52:00 -05:00
////////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: EndpointCore.cs
//
// HACK: Because we currently compile this file as part of the Kernel with C#, we can't
// make EndpointCore a rep struct, which is necessary for inheriting from it.
// The compiler and Bartok recognize EndpointCore as special and treat it as
// unsealed.
// This hack can be removed, once we compile it with Sing#.
// DON'T change the name until then!
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Diagnostics;
using Microsoft.Singularity.Channels;
using Microsoft.Singularity.Security;
using Microsoft.Singularity.Memory;
namespace Microsoft.Singularity.Channels
{
using Microsoft.Singularity.V1.Threads;
using Microsoft.Singularity.V1.Security;
using Microsoft.Singularity.V1.Services;
using Microsoft.Singularity.V1.Types;
using Allocation = Microsoft.Singularity.Memory.SharedHeap.Allocation;
using System.Threading;
using SharedHeap = Microsoft.Singularity.Memory.SharedHeap;
[CLSCompliant(false)]
public enum EndpointCoreEvent : ushort
{
Connect = 4,
TransferToProcess = 5,
}
2008-11-17 18:29:00 -05:00
2008-03-05 09:52:00 -05:00
[CLSCompliant(false)]
[CCtorIsRunDuringStartup]
unsafe public struct EndpointCore
{
2008-11-17 18:29:00 -05:00
////////////////////////////////////////////////////////////////////
// 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
2008-03-05 09:52:00 -05:00
/// <summary>
2008-11-17 18:29:00 -05:00
/// Handle to the actual message delivery mechanism
2008-03-05 09:52:00 -05:00
/// </summary>
2008-11-17 18:29:00 -05:00
private DeliveryHandle deliveryHandle;
2008-03-05 09:52:00 -05:00
/// <summary>
2008-11-17 18:29:00 -05:00
/// Event handle in case this endpoint is part of a collection
2008-03-05 09:52:00 -05:00
/// </summary>
2008-11-17 18:29:00 -05:00
private AutoResetEventHandle collectionEvent;
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
//
// 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.
//
2008-03-05 09:52:00 -05:00
/// <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>
2008-11-17 18:29:00 -05:00
private AutoResetEventHandle cachedMessageEvent;
2008-03-05 09:52:00 -05:00
/// <summary>
2008-11-17 18:29:00 -05:00
/// Closed flag
2008-03-05 09:52:00 -05:00
/// </summary>
2008-11-17 18:29:00 -05:00
private bool cachedClosed;
2008-03-05 09:52:00 -05:00
/// <summary>
/// Contains the process id of the process currently owning this end of the
/// channel.
/// </summary>
2008-11-17 18:29:00 -05:00
private int cachedOwnerProcessId;
2008-03-05 09:52:00 -05:00
/// <summary>
2008-11-17 18:29:00 -05:00
/// Contains the channelId (positive on the EXP endpoint, negative on the imp endpoint)
2008-03-05 09:52:00 -05:00
/// </summary>
2008-11-17 18:29:00 -05:00
private int cachedChannelId;
2008-03-05 09:52:00 -05:00
/// <summary>
2008-11-17 18:29:00 -05:00
/// Whether to marshall or not
2008-03-05 09:52:00 -05:00
/// </summary>
2008-11-17 18:29:00 -05:00
private bool cachedMarshall;
2008-03-05 09:52:00 -05:00
/// <summary>
2008-11-17 18:29:00 -05:00
/// Points to the peer endpoint
2008-03-05 09:52:00 -05:00
/// </summary>
2008-11-17 18:29:00 -05:00
private Allocation* /*EndpointCore* opt(ExHeap)*/ cachedPeer;
2008-03-05 09:52:00 -05:00
/// <summary>
2008-11-17 18:29:00 -05:00
/// If true then the peer state can be queried directly from cachedPeer
2008-03-05 09:52:00 -05:00
/// </summary>
2008-11-17 18:29:00 -05:00
private bool peerStateValid;
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
////////////////////////////////////////////////////////////////////
// Static Fields
////////////////////////////////////////////////////////////////////
2008-03-05 09:52:00 -05:00
/// <summary>
2008-11-17 18:29:00 -05:00
/// Number of open channels (using any delivery mechanism)
2008-03-05 09:52:00 -05:00
/// </summary>
2008-11-17 18:29:00 -05:00
private static int openChannelCount; // TODO open channel count!!!
2008-03-05 09:52:00 -05:00
/// <summary>
2008-11-17 18:29:00 -05:00
/// Channel id generator used to create unique channel id's accross delivery
/// mechanisms.
2008-03-05 09:52:00 -05:00
/// </summary>
2008-11-17 18:29:00 -05:00
private static int channelIdGenerator;
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
////////////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////////////
public enum DelegationState {None, ByCapability, ByMediation, Mediated};
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
////////////////////////////////////////////////////////////////////
// Methods
////////////////////////////////////////////////////////////////////
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
/// <summary>
/// Retrieve underlying delivery mechanism for a given endpoint allocation pointer
/// </summary>
[NoHeapAllocation]
internal static DeliveryImpl AllocationEndpointDeliveryImpl(
Allocation* /*EndpointCore* opt(ExHeap)!*/ endpoint)
{
EndpointCore * ep = (EndpointCore *) Allocation.GetData(endpoint);
if (ep == null) {
return null;
} else {
return ep->EndpointDeliveryImpl;
2008-03-05 09:52:00 -05:00
}
}
/// <summary>
2008-11-17 18:29:00 -05:00
/// Retrieve underlying delivery mechanism for a given endpoint allocation pointer
/// using GetDataUnchecked.
2008-03-05 09:52:00 -05:00
/// </summary>
2008-11-17 18:29:00 -05:00
[NoHeapAllocation]
internal static DeliveryImpl AllocationEndpointDeliveryImplUnchecked(
Allocation* /*EndpointCore* opt(ExHeap)!*/ endpoint)
{
EndpointCore * ep = (EndpointCore *) Allocation.GetDataUnchecked(endpoint);
if (ep == null) {
return null;
} else {
return ep->EndpointDeliveryImpl;
2008-03-05 09:52:00 -05:00
}
}
2008-11-17 18:29:00 -05:00
/// <summary>
/// Retrieve underlying delivery mechanism for this endpoint
/// </summary>
internal DeliveryImpl EndpointDeliveryImpl {
[NoHeapAllocation]
get {
if (deliveryHandle != DeliveryHandle.Zero) {
return DeliveryHandle.GetImpl(deliveryHandle);
} else {
unsafe {
DebugStub.WriteLine("deliveryHandle value is {0,8:x}\n", __arglist((uint) deliveryHandle.id));
}
DebugStub.Break();
return null;
}
2008-03-05 09:52:00 -05:00
}
}
/// <summary>
/// Performs the initialization of the core part of each endpoint and cross links
2008-11-17 18:29:00 -05:00
/// them to form a channel. Uses the standard shared address space delivery
/// mechanism.
2008-03-05 09:52:00 -05:00
/// </summary>
public static void Connect(
Allocation* /*EndpointCore* opt(ExHeap)!*/ imp,
2008-11-17 18:29:00 -05:00
Allocation* /*EndpointCore* opt(ExHeap)!*/ exp,
Allocation* /*EndpointCore* opt(ExHeap)!*/ securityEp)
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
Connect(imp, exp, securityEp, SingleAddrSpaceDelivery.ImplName);
2008-03-05 09:52:00 -05:00
}
/// <summary>
2008-11-17 18:29:00 -05:00
/// Performs the initialization of the core part of each endpoint and cross links
/// them to form a channel. Uses the given delivery mechanism.
2008-03-05 09:52:00 -05:00
/// </summary>
2008-11-17 18:29:00 -05:00
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");
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
Tracing.Log(Tracing.Debug, "connect {0:x8} and {1:x8}",
(UIntPtr)imp, (UIntPtr)exp);
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
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");
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
#if false
DebugStub.Print("imp handle {0,8:x} exp handle {1,8:x}\n",
__arglist((uint)impData->deliveryHandle.id, (uint)expData->deliveryHandle.id));
2008-03-05 09:52:00 -05:00
#endif
2008-11-17 18:29:00 -05:00
DeliveryImpl impDi = impData->EndpointDeliveryImpl;
DeliveryImpl expDi = expData->EndpointDeliveryImpl;
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
VTable.Assert(impDi != null && expDi != null);
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
impDi.Connect(expDi, securityEp);
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
// keep track of how many channels are open
Interlocked.Increment(ref openChannelCount);
#if CHANNEL_COUNT
PerfCounters.IncrementChannelsCreated();
#endif
2008-03-05 09:52:00 -05:00
Monitoring.Log(Monitoring.Provider.EndpointCore,
2008-11-17 18:29:00 -05:00
(ushort)EndpointCoreEvent.Connect, 0,
(uint)expData->ChannelId, 0, 0, 0, 0);
2008-03-05 09:52:00 -05:00
}
/// <summary>
2008-11-17 18:29:00 -05:00
/// Set this end to closed
2008-03-05 09:52:00 -05:00
/// </summary>
2008-11-17 18:29:00 -05:00
public void Close()
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
DeliveryImpl di = EndpointDeliveryImpl;
if (di != null) {
di.Close();
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
}
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
[NoHeapAllocation]
public bool Closed()
{
DeliveryImpl di = EndpointDeliveryImpl;
if (di != null) {
return di.Closed;
} else {
// endpoint has not yet been connected
return true;
2008-03-05 09:52:00 -05:00
}
}
2008-11-17 18:29:00 -05:00
2008-03-05 09:52:00 -05:00
/// <summary>
2008-11-17 18:29:00 -05:00
/// 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.
2008-03-05 09:52:00 -05:00
/// </summary>
2008-11-17 18:29:00 -05:00
public bool Dispose()
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
DeliveryImpl di = EndpointDeliveryImpl;
if (di != null) {
return EndpointDeliveryImpl.Dispose();
} else {
return true; // endpoint was not yet connected
2008-03-05 09:52:00 -05:00
}
}
/// <summary>
2008-11-17 18:29:00 -05:00
/// Explicitly frees this end of the channel.
2008-03-05 09:52:00 -05:00
///
2008-11-17 18:29:00 -05:00
/// 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.
2008-03-05 09:52:00 -05:00
/// </summary>
2008-11-17 18:29:00 -05:00
public unsafe static void Free(Allocation* /*EndpointCore* opt(ExHeap)!*/ endpoint)
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
// 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);
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
} 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);
2008-03-05 09:52:00 -05:00
}
}
}
/// <summary>
2008-11-17 18:29:00 -05:00
/// The event to wait for messages on this endpoint. Used by Select.
2008-03-05 09:52:00 -05:00
/// </summary>
2008-11-17 18:29:00 -05:00
public SyncHandle GetWaitHandle() {
DeliveryImpl di = EndpointDeliveryImpl;
VTable.Assert(di != null);
return di.MessageEvent;
2008-03-05 09:52:00 -05:00
}
/// <summary>
2008-11-17 18:29:00 -05:00
/// Get the AutoResetEventHandle
2008-03-05 09:52:00 -05:00
/// </summary>
2008-11-17 18:29:00 -05:00
public AutoResetEventHandle GetAreHandle() {
DeliveryImpl di = EndpointDeliveryImpl;
VTable.Assert(di != null);
return di.AreHandle;
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
/// <summary>
/// Notify the peer of this endpoint that a message is ready.
/// Notifies the set owner if this endpoint is part of a set.
/// </summary>
public void NotifyPeer() {
DeliveryImpl di = EndpointDeliveryImpl;
VTable.Assert(di != null);
di.NotifyPeer();
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
/// <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)
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
return DeliveryImpl.MoveData(fromHeap, toHeap, newOwner, ep);
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
public static void AcceptDelegation(Allocation* /*EndpointCore* opt(ExHeap)!*/ imp,
Allocation* /*EndpointCore* opt(ExHeap)!*/ exp,
Allocation* /*EndpointCore* opt(ExHeap)!*/ ep)
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
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);
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
public void EnableDelegation(bool allowMediation)
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
EndpointDeliveryImpl.EnableDelegation(allowMediation);
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
public DelegationState OwnerDelegationState
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
[NoHeapAllocation]
get { return EndpointDeliveryImpl.OwnerDelegationState; }
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
public PrincipalHandle OwnerPrincipalHandle
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
[NoHeapAllocation]
get { return EndpointDeliveryImpl.OwnerPrincipalHandle; }
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
public PrincipalHandle PeerPrincipalHandle
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
[NoHeapAllocation]
get { return EndpointDeliveryImpl.PeerPrincipalHandle; }
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
public int PeerReceiveCount
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
[NoHeapAllocation]
get {
DeliveryImpl di = EndpointDeliveryImpl;
if (di != null) {
return di.PeerReceiveCount;
} else {
// not yet connected, therefore no peer yet
return 0;
}
2008-03-05 09:52:00 -05:00
}
}
2008-11-17 18:29:00 -05:00
//versions of begin update and marshallpointer that handle objects with pointers
//greater than one level deep
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
internal void BeginUpdate(byte* basep, byte* source, int* tagAddress, int msgSize)
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
DeliveryImpl di = EndpointDeliveryImpl;
VTable.Assert(di != null);
// DebugStub.Print("BeginUpdate delivery handle {0,8:x}\n", __arglist((uint)deliveryHandle.id));
di.BeginUpdate(basep, source, tagAddress, msgSize);
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
public void MarshallPointer(byte* basep, byte** target, SystemType type, byte* parent, int offset)
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
if (target == null) return;
DeliveryImpl di = EndpointDeliveryImpl;
// DebugStub.Print("Marshall Pointer delivery handle {0,8:x}\n", __arglist((uint)deliveryHandle.id));
VTable.Assert(di != null);
di.MarshallPointer(basep, target, type, parent, offset);
}
public static PrincipalHandle TransferPrincipal(PrincipalHandle oldH,
int processId,
ref DelegationState delegationState)
{
Process p = Process.GetProcessByID(processId);
if (p == null)
throw new ApplicationException("Delegate endpoint process is null");
DelegationState newstate;
Principal pr;
switch (delegationState) {
case DelegationState.ByMediation:
pr = PrincipalImpl.NewDelegation(
PrincipalImpl.MakePrincipal(oldH.val), p.Principal);
newstate = DelegationState.Mediated;
break;
case DelegationState.ByCapability:
pr = PrincipalImpl.NewDelegation(
PrincipalImpl.MakePrincipal(oldH.val), p.Principal);
newstate = DelegationState.None;
break;
case DelegationState.Mediated:
pr = p.Principal;
newstate = DelegationState.None;
break;
case DelegationState.None:
default:
pr = p.Principal;
newstate = DelegationState.None;
2008-03-05 09:52:00 -05:00
break;
}
2008-11-17 18:29:00 -05:00
delegationState = newstate;
return new PrincipalHandle(pr.Val);
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
#if SINGULARITY_KERNEL && CHANNEL_COUNT
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
internal static void IncreaseBytesSentCount(long bytes)
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
PerfCounters.AddBytesSent(bytes);
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
#endif // SINGULARITY_KERNEL
2008-03-05 09:52:00 -05:00
/// <summary>
2008-11-17 18:29:00 -05:00
/// Transfer the given Allocation block to the target endpoint
2008-03-05 09:52:00 -05:00
/// </summary>
2008-11-17 18:29:00 -05:00
public static void TransferBlockOwnership(Allocation* ptr, ref EndpointCore target)
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
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);
2008-03-05 09:52:00 -05:00
}
/// <summary>
2008-11-17 18:29:00 -05:00
/// Transfer any contents that needs to be adjusted from the transferee to the target
/// endpoint.
2008-03-05 09:52:00 -05:00
/// </summary>
2008-11-17 18:29:00 -05:00
// 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);
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
public static int OpenChannelCount {
[NoHeapAllocation]
get { return openChannelCount; }
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
public static void IncOpenChannelCount () {
Interlocked.Increment(ref openChannelCount);
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
public static void DecOpenChannelCount () {
Interlocked.Decrement(ref openChannelCount);
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
//
// These getter defer to the delivery implementation, as the kernel only
// trusts the shadow versions held in Kernel memory space.
//
public bool PeerClosed()
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
DeliveryImpl di = EndpointDeliveryImpl;
if (di != null) {
return di.PeerClosed();
} else {
// endpoint has not yet been connected
return true;
}
2008-03-05 09:52:00 -05:00
}
/// <summary>
2008-11-17 18:29:00 -05:00
/// Return a handle for the peer
2008-03-05 09:52:00 -05:00
/// </summary>
2008-11-17 18:29:00 -05:00
public Allocation* Peer(out bool marshall)
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
DeliveryImpl di = EndpointDeliveryImpl;
VTable.Assert(di != null);
return di.Peer(out marshall);
2008-03-05 09:52:00 -05:00
}
public int ChannelId
{
[NoHeapAllocation]
2008-11-17 18:29:00 -05:00
get {
DeliveryImpl di = EndpointDeliveryImpl;
VTable.Assert(di != null);
return di.ChannelId;
}
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
2008-03-05 09:52:00 -05:00
public int ProcessId
{
[NoHeapAllocation]
2008-11-17 18:29:00 -05:00
get {
DeliveryImpl di = EndpointDeliveryImpl;
VTable.Assert(di != null);
return di.ProcessId;
}
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
2008-03-05 09:52:00 -05:00
public int ReceiveCount
{
2008-11-17 18:29:00 -05:00
get {
DeliveryImpl di = EndpointDeliveryImpl;
VTable.Assert(di != null);
return di.ReceiveCount;
}
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
2008-03-05 09:52:00 -05:00
public int PeerProcessId
{
[NoHeapAllocation]
2008-11-17 18:29:00 -05:00
get {
DeliveryImpl di = EndpointDeliveryImpl;
VTable.Assert(di != null);
return di.PeerProcessId;
}
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
public DeliveryHandle dImpHandle
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
get {
return deliveryHandle;
}
set {
deliveryHandle = value;
}
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
public AutoResetEventHandle CollectionEvent
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
get {
return collectionEvent;
}
set {
collectionEvent = value;
}
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
internal static int GetNextChannelId()
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
return Interlocked.Increment(ref channelIdGenerator);
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
//
// These methods only set the user accessable cached copies, real changes should
// be made to the delivery implementation copies.
//
[NoHeapAllocation]
public void SetCachedClose(bool closed) { cachedClosed = closed; }
[NoHeapAllocation]
public void SetCachedProcessId(int pid) { cachedOwnerProcessId = pid; }
[NoHeapAllocation]
public void SetCachedChannelId(int cid) { cachedChannelId = cid; }
[NoHeapAllocation]
public void SetCachedMarshall(bool marshall) { cachedMarshall = marshall; }
[NoHeapAllocation]
public void SetCachedMessageEvent(AutoResetEventHandle mh)
{
cachedMessageEvent = mh;
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
[NoHeapAllocation]
public void SetCachedPeer(Allocation * /* EndpointCore */ peer)
{
cachedPeer = peer;
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
[NoHeapAllocation]
public void SetPeerStateValid(bool valid)
{
peerStateValid = valid;
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
}
public class EndpointCoreException: Exception
{
public EndpointCoreException (string message) : base(message)
2008-03-05 09:52:00 -05:00
{
}
}
}