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

145 lines
4.4 KiB
C#

////////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: DeliveryHandle.cs
//
// Note: An indirection mechanism used by EndpointCore to abstract the
// Delivery mechanism used to notify the another endpoint of a new
// message and potentially marshall and copy the message to another
// Domain.
//
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using Microsoft.Singularity;
using Microsoft.Singularity.Memory;
using Allocation = Microsoft.Singularity.Memory.SharedHeap.Allocation;
namespace Microsoft.Singularity.Channels
{
[CLSCompliant(false)]
public struct DeliveryHandle
{
public readonly UIntPtr id;
public static readonly DeliveryHandle Zero = new DeliveryHandle();
public DeliveryHandle(UIntPtr id)
{
this.id = id;
}
public unsafe static bool Create(
string implName,
Allocation* /*EndpointCore* opt(ExHeap)!*/ endpoint,
out DeliveryHandle handle)
{
DeliveryImpl deliveryImpl;
switch (implName) {
case SingleAddrSpaceDelivery.ImplName:
deliveryImpl = new SingleAddrSpaceDelivery(endpoint);
break;
#if PAGING
// TODO paging
#endif
default:
throw new DeliveryHandleException(
"Unknown channel delivery implementation \"" +
implName +
"\" requested");
}
if (!deliveryImpl.IsMechanismInitialized()) {
DebugStub.Print("Ack! IsMechInit returns false!\n");
DebugStub.Break();
handle = Zero;
return false;
}
handle = new DeliveryHandle(
Process.kernelProcess.AllocateHandle(deliveryImpl));
#if false
unsafe {
DebugStub.WriteLine("DeliveryHandle.Create: got handle {0,8:x}\n", __arglist((uint)handle.id));
}
#endif
return true;
}
public static void Dispose(DeliveryHandle handle)
{
Dispose(Process.kernelProcess, handle);
}
internal static void Dispose(Process process,
DeliveryHandle handle)
{
Tracing.Log(Tracing.Debug, "DeliveryHandle.Dispose(id={0:x8})",
handle.id);
//
// Releasing the handle will allow the deliveryImpl to be garbage-
// collected
//
process.ReleaseHandle(handle.id);
}
public static bool Free(DeliveryHandle handle)
{
DeliveryImpl di = GetImpl(handle);
// This is a pretty kludgy hack, but is necessary since static
// methods can't be called on an object.
switch (di.GetImplName()) {
case SingleAddrSpaceDelivery.ImplName:
return SingleAddrSpaceDelivery.Free((SingleAddrSpaceDelivery)di);
#if PAGING
// TODO paging
#endif
default:
throw new DeliveryHandleException(
"Free of unknown channel delivery implementation \"" +
di.GetImplName() +
"\" requested");
}
}
/// <summary>
/// Returns the delivery implementation object associated with the
/// given handle.
/// </summary>
[NoHeapAllocation]
public static DeliveryImpl GetImpl(DeliveryHandle handle) {
DeliveryImpl di = HandleTable.GetHandle(handle.id) as DeliveryImpl;
return di;
}
[NoHeapAllocation]
public static bool operator != (DeliveryHandle d1, DeliveryHandle d2)
{
return d1.id != d2.id;
}
[NoHeapAllocation]
public static bool operator == (DeliveryHandle d1, DeliveryHandle d2)
{
return d1.id == d2.id;
}
}
public class DeliveryHandleException: Exception
{
public DeliveryHandleException (string message) : base(message)
{
}
}
}