singrdk/base/Kernel/Native/EventingKernel.cpp

432 lines
12 KiB
C++

////////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: EventController.cpp
//
// Note: Kernel & Process
//
#include "hal.h"
#include "eventing.h"
extern SOURCE_CONTROLLER SourceController;
#include "csformat.inc"
extern int strformat(void (*pfOutput)(void *pContext, char c), void *pContext,
const char * pszFmt, va_list args);
struct SNPRINT_CONTEXT {
char ** CrtPos;
char * EndBuffer;
};
static void snprintfout(void *pContext, char c)
{
SNPRINT_CONTEXT * context = (SNPRINT_CONTEXT *)pContext;
if (*(context->CrtPos) < context->EndBuffer) {
*(*context->CrtPos)++ = c;
}
}
int snprintf(char *pszOut, int outSize, const char *pszFmt, ...)
{
int nOut;
va_list args;
SNPRINT_CONTEXT context = {&pszOut, pszOut + outSize - 1};
va_start(args, pszFmt);
nOut = strformat(snprintfout, &context, pszFmt, args);
va_end(args);
*pszOut = '\0';
return nOut;
}
extern void kdprints(const char * pszFmt);
PEVENT_FIELD_DESCRIPTOR GetDescriptorField(PEVENT_DESCRIPTOR typeEntry, int fieldIndex)
{
PEVENT_FIELD_DESCRIPTOR field;
//
// TODO: This needs to be optimized caching the total number of fields
//
int numFields = 0;
for (field = typeEntry->fieldsLink; (field != NULL); field = field->fieldsLink) {
numFields++;
}
fieldIndex = numFields - fieldIndex - 1;
for (field = typeEntry->fieldsLink; (field != NULL) && (fieldIndex > 0); field = field->fieldsLink) {
fieldIndex--;
}
return field;
}
PEVENT_FIELD_DESCRIPTOR FindFieldDescriptor(PEVENT_DESCRIPTOR typeEntry, int offset)
{
PEVENT_FIELD_DESCRIPTOR field;
for (field = typeEntry->fieldsLink; field != NULL; field = field->fieldsLink) {
if (field->Offset == offset) {
return field;
}
}
return NULL;
}
uint64 ReadValueAs(void * baseAddress, int offset, int type)
{
void * memLocation = (char *)baseAddress + offset;
if (type & EVENT_FIELD_TYPE_arrayType) {
return *(uint16 *)memLocation;
}
switch (type) {
case EVENT_FIELD_TYPE_int8:
case EVENT_FIELD_TYPE_uint8:
return *(uint8 *)memLocation;
case EVENT_FIELD_TYPE_int16:
case EVENT_FIELD_TYPE_uint16:
return *(uint16 *)memLocation;
case EVENT_FIELD_TYPE_int32:
case EVENT_FIELD_TYPE_uint32:
return *(uint32 *)memLocation;
case EVENT_FIELD_TYPE_int64:
case EVENT_FIELD_TYPE_uint64:
return *(uint64 *)memLocation;
case EVENT_FIELD_TYPE_IntPtr:
case EVENT_FIELD_TYPE_UIntPtr:
return (uint64)(*(UIntPtr *)memLocation);
}
return 0;
}
uint64 GetFieldValue(UIntPtr EntryHandle, int fieldIndex)
{
PMEMORY_HEADER entry = HANDLE_TO_HEADER(EntryHandle);
PEVENT_DESCRIPTOR typeEntry = HANDLE_TO_TYPE(entry->Type);
PEVENT_FIELD_DESCRIPTOR field = GetDescriptorField(typeEntry, fieldIndex);
void * base = GetUserRecordStructure(entry);
if (field != NULL) {
return ReadValueAs(GetUserRecordStructure(entry), field->Offset, field->Type);
}
return 0;
}
struct PRINT_EVENT_CONTEXT {
UIntPtr EntryHandle;
int ArgOffset;
};
int WriteSymbolicValue(char *pszOut, int bufferSize, PENUM_DESCRIPTOR enumDescriptor, uint64 value)
{
PEVENT_VALUE_DESCRIPTOR field;
int retValue = 0;
uint64 flags = value & enumDescriptor->FlagsMask;
uint64 item = value & ~enumDescriptor->FlagsMask;
for (field = enumDescriptor->fieldsLink; field != NULL; field = field->fieldsLink) {
int ret = 0;
if ((field->FlagLetter != 0)) {
//
// This needs to be elaborated further with using a string for the false case too
//
char symbol = ((field->Value & flags) == field->Value) ? field->FlagLetter : '.';
ret = snprintf(pszOut, bufferSize, "%c", symbol);
} else if (field->Value == item) {
char * strValue = GetExtendedString((UIntPtr)((PMEMORY_HEADER)field - 1), 1);
ret = snprintf(pszOut, bufferSize, "%s", strValue);
}
//
// Advance the output buffer, updating the current number of bytes written
//
retValue += ret;
pszOut += ret;
bufferSize -= ret;
}
return retValue;
}
char * GetStringField(void * context, int argIdx)
{
PRINT_EVENT_CONTEXT * eventContext = (PRINT_EVENT_CONTEXT*) context;
argIdx += eventContext->ArgOffset;
PMEMORY_HEADER entry = HANDLE_TO_HEADER(eventContext->EntryHandle);
PEVENT_DESCRIPTOR typeEntry = HANDLE_TO_TYPE(entry->Type);
PEVENT_FIELD_DESCRIPTOR field = GetDescriptorField(typeEntry, argIdx);
if (field->Type & (Class_Microsoft_Singularity_Eventing_DataType___string |
Class_Microsoft_Singularity_Eventing_DataType___szChar)) {
int extendedIndex = (int)GetFieldValue(eventContext->EntryHandle, argIdx);
if (extendedIndex > 0) {
char * str = GetExtendedString(eventContext->EntryHandle, extendedIndex);
//
// From this point all formating is relative to this string
//
eventContext->ArgOffset = argIdx + 1;
return str;
}
}
return NULL;
}
int PrintEventField(void * context, char *pszOut, int bufferSize, int aln, int wid, char fmt, int argIdx)
{
PRINT_EVENT_CONTEXT * eventContext = (PRINT_EVENT_CONTEXT*) context;
argIdx += eventContext->ArgOffset;
PMEMORY_HEADER entry = HANDLE_TO_HEADER(eventContext->EntryHandle);
PEVENT_DESCRIPTOR typeEntry = HANDLE_TO_TYPE(entry->Type);
PEVENT_FIELD_DESCRIPTOR field = GetDescriptorField(typeEntry, argIdx);
if (field == NULL) return 0;
int retValue = 0;
char * str = NULL;
if (field->Type == GENERIC_TYPE_SIGNATURE) {
//
// This might be a nested structure or an enum. The process of retrieving the
// actual value becomes a bit more complicated. The existing entry will be placed
// at a known offset in the parent structure, but we cannot interpret the value unless
// we find out the descriptor for this field.
//
if (((PMEMORY_HEADER)field - 1)->Flags == RECORD_EVENT_GENERIC_FIELD) {
//
// After validating the descriptor version agains the nested type, we can safely
// cast to a generic field
//
PEVENT_GENERIC_TYPE_DESCRIPTOR genericType = (PEVENT_GENERIC_TYPE_DESCRIPTOR)field;
UIntPtr typeHandle = genericType->GenericTypeHandle;
PEVENT_DESCRIPTOR descriptor = (PEVENT_DESCRIPTOR)GetUserRecordStructure(HANDLE_TO_HEADER(typeHandle));
if (((PMEMORY_HEADER)descriptor - 1)->Flags == RECORD_EVENT_ENUM) {
//
// The field is an enum. Handle here the symbolic
//
PENUM_DESCRIPTOR enumDescriptor = (PENUM_DESCRIPTOR)descriptor;
uint16 valueBasicType = enumDescriptor->Type;
uint64 value = ReadValueAs(GetUserRecordStructure(entry), field->Offset, valueBasicType);
retValue = WriteSymbolicValue(pszOut, bufferSize, enumDescriptor, value);
} else {
retValue = snprintf(pszOut, bufferSize, "(unsupported field)");
}
} else {
retValue = snprintf(pszOut, bufferSize, "(unknown)");
}
} else if (field->Type &
(Class_Microsoft_Singularity_Eventing_DataType___string |
Class_Microsoft_Singularity_Eventing_DataType___szChar)) {
int extendedIndex = (int)GetFieldValue(eventContext->EntryHandle, argIdx);
if (extendedIndex > 0) {
char * str = GetExtendedString(eventContext->EntryHandle, extendedIndex);
if (str != NULL) {
retValue = snprintf(pszOut, bufferSize, "%s", str);
} else {
retValue = snprintf(pszOut, bufferSize, "(invalid string index)");
}
}
} else {
uint64 value = GetFieldValue(eventContext->EntryHandle, argIdx);
if (aln < wid) {
aln = wid;
}
if (fmt == 'x') {
if (wid > 0) {
retValue = snprintf(pszOut, bufferSize, "%0x", value);
}
else {
retValue = snprintf(pszOut, bufferSize, "%x", value);
}
}
else {
retValue = snprintf(pszOut, bufferSize, "%d", value);
}
}
return retValue;
}
void DebugPrintEvent(UIntPtr eventHandle)
{
char msg[256];
PRINT_EVENT_CONTEXT printContext = {eventHandle, 0};
PMEMORY_HEADER entry = HANDLE_TO_HEADER(eventHandle);
char * frmt = GetExtendedString(entry->Type, 2);
if (frmt != NULL) {
FormatCSOutput(&printContext, frmt, msg, sizeof(msg),PrintEventField, GetStringField);
}
bartok_char wmsg[256];
int lMsg = strlen(msg);
if (lMsg < (sizeof(msg) - 1)) {
msg[lMsg] = '\n';
lMsg += 1;
msg[lMsg] = 0;
}
for (int i = 0; i < lMsg; i++) {
wmsg[i] = msg[i];
}
Class_Microsoft_Singularity_DebugStub::g_Print(wmsg, lMsg);
//kdprints(msg);
}
bool Class_Microsoft_Singularity_Eventing_KernelController::
g_DebugPrintLogEntry(UIntPtr controllerHandle, UIntPtr entryHandle)
{
//
// TODO: Handle the paging case with apporpriate access as
//
DebugPrintEvent(entryHandle);
return true;
}
bool Class_Microsoft_Singularity_Eventing_KernelController::
g_RegisterExternalController(UIntPtr storageHandle, UIntPtr contextHandle)
{
// The external caller is responsible with the synchronization
EXTERNAL_CONTROLLER_DESCRIPTOR source = {NULL, storageHandle, contextHandle};
if (SourceController.FreeControllerList != NULL) {
PEXTERNAL_CONTROLLER_DESCRIPTOR controller = SourceController.FreeControllerList;
SourceController.FreeControllerList = controller->Link;
*controller = source;
RegisterExternalController(controller);
} else {
PMEMORY_HEADER Entry = InternalLogFixedRecord( GetLocalRepositoryHandle(),
RECORD_EVENT_CONTROLLER,
0,
&source,
sizeof(source));
if (Entry == NULL) {
return false;
}
PEXTERNAL_CONTROLLER_DESCRIPTOR newSource = (PEXTERNAL_CONTROLLER_DESCRIPTOR)GetUserRecordStructure(Entry);
RegisterExternalController(newSource);
}
return true;
}
void Class_Microsoft_Singularity_Eventing_KernelController::
g_UnRegisterExternalController(UIntPtr controllerHandle, UIntPtr contextHandle)
{
// Note the caller of this function needs to assure mutual exclusion
PEXTERNAL_CONTROLLER_DESCRIPTOR tmpController = SourceController.ExternalControllers;
for (tmpController = SourceController.ExternalControllers;
tmpController != NULL;
tmpController = tmpController->Link) {
if ((tmpController->ContextHandle == contextHandle) &&
(tmpController->ControllerHandle == controllerHandle)){
UnRegisterExternalController(tmpController);
return;
}
}
}
//
///////////////////////////////////////////////////////////////// End of File.