singrdk/base/Kernel/Singularity/Memory/MemoryDiagnosis.cs

246 lines
8.0 KiB
C#

////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: MemoryDiagnosis.cs
//
//
using System;
using System.Threading;
using System.Runtime.CompilerServices;
using Microsoft.Singularity;
using Microsoft.Singularity.V1.Services;
using Microsoft.Singularity.Eventing;
using System.Collections;
namespace Microsoft.Singularity.Eventing
{
[CLSCompliant(false)]
public class SystemAllocationLogger : EventSource {
private const uint DefaultLogSize = 0x10000;
public static SystemAllocationLogger Create(string sourceName) {
EventingStorage storage = EventingStorage.CreateLocalStorage(QualityOfService.RecyclableEvents,
DefaultLogSize);
if (storage == null) {
return null;
}
SystemAllocationLogger Logger = new SystemAllocationLogger(sourceName,
storage,
ENABLE_ALL_MASK);
if (Logger != null) {
Logger.Register();
}
return Logger;
}
//[EventType=Interrupt]
[NoHeapAllocation]
public bool Log(ushort processTag, ushort memoryType, UIntPtr address, UIntPtr size) { // !!!!! this line must be entered to define a schema
if ((ControlFlags & MemoryAllocation_Control_flag) != 0) {
unsafe {
MemoryAllocationEvent memEvent;
memEvent.MemoryType = memoryType;
memEvent.ProcessTag = processTag;
memEvent.Address = address;
memEvent.Size = size;
return (LogEntry(ControlFlags,
eventTypeMemoryAllocation,
(byte *)&memEvent,
sizeof(MemoryAllocationEvent)) != 0);
}
}
return false;
}
public unsafe struct MemoryAllocationEvent {
public UIntPtr Address;
public UIntPtr Size;
public ushort ProcessTag;
public ushort MemoryType;
};
UIntPtr eventTypeMemoryAllocation;
const uint MemoryAllocation_Control_flag = 0x10000;
public override bool Register() {
if (!base.Register()) {
return false;
}
if (HostController.RegisterEvent("SystemMemoryAllocation",
"Memory allocation event: Address={0}, Memory type = {3}",
ref eventTypeMemoryAllocation)) {
HostController.RegisterEventField(eventTypeMemoryAllocation,
"Address",
0,
DataType.__UIntPtr);
HostController.RegisterEventField(eventTypeMemoryAllocation,
"Size",
0,
DataType.__UIntPtr);
HostController.RegisterEventField(eventTypeMemoryAllocation,
"ProcessTag",
0,
DataType.__uint16);
HostController.RegisterEventField(eventTypeMemoryAllocation,
"MemoryType",
0,
DataType.__uint16);
} else {
// The event might have been registered already
// Check whether we foundit already in the table or not
if (eventTypeMemoryAllocation == 0) {
return false;
}
}
return true;
}
SystemAllocationLogger (string sourceName, EventingStorage storage, uint controlFlags)
:base(sourceName, storage, controlFlags) {}
}
[CLSCompliant(false)]
[NoCCtor]
public class FreeMemoryDistribution : ActiveSource{
// Empty function declaration. Active counters are never logged through functions
// Present here for further usage with Phoenix codegen
// [ActiveCounter]
void TraceFreeBlock(UIntPtr BlockCount, UIntPtr TotalBlocksSize){}
// Here should start the codegen's work. Do it by hand for now
public struct tmpFreeBlockEntry{
public UIntPtr BlockCount;
public UIntPtr TotalBucketSize;
}
internal tmpFreeBlockEntry[] Buffer;
public static FreeMemoryDistribution Create(string sourceName, int size) {
FreeMemoryDistribution Logger = new FreeMemoryDistribution(sourceName, size, ENABLE_ALL_MASK);
if (Logger != null) {
Logger.Register();
}
return Logger;
}
public override bool Register() {
Buffer = new tmpFreeBlockEntry[Count];
if (Buffer == null) {
return false;
}
if (HostController.RegisterEvent("MemoryFreeBucket",
"Memory free buckets: Count = {0}",
ref EventTypeHandle)) {
HostController.RegisterEventField(EventTypeHandle,
"BlockCount",
0,
DataType.__UIntPtr);
HostController.RegisterEventField(EventTypeHandle,
"TotalBucketSize",
0,
DataType.__UIntPtr);
} else {
// The event might have been registered already
// Check whether we foundit already in the table or not
if (EventTypeHandle == 0) {
return false;
}
}
unsafe {
fixed (void * ptr = &Buffer[0]) {
DebugBufferAddress = (UIntPtr)ptr;
}
}
// After all internal fields are setup, we can go ahead and register with the controller
if (!base.Register()) {
return false;
}
return true;
}
public tmpFreeBlockEntry this[int index]
{
get {
return Buffer[index];
}
}
public override unsafe bool GetActiveEntry(int index,
UIntPtr * type,
byte * buffer,
UInt16 bufferSize )
{
if (!base.GetActiveEntry(index, type, buffer, bufferSize)) {
return false;
}
*(tmpFreeBlockEntry *)buffer = Buffer[index];
return true;
}
FreeMemoryDistribution(string sourceName, int size, uint controlFlags)
:base(sourceName, size, controlFlags)
{
unsafe {
EntrySize = (ushort)sizeof(tmpFreeBlockEntry);
}
}
}
}