#endif // STRESS_LOG
#define STRESS_LOG_READONLY
#include "../../../inc/stresslog.h"
+#include "StressMsgReader.h"
void GcHistClear();
-void GcHistAddLog(LPCSTR msg, StressMsg* stressMsg);
+void GcHistAddLog(LPCSTR msg, StressMsgReader stressMsg);
/*********************************************************************************/
for (const ThreadStressLog* ptr = this; ptr != NULL; ptr = ptr->next)
{
if (ptr->readPtr != NULL)
- if (latestLog == 0 || ptr->readPtr->GetTimeStamp() > latestLog->readPtr->GetTimeStamp())
+ if (latestLog == 0 || StressMsgReader(ptr->readPtr).GetTimeStamp() > StressMsgReader(latestLog->readPtr).GetTimeStamp())
latestLog = ptr;
}
return const_cast<ThreadStressLog*>(latestLog);
// TODO: fix on 64 bit
inProcPtr->Activate ();
- if (inProcPtr->readPtr->GetTimeStamp() > lastTimeStamp)
+ if (StressMsgReader(inProcPtr->readPtr).GetTimeStamp() > lastTimeStamp)
{
- lastTimeStamp = inProcPtr->readPtr->GetTimeStamp();
+ lastTimeStamp = StressMsgReader(inProcPtr->readPtr).GetTimeStamp();
}
outProcPtr = TO_CDADDR(inProcPtr->next);
break;
}
- StressMsg* latestMsg = latestLog->readPtr;
- if (latestMsg->GetFormatOffset() != 0 && !latestLog->CompletedDump())
+ StressMsgReader latestMsg = latestLog->readPtr;
+ if (latestMsg.GetFormatOffset() != 0 && !latestLog->CompletedDump())
{
- TADDR taFmt = (latestMsg->GetFormatOffset()) + TO_TADDR(g_hThisInst);
+ TADDR taFmt = (latestMsg.GetFormatOffset()) + TO_TADDR(g_hThisInst);
hr = memCallBack->ReadVirtual(TO_CDADDR(taFmt), format, 256, 0);
if (hr != S_OK)
strcpy_s(format, ARRAY_SIZE(format), "Could not read address of format string");
- double deltaTime = ((double) (latestMsg->GetTimeStamp() - inProcLog.startTimeStamp)) / inProcLog.tickFrequency;
+ double deltaTime = ((double) (latestMsg.GetTimeStamp() - inProcLog.startTimeStamp)) / inProcLog.tickFrequency;
if (bDoGcHist)
{
if (strcmp(format, ThreadStressLog::TaskSwitchMsg()) == 0)
{
- latestLog->threadId = (unsigned)(size_t)latestMsg->args[0];
+ latestLog->threadId = (unsigned)(size_t)latestMsg.GetArgs()[0];
}
GcHistAddLog(format, latestMsg);
}
{
if (strcmp(format, ThreadStressLog::TaskSwitchMsg()) == 0)
{
- fprintf (file, "Task was switched from %x\n", (unsigned)(size_t)latestMsg->args[0]);
- latestLog->threadId = (unsigned)(size_t)latestMsg->args[0];
+ fprintf (file, "Task was switched from %x\n", (unsigned)(size_t)latestMsg.GetArgs()[0]);
+ latestLog->threadId = (unsigned)(size_t)latestMsg.GetArgs()[0];
}
else
{
- args = latestMsg->args;
- formatOutput(memCallBack, file, format, (unsigned)latestLog->threadId, deltaTime, latestMsg->GetFacility(), args);
+ args = latestMsg.GetArgs();
+ formatOutput(memCallBack, file, format, (unsigned)latestLog->threadId, deltaTime, latestMsg.GetFacility(), args);
}
}
msgCtr++;
}
- latestLog->readPtr = latestLog->AdvanceRead(latestMsg->GetNumberOfArgs());
+ latestLog->readPtr = latestLog->AdvanceRead(latestMsg.GetNumberOfArgs());
if (latestLog->CompletedDump())
{
latestLog->readPtr = NULL;
#include <stddef.h>
#include "../../../inc/stresslog.h"
+#include "StressMsgReader.h"
size_t StressLog::writing_base_address;
size_t StressLog::reading_base_address;
{
}
-void GcHistAddLog(LPCSTR msg, StressMsg* stressMsg)
+void GcHistAddLog(LPCSTR msg, StressMsgReader stressMsg)
{
}
struct StressThreadAndMsg
{
uint64_t threadId;
- StressMsg* msg;
+ StressMsgReader msg;
uint64_t msgId;
};
const StressThreadAndMsg* msg1 = (const StressThreadAndMsg*)p1;
const StressThreadAndMsg* msg2 = (const StressThreadAndMsg*)p2;
- if (msg1->msg->GetTimeStamp() < msg2->msg->GetTimeStamp())
+ if (msg1->msg.GetTimeStamp() < msg2->msg.GetTimeStamp())
return 1;
- if (msg1->msg->GetTimeStamp() > msg2->msg->GetTimeStamp())
+ if (msg1->msg.GetTimeStamp() > msg2->msg.GetTimeStamp())
return -11;
if (msg1->threadId < msg2->threadId)
volatile LONG workStarted;
volatile LONG workFinished;
ThreadStressLog* tsl;
- StressMsg* earliestMessage;
+ StressMsgReader earliestMessage;
ThreadStressLogDesc() : workStarted(0), workFinished(0), tsl(nullptr), earliestMessage(nullptr)
{
static double s_timeFilterEnd = 0;
static const char* s_outputFileName = nullptr;
-static StressLog::StressLogHeader* s_hdr;
+StressLog::StressLogHeader* s_hdr;
static bool s_fPrintFormatStrings;
return true;
}
-static void IncludeMessage(uint64_t threadId, StressMsg* msg)
+static void IncludeMessage(uint64_t threadId, StressMsgReader msg)
{
LONGLONG msgCount = InterlockedIncrement64(&s_msgCount) - 1;
if (msgCount < MAX_MESSAGE_COUNT)
wrappedWriteThreadCount++;
}
// printf("thread: %zx\n", tsl->threadId);
- StressMsg* msg = StressLog::TranslateMemoryMappedPointer(tsl->curPtr);
+ void* msg = StressLog::TranslateMemoryMappedPointer(tsl->curPtr);
StressLogChunk* slc = StressLog::TranslateMemoryMappedPointer(tsl->curWriteChunk);
int chunkCount = 0;
- StressMsg* prevMsg = nullptr;
+ void* prevMsg = nullptr;
while (true)
{
// printf("stress log chunk %zx\n", (size_t)slc);
{
while (p < end && *p == 0)
p++;
- msg = (StressMsg*)p;
+ msg = (void*)p;
}
- StressMsg* endMsg = (StressMsg*)end;
+ void* endMsg = (void*)end;
while (msg < endMsg)
{
+ StressMsgReader msgReader(msg);
totalMsgCount++;
- char* format = (char*)(hdr->moduleImage + msg->GetFormatOffset());
- double deltaTime = ((double)(msg->GetTimeStamp() - hdr->startTimeStamp)) / hdr->tickFrequency;
+ char* format = (char*)(hdr->moduleImage + msgReader.GetFormatOffset());
+ double deltaTime = ((double)(msgReader.GetTimeStamp() - hdr->startTimeStamp)) / hdr->tickFrequency;
bool fIgnoreMessage = false;
if (fTimeFilter)
{
fIgnoreMessage = true;
}
}
- int numberOfArgs = msg->GetNumberOfArgs();
+ int numberOfArgs = msgReader.GetNumberOfArgs();
if (!fIgnoreMessage)
{
- bool fIncludeMessage = s_showAllMessages || FilterMessage(hdr, tsl, msg->GetFacility(), format, deltaTime, numberOfArgs, msg->args);
+ bool fIncludeMessage = s_showAllMessages || FilterMessage(hdr, tsl, msgReader.GetFacility(), format, deltaTime, numberOfArgs, msgReader.GetArgs());
if (!fIncludeMessage && s_valueFilterCount > 0)
{
for (int i = 0; i < numberOfArgs; i++)
{
for (int j = 0; j < s_valueFilterCount; j++)
{
- if (s_valueFilter[j].start <= (size_t)msg->args[i] && (size_t)msg->args[i] <= s_valueFilter[j].end)
+ if (s_valueFilter[j].start <= (size_t)msgReader.GetArgs()[i] && (size_t)msgReader.GetArgs()[i] <= s_valueFilter[j].end)
{
fIncludeMessage = true;
break;
}
}
prevMsg = msg;
- msg = (StressMsg*)&msg->args[numberOfArgs];
+ msg = (StressMsg*)&msgReader.GetArgs()[numberOfArgs];
}
if (slc == StressLog::TranslateMemoryMappedPointer(tsl->chunkListTail) && !tsl->writeHasWrapped)
break;
printf("%11.9f billion", n / 1000000000.0);
}
-static void PrintMessage(CorClrData& corClrData, FILE *outputFile, uint64_t threadId, StressMsg* msg)
+static void PrintMessage(CorClrData& corClrData, FILE *outputFile, uint64_t threadId, StressMsgReader msg)
{
void* argBuffer[StressMsg::maxArgCnt];
- char* format = (char*)(s_hdr->moduleImage + msg->GetFormatOffset());
- int numberOfArgs = msg->GetNumberOfArgs();
+ char* format = (char*)(s_hdr->moduleImage + msg.GetFormatOffset());
+ int numberOfArgs = msg.GetNumberOfArgs();
for (int i = 0; i < numberOfArgs; i++)
{
- argBuffer[i] = msg->args[i];
+ argBuffer[i] = msg.GetArgs()[i];
}
- double deltaTime = ((double)(msg->GetTimeStamp() - s_hdr->startTimeStamp)) / s_hdr->tickFrequency;
+ double deltaTime = ((double)(msg.GetTimeStamp() - s_hdr->startTimeStamp)) / s_hdr->tickFrequency;
if (!s_printHexTidForGcThreads)
{
GcThread gcThread;
threadId |= 0x4000000000000000;
}
}
- formatOutput(&corClrData, outputFile, format, threadId, deltaTime, msg->GetFacility(), argBuffer, s_fPrintFormatStrings);
+ formatOutput(&corClrData, outputFile, format, threadId, deltaTime, msg.GetFacility(), argBuffer, s_fPrintFormatStrings);
}
int ProcessStressLog(void* baseAddress, int argc, char* argv[])
StressLog::StressLogHeader* hdr = (StressLog::StressLogHeader*)baseAddress;
if (hdr->headerSize != sizeof(*hdr) ||
hdr->magic != *(uint32_t*)"LRTS" ||
- hdr->version != 0x00010001)
+ (hdr->version != 0x00010001 &&
+ hdr->version != 0x00010002))
{
printf("Unrecognized file format\n");
return 1;
int remMsgCount = 0;
for (int msgIndex = 0; msgIndex < s_msgCount; msgIndex++)
{
- StressMsg* msg = s_threadMsgBuf[msgIndex].msg;
- double deltaTime = ((double)(msg->GetTimeStamp() - hdr->startTimeStamp)) / hdr->tickFrequency;
+ StressMsgReader msg = s_threadMsgBuf[msgIndex].msg;
+ double deltaTime = ((double)(msg.GetTimeStamp() - hdr->startTimeStamp)) / hdr->tickFrequency;
if (startTime <= deltaTime && deltaTime <= endTime)
{
s_threadMsgBuf[remMsgCount] = s_threadMsgBuf[msgIndex];
for (LONGLONG i = 0; i < s_msgCount; i++)
{
uint64_t threadId = (unsigned)s_threadMsgBuf[i].threadId;
- StressMsg* msg = s_threadMsgBuf[i].msg;
+ StressMsgReader msg = s_threadMsgBuf[i].msg;
PrintMessage(corClrData, outputFile, threadId, msg);
}
LONGLONG earliestStartCount = s_msgCount;
for (int threadStressLogIndex = 0; threadStressLogIndex < s_threadStressLogCount; threadStressLogIndex++)
{
- StressMsg* msg = s_threadStressLogDesc[threadStressLogIndex].earliestMessage;
+ StressMsgReader msg = s_threadStressLogDesc[threadStressLogIndex].earliestMessage;
if (msg == nullptr)
continue;
bool fIncludeMessage = s_printEarliestMessages;
for (LONGLONG i = earliestStartCount; i < s_msgCount; i++)
{
uint64_t threadId = (unsigned)s_threadMsgBuf[i].threadId;
- StressMsg* msg = s_threadMsgBuf[i].msg;
+ StressMsgReader msg = s_threadMsgBuf[i].msg;
PrintMessage(corClrData, outputFile, threadId, msg);
}
}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#include <stdint.h>
+
+extern StressLog::StressLogHeader* s_hdr;
+
+// A version-aware reader for memory-mapped stress log messages.
+struct StressMsgReader
+{
+private:
+ struct StressMsgSmallOffset
+ {
+ uint32_t numberOfArgsLow : 3; // at most 7 arguments here
+ uint32_t formatOffset : 26; // low bits offset of format string in modules
+ uint32_t numberOfArgsHigh : 3; // extend number of args in a backward compat way
+ uint32_t facility; // facility used to log the entry
+ uint64_t timeStamp; // time when mssg was logged
+ void* args[0]; // variable number of arguments
+ };
+
+ void* m_rawMsg;
+public:
+ StressMsgReader() = default;
+
+ StressMsgReader(void* msg)
+ :m_rawMsg(msg)
+ {
+ }
+
+ uint64_t GetFormatOffset() const
+ {
+ if (s_hdr->version == 0x00010001)
+ {
+ return ((StressMsgSmallOffset*)m_rawMsg)->formatOffset;
+ }
+ return ((StressMsg*)m_rawMsg)->GetFormatOffset();
+ }
+
+ uint32_t GetNumberOfArgs() const
+ {
+ if (s_hdr->version == 0x00010001)
+ {
+ return ((StressMsgSmallOffset*)m_rawMsg)->numberOfArgsHigh << 3 | ((StressMsgSmallOffset*)m_rawMsg)->numberOfArgsLow;
+ }
+ return ((StressMsg*)m_rawMsg)->GetNumberOfArgs();
+ }
+
+ uint32_t GetFacility() const
+ {
+ if (s_hdr->version == 0x00010001)
+ {
+ return ((StressMsgSmallOffset*)m_rawMsg)->facility;
+ }
+ return ((StressMsg*)m_rawMsg)->GetFacility();
+ }
+
+ uint64_t GetTimeStamp() const
+ {
+ if (s_hdr->version == 0x00010001)
+ {
+ return ((StressMsgSmallOffset*)m_rawMsg)->timeStamp;
+ }
+ return ((StressMsg*)m_rawMsg)->GetTimeStamp();
+ }
+
+ void** GetArgs() const
+ {
+ if (s_hdr->version == 0x00010001)
+ {
+ return ((StressMsgSmallOffset*)m_rawMsg)->args;
+ }
+ return ((StressMsg*)m_rawMsg)->args;
+ }
+
+ bool operator==(std::nullptr_t) const
+ {
+ return m_rawMsg == nullptr;
+ }
+};