2008-03-05 09:52:00 -05:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Microsoft Research Singularity
|
|
|
|
//
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
//
|
|
|
|
// Note:
|
|
|
|
//
|
|
|
|
|
|
|
|
using System;
|
|
|
|
using System.Collections;
|
|
|
|
using System.Reflection;
|
|
|
|
using System.Threading;
|
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
|
|
|
using Microsoft.Bartok.Runtime;
|
2008-11-17 18:29:00 -05:00
|
|
|
using Microsoft.Singularity.Io;
|
|
|
|
using Microsoft.Singularity.V1.Services;
|
2008-03-05 09:52:00 -05:00
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
using Microsoft.Singularity.Eventing;
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
[assembly: AssemblyTitle("Microsoft.Singularity")]
|
|
|
|
[assembly: AssemblyProduct("Microsoft Research Singularity Runtime")]
|
|
|
|
[assembly: AssemblyCompany("Microsoft Corporation")]
|
|
|
|
[assembly: AssemblyVersion("1.0.0.0")]
|
|
|
|
[assembly: AssemblyKeyFile("public.snk")]
|
|
|
|
[assembly: AssemblyDelaySign(true)]
|
|
|
|
|
|
|
|
namespace Microsoft.Singularity
|
|
|
|
{
|
|
|
|
|
|
|
|
[NoCCtor]
|
|
|
|
[CLSCompliant(false)]
|
2008-11-17 18:29:00 -05:00
|
|
|
[AccessedByRuntime("referenced from hal.cpp")]
|
2008-03-05 09:52:00 -05:00
|
|
|
public class AppRuntime
|
|
|
|
{
|
|
|
|
// Note: This function is called by Hal.cpp.
|
|
|
|
[AccessedByRuntime("referenced from hal.cpp")]
|
|
|
|
public static unsafe int AppStart(Type userClass)
|
|
|
|
{
|
|
|
|
System.GCs.Transitions.ThreadStart();
|
|
|
|
|
|
|
|
int result = 0;
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
string arg0 = "(unknown)";
|
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
try {
|
|
|
|
Tracing.Log(Tracing.Audit, "Runtime.Main()");
|
|
|
|
|
|
|
|
// Initialize the primitive runtime, which calls the
|
|
|
|
// class constructor for Runtime().
|
|
|
|
VTable.Initialize((RuntimeType)typeof(AppRuntime));
|
2008-11-17 18:29:00 -05:00
|
|
|
//VTable.ParseArgs(args);
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
Tracing.Log(Tracing.Audit, "Enabling GC Heap");
|
|
|
|
GC.EnableHeap();
|
2008-11-17 18:29:00 -05:00
|
|
|
Controller.InitializeSystem();
|
|
|
|
GCProfilerLogger.StartProfiling();
|
2008-03-05 09:52:00 -05:00
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
InitializeConsole();
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
SetDebuggerPresence(DebugService.IsDebuggerPresent());
|
|
|
|
|
|
|
|
int argCount = 0;
|
|
|
|
int argMaxLen = 0;
|
|
|
|
for (;; argCount++) {
|
|
|
|
int len = ProcessService.GetStartupArg(argCount, null, 0);
|
|
|
|
if (len == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (argMaxLen < len) {
|
|
|
|
argMaxLen = len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
char[] argArray = new char [argMaxLen];
|
|
|
|
string[] args = new string[argCount];
|
|
|
|
for (int arg = 0; arg < argCount; arg++) {
|
|
|
|
fixed (char *argptr = &argArray[0]) {
|
|
|
|
int len = ProcessService.GetStartupArg(arg,
|
|
|
|
argptr,
|
|
|
|
argArray.Length);
|
|
|
|
args[arg] = String.StringCTOR(argptr, 0, len);
|
2008-11-17 18:29:00 -05:00
|
|
|
if (arg == 0)
|
|
|
|
arg0 = args[arg];
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
#if DEBUG || true
|
|
|
|
// Record the first argument passed to this program, under the assumption that
|
|
|
|
// this is the application name. We use this string in DebugStub.WriteLine.
|
|
|
|
// Also, if the name has an extension, such as ".x86", chop it off.
|
|
|
|
// Also chop off any path prefix, such as "/init/".
|
|
|
|
appName = arg0;
|
|
|
|
int index = appName.LastIndexOf('.');
|
|
|
|
if (index != -1)
|
|
|
|
appName = appName.Substring(0, index);
|
|
|
|
index = appName.LastIndexOf('/');
|
|
|
|
if (index != -1)
|
|
|
|
appName = appName.Substring(index + 1);
|
|
|
|
|
|
|
|
// The default DebugName value for the main thread is "main";
|
|
|
|
// apps can override this by setting Thread.CurrentThread.DebugName.
|
|
|
|
Thread mainThread = Thread.CurrentThread;
|
|
|
|
if (mainThread != null) {
|
|
|
|
mainThread.DebugName = "main";
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
if (userClass != null) {
|
|
|
|
VTable.initType((RuntimeType)userClass);
|
|
|
|
}
|
|
|
|
|
|
|
|
result = CallMain(args);
|
|
|
|
if (!MainReturnsInt()) result = 0;
|
|
|
|
|
|
|
|
Tracing.Log(Tracing.Audit, "Main thread exited [{0}]",
|
|
|
|
(UIntPtr)unchecked((uint)result));
|
|
|
|
}
|
|
|
|
catch (Exception e) {
|
|
|
|
Tracing.Log(Tracing.Fatal, "Failed with exception {0}.{1}",
|
|
|
|
e.GetType().Namespace, e.GetType().Name);
|
|
|
|
Tracing.Log(Tracing.Trace, "Exception message was {0}",
|
|
|
|
e.ToString());
|
2008-11-17 18:29:00 -05:00
|
|
|
TopLevelException(e);
|
2008-03-05 09:52:00 -05:00
|
|
|
result = -1;
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
Thread.RemoveThread(Thread.CurrentThread.threadIndex);
|
|
|
|
Thread.JoinAll();
|
|
|
|
|
|
|
|
try {
|
|
|
|
FinalizeConsole();
|
|
|
|
}
|
|
|
|
catch (Exception e) {
|
|
|
|
Tracing.Log(Tracing.Fatal, "An exception occurred while shutting down the console: {0}",
|
|
|
|
e.ToString());
|
|
|
|
}
|
|
|
|
|
|
|
|
Controller.Finalize();
|
2008-03-05 09:52:00 -05:00
|
|
|
Tracing.Log(Tracing.Audit, "Runtime shutdown started.");
|
|
|
|
VTable.Shutdown(result);
|
|
|
|
Tracing.Log(Tracing.Audit, "Runtime exiting [{0}]",
|
|
|
|
(UIntPtr)unchecked((uint)result));
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// This method runs when the "main" thread terminates by throwing an exception.
|
|
|
|
/// It is a separate method, rather than simply code within the AppStart method,
|
|
|
|
/// in order to make life easier during debugging.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="ex"></param>
|
|
|
|
private static void TopLevelException(Exception/*!*/ ex)
|
|
|
|
{
|
|
|
|
DebugStub.WriteLine("AppRuntime: Main app thread terminated with exception:");
|
|
|
|
for (Exception focus = ex; focus != null; focus = focus.InnerException) {
|
|
|
|
DebugStub.WriteLine("{0}: {1}", __arglist(focus.GetType().FullName, focus.Message));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if DEBUG || true
|
|
|
|
/// <summary>
|
|
|
|
/// Returns the name of the application, as determined by the first parameter
|
|
|
|
/// passed in the argv block. This property is only present on DEBUG builds
|
|
|
|
/// (Debug and Prototype). It is provided for DebugStub.WriteLine, to provide
|
|
|
|
/// useful debugging spew.
|
|
|
|
/// </summary>
|
|
|
|
public static string AppName
|
|
|
|
{
|
|
|
|
[NoHeapAllocation]
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return appName;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private static string appName;
|
|
|
|
#endif
|
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
[AccessedByRuntime("output to header : defined in hal.cpp")]
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
|
|
[StackBound(256)]
|
|
|
|
private static extern int CallMain(String[] args);
|
|
|
|
|
|
|
|
[AccessedByRuntime("output to header: defined in hal.cpp")]
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
|
|
[StackBound(256)]
|
|
|
|
private static extern bool MainReturnsInt();
|
|
|
|
|
|
|
|
[AccessedByRuntime("output to header: defined in hal.cpp")]
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
|
|
[StackBound(256)]
|
|
|
|
private static extern void SetDebuggerPresence(bool debuggerPresent);
|
|
|
|
|
|
|
|
internal static void Shutdown(int exitCode)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Gracefully close down the process.
|
|
|
|
//
|
|
|
|
Tracing.Log(Tracing.Audit, "Runtime.Shutdown({0})",
|
|
|
|
(UIntPtr)unchecked((uint)exitCode));
|
|
|
|
|
|
|
|
DebugStub.WriteLine("Runtime.Shutdown({0})", __arglist(exitCode));
|
|
|
|
|
|
|
|
VTable.Shutdown(exitCode);
|
|
|
|
Tracing.Log(Tracing.Audit, "Runtime.Shutdown({0}) terminating",
|
|
|
|
(UIntPtr)unchecked((uint)exitCode));
|
|
|
|
ProcessService.Stop(exitCode);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal static void Stop(int exitCode)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Halt the process immediately.
|
|
|
|
//
|
|
|
|
Tracing.Log(Tracing.Audit, "Runtime.Stop({0})",
|
|
|
|
(UIntPtr)unchecked((uint)exitCode));
|
|
|
|
|
|
|
|
DebugStub.WriteLine("Runtime.Stop({0})", __arglist(exitCode));
|
|
|
|
|
|
|
|
ProcessService.Stop(exitCode);
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
[NoHeapAllocation]
|
|
|
|
public static UIntPtr AddressOf(Object o)
|
|
|
|
{
|
|
|
|
return Magic.addressOf(o);
|
|
|
|
}
|
|
|
|
|
|
|
|
[NoHeapAllocation]
|
|
|
|
public static UIntPtr SizeOf(Object o)
|
|
|
|
{
|
|
|
|
return System.GCs.ObjectLayout.Sizeof(o);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void InitType(Type ty)
|
|
|
|
{
|
|
|
|
VTable.initType((RuntimeType) ty);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void DumpPageTable()
|
|
|
|
{
|
|
|
|
System.GCs.PageTable.Dump("PageTable");
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
public static bool EnableGCVerify
|
|
|
|
{
|
|
|
|
get {
|
|
|
|
return VTable.enableGCVerify;
|
|
|
|
}
|
|
|
|
set {
|
|
|
|
VTable.enableGCVerify = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static bool EnableGCAccounting
|
|
|
|
{
|
|
|
|
get {
|
|
|
|
return VTable.enableGCAccounting;
|
|
|
|
}
|
|
|
|
set {
|
|
|
|
VTable.enableGCAccounting = value;
|
|
|
|
if (value == true) {
|
|
|
|
System.GCs.MemoryAccounting.Initialize(GC.gcType);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static uint GCPerfCounter
|
|
|
|
{
|
|
|
|
get {
|
|
|
|
return System.GC.perfCounter;
|
|
|
|
}
|
|
|
|
set {
|
|
|
|
System.GC.perfCounter = value;
|
|
|
|
}
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// This stub method is provided for so that System.Console.dll can override it for those
|
|
|
|
/// apps that want a console. This is necessary, in order to initialize and shutdown the
|
|
|
|
/// console at the right time.
|
|
|
|
/// </summary>
|
|
|
|
private static void InitializeConsole()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// This stub method is provided for so that System.Console.dll can override it for those
|
|
|
|
/// apps that want a console. This is necessary, in order to initialize and shutdown the
|
|
|
|
/// console at the right time.
|
|
|
|
/// </summary>
|
|
|
|
private static void FinalizeConsole()
|
|
|
|
{
|
|
|
|
}
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
}
|