singrdk/base/Applications/Runtime/Full/Singularity/DebugStub.cs

365 lines
10 KiB
C#

////////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Note:
//
using System;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.Singularity.V1.Services;
namespace Microsoft.Singularity
{
[NoCCtor]
[CLSCompliant(false)]
[AccessedByRuntime("referenced in halkd.cpp")]
public class DebugStub
{
/////////////////////////////////////////////////////// Print Methods.
//
[NoHeapAllocation]
public static void Print(byte value)
{
Print("{0:x2}", __arglist(value));
}
[NoHeapAllocation]
public static void Print(ushort value)
{
Print("{0:x4}", __arglist(value));
}
[NoHeapAllocation]
public static void Print(uint value)
{
Print("{0:x8}", __arglist(value));
}
[NoHeapAllocation]
public static void Print(ulong value)
{
Print("{0:x}", __arglist(value));
}
[NoHeapAllocation]
public static void Print(UIntPtr value)
{
Print("{0:x8}", __arglist(value));
}
[NoHeapAllocation]
public static void Print(sbyte value)
{
Print("{0}", __arglist(value));
}
[NoHeapAllocation]
public static void Print(short value)
{
Print("{0}", __arglist(value));
}
[NoHeapAllocation]
public static void Print(int value)
{
Print("{0}", __arglist(value));
}
[NoHeapAllocation]
public static void Print(long value)
{
Print("{0}", __arglist(value));
}
//////////////////////////////////////////////////////////////////////
//
[NoHeapAllocation]
public static void Print(String value)
{
if (value != null) {
Print(value, new ArgIterator());
}
}
[NoHeapAllocation]
public static void Print(String format, __arglist)
{
Print(format, new ArgIterator(__arglist));
}
[NoHeapAllocation]
public static unsafe void Print(String format, ArgIterator args)
{
WriteLine(format, args);
}
//////////////////////////////////////////////////////////////////////
//
[NoHeapAllocation]
public static void Write(String value)
{
if (value != null) {
WriteLine(value, new ArgIterator());
}
}
[NoHeapAllocation]
public static void Write(String format, __arglist)
{
Write(format, new ArgIterator(__arglist));
}
[NoHeapAllocation]
public static unsafe void Write(String format, ArgIterator args)
{
WriteLine(format, args);
}
//////////////////////////////////////////////////////////////////////
//
[NoHeapAllocation]
public static void WriteLine()
{
WriteLine("", new ArgIterator());
}
[NoHeapAllocation]
public static void WriteLine(String value)
{
if (value != null) {
WriteLine(value, new ArgIterator());
}
}
[NoHeapAllocation]
public static void WriteLine(String format, __arglist)
{
WriteLine(format, new ArgIterator(__arglist));
}
[NoHeapAllocation]
public static unsafe void WriteLine(String format, ArgIterator args)
{
char *buffer;
int length;
int used = 0;
DebugService.PrintBegin(out buffer, out length);
try {
if (buffer != null) {
AddLineHeader(buffer, ref used, length);
int format_used = String.LimitedFormatTo(format, args, buffer+used, length-used);
used += format_used;
// If the line had \r or \n at the start, replace with spaces.
for (int i = 0; i < used; i++) {
char c = buffer[i];
if (c == '\r' || c == '\n') {
buffer[i] = ' ';
}
else {
break;
}
}
// Remove whitespace (including \r\n) from the end.
while (used > 0) {
char c = buffer[used - 1];
if (c == ' ' || c == '\r' || c == '\n' || c == '\t') {
used--;
}
else {
break;
}
}
// Add our own \r\n
if (used < length) {
buffer[used++] = '\n';
}
}
}
finally {
DebugService.PrintComplete(buffer, used);
}
}
/// <summary>
/// This method adds prefix to each line sent to the debugger, containing the app name,
/// process id, thread id, and thread name. The thread name can be changed by setting
/// the DebugName property of a thread.
/// </summary>
[NoHeapAllocation]
private static unsafe void AddLineHeader(char* buffer, ref int length, int maxLength)
{
uint processId = ProcessService.GetCurrentProcessId();
uint threadId = unchecked((uint)Thread.GetCurrentThreadIndex());
string appName;
string threadName;
#if DEBUG
appName = AppRuntime.AppName;
if (appName == null)
appName = "?";
Thread currentThread = Thread.CurrentThread;
if (currentThread != null) {
threadName = currentThread.DebugName;
if (threadName == null) {
threadName = "";
}
}
else {
threadName = "";
}
#else
appName = "?";
threadName = "";
#endif
InsertFormat(buffer, ref length, maxLength, "[{0,10} p{1,2} t{2,2} {3,6}] ", __arglist(appName, processId, threadId, threadName));
}
[NoHeapAllocation]
private static unsafe void InsertFormat(char* buffer, ref int length, int maxLength, String format, __arglist)
{
int count = String.LimitedFormatTo(format, new ArgIterator(__arglist), &buffer[length], maxLength - length);
length += count;
}
////////////////////////////////////////////////////// Assert Methods.
//
[NoHeapAllocation]
public static void NotImplemented()
{
failAssert("Not implemented.");
}
[NoHeapAllocation]
public static void NotImplemented(String msg)
{
failAssert(/*"Not implemented: "+*/msg);
}
[Conditional("DEBUG")]
[NoInline]
[NoHeapAllocation]
public static void NotReached()
{
failAssert("Unreachable code reached.");
}
[Conditional("DEBUG")]
[NoInline]
[NoHeapAllocation]
public static void NotReached(String msg)
{
failAssert(/*"Unreachable code reached: "+*/msg);
}
[Conditional("DEBUG")]
[NoInline]
[ManualRefCounts]
[NoHeapAllocation]
public static void Assert(bool expr)
{
if (!expr) {
failAssert(null);
}
}
[Conditional("DEBUG")]
[NoInline]
[ManualRefCounts]
[NoHeapAllocation]
public static void Deny(bool expr)
{
if (expr) {
failAssert(null);
}
}
[Conditional("DEBUG")]
[NoInline]
[ManualRefCounts]
[NoHeapAllocation]
public static void Assert(bool expr, String s)
{
if (!expr) {
failAssert(s);
}
}
[Conditional("DEBUG")]
[NoInline]
[NoHeapAllocation]
public static void Deny(bool expr, String s)
{
if (expr) {
failAssert(s);
}
}
[ManualRefCounts]
[NoHeapAllocation]
private static void failAssert(String s)
{
if (s != null) {
Print("Assertion failed: {0}", __arglist(s));
}
else {
Print("Assertion failed.");
}
Break();
}
//////////////////////////////////////////////////////////////////////
//
[NoHeapAllocation]
public static ulong ReadPerfCounter(uint which)
{
return DebugService.ReadPerfCounter(which);
}
[NoHeapAllocation]
public static bool WritePerfCounter(uint which, ulong value)
{
return DebugService.WritePerfCounter(which, value);
}
[NoHeapAllocation]
public static bool AddToPerfCounter(uint which, ulong value)
{
return DebugService.AddToPerfCounter(which, value);
}
/////////////////////////////////////////////////////// State Methods.
//
#if true
[AccessedByRuntime("output to header : defined in halkd.cpp")]
[MethodImpl(MethodImplOptions.InternalCall)]
[StackBound(638)]
[NoHeapAllocation]
public static extern void Break();
#else
[NoHeapAllocation]
public static void Break()
{
DebugService.Break();
}
#endif
}
}