singrdk/base/Kernel/Singularity/V1/Services/ProcessService.cs

534 lines
18 KiB
C#

////////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity - Singularity ABI
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: ProcessService.cs
//
// Note:
//
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using Microsoft.Singularity;
using Microsoft.Singularity.Memory;
using Microsoft.Singularity.Security;
using Microsoft.Singularity.Io;
using Microsoft.Singularity.V1.Security;
namespace Microsoft.Singularity.V1.Services
{
[CLSCompliant(false)]
public struct LogEntry
{
}
public enum ParameterCode {
Success,
OutOfRange,
NotSet,
Retrieved,
Undefined,
}
[CLSCompliant(false)]
public struct ProcessService
{
// In order to pass the arguments to the kernel, we first need to
// flatten the arguments parameter from an array of strings to
// an array of characters (containing the contents of the strings).
// If argVector is null we compute the the length needed to store
// the result. It is up to the calling process to then allocate
// the memory and call again.
private static unsafe int FlattenStringArray(string[] arguments,
int* argLengths,
char* argVector
)
{
int totalCharacters = 0;
int len = arguments.Length;
for (int arg = 0; arg < len; arg++) {
string argstring = arguments[arg];
if (argstring == null) continue;
totalCharacters += argstring.Length;
}
if (argVector == null ) {
return totalCharacters;
}
int offset = 0;
for (int arg = 0; arg < len; arg++) {
string argstring = arguments[arg];
if (argstring == null) {
argLengths[arg] = 0;
continue;
}
int alen = argstring.Length;
//argstring.CopyTo(0, argVector, offset, alen);
for (int i=0; i < alen; i++){
argVector[offset+i] = argstring[i];
}
offset += alen;
argLengths[arg] = alen;
}
return totalCharacters;
}
[ExternalEntryPoint]
public static void Stop(int exitCode)
{
Tracing.Log(Tracing.Debug, "ProcessService.Stop(exit={0})",
(UIntPtr)unchecked((uint)exitCode));
Thread.CurrentProcess.Stop(exitCode);
}
[ExternalEntryPoint]
public static TimeSpan GetUpTime()
{
TimeSpan ts = SystemClock.KernelUpTime;
return ts;
}
[ExternalEntryPoint]
public static DateTime GetUtcTime()
{
DateTime dt = SystemClock.GetUtcTime();
return dt;
}
[ExternalEntryPoint]
public static long GetCycleCount()
{
return (long)Processor.CycleCount;
}
[ExternalEntryPoint]
public static long GetCyclesPerSecond()
{
Kernel.Waypoint(300);
return (long)Processor.CyclesPerSecond;
}
[ExternalEntryPoint]
public static long GetContextSwitchCount()
{
return Processor.CurrentProcessor.NumContextSwitches;
}
[ExternalEntryPoint]
public static void SetGcPerformanceCounters(TimeSpan spent, long bytes)
{
Thread.CurrentProcess.SetGcPerformanceCounters(spent, bytes);
}
[ExternalEntryPoint]
public static long GetKernelGcCount()
{
int collectorCount;
long collectorMillis;
long collectorBytes;
GC.PerformanceCounters(out collectorCount,
out collectorMillis,
out collectorBytes);
return collectorCount;
}
[ExternalEntryPoint]
public static long GetKernelBootCount()
{
return Resources.GetWarmBootCount();
}
[ExternalEntryPoint]
public static long GetKernelInterruptCount()
{
return Processor.CurrentProcessor.NumInterrupts;
}
[ExternalEntryPoint]
public static ushort GetCurrentProcessId()
{
return (ushort)Thread.CurrentProcess.ProcessId;
}
/*
[ExternalEntryPoint]
public static PrincipalHandle GetCurrentPrincipal()
{
return new PrincipalHandle(Thread.CurrentProcess.PrincipalId.val);
}
*/
[ExternalEntryPoint]
// Return parameter is really: DirectoryService.Imp opt(ExHeap) *
public static unsafe SharedHeapService.Allocation * GetNamespaceEndpoint()
{
return (SharedHeapService.Allocation *)
Thread.CurrentProcess.GetNamespaceEndpoint();
}
[ExternalEntryPoint]
public static int GetStartupEndpointCount() {
return Thread.CurrentProcess.GetStartupEndpointCount();
}
[ExternalEntryPoint]
// Return parameter is really: ExtensionContract.Exp opt(ExHeap) *
public static unsafe SharedHeapService.Allocation * GetStartupEndpoint(int arg)
{
return (SharedHeapService.Allocation *)
Thread.CurrentProcess.GetStartupEndpoint(arg);
}
[ExternalEntryPoint]
// Parameter is really: ExtensionContract.Exp opt(ExHeap) *
public static unsafe void SetStartupEndpoint(int arg,
SharedHeapService.Allocation * ep)
{
SharedHeap.Allocation * mep = (SharedHeap.Allocation *)ep;
Thread.CurrentProcess.SetEndpoint(arg, ref mep);
}
[ExternalEntryPoint]
public static int GetStartupArgCount()
{
return Thread.CurrentProcess.GetStartupArgCount();
}
[ExternalEntryPoint]
public static unsafe int GetStartupArg(int arg, char * output, int maxput)
{
string s = Thread.CurrentProcess.GetStartupArg(arg);
Tracing.Log(Tracing.Debug,
"Process.GetStartupArg(arg={0}, out={1:x8}, max={2}) = {3}",
(UIntPtr)unchecked((uint)arg),
(UIntPtr)output,
(UIntPtr)unchecked((uint)maxput),
(UIntPtr)unchecked((uint)(s != null ? s.Length : 0)));
if (s == null) {
return 0;
}
if (output == null) {
return s.Length + 1;
}
return s.InternalGetChars(output, maxput);
}
[ExternalEntryPoint]
public static TimeSpan GetThreadTime() {
return Thread.CurrentThread.ExecutionTime;
}
[ExternalEntryPoint]
public static long GetThreadsCreatedCount() {
return PerfCounters.ThreadsCreated;
}
[ExternalEntryPoint]
public static unsafe void GetTracingHeadersImpl(
LogEntry **logBegin,
LogEntry **logLimit,
LogEntry ***logHead,
byte **txtBegin,
byte **txtLimit,
byte ***txtHead)
{
GetTracingHeaders(out *logBegin, out *logLimit, out *logHead,
out *txtBegin, out *txtLimit, out *txtHead);
}
[AccessedByRuntime("referenced from Tracing.cpp")]
public static unsafe void GetTracingHeaders(out LogEntry *logBegin,
out LogEntry *logLimit,
out LogEntry **logHead,
out byte *txtBegin,
out byte *txtLimit,
out byte **txtHead)
{
Tracing.LogEntry *_logBegin;
Tracing.LogEntry *_logLimit;
Tracing.LogEntry **_logHead;
Tracing.GetTracingHeaders(out _logBegin, out _logLimit, out _logHead,
out txtBegin, out txtLimit, out txtHead);
logBegin = (LogEntry *)_logBegin;
logLimit = (LogEntry *)_logLimit;
logHead = (LogEntry **)_logHead;
}
[ExternalEntryPoint]
public static unsafe void GetMonitoringHeadersImpl(byte * * _buffer)
{
GetMonitoringHeaders(out *_buffer);
}
[AccessedByRuntime("referenced from Monitoring.cpp")]
public static unsafe void GetMonitoringHeaders(out byte * _buffer)
{
Monitoring.GetMonitoringHeaders(out _buffer);
}
[ExternalEntryPoint]
public static void Waypoint0()
{
Kernel.Waypoint0();
}
[ExternalEntryPoint]
public static void Waypoint(int num)
{
Kernel.Waypoint(num);
}
[ExternalEntryPoint]
public static void WaypointDone()
{
Kernel.WaypointDone();
}
[ExternalEntryPoint]
public static void WaypointDump()
{
Kernel.WaypointDump();
}
[ExternalEntryPoint]
public static int GetStartupBoolArgCount() {
return Thread.CurrentProcess.GetStartupBoolArgCount();
}
[ExternalEntryPoint]
public static int GetStartupLongArgCount() {
return Thread.CurrentProcess.GetStartupLongArgCount();
}
[ExternalEntryPoint]
public static int GetStartupStringArgCount() {
return Thread.CurrentProcess.GetStartupStringArgCount();
}
[ExternalEntryPoint]
public static int GetStartupStringArrayArgCount() {
return Thread.CurrentProcess.GetStartupStringArrayArgCount();
}
[ExternalEntryPoint]
public static unsafe ParameterCode GetStartupLongArgImpl(
int index,
long * value)
{
return GetStartupLongArg(index, out *value);
}
public static ParameterCode GetStartupLongArg(int index, out long value) {
return (ParameterCode) Thread.CurrentProcess.GetStartupLongArg(index, out value);
}
[ExternalEntryPoint]
public static unsafe ParameterCode GetStartupBoolArgImpl(
int index,
bool * value)
{
return GetStartupBoolArg(index, out *value);
}
public static ParameterCode GetStartupBoolArg(int index, out bool value) {
return (ParameterCode)Thread.CurrentProcess.GetStartupBoolArg(index, out value);
}
[ExternalEntryPoint]
public static unsafe ParameterCode GetStartupStringArrayArgImpl(
int index,
char *strbuff,
int *len,
int *arrayLength,
int *totalCharCount)
{
ParameterCode code;
string[] strings;
code = (ParameterCode) Thread.CurrentProcess.GetStartupStringArrayArg(index, out strings);
if (code != ParameterCode.Success) {
*arrayLength = 0;
*totalCharCount = 0;
return code;
}
if (strings == null) {
*arrayLength = 0;
*totalCharCount = 0;
return ParameterCode.NotSet;
}
*totalCharCount = FlattenStringArray(strings, len, strbuff);
*arrayLength = strings.Length;
return ParameterCode.Success;
}
[ExternalEntryPoint]
public static unsafe ParameterCode GetStartupStringArgImpl(
int arg,
char * output,
int * maxput)
{
return GetStartupStringArg(arg, output, ref *maxput);
}
public static unsafe ParameterCode GetStartupStringArg(int arg, char * output, ref int maxput)
{
string s;
ParameterCode code = (ParameterCode)Thread.CurrentProcess.GetStartupStringArg(arg, out s);
Tracing.Log(Tracing.Debug,
"Process.GetStartupStringArg(arg={0}, out={1:x8}, max={2}) = {3}",
(UIntPtr)unchecked((uint)arg),
(UIntPtr)output,
(UIntPtr)unchecked((uint)maxput),
(UIntPtr)unchecked((uint)(s != null ? s.Length : 0)));
if (code != ParameterCode.Success) {
return code;
}
if (output == null) {
if (s == null) maxput = 0;
else maxput = s.Length ;
return ParameterCode.Success;
}
if (s != null) s.InternalGetChars(output, maxput);
return ParameterCode.Success;
}
// haryadi -- interface to run ping pong from app
[ExternalEntryPoint]
public static int RunPingPongInt(int start)
{
return Processor.RunPingPongInt(start);
}
// haryadi
// Note: [NoHeapAllocation] is bad .. Since HelloProcessABI
// is called from Processor.DispatchSpecificInterrupt(), then
// every ABI should be annotated with [NoHeapAllocation]
// Probably, in the future when we already use the scheduler,
// instead of direct invocation during interrupt context, we
// don't need [NoHeapAllocation]
[ExternalEntryPoint]
[ NoHeapAllocation ]
public static int HelloProcessABI(int num, int num2)
{
DebugStub.WriteLine
("HSG: ** cpu.{0} HelloProcessABI({1:x8},{2:x8})",
__arglist(Processor.GetCurrentProcessorId(),
num, num2));
// return the power of 2 of the value
return num+num2;
}
[ExternalEntryPoint]
[ NoHeapAllocation ]
public static unsafe ulong TestAbiCallOne(ulong a) {
DebugStub.WriteLine("HSG: ** TestAbiCallOne({0:x16})}",
__arglist(a));
return 18000000000000000000 + a; // 64 bit
}
[ExternalEntryPoint]
[ NoHeapAllocation ]
public static unsafe int TestAbiCallTwo(uint a, char *b)
{
DebugStub.WriteLine("HSG: ** TestAbiCallTwo({0:x8}, {1:x8})}",
__arglist((int)(a), (int)(b)));
return ((int)(b) + (int)a);
}
[ExternalEntryPoint]
[ NoHeapAllocation ]
public static unsafe char* TestAbiCallThree(int a, int *b, byte c)
{
DebugStub.WriteLine
("HSG: ** TestAbiCallOne({0:x8}, {1:x8}, {2:x8})}",
__arglist((int)(a), (int)(b), (int)(c)));
return (char*)((int)b + a + (int)c);
}
#if FALSE
[ExternalEntryPoint]
public static int StubHelloProcessABI2(int num)
{
int ap = Processor.GetCurrentProcessorId();
int bsp = 0;
DebugStub.WriteLine
("\n\nHSG: ** cpu.{0} ProcessService.StubHelloProcessABI({1})",
__arglist(ap, num));
DebugStub.WriteLine("HSG: ** -----------------------------------");
bool iflag = Processor.DisableInterrupts();
MpExecution.AbiCall abiCall = new MpExecution.AbiCall();
// 1) set up all the parameters
abiCall.argVal = num;
// prepare IPI
DebugStub.Print
("HSG: ** cpu.{0} PutAbiCall(cpu.{1}, arg.{2}) --> ",
__arglist(ap, bsp, abiCall.argVal));
// 2) register the abiCall,
// after this, we get the position
int pos = MpExecution.PutAbiCall(bsp, abiCall);
DebugStub.WriteLine("pos.{0}", __arglist(pos));
DebugStub.WriteLine
("HSG: ** cpu.{0} SendAbiCall(cpu.{1}, cpu.{2})",
__arglist(ap, ap, bsp));
// 3) send
MpExecution.SendAbiCall(ap, bsp);
DebugStub.WriteLine
("HSG: ** cpu.{0} WaitAbiCall(cpu.{1}, pos.{2}) ... zzz ... zzz ... ",
__arglist(ap, bsp, pos));
// 4) spin until done
MpExecution.WaitAbiCall(bsp, pos, out abiCall);
// 5) we have the return value
int retval = abiCall.retVal;
DebugStub.WriteLine
("HSG: ** cpu.{0} is waken up and receives retval.{1}",
__arglist(ap, retval));
DebugStub.WriteLine
("HSG: ** cpu.{0} ReleaseAbiCall(cpu.{1}, pos.{2})",
__arglist(ap, bsp, pos));
// 6) release abiCall
MpExecution.ReleaseAbiCall(bsp, pos);
Processor.RestoreInterrupts(iflag);
return retval;
}
#endif
}
}