446 lines
16 KiB
C#
446 lines
16 KiB
C#
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
// File: EventingKernel.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)]
|
||
|
[AccessedByRuntime("output to header : defined in EventController.cpp")]
|
||
|
public class KernelController : LocalController {
|
||
|
|
||
|
internal EventingStorage GeneralPurposeStorage;
|
||
|
|
||
|
static public KernelController KernelControllerObject = null;
|
||
|
|
||
|
internal override void Initialize() {
|
||
|
|
||
|
if (KernelControllerObject != null) {
|
||
|
|
||
|
// Already initialized
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
base.Initialize();
|
||
|
ProcessContext.Initialize();
|
||
|
|
||
|
GeneralPurposeStorage = EventingStorage.CreateLocalStorage(QualityOfService.RecyclableEvents,
|
||
|
BUFFER_EXPANSION_SIZE);
|
||
|
|
||
|
KernelControllerObject = this;
|
||
|
}
|
||
|
|
||
|
public override EventingStorage OpenStorage(UIntPtr storageHandle)
|
||
|
{
|
||
|
if (storageHandle == 0) {
|
||
|
|
||
|
return GeneralPurposeStorage;
|
||
|
}
|
||
|
|
||
|
return new GlobalStorage(storageHandle);
|
||
|
}
|
||
|
|
||
|
|
||
|
public override void UnRegisterController(int processId)
|
||
|
{
|
||
|
Lock.AcquireMutex();
|
||
|
ProcessContext ctx = ProcessContext.GetProcessContext(processId);
|
||
|
|
||
|
if (ctx != null) {
|
||
|
|
||
|
ctx.Delete();
|
||
|
}
|
||
|
|
||
|
Lock.ReleaseMutex();
|
||
|
}
|
||
|
|
||
|
public class ProcessContext {
|
||
|
|
||
|
static Hashtable Clients;
|
||
|
|
||
|
static public void Initialize() {
|
||
|
|
||
|
Clients = new Hashtable();
|
||
|
}
|
||
|
|
||
|
uint ProcessId;
|
||
|
UIntPtr ControllerHandle;
|
||
|
UIntPtr Context;
|
||
|
|
||
|
public bool Initialize(UIntPtr controllerHandle, UIntPtr context)
|
||
|
{
|
||
|
Clients[Thread.CurrentProcess.ProcessId] = this;
|
||
|
|
||
|
ControllerHandle = controllerHandle;
|
||
|
Context = context;
|
||
|
|
||
|
if (!KernelController.RegisterExternalController(controllerHandle, context)) {
|
||
|
|
||
|
Clients.Remove(Thread.CurrentProcess.ProcessId);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
[Inline]
|
||
|
static public ProcessContext GetProcessContext(int processId)
|
||
|
{
|
||
|
return Clients[processId] as ProcessContext;
|
||
|
}
|
||
|
|
||
|
public void Delete()
|
||
|
{
|
||
|
if (ControllerHandle != 0) {
|
||
|
|
||
|
DebugStub.WriteLine("UnregisterController {0}, {1}", __arglist(ControllerHandle, Context));
|
||
|
UnRegisterExternalController(ControllerHandle, Context);
|
||
|
}
|
||
|
|
||
|
ProcessId = 0;
|
||
|
Clients.Remove(Thread.CurrentProcess.ProcessId);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// System calls functions implementation.
|
||
|
// TODO: Currently the handles passed to SIPs are actually the handles used by
|
||
|
// the kernel. This must be changed to maintain a handle table for each SIP
|
||
|
// and always use the conversion in these syscalls routines
|
||
|
|
||
|
static public UIntPtr OpenStorageImpl(UIntPtr storageHandle)
|
||
|
{
|
||
|
if (storageHandle == 0) {
|
||
|
|
||
|
// Just return the kernel handle for now.
|
||
|
return KernelControllerObject.GeneralPurposeStorage.StorageHandle;
|
||
|
}
|
||
|
|
||
|
// TODO: validate the handle against the existing list and
|
||
|
// potential permissions.
|
||
|
|
||
|
return storageHandle;
|
||
|
}
|
||
|
|
||
|
public void CloseStorageImpl(UIntPtr storageHandle)
|
||
|
{
|
||
|
// See comments above for syscalls validations
|
||
|
// There are no states maintained currently. Here will be however the
|
||
|
// cleanup code for the storage returned to the process
|
||
|
}
|
||
|
|
||
|
public bool RegisterControllerImpl(UIntPtr controllerHandle, UIntPtr context)
|
||
|
{
|
||
|
ProcessContext ctx = new ProcessContext();
|
||
|
|
||
|
if (ctx == null){
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
Lock.AcquireMutex();
|
||
|
bool success = ctx.Initialize(controllerHandle, context);
|
||
|
Lock.ReleaseMutex();
|
||
|
|
||
|
return success;
|
||
|
}
|
||
|
|
||
|
static public unsafe bool RegisterEventImpl(char * eventName,
|
||
|
char * eventDescription,
|
||
|
UIntPtr * eventHandle)
|
||
|
{
|
||
|
UIntPtr handle = 0;
|
||
|
|
||
|
string name = new string(eventName);
|
||
|
string description = new string(eventDescription);
|
||
|
|
||
|
bool success = Controller.GetLocalController().RegisterEvent(name,
|
||
|
description,
|
||
|
ref handle);
|
||
|
|
||
|
if (success) {
|
||
|
|
||
|
*eventHandle = handle;
|
||
|
}
|
||
|
return success;
|
||
|
}
|
||
|
|
||
|
static public unsafe bool RegisterEventFieldImpl(UIntPtr eventHandle,
|
||
|
char * fieldName,
|
||
|
UInt16 offset,
|
||
|
UInt16 type)
|
||
|
{
|
||
|
string name = new string(fieldName);
|
||
|
|
||
|
return Controller.GetLocalController().RegisterEventField(eventHandle,
|
||
|
name,
|
||
|
offset,
|
||
|
type);
|
||
|
}
|
||
|
|
||
|
[NoHeapAllocation]
|
||
|
static public unsafe UIntPtr LogSourceEntryImpl(UIntPtr storageHandle,
|
||
|
uint flags,
|
||
|
UIntPtr eventType,
|
||
|
byte * buffer,
|
||
|
int size)
|
||
|
{
|
||
|
return EventSource.LogSourceEntryImpl(storageHandle,flags, eventType, buffer, size);
|
||
|
}
|
||
|
|
||
|
[NoHeapAllocation]
|
||
|
static public unsafe UIntPtr LogSourceEntryImpl(UIntPtr storageHandle,
|
||
|
uint flags,
|
||
|
UIntPtr eventType,
|
||
|
byte * buffer,
|
||
|
int size,
|
||
|
int arraysCount,
|
||
|
void ** arrays)
|
||
|
{
|
||
|
return EventSource.LogSourceEntryImpl(storageHandle,
|
||
|
flags,
|
||
|
eventType,
|
||
|
buffer,
|
||
|
size,
|
||
|
arraysCount,
|
||
|
(ArrayType *)arrays);
|
||
|
}
|
||
|
|
||
|
[NoHeapAllocation]
|
||
|
static public UIntPtr CreateQueryViewImpl(UIntPtr storageHandle, bool forward)
|
||
|
{
|
||
|
return MemoryStorage.CreateQueryViewImpl(storageHandle, forward);
|
||
|
}
|
||
|
|
||
|
[NoHeapAllocation]
|
||
|
static public void DeleteQueryViewImpl(UIntPtr storageHandle)
|
||
|
{
|
||
|
MemoryStorage.DeleteQueryViewImpl(storageHandle);
|
||
|
}
|
||
|
|
||
|
static public unsafe UIntPtr GetNextEntryImpl(UIntPtr queryHandle,
|
||
|
UIntPtr * type,
|
||
|
UInt32 * userOffset,
|
||
|
byte * buffer,
|
||
|
UInt16 bufferSize )
|
||
|
{
|
||
|
return MemoryStorage.GetNextEntryImpl(queryHandle,
|
||
|
type,
|
||
|
userOffset,
|
||
|
buffer,
|
||
|
bufferSize);
|
||
|
}
|
||
|
|
||
|
public static unsafe bool RegisterEvent(char * eventName,
|
||
|
char * eventDescription,
|
||
|
UIntPtr * eventHandle)
|
||
|
{
|
||
|
bool success;
|
||
|
UIntPtr handle = 0;
|
||
|
|
||
|
string name = new string(eventName);
|
||
|
string description = new string(eventDescription);
|
||
|
|
||
|
success = KernelControllerObject.RegisterEvent(name, description, ref handle);
|
||
|
|
||
|
*eventHandle = handle;
|
||
|
|
||
|
return success;
|
||
|
}
|
||
|
|
||
|
public static unsafe bool RegisterEventField(UIntPtr eventHandle,
|
||
|
char * fieldName,
|
||
|
UInt16 offset,
|
||
|
UInt16 type) {
|
||
|
|
||
|
string name = new string(fieldName);
|
||
|
|
||
|
return KernelControllerObject.RegisterEventField(eventHandle,
|
||
|
name,
|
||
|
offset,
|
||
|
type);
|
||
|
}
|
||
|
|
||
|
public static unsafe bool RegisterEventGenericField(UIntPtr eventHandle,
|
||
|
char * fieldName,
|
||
|
UInt16 offset,
|
||
|
UInt16 size,
|
||
|
UIntPtr fieldTypeHandle)
|
||
|
{
|
||
|
|
||
|
string name = new string(fieldName);
|
||
|
|
||
|
return KernelControllerObject.RegisterEventGenericField(eventHandle,
|
||
|
name,
|
||
|
offset,
|
||
|
size,
|
||
|
fieldTypeHandle);
|
||
|
}
|
||
|
|
||
|
public static unsafe bool RegisterEnum(char * enumName,
|
||
|
UInt16 type,
|
||
|
UIntPtr * eventHandle)
|
||
|
{
|
||
|
bool success;
|
||
|
UIntPtr handle = 0;
|
||
|
|
||
|
string name = new string(enumName);
|
||
|
|
||
|
success = KernelControllerObject.RegisterEnum(name, type, ref handle);
|
||
|
|
||
|
*eventHandle = handle;
|
||
|
|
||
|
return success;
|
||
|
}
|
||
|
|
||
|
public static unsafe bool RegisterEnumValue(UIntPtr eventHandle,
|
||
|
char * valueName,
|
||
|
UInt64 value,
|
||
|
byte flagChar)
|
||
|
{
|
||
|
|
||
|
string name = new string(valueName);
|
||
|
|
||
|
return KernelControllerObject.RegisterEnumValue(eventHandle,
|
||
|
name,
|
||
|
value,
|
||
|
flagChar);
|
||
|
}
|
||
|
|
||
|
public static unsafe UIntPtr WalkEventDescriptor(UIntPtr eventHandle,
|
||
|
UIntPtr currentField,
|
||
|
UInt16 * offset,
|
||
|
UInt16 * type,
|
||
|
char * bufferName,
|
||
|
UInt16 bufferSize )
|
||
|
{
|
||
|
return MemoryStorage.WalkEventDescriptorImpl(eventHandle,
|
||
|
currentField,
|
||
|
offset,
|
||
|
type,
|
||
|
bufferName,
|
||
|
bufferSize);
|
||
|
}
|
||
|
|
||
|
public static unsafe bool GetSourceInformation(UIntPtr sourceHandle,
|
||
|
UIntPtr * storageHandle,
|
||
|
UIntPtr * eventType,
|
||
|
UInt16 * count,
|
||
|
char * bufferName,
|
||
|
UInt16 bufferSize )
|
||
|
{
|
||
|
UIntPtr tmpStorageHandle = 0;
|
||
|
UIntPtr tmpEventType = 0;
|
||
|
UInt16 tmpCount = 0;
|
||
|
String name = "";
|
||
|
|
||
|
bool success = KernelControllerObject.GetSourceInformation(sourceHandle,
|
||
|
ref tmpStorageHandle,
|
||
|
ref tmpEventType,
|
||
|
ref tmpCount,
|
||
|
ref name);
|
||
|
|
||
|
if (success) {
|
||
|
|
||
|
*storageHandle = tmpStorageHandle;
|
||
|
*eventType = tmpEventType;
|
||
|
*count = tmpCount;
|
||
|
|
||
|
String.LimitedFormatTo(name, new ArgIterator(), bufferName, bufferSize);
|
||
|
}
|
||
|
|
||
|
return success;
|
||
|
}
|
||
|
|
||
|
public static unsafe int QuerySourcesList(UIntPtr * buffer, int size)
|
||
|
{
|
||
|
int returnValue = 0;
|
||
|
UIntPtr [] tmpBuffer = new UIntPtr[size];
|
||
|
|
||
|
if (tmpBuffer != null) {
|
||
|
|
||
|
returnValue = KernelControllerObject.QuerySourcesList(tmpBuffer, size);
|
||
|
|
||
|
if (returnValue < size) {
|
||
|
|
||
|
size = returnValue;
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < size; i++) {
|
||
|
|
||
|
buffer[i] = tmpBuffer[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
public static unsafe int QueryEventTypeList(UIntPtr * buffer, int size)
|
||
|
{
|
||
|
int returnValue = 0;
|
||
|
UIntPtr [] tmpBuffer = new UIntPtr[size];
|
||
|
|
||
|
if (tmpBuffer != null) {
|
||
|
|
||
|
returnValue = KernelControllerObject.QueryEventTypeList(tmpBuffer, size);
|
||
|
|
||
|
if (returnValue < size) {
|
||
|
|
||
|
size = returnValue;
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < size; i++) {
|
||
|
|
||
|
buffer[i] = tmpBuffer[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
static public bool TestKernelStorageImpl()
|
||
|
{
|
||
|
TestKernelLogging.TestAllCases();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// ABI calls
|
||
|
|
||
|
[AccessedByRuntime("output to header : defined in EventController.cpp")]
|
||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||
|
[StackBound(256)]
|
||
|
[NoHeapAllocation]
|
||
|
public static extern unsafe bool RegisterExternalController(UIntPtr controllerHandle, UIntPtr storageHandle);
|
||
|
|
||
|
[AccessedByRuntime("output to header : defined in EventController.cpp")]
|
||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||
|
[StackBound(256)]
|
||
|
[NoHeapAllocation]
|
||
|
public static extern unsafe void UnRegisterExternalController(UIntPtr controllerHandle, UIntPtr storageHandle);
|
||
|
|
||
|
[AccessedByRuntime("output to header : defined in EventController.cpp")]
|
||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||
|
[StackBound(512)]
|
||
|
[NoHeapAllocation]
|
||
|
public static extern unsafe bool DebugPrintLogEntry(UIntPtr controllerHandle, UIntPtr entryHandle);
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|