PageRenderTime 51ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/base/Kernel/Singularity/Channels/SingleAddrSpaceDelivery.cs

#
C# | 253 lines | 159 code | 43 blank | 51 comment | 11 complexity | 2e45004c2af4b20169f2eca952e475c2 MD5 | raw file
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft Research Singularity
  4. //
  5. // Copyright (c) Microsoft Corporation. All rights reserved.
  6. //
  7. // File: SingleAddrSpaceDelivery.cs
  8. //
  9. // Note: Standard single address space implementation of channel delivery
  10. // mechanism.
  11. //
  12. using System;
  13. using System.Threading;
  14. using System.Runtime.CompilerServices;
  15. using Microsoft.Singularity;
  16. using Microsoft.Singularity.V1.Threads;
  17. using Microsoft.Singularity.V1.Security;
  18. using Microsoft.Singularity.V1.Services;
  19. using Microsoft.Singularity.V1.Types;
  20. using Allocation = Microsoft.Singularity.Memory.SharedHeap.Allocation;
  21. using SharedHeap = Microsoft.Singularity.Memory.SharedHeap;
  22. using DelegationState = Microsoft.Singularity.Channels.EndpointCore.DelegationState;
  23. namespace Microsoft.Singularity.Channels
  24. {
  25. [CLSCompliant(false)]
  26. public unsafe sealed class SingleAddrSpaceDelivery: DeliveryImpl
  27. {
  28. public const string ImplName = "SingleAddrSpaceChannels";
  29. private Allocation * /* EndpointCore */ peerEp;
  30. internal SingleAddrSpaceDelivery(
  31. Allocation* /*EndpointCore* opt(ExHeap)!*/ endpoint): base(endpoint)
  32. {
  33. }
  34. internal override void Initialize(DeliveryImpl peerDi)
  35. {
  36. peerEp = SharedHeap.CurrentProcessSharedHeap.Share(peerDi.EndpointAlloc,
  37. SharedHeap.CurrentProcessSharedHeap.EndpointPeerOwnerId,
  38. (UIntPtr)0,
  39. Allocation.GetSize(peerDi.EndpointAlloc));
  40. this.endpoint->SetCachedPeer(peerEp);
  41. this.endpoint->SetPeerStateValid(true);
  42. }
  43. internal override void Connect(DeliveryImpl expDi,
  44. Allocation* /*EndpointCore* opt(ExHeap)!*/ securityEp)
  45. {
  46. base.Connect(expDi, securityEp);
  47. this.Initialize(expDi);
  48. expDi.Initialize(this);
  49. }
  50. public override void Close() {
  51. this.Closed = true;
  52. // clear the collectionEvent.
  53. // Needed in case we are called from the cleanup thread.
  54. this.endpoint->CollectionEvent = new AutoResetEventHandle();
  55. }
  56. /// <summary>
  57. /// Explicitly frees this end of the channel. If other end is also
  58. /// freed, the channel is deallocated, meaning we have to deallocate
  59. /// the kernel handles for the auto reset events.
  60. /// Since both threads on the channel could try to do this simultaneously,
  61. /// we use the ref counting on the underlying endpoints to let the last
  62. /// free operation (the one pulling the ref count to 0) to free the associated
  63. /// event.
  64. /// </summary>
  65. internal static bool Free(SingleAddrSpaceDelivery dm)
  66. {
  67. Tracing.Log(Tracing.Debug,
  68. "Freeing endpoint {0:x8} of deliveryImpl type:" + ImplName,
  69. (UIntPtr)dm.endpointAlloc);
  70. bool isExp = (dm.endpoint->ChannelId > 0);
  71. bool peerFreed = false;
  72. bool meFreed = false;
  73. if (dm.Peer() != null) {
  74. // release our ref count on the peer
  75. peerFreed = TryFreeResources(dm.Peer(),
  76. SharedHeap.CurrentProcessSharedHeap.EndpointPeerOwnerId);
  77. }
  78. // release our endpoint
  79. meFreed = TryFreeResources(dm.endpointAlloc,
  80. SharedHeap.CurrentProcessSharedHeap.EndpointOwnerId);
  81. // our definition of freeing the channel is if we freed the exp
  82. // side
  83. return ((isExp && meFreed) || (!isExp && peerFreed));
  84. }
  85. /// <summary>
  86. /// The peer thread might try this too, so we use the ref count of the
  87. /// underlying memory to allow only the last freeer to also free the
  88. /// associated auto-reset event handle. Make sure to grab the handle
  89. /// before freeing the endpoint.
  90. /// </summary>
  91. unsafe private static bool TryFreeResources(
  92. Allocation* /*EndpointCore*/ endpoint,
  93. SharedHeap.AllocationOwnerId ownerId)
  94. {
  95. EndpointCore* epData =
  96. (EndpointCore*)Allocation.GetDataUnchecked(endpoint);
  97. AutoResetEventHandle areHandle = epData->GetAreHandle();
  98. DeliveryHandle dh = epData->dImpHandle;
  99. int channelId = epData->ChannelId;
  100. bool lastRefGone = SharedHeap.KernelSharedHeap.Free(endpoint,
  101. ownerId);
  102. if (lastRefGone) {
  103. if (dh != DeliveryHandle.Zero) {
  104. DeliveryHandle.Dispose(dh);
  105. }
  106. if (areHandle.id != UIntPtr.Zero) {
  107. Process.kernelProcess.ReleaseHandle(areHandle.id);
  108. }
  109. }
  110. return lastRefGone;
  111. }
  112. internal override Allocation* MoveEndpoint(SharedHeap fromHeap,
  113. SharedHeap toHeap,
  114. Process newOwner)
  115. {
  116. DebugStub.Assert(fromHeap == toHeap);
  117. // Careful about the order.
  118. // Since we don't know if this is a release (current process owns it)
  119. // or an acquire (current process does not necessarily own it), we
  120. // have to bypass the owner check here.
  121. int processId = newOwner.ProcessId;
  122. this.ProcessId = processId;
  123. this.OwnerPrincipalHandle = new PrincipalHandle(newOwner.Principal.Val);
  124. // Don't check for delegation here since this is for kernel calls on
  125. // moving endpoints to SIPs. Delegation should not be involved.
  126. // The following should not be necessary, but just in case:
  127. this.OwnerDelegationState = DelegationState.None;
  128. Allocation.SetOwnerProcessId(this.endpointAlloc, processId);
  129. Allocation.SetOwnerProcessId(this.peerEp, processId);
  130. Monitoring.Log(Monitoring.Provider.EndpointCore,
  131. (ushort)EndpointCoreEvent.TransferToProcess, 0,
  132. (uint)ChannelId, (uint)processId, 0, 0, 0);
  133. return this.endpointAlloc;
  134. }
  135. /// <summary>
  136. /// Notify the peer that a message is ready.
  137. /// </summary>
  138. internal override void NotifyPeer()
  139. {
  140. PeerImpl().Notify();
  141. #if CHANNEL_COUNT
  142. //Interlocked.Increment(ref messageCount);
  143. PerfCounters.IncrementMsgsSent();
  144. #endif
  145. }
  146. [NoHeapAllocation]
  147. public override Allocation* Peer()
  148. {
  149. return this.peerEp;
  150. }
  151. [NoHeapAllocation]
  152. private DeliveryImpl PeerImpl() {
  153. return EndpointCore.AllocationEndpointDeliveryImpl(Peer());
  154. }
  155. /// <summary>
  156. /// Close peer endpoint.
  157. /// </summary>
  158. internal override bool ClosePeer()
  159. {
  160. PeerImpl().Close();
  161. return true;
  162. }
  163. /// <summary>
  164. /// Is peer endpoint closed.
  165. /// </summary>
  166. internal override bool PeerClosed()
  167. {
  168. return PeerImpl().Closed;
  169. }
  170. internal override int PeerProcessId {
  171. [NoHeapAllocation]
  172. get {
  173. return PeerImpl().ProcessId;
  174. }
  175. }
  176. internal override int PeerReceiveCount {
  177. [NoHeapAllocation]
  178. get {
  179. return PeerImpl().ReceiveCount;
  180. }
  181. }
  182. internal override PrincipalHandle PeerPrincipalHandle {
  183. [NoHeapAllocation]
  184. get {
  185. return PeerImpl().OwnerPrincipalHandle;
  186. }
  187. set {
  188. PeerImpl().OwnerPrincipalHandle = value;
  189. }
  190. }
  191. internal override bool IsMechanismInitialized()
  192. {
  193. // is initialized at kernel start time
  194. return true;
  195. }
  196. //new versions for deep pointers
  197. internal override void BeginUpdate(byte* basep, byte* source, int* tagAddress, int msgSize)
  198. {
  199. return;
  200. }
  201. unsafe internal override void MarshallPointer(byte* basep, byte** target, SystemType type, byte* targetParent, int offset)
  202. {
  203. return;
  204. }
  205. internal override string GetImplName()
  206. {
  207. return ImplName;
  208. }
  209. }
  210. }