//////////////////////////////////////////////////////////////////////////////// // // 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.