538 lines
16 KiB
C++
538 lines
16 KiB
C++
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Microsoft Research Singularity
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
// File: EventDescriptor.cpp
|
||
|
//
|
||
|
// Note: Kernel & Process
|
||
|
//
|
||
|
|
||
|
#include "hal.h"
|
||
|
#include "eventing.h"
|
||
|
|
||
|
#ifdef SINGULARITY_KERNEL
|
||
|
extern UIntPtr MonitoringTypeHandle;
|
||
|
extern UIntPtr TracingTypeHandle;
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#define _LOGGING_TO_REPOSITORY
|
||
|
|
||
|
#define DECLARE_STRUCTURE_BEGIN(x,d) UIntPtr Handle_##x;
|
||
|
#define DECLARE_ENUM_BEGIN(x,sz) UIntPtr Handle_##x;
|
||
|
|
||
|
#include "SystemEvents.inl"
|
||
|
|
||
|
#undef _LOGGING_TO_REPOSITORY
|
||
|
|
||
|
uint16 GetFieldSize(uint16 type)
|
||
|
{
|
||
|
if (type & EVENT_FIELD_TYPE_arrayType) {
|
||
|
|
||
|
return sizeof(uint16);
|
||
|
}
|
||
|
|
||
|
switch (type) {
|
||
|
|
||
|
case EVENT_FIELD_TYPE_int8:
|
||
|
case EVENT_FIELD_TYPE_uint8:
|
||
|
return sizeof(uint8);
|
||
|
|
||
|
case EVENT_FIELD_TYPE_int16:
|
||
|
case EVENT_FIELD_TYPE_uint16:
|
||
|
return sizeof(uint16);
|
||
|
|
||
|
case EVENT_FIELD_TYPE_int32:
|
||
|
case EVENT_FIELD_TYPE_uint32:
|
||
|
return sizeof(uint32);
|
||
|
|
||
|
case EVENT_FIELD_TYPE_int64:
|
||
|
case EVENT_FIELD_TYPE_uint64:
|
||
|
return sizeof(uint64);
|
||
|
|
||
|
case EVENT_FIELD_TYPE_IntPtr:
|
||
|
case EVENT_FIELD_TYPE_UIntPtr:
|
||
|
return sizeof(UIntPtr);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
uint16 GetFixedTypeSize(PEVENT_DESCRIPTOR typeEntry)
|
||
|
{
|
||
|
PEVENT_FIELD_DESCRIPTOR field;
|
||
|
uint16 size = 0;
|
||
|
|
||
|
for (field = typeEntry->fieldsLink; field != NULL; field = field->fieldsLink) {
|
||
|
|
||
|
uint16 fieldSize = GetFieldSize(field->Type);
|
||
|
|
||
|
if (size < (field->Offset + fieldSize)) {
|
||
|
|
||
|
size = field->Offset + fieldSize;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
char * GetExtendedString(UIntPtr EntryHandle, int index)
|
||
|
{
|
||
|
PMEMORY_HEADER entry = HANDLE_TO_HEADER(EntryHandle);
|
||
|
char * endPtr = (char *)(entry) + entry->Size;
|
||
|
|
||
|
int entrySize;
|
||
|
|
||
|
switch (entry->Flags) {
|
||
|
|
||
|
case RECORD_EVENT_TYPE:
|
||
|
entrySize = sizeof(EVENT_DESCRIPTOR);
|
||
|
break;
|
||
|
|
||
|
case RECORD_EVENT_FIELD:
|
||
|
entrySize = sizeof(EVENT_FIELD_DESCRIPTOR);
|
||
|
break;
|
||
|
|
||
|
case RECORD_EVENT_GENERIC_FIELD:
|
||
|
entrySize = sizeof(EVENT_GENERIC_TYPE_DESCRIPTOR);
|
||
|
break;
|
||
|
|
||
|
case RECORD_EVENT_VALUE:
|
||
|
entrySize = sizeof(EVENT_VALUE_DESCRIPTOR);
|
||
|
break;
|
||
|
|
||
|
case RECORD_EVENT_ENUM:
|
||
|
entrySize = sizeof(ENUM_DESCRIPTOR);
|
||
|
break;
|
||
|
|
||
|
default : {
|
||
|
|
||
|
PEVENT_DESCRIPTOR typeEntry = HANDLE_TO_TYPE(entry->Type);
|
||
|
entrySize = GetFixedTypeSize(typeEntry);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void * base = GetUserRecordStructure(entry);
|
||
|
|
||
|
char * crtPtr = (char *)base + entrySize;
|
||
|
|
||
|
crtPtr = (char *)ROUND_UP_TO_POWER2(crtPtr, sizeof(int));
|
||
|
if (crtPtr >= endPtr) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
for (int i = 1; i < index; i++) {
|
||
|
|
||
|
uint16 length;
|
||
|
|
||
|
// copy the structure localy since it may not be aligned.
|
||
|
|
||
|
memcpy(&length, crtPtr, sizeof(uint16));
|
||
|
crtPtr += length + sizeof(uint16);
|
||
|
if (crtPtr >= endPtr) {
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
char * ptr = crtPtr + sizeof(uint16); // skip also the size of the string
|
||
|
if (ptr >= endPtr) {
|
||
|
return NULL;
|
||
|
}
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// Shared routines to handle both unicode and ascii names for eventing
|
||
|
//
|
||
|
|
||
|
PMEMORY_HEADER
|
||
|
RegisterEventDescriptorImplementation(int stringType,
|
||
|
PVOID name,
|
||
|
uint16 nameLength,
|
||
|
PVOID description,
|
||
|
uint16 descriptionLength)
|
||
|
{
|
||
|
EVENT_DESCRIPTOR Event = {NULL, 0, 1, 2};
|
||
|
|
||
|
Struct_Microsoft_Singularity_Eventing_ArrayType array[] = {
|
||
|
{nameLength,
|
||
|
sizeof(char),
|
||
|
stringType,
|
||
|
name},
|
||
|
{descriptionLength,
|
||
|
sizeof(char),
|
||
|
stringType,
|
||
|
description}};
|
||
|
|
||
|
if (descriptionLength == 0) {
|
||
|
|
||
|
Event.Description = 0;
|
||
|
}
|
||
|
|
||
|
PMEMORY_HEADER Entry = InternalLogVariableRecord( true,
|
||
|
GetLocalRepositoryHandle(),
|
||
|
RECORD_EVENT_TYPE,
|
||
|
0,
|
||
|
&Event,
|
||
|
sizeof(Event),
|
||
|
(descriptionLength) ? 2 : 1,
|
||
|
array);
|
||
|
|
||
|
return Entry;
|
||
|
|
||
|
}
|
||
|
|
||
|
PMEMORY_HEADER
|
||
|
RegisterFieldDescriptorImplementation(int stringType,
|
||
|
PMEMORY_HEADER Descriptor,
|
||
|
PVOID name,
|
||
|
uint32 nameLength,
|
||
|
uint16 offset,
|
||
|
uint16 type )
|
||
|
{
|
||
|
PEVENT_DESCRIPTOR eventDescriptor = (PEVENT_DESCRIPTOR)GetUserRecordStructure(Descriptor);
|
||
|
int fieldSize = GetFieldSize(type);
|
||
|
|
||
|
if (offset == 0) {
|
||
|
|
||
|
offset = eventDescriptor->Size;
|
||
|
|
||
|
//
|
||
|
// Align naturaly the field
|
||
|
//
|
||
|
|
||
|
offset = (uint16)ROUND_UP_TO_POWER2(offset, fieldSize);
|
||
|
}
|
||
|
|
||
|
EV_ASSERT(offset == ROUND_UP_TO_POWER2(offset, fieldSize));
|
||
|
EV_ASSERT(offset >= eventDescriptor->Size);
|
||
|
|
||
|
EVENT_FIELD_DESCRIPTOR Field = {NULL, offset, type, NULL};
|
||
|
Struct_Microsoft_Singularity_Eventing_ArrayType array[] = {
|
||
|
{nameLength,
|
||
|
sizeof(char),
|
||
|
stringType,
|
||
|
name}};
|
||
|
|
||
|
PMEMORY_HEADER Entry = InternalLogVariableRecord( false,
|
||
|
GetLocalRepositoryHandle(),
|
||
|
RECORD_EVENT_FIELD,
|
||
|
(UIntPtr)Descriptor,
|
||
|
&Field,
|
||
|
sizeof(Field),
|
||
|
1,
|
||
|
array);
|
||
|
|
||
|
if (Entry != NULL) {
|
||
|
|
||
|
PEVENT_FIELD_DESCRIPTOR newField = (PEVENT_FIELD_DESCRIPTOR)GetUserRecordStructure(Entry);
|
||
|
|
||
|
newField->fieldsLink = eventDescriptor->fieldsLink;
|
||
|
eventDescriptor->fieldsLink = newField;
|
||
|
eventDescriptor->Size = offset + fieldSize;
|
||
|
|
||
|
CommitEventEntry(Entry);
|
||
|
}
|
||
|
|
||
|
return Entry;
|
||
|
}
|
||
|
|
||
|
PMEMORY_HEADER
|
||
|
RegisterGenericFieldDescriptorImplementation( int stringType,
|
||
|
PMEMORY_HEADER event,
|
||
|
PVOID name,
|
||
|
uint32 nameLength,
|
||
|
uint16 offset,
|
||
|
uint16 size,
|
||
|
UIntPtr typeFieldDescriptor)
|
||
|
{
|
||
|
PEVENT_DESCRIPTOR eventDescriptor = (PEVENT_DESCRIPTOR)GetUserRecordStructure(event);
|
||
|
|
||
|
if (offset == 0) {
|
||
|
|
||
|
offset = eventDescriptor->Size;
|
||
|
|
||
|
//
|
||
|
// Align naturaly the field
|
||
|
//
|
||
|
|
||
|
offset = (uint16)ROUND_UP_TO_POWER2(offset, size);
|
||
|
}
|
||
|
|
||
|
EV_ASSERT(offset == ROUND_UP_TO_POWER2(offset, size));
|
||
|
EV_ASSERT(offset >= eventDescriptor->Size);
|
||
|
|
||
|
EVENT_GENERIC_TYPE_DESCRIPTOR Field = {NULL,
|
||
|
offset,
|
||
|
GENERIC_TYPE_SIGNATURE,
|
||
|
size,
|
||
|
typeFieldDescriptor,
|
||
|
1};
|
||
|
|
||
|
Struct_Microsoft_Singularity_Eventing_ArrayType array[] = {
|
||
|
{nameLength,
|
||
|
sizeof(char),
|
||
|
stringType,
|
||
|
name}};
|
||
|
|
||
|
PMEMORY_HEADER Entry = InternalLogVariableRecord( false,
|
||
|
GetLocalRepositoryHandle(),
|
||
|
RECORD_EVENT_GENERIC_FIELD,
|
||
|
(UIntPtr)event,
|
||
|
&Field,
|
||
|
sizeof(Field),
|
||
|
1,
|
||
|
array);
|
||
|
|
||
|
if (Entry != NULL) {
|
||
|
|
||
|
PEVENT_FIELD_DESCRIPTOR newField = (PEVENT_FIELD_DESCRIPTOR)GetUserRecordStructure(Entry);
|
||
|
|
||
|
newField->fieldsLink = eventDescriptor->fieldsLink;
|
||
|
eventDescriptor->fieldsLink = newField;
|
||
|
eventDescriptor->Size = offset + size;
|
||
|
|
||
|
CommitEventEntry(Entry);
|
||
|
}
|
||
|
|
||
|
return Entry;
|
||
|
}
|
||
|
|
||
|
PMEMORY_HEADER
|
||
|
RegisterEnumDescriptorImplementation(int stringType,
|
||
|
PVOID name,
|
||
|
uint16 nameLength,
|
||
|
uint16 type)
|
||
|
{
|
||
|
ENUM_DESCRIPTOR Event = {NULL, type, 0, 1, 2};
|
||
|
|
||
|
Struct_Microsoft_Singularity_Eventing_ArrayType array[] = {
|
||
|
{nameLength,
|
||
|
sizeof(char),
|
||
|
stringType,
|
||
|
name}};
|
||
|
|
||
|
PMEMORY_HEADER Entry = InternalLogVariableRecord( true,
|
||
|
GetLocalRepositoryHandle(),
|
||
|
RECORD_EVENT_ENUM,
|
||
|
0,
|
||
|
&Event,
|
||
|
sizeof(Event),
|
||
|
1,
|
||
|
array);
|
||
|
|
||
|
return Entry;
|
||
|
|
||
|
}
|
||
|
|
||
|
PMEMORY_HEADER
|
||
|
RegisterValueDescriptorImplementation(int stringType,
|
||
|
PMEMORY_HEADER descriptor,
|
||
|
PVOID name,
|
||
|
uint32 nameLength,
|
||
|
uint64 value,
|
||
|
uint8 flagLetter)
|
||
|
{
|
||
|
EVENT_VALUE_DESCRIPTOR Field = {NULL, flagLetter, value, NULL };
|
||
|
|
||
|
Struct_Microsoft_Singularity_Eventing_ArrayType array[] = {
|
||
|
{nameLength,
|
||
|
sizeof(char),
|
||
|
stringType,
|
||
|
name}};
|
||
|
|
||
|
PMEMORY_HEADER Entry = InternalLogVariableRecord( false,
|
||
|
GetLocalRepositoryHandle(),
|
||
|
RECORD_EVENT_VALUE,
|
||
|
(UIntPtr)descriptor,
|
||
|
&Field,
|
||
|
sizeof(Field),
|
||
|
1,
|
||
|
array);
|
||
|
if (Entry != NULL) {
|
||
|
|
||
|
PENUM_DESCRIPTOR eventDescriptor = (PENUM_DESCRIPTOR)GetUserRecordStructure(descriptor);
|
||
|
PEVENT_VALUE_DESCRIPTOR newField = (PEVENT_VALUE_DESCRIPTOR)GetUserRecordStructure(Entry);
|
||
|
|
||
|
newField->fieldsLink = eventDescriptor->fieldsLink;
|
||
|
eventDescriptor->fieldsLink = newField;
|
||
|
|
||
|
if (flagLetter) {
|
||
|
|
||
|
eventDescriptor->FlagsMask |= value;
|
||
|
}
|
||
|
|
||
|
CommitEventEntry(Entry);
|
||
|
}
|
||
|
|
||
|
return Entry;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
PMEMORY_HEADER
|
||
|
RegisterEventDescriptor(PCHAR name,
|
||
|
uint16 nameLength,
|
||
|
PCHAR description,
|
||
|
uint16 descriptionLength)
|
||
|
{
|
||
|
return RegisterEventDescriptorImplementation(EVENT_FIELD_TYPE_szChar,
|
||
|
name,
|
||
|
nameLength,
|
||
|
description,
|
||
|
descriptionLength);
|
||
|
}
|
||
|
|
||
|
PMEMORY_HEADER
|
||
|
RegisterFieldDescriptor(PMEMORY_HEADER Descriptor,
|
||
|
PCHAR name,
|
||
|
uint32 nameLength,
|
||
|
uint16 offset,
|
||
|
uint16 type )
|
||
|
{
|
||
|
return RegisterFieldDescriptorImplementation(
|
||
|
EVENT_FIELD_TYPE_szChar,
|
||
|
Descriptor,
|
||
|
name,
|
||
|
nameLength,
|
||
|
offset,
|
||
|
type);
|
||
|
}
|
||
|
|
||
|
PMEMORY_HEADER
|
||
|
RegisterGenericFieldDescriptor(PMEMORY_HEADER event,
|
||
|
PCHAR name,
|
||
|
uint32 nameLength,
|
||
|
uint16 offset,
|
||
|
uint16 size,
|
||
|
UIntPtr typeFieldDescriptor)
|
||
|
{
|
||
|
return RegisterGenericFieldDescriptorImplementation( EVENT_FIELD_TYPE_szChar,
|
||
|
event,
|
||
|
name,
|
||
|
nameLength,
|
||
|
offset,
|
||
|
size,
|
||
|
typeFieldDescriptor);
|
||
|
}
|
||
|
|
||
|
PMEMORY_HEADER
|
||
|
RegisterEnumDescriptor(PCHAR name,
|
||
|
uint16 nameLength,
|
||
|
uint16 type)
|
||
|
{
|
||
|
return RegisterEnumDescriptorImplementation(EVENT_FIELD_TYPE_szChar,
|
||
|
name,
|
||
|
nameLength,
|
||
|
type);
|
||
|
}
|
||
|
|
||
|
PMEMORY_HEADER
|
||
|
RegisterValueDescriptor(PMEMORY_HEADER descriptor,
|
||
|
PCHAR name,
|
||
|
uint32 nameLength,
|
||
|
uint64 value,
|
||
|
uint8 flagLetter)
|
||
|
{
|
||
|
|
||
|
return RegisterValueDescriptorImplementation(EVENT_FIELD_TYPE_szChar,
|
||
|
descriptor,
|
||
|
name,
|
||
|
nameLength,
|
||
|
value,
|
||
|
flagLetter);
|
||
|
}
|
||
|
|
||
|
|
||
|
// Declare the system event structures
|
||
|
|
||
|
void
|
||
|
InitializeRegistrationSystem(void * buffer, size_t size)
|
||
|
{
|
||
|
|
||
|
// Create a bufffer which does not recycle memory
|
||
|
|
||
|
UIntPtr LocalStorageHandle = Class_Microsoft_Singularity_Eventing_MemoryStorage::
|
||
|
g_MemoryStorageCreateImpl(MEMORY_STORAGE_FLAGS_PERMANENT, (uint8 *)buffer, (uint32)size, 0);
|
||
|
|
||
|
RegisterRepositoryStorage(HANDLE_TO_STORAGE(LocalStorageHandle));
|
||
|
}
|
||
|
|
||
|
void
|
||
|
RegisterNativeTypes()
|
||
|
{
|
||
|
//
|
||
|
// Use this opportunity to validate the assumptions around the basic definition
|
||
|
// layouts
|
||
|
//
|
||
|
|
||
|
#define _VALIDATE_INVARIANTS
|
||
|
|
||
|
#define _LOGGING_TO_REPOSITORY
|
||
|
|
||
|
|
||
|
#define DECLARE_STRUCTURE_BEGIN(x,d) \
|
||
|
{ \
|
||
|
PMEMORY_HEADER __Event; \
|
||
|
__Event = RegisterEventDescriptor("System."#x, sizeof("System."#x) - 1, d, sizeof(d)); \
|
||
|
if (__Event != NULL) { \
|
||
|
PMEMORY_HEADER __Field; \
|
||
|
Handle_##x = (UIntPtr)__Event;
|
||
|
|
||
|
#define DECLARE_ENUM_BEGIN(x,t) \
|
||
|
{ \
|
||
|
PMEMORY_HEADER __Event; \
|
||
|
__Event = RegisterEnumDescriptor("System."#x, sizeof("System."#x) - 1, EVENT_FIELD_##t); \
|
||
|
if (__Event != NULL) { \
|
||
|
PMEMORY_HEADER __Field; \
|
||
|
Handle_##x = (UIntPtr)__Event;
|
||
|
|
||
|
#define DECLARE_STRUCTURE_END(x) }}
|
||
|
|
||
|
#define DECLARE_ENUM_END DECLARE_STRUCTURE_END
|
||
|
|
||
|
#define DECLARE_FIELD(s,t,n) \
|
||
|
__Field = RegisterFieldDescriptor(__Event, #n, sizeof(#n), offsetof(s, n), EVENT_FIELD_##t);
|
||
|
|
||
|
#define DECLARE_SPECIAL_FIELD(s,t,n) \
|
||
|
__Field = RegisterFieldDescriptor(__Event, #n, sizeof(#n), offsetof(s, n), \
|
||
|
EVENT_FIELD_TYPE_UIntPtr);
|
||
|
|
||
|
#define DECLARE_EXTENDED_ARRAY_FIELD(s,t,n) \
|
||
|
__Field = RegisterFieldDescriptor(__Event, #n, sizeof(#n), offsetof(s, n), \
|
||
|
EVENT_FIELD_TYPE_arrayType | EVENT_FIELD_##t);
|
||
|
|
||
|
#define DECLARE_VALUE(s,v,f,n) \
|
||
|
__Field = RegisterValueDescriptor(__Event, #n, sizeof(#n), v, f);
|
||
|
|
||
|
#define DECLARE_GENERIC_FIELD(s,t,sz,t1,n) \
|
||
|
__Field = RegisterGenericFieldDescriptor(__Event, #n, sizeof(#n), offsetof(s, n), sz, Handle_##t1);
|
||
|
|
||
|
#include "SystemEvents.inl"
|
||
|
|
||
|
#undef _LOGGING_TO_REPOSITORY
|
||
|
|
||
|
#ifdef SINGULARITY_KERNEL
|
||
|
|
||
|
//
|
||
|
// For apps, discard the use of handles that have been registered, since these shared
|
||
|
// events are going to use the system handles
|
||
|
//
|
||
|
|
||
|
MonitoringTypeHandle = Handle_MONITORING_ENTRY;
|
||
|
TracingTypeHandle = Handle_LEGACY_LOG_ENTRY;
|
||
|
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////// End of File.
|
||
|
|