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

/base/Kernel/Singularity/V1/Services/ChannelService.cs

#
C# | 420 lines | 238 code | 49 blank | 133 comment | 2 complexity | 6d79eabf0e4afb77dd7af8c8419cde15 MD5 | raw file
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft Research Singularity - Singularity ABI Implementation
  4. // Copyright (c) Microsoft Corporation. All rights reserved.
  5. //
  6. // File: EndpointCore.cs
  7. //
  8. // Note:
  9. //
  10. using System;
  11. using System.Threading;
  12. using System.Runtime.CompilerServices;
  13. using Microsoft.Singularity;
  14. using Microsoft.Singularity.Channels;
  15. using Microsoft.Singularity.Security;
  16. using Microsoft.Singularity.Memory;
  17. using Microsoft.Singularity.V1.Security;
  18. using Microsoft.Singularity.V1.Threads;
  19. using Microsoft.Singularity.V1.Types;
  20. namespace Microsoft.Singularity.V1.Services
  21. {
  22. using Allocation = SharedHeapService.Allocation;
  23. using EndpointCoreImplementation = Microsoft.Singularity.Channels.EndpointCore;
  24. [CLSCompliant(false)]
  25. public enum ChannelServiceEvent : ushort
  26. {
  27. TransferBlockOwnership = 1,
  28. TransferContentOwnership = 2,
  29. }
  30. [CLSCompliant(false)]
  31. unsafe public struct EndpointCore
  32. {
  33. ////////////////////////////////////////////////////////////////////
  34. // Fields
  35. ////////////////////////////////////////////////////////////////////
  36. //
  37. // NOTE: The fields specified here must match those in:
  38. // Kernel/Singularity/Channels/EndpointCore.cs
  39. // Kernel/Singularity/V1/Services/ChannelServices.cs
  40. // Libraries/Singuarity.V1/Services/ChannelServices.cs
  41. /// <summary>
  42. /// Handle to the actual message delivery mechanism
  43. /// </summary>
  44. private DeliveryHandle deliveryHandle;
  45. /// <summary>
  46. /// Event handle in case this endpoint is part of a collection
  47. /// </summary>
  48. private AutoResetEventHandle collectionEvent;
  49. //
  50. // These "cached" fields are directly accessable by user programs,
  51. // but are not trusted by the kernel (as they could be modified by untrusted
  52. // code). The kernel relies on the trusted shadow copies held in the
  53. // deliveryImpl object, but updates these fields to reflect any changes to user
  54. // apps.
  55. //
  56. /// <summary>
  57. /// Event on which sends are signaled to this endpoint.
  58. /// The handle is owned by the kernel, since the endpoint can move.
  59. /// The kernel deallocates the handle when the channel is deallocated.
  60. /// NOTE: stays valid until the entire channel gets collected.
  61. /// </summary>
  62. private AutoResetEventHandle cachedMessageEvent;
  63. /// <summary>
  64. /// Closed flag
  65. /// </summary>
  66. private bool cachedClosed;
  67. /// <summary>
  68. /// Contains the process id of the process currently owning this end of the
  69. /// channel.
  70. /// </summary>
  71. private int cachedOwnerProcessId;
  72. /// <summary>
  73. /// Contains the channelId (positive on the EXP endpoint, negative on the imp endpoint)
  74. /// </summary>
  75. private int cachedChannelId;
  76. /// <summary>
  77. /// Whether to marshall or not
  78. /// </summary>
  79. private bool cachedMarshall;
  80. /// <summary>
  81. /// Points to the peer endpoint
  82. /// </summary>
  83. private Allocation* /*EndpointCore* opt(ExHeap)*/ cachedPeer;
  84. /// <summary>
  85. /// If true then the peer state can be queried directly from cachedPeer
  86. /// </summary>
  87. private bool peerStateValid;
  88. ////////////////////////////////////////////////////////////////////
  89. // Methods
  90. ////////////////////////////////////////////////////////////////////
  91. /// <summary>
  92. /// Used to allocate a channel endpoint. The size must be correctly computed by
  93. /// the trusted caller (currently trusted code NewChannel)
  94. /// </summary>
  95. [ExternalEntryPoint]
  96. public static Allocation* //EndpointCore* opt(ExHeap)!
  97. Allocate(uint size, SystemType st)
  98. {
  99. Allocation* ep = (Allocation*) SharedHeap.CurrentProcessSharedHeap.Allocate(
  100. size, st.id, 0, SharedHeap.CurrentProcessSharedHeap.EndpointOwnerId);
  101. if (ep == null) {
  102. throw new ApplicationException("SharedHeap.Allocate returned null");
  103. }
  104. return ep;
  105. }
  106. /// <summary>
  107. /// Closes this end of the channel and frees associated resources, EXCEPT the block
  108. /// of memory for this endpoint. It must be released by the caller. Sing# does this
  109. /// for the programmer.
  110. /// Returns true for success, false for failure.
  111. /// </summary>
  112. [ExternalEntryPoint]
  113. public static bool Dispose(ref EndpointCore endpoint)
  114. {
  115. fixed (EndpointCore* ep = &endpoint) {
  116. EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
  117. return epimp->Dispose();
  118. }
  119. }
  120. /// <summary>
  121. /// Deallocates this end of the channel. If other end is also
  122. /// deallocated, the entire channel is deallocated.
  123. /// </summary>
  124. [ExternalEntryPoint]
  125. public static void Free(Allocation* /* EndpointCore* opt(ExHeap) */ endpoint)
  126. {
  127. EndpointCoreImplementation.Free((SharedHeap.Allocation*)endpoint);
  128. }
  129. /// <summary>
  130. /// Performs the initialization of the core part of each endpoint and cross links
  131. /// them to form a channel.
  132. /// </summary>
  133. [ExternalEntryPoint]
  134. public static void Connect(
  135. Allocation* /*EndpointCore* opt(ExHeap)!*/ imp,
  136. Allocation* /*EndpointCore* opt(ExHeap)!*/ exp,
  137. Allocation* /*EndpointCore* opt(ExHeap) */ ep)
  138. {
  139. EndpointCoreImplementation.Connect((SharedHeap.Allocation*)imp,
  140. (SharedHeap.Allocation*)exp,
  141. (SharedHeap.Allocation*)ep);
  142. }
  143. /// <summary>
  144. /// Indicates if this endpoint is closed
  145. /// </summary>
  146. [NoHeapAllocation]
  147. public static bool Closed(ref EndpointCore endpoint)
  148. {
  149. // kernel methods always access the shadowed copy in deliveryImpl
  150. // not the user accessable copy in EndpointCore
  151. fixed (EndpointCore* ep = &endpoint) {
  152. EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
  153. return epimp->Closed();
  154. }
  155. }
  156. /// <summary>
  157. /// Indicates if the peer endpoint is closed
  158. /// </summary>
  159. public static bool PeerClosed(ref EndpointCore ep)
  160. {
  161. // kernel methods always access the shadowed copy in deliveryImpl
  162. // not the user accessable copy in EndpointCore
  163. return PeerClosedABI(ref ep);
  164. }
  165. /// <summary>
  166. /// Indicates if the peer endpoint is closed (ABI call)
  167. /// </summary>
  168. [ExternalEntryPoint]
  169. public static bool PeerClosedABI(ref EndpointCore endpoint) {
  170. fixed (EndpointCore* ep = &endpoint) {
  171. EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
  172. return epimp->PeerClosed();
  173. }
  174. }
  175. /// <summary>
  176. /// Set this end to closed
  177. /// </summary>
  178. [ExternalEntryPoint]
  179. public static void Close(ref EndpointCore endpoint) {
  180. fixed (EndpointCore* ep = &endpoint) {
  181. EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
  182. epimp->Close();
  183. }
  184. }
  185. /// <summary>
  186. /// The endpoint to which this endpoint is connected.
  187. /// </summary>
  188. public static Allocation* /*EndpointCore* opt(ExHeap) */ GetPeer(ref EndpointCore ep,
  189. out bool marshall)
  190. {
  191. // kernel methods always access the shadowed copy in deliveryImpl
  192. // not the user accessable copy in EndpointCore
  193. return GetPeerABI(ref ep, out marshall);
  194. }
  195. [ExternalEntryPoint]
  196. public static Allocation* /*EndpointCore* opt(ExHeap) */ GetPeerABI(ref EndpointCore endpoint,
  197. out bool marshall)
  198. {
  199. fixed (EndpointCore* ep = &endpoint) {
  200. EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
  201. return (Allocation*) epimp->Peer(out marshall);
  202. }
  203. }
  204. /// <summary>
  205. /// The event to wait for messages on this endpoint. Used by Select.
  206. /// </summary>
  207. public static SyncHandle GetWaitHandle(ref EndpointCore endpoint)
  208. {
  209. // kernel methods always access the shadowed copy in deliveryImpl
  210. // not the user accessable copy in EndpointCore
  211. fixed (EndpointCore* ep = &endpoint) {
  212. EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
  213. return epimp->GetWaitHandle();
  214. }
  215. }
  216. /// <summary>
  217. /// Notify the owner of this endpoint that a message is ready.
  218. /// Notifies the set owner if this endpoint is part of a set.
  219. /// </summary>
  220. [ExternalEntryPoint]
  221. public static void NotifyPeer(ref EndpointCore endpoint) {
  222. fixed (EndpointCore* ep = &endpoint) {
  223. EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
  224. epimp->NotifyPeer();
  225. }
  226. }
  227. /// <summary>
  228. /// Wait for a message to arrive on this endpoint.
  229. /// </summary>
  230. public static void Wait(ref EndpointCore ep) {
  231. SyncHandle.WaitOne(GetWaitHandle(ref ep));
  232. }
  233. /// <summary>
  234. /// Transfer the given Allocation block to the target endpoint
  235. /// </summary>
  236. [ExternalEntryPoint]
  237. public static void TransferBlockOwnership(Allocation* ptr, ref EndpointCore target)
  238. {
  239. fixed (EndpointCore* ep = &target) {
  240. EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
  241. EndpointCoreImplementation.TransferBlockOwnership((SharedHeap.Allocation*)ptr, ref *epimp);
  242. }
  243. }
  244. /// <summary>
  245. /// Transfer any contents that needs to be adjusted from the transferee to the target
  246. /// endpoint. Currently, this means setting the ownerProcessId of the
  247. /// transferee to that of the target.
  248. /// </summary>
  249. [ExternalEntryPoint]
  250. public static void TransferContentOwnership(
  251. ref EndpointCore transferee,
  252. ref EndpointCore target)
  253. {
  254. fixed (EndpointCore* ep1 = &transferee, ep2 = &target) {
  255. EndpointCoreImplementation* epimp1 = (EndpointCoreImplementation*)ep1;
  256. EndpointCoreImplementation* epimp2 = (EndpointCoreImplementation*)ep2;
  257. EndpointCoreImplementation.TransferContentOwnership(ref *epimp1, ref *epimp2);
  258. }
  259. }
  260. [NoHeapAllocation]
  261. public static int GetChannelID(ref EndpointCore endpoint)
  262. {
  263. // kernel methods always access the shadowed copy in deliveryImpl
  264. // not the user accessable copy in EndpointCore
  265. fixed (EndpointCore* ep = &endpoint) {
  266. EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
  267. return epimp->ChannelId;
  268. }
  269. }
  270. [NoHeapAllocation]
  271. public static int GetOwnerProcessID(ref EndpointCore endpoint)
  272. {
  273. // kernel methods always access the shadowed copy in deliveryImpl
  274. // not the user accessable copy in EndpointCore
  275. fixed (EndpointCore* ep = &endpoint) {
  276. EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
  277. return epimp->ProcessId;
  278. }
  279. }
  280. [NoHeapAllocation]
  281. public static int GetPeerProcessID(ref EndpointCore ep)
  282. {
  283. // kernel methods always access the shadowed copy in deliveryImpl
  284. // not the user accessable copy in EndpointCore
  285. return GetPeerProcessIDABI(ref ep);
  286. }
  287. [ExternalEntryPoint]
  288. [NoHeapAllocation]
  289. public static int GetPeerProcessIDABI(ref EndpointCore endpoint)
  290. {
  291. fixed (EndpointCore* ep = &endpoint) {
  292. EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
  293. return epimp->PeerProcessId;
  294. }
  295. }
  296. [ExternalEntryPoint]
  297. public static void AcceptDelegation(Allocation* /*EndpointCore* opt(ExHeap)!*/ imp,
  298. Allocation* /*EndpointCore* opt(ExHeap)!*/ exp,
  299. Allocation* /*EndpointCore* opt(ExHeap)!*/ ep)
  300. {
  301. EndpointCoreImplementation.AcceptDelegation((SharedHeap.Allocation*)imp,
  302. (SharedHeap.Allocation*)exp,
  303. (SharedHeap.Allocation*)ep);
  304. }
  305. [ExternalEntryPoint]
  306. public static void EnableDelegation(ref EndpointCore endpoint, bool allowMediation)
  307. {
  308. fixed (EndpointCore* ep = &endpoint) {
  309. EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
  310. epimp->EnableDelegation(allowMediation);
  311. }
  312. }
  313. [ExternalEntryPoint]
  314. [NoHeapAllocation]
  315. public static PrincipalHandle GetPeerPrincipalHandle(ref EndpointCore endpoint)
  316. {
  317. fixed (EndpointCore* ep = &endpoint) {
  318. EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
  319. return epimp->PeerPrincipalHandle;
  320. }
  321. }
  322. [ExternalEntryPoint]
  323. [NoHeapAllocation]
  324. public static PrincipalHandle GetOwnerPrincipalHandle(ref EndpointCore endpoint)
  325. {
  326. fixed (EndpointCore* ep = &endpoint) {
  327. EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
  328. return epimp->OwnerPrincipalHandle;
  329. }
  330. }
  331. /// <summary>
  332. /// Instruct the selectable object to signal events on the given AutoResetEvent
  333. /// rather than its normal event in order to aggregate signalling into a set.
  334. /// A selectable object need only support being part of a single collection at
  335. /// any point in time.
  336. /// </summary>
  337. public static void LinkIntoCollection(ref EndpointCore ep,
  338. AutoResetEventHandle ev) {
  339. ep.collectionEvent = ev;
  340. }
  341. /// <summary>
  342. /// Instruct the selectable object to stop signalling events on the given
  343. /// AutoResetEvent.
  344. /// </summary>
  345. public static void UnlinkFromCollection(ref EndpointCore ep,
  346. AutoResetEventHandle ev) {
  347. ep.collectionEvent = new AutoResetEventHandle();
  348. }
  349. [ExternalEntryPoint]
  350. unsafe public static void MarshallMessage(ref EndpointCore endpoint,
  351. byte* basep,
  352. byte* source,
  353. int* tagAddress,
  354. int msgSize)
  355. {
  356. fixed (EndpointCore* ep = &endpoint) {
  357. EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
  358. epimp->BeginUpdate(basep, source, tagAddress, msgSize);
  359. }
  360. }
  361. [ExternalEntryPoint]
  362. public static void MarshallPointer(ref EndpointCore endpoint, byte* basep, byte** target, SystemType type, byte* parent, int offset)
  363. {
  364. fixed (EndpointCore* ep = &endpoint)
  365. {
  366. EndpointCoreImplementation* epimp = (EndpointCoreImplementation*)ep;
  367. epimp->MarshallPointer(basep, target, type, parent, offset);
  368. }
  369. }
  370. }
  371. }