2019-10-11 17:43:21 -07:00
|
|
|
|
2019-10-14 23:34:12 -07:00
|
|
|
#include "efifeatures.h"
|
2019-10-11 17:43:21 -07:00
|
|
|
#include "perf_trace.h"
|
|
|
|
#include "efitime.h"
|
|
|
|
#include "os_util.h"
|
|
|
|
|
2019-11-19 17:36:47 -08:00
|
|
|
|
|
|
|
#ifndef TRACE_BUFFER_LENGTH
|
2019-10-14 23:34:12 -07:00
|
|
|
#define TRACE_BUFFER_LENGTH 2048
|
2019-11-19 17:36:47 -08:00
|
|
|
#endif /* TRACE_BUFFER_LENGTH */
|
2019-10-11 17:43:21 -07:00
|
|
|
|
2019-10-14 23:34:12 -07:00
|
|
|
enum class EPhase : char
|
2019-10-11 17:43:21 -07:00
|
|
|
{
|
|
|
|
Start,
|
|
|
|
End,
|
|
|
|
InstantThread,
|
|
|
|
InstantGlobal,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct TraceEntry
|
|
|
|
{
|
|
|
|
PE Event;
|
2019-10-14 23:34:12 -07:00
|
|
|
EPhase Phase;
|
2019-10-11 17:43:21 -07:00
|
|
|
uint8_t Data;
|
|
|
|
uint8_t ThreadId;
|
|
|
|
uint32_t Timestamp;
|
|
|
|
};
|
|
|
|
|
|
|
|
static_assert(sizeof(TraceEntry) == 8);
|
|
|
|
|
|
|
|
static TraceEntry s_traceBuffer[TRACE_BUFFER_LENGTH];
|
|
|
|
static size_t s_nextIdx = 0;
|
|
|
|
|
2019-10-14 23:34:12 -07:00
|
|
|
static bool s_isTracing = true;
|
|
|
|
|
|
|
|
void perfEventImpl(PE event, EPhase phase, uint8_t data)
|
2019-10-11 17:43:21 -07:00
|
|
|
{
|
2019-10-14 23:34:12 -07:00
|
|
|
if constexpr (!ENABLE_PERF_TRACE) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!s_isTracing) {
|
2019-10-11 17:43:21 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t timestamp = getTimeNowLowerNt();
|
|
|
|
|
|
|
|
size_t idx;
|
|
|
|
|
|
|
|
// Critical section: reserve index under lock
|
|
|
|
{
|
|
|
|
bool wasLocked = lockAnyContext();
|
|
|
|
|
|
|
|
idx = s_nextIdx++;
|
2019-10-14 23:34:12 -07:00
|
|
|
if (s_nextIdx >= TRACE_BUFFER_LENGTH) {
|
2019-10-11 17:43:21 -07:00
|
|
|
s_nextIdx = 0;
|
2019-10-14 23:34:12 -07:00
|
|
|
s_isTracing = false;
|
2019-10-11 17:43:21 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!wasLocked) {
|
|
|
|
unlockAnyContext();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// We can safely write data out of the lock, our spot is reserved
|
2019-10-14 23:34:12 -07:00
|
|
|
volatile TraceEntry& entry = s_traceBuffer[idx];
|
2019-10-11 17:43:21 -07:00
|
|
|
|
|
|
|
entry.Event = event;
|
2019-10-14 23:34:12 -07:00
|
|
|
entry.Phase = phase;
|
|
|
|
entry.ThreadId = static_cast<uint8_t>(SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk);
|
2019-10-11 17:43:21 -07:00
|
|
|
entry.Timestamp = timestamp;
|
|
|
|
entry.Data = data;
|
|
|
|
}
|
|
|
|
|
2019-10-14 23:34:12 -07:00
|
|
|
void perfEventBegin(PE event, uint8_t data) {
|
|
|
|
perfEventImpl(event, EPhase::Start, data);
|
2019-10-11 17:43:21 -07:00
|
|
|
}
|
|
|
|
|
2019-10-14 23:34:12 -07:00
|
|
|
void perfEventEnd(PE event, uint8_t data) {
|
|
|
|
perfEventImpl(event, EPhase::End, data);
|
2019-10-11 17:43:21 -07:00
|
|
|
}
|
|
|
|
|
2019-10-14 23:34:12 -07:00
|
|
|
void perfEventInstantGlobal(PE event, uint8_t data) {
|
|
|
|
perfEventImpl(event, EPhase::InstantGlobal, data);
|
2019-10-11 17:43:21 -07:00
|
|
|
}
|
|
|
|
|
2019-10-14 23:40:51 -07:00
|
|
|
void perfTraceEnable() {
|
2019-10-14 23:34:12 -07:00
|
|
|
s_isTracing = true;
|
|
|
|
}
|
|
|
|
|
2019-10-14 23:40:51 -07:00
|
|
|
const TraceBufferResult perfTraceGetBuffer() {
|
|
|
|
// stop tracing if you try to get the buffer early
|
|
|
|
s_isTracing = false;
|
|
|
|
|
|
|
|
return {reinterpret_cast<const uint8_t*>(s_traceBuffer), sizeof(s_traceBuffer)};
|
2019-10-11 17:43:21 -07:00
|
|
|
}
|