diff options
Diffstat (limited to 'src/vm/eventpipebuffermanager.h')
-rw-r--r-- | src/vm/eventpipebuffermanager.h | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/src/vm/eventpipebuffermanager.h b/src/vm/eventpipebuffermanager.h new file mode 100644 index 0000000000..a53721b7b8 --- /dev/null +++ b/src/vm/eventpipebuffermanager.h @@ -0,0 +1,161 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef __EVENTPIPE_BUFFERMANAGER_H__ +#define __EVENTPIPE_BUFFERMANAGER_H__ + +#ifdef FEATURE_PERFTRACING + +#include "eventpipefile.h" +#include "eventpipebuffer.h" +#include "spinlock.h" + +class EventPipeBufferList; + +class EventPipeBufferManager +{ + + // Declare friends. + friend class EventPipeBufferList; + +private: + + // A list of linked-lists of buffer objects. + // Each entry in this list represents a set of buffers owned by a single thread. + // The actual Thread object has a pointer to the object contained in this list. This ensures that + // each thread can access its own list, while at the same time, ensuring that when + // a thread is destroyed, we keep the buffers around without having to perform any + // migration or book-keeping. + SList<SListElem<EventPipeBufferList*>> *m_pPerThreadBufferList; + + // The total allocation size of buffers under management. + size_t m_sizeOfAllBuffers; + + // Lock to protect access to the per-thread buffer list and total allocation size. + SpinLock m_lock; + +#ifdef _DEBUG + // For debugging purposes. + unsigned int m_numBuffersAllocated; + unsigned int m_numBuffersStolen; + unsigned int m_numBuffersLeaked; + Volatile<LONG> m_numEventsStored; + LONG m_numEventsWritten; +#endif // _DEBUG + + // Allocate a new buffer for the specified thread. + // This function will store the buffer in the thread's buffer list for future use and also return it here. + // A NULL return value means that a buffer could not be allocated. + EventPipeBuffer* AllocateBufferForThread(Thread *pThread, unsigned int requestSize); + + // Add a buffer to the thread buffer list. + void AddBufferToThreadBufferList(EventPipeBufferList *pThreadBuffers, EventPipeBuffer *pBuffer); + + // Find the thread that owns the oldest buffer that is eligible to be stolen. + EventPipeBufferList* FindThreadToStealFrom(); + + // De-allocates the input buffer. + void DeAllocateBuffer(EventPipeBuffer *pBuffer); + +public: + + EventPipeBufferManager(); + + // Write an event to the input thread's current event buffer. + // An optional eventThread can be provided for sample profiler events. + // This is because the thread that writes the events is not the same as the "event thread". + // An optional stack trace can be provided for sample profiler events. + // Otherwise, if a stack trace is needed, one will be automatically collected. + bool WriteEvent(Thread *pThread, EventPipeEvent &event, BYTE *pData, unsigned int length, LPCGUID pActivityId, LPCGUID pRelatedActivityId, Thread *pEventThread = NULL, StackContents *pStack = NULL); + + // Write the contents of the managed buffers to the specified file. + // The stopTimeStamp is used to determine when tracing was stopped to ensure that we + // skip any events that might be partially written due to races when tracing is stopped. + void WriteAllBuffersToFile(EventPipeFile *pFile, LARGE_INTEGER stopTimeStamp); + + // Attempt to de-allocate resources as best we can. It is possible for some buffers to leak because + // threads can be in the middle of a write operation and get blocked, and we may not get an opportunity + // to free their buffer for a very long time. + void DeAllocateBuffers(); + +#ifdef _DEBUG + bool EnsureConsistency(); +#endif // _DEBUG +}; + +// Represents a list of buffers associated with a specific thread. +class EventPipeBufferList +{ +private: + + // The buffer manager that owns this list. + EventPipeBufferManager *m_pManager; + + // Buffers are stored in an intrusive linked-list from oldest to newest. + // Head is the oldest buffer. Tail is the newest (and currently used) buffer. + EventPipeBuffer *m_pHeadBuffer; + EventPipeBuffer *m_pTailBuffer; + + // The number of buffers in the list. + unsigned int m_bufferCount; + + // The current read buffer (used when processing events on tracing stop). + EventPipeBuffer *m_pReadBuffer; + + // True if this thread is owned by a thread. + // If it is false, then this buffer can be de-allocated after it is drained. + Volatile<bool> m_ownedByThread; + +#ifdef _DEBUG + // For diagnostics, keep the thread pointer. + Thread *m_pCreatingThread; +#endif // _DEBUG + +public: + + EventPipeBufferList(EventPipeBufferManager *pManager); + + // Get the head node of the list. + EventPipeBuffer* GetHead(); + + // Get the tail node of the list. + EventPipeBuffer* GetTail(); + + // Insert a new buffer at the tail of the list. + void InsertTail(EventPipeBuffer *pBuffer); + + // Remove the head node of the list. + EventPipeBuffer* GetAndRemoveHead(); + + // Get the count of buffers in the list. + unsigned int GetCount() const; + + // Get the next event as long as it is before the specified timestamp. + EventPipeEventInstance* PeekNextEvent(LARGE_INTEGER beforeTimeStamp, EventPipeBuffer **pContainingBuffer); + + // Get the next event as long as it is before the specified timestamp, and also mark it as read. + EventPipeEventInstance* PopNextEvent(LARGE_INTEGER beforeTimeStamp); + + // True if a thread owns this list. + bool OwnedByThread(); + + // Set whether or not this list is owned by a thread. + // If it is not owned by a thread, then it can be de-allocated + // after the buffer is drained. + // The default value is true. + void SetOwnedByThread(bool value); + +#ifdef _DEBUG + // Get the thread associated with this list. + Thread* GetThread(); + + // Validate the consistency of the list. + // This function will assert if the list is in an inconsistent state. + bool EnsureConsistency(); +#endif // _DEBUG +}; + +#endif // FEATURE_PERFTRACING + +#endif // __EVENTPIPE_BUFFERMANAGER_H__ |