4coder/4ed_internal.h

189 lines
5.1 KiB
C

/*
* Mr. 4th Dimention - Allen Webster
*
* 16.05.2015
*
* Fascilities available for development but not intended for shipping.
*
*/
/*
* Profiling
*/
#if FRED_INTERNAL == 1
enum Debug_Event_Type{
DBGEV_START,
DBGEV_END,
DBGEV_MOMENT,
// never below this
DBGEV_COUNT
};
struct Debug_Event{
i64 time;
char *name;
Debug_Event_Type type;
i32 which_hit;
i32 event_index;
i32 thread_index;
};
struct Debug_Event_Array{
volatile u32 count;
Debug_Event e[512];
};
struct Profile_Frame{
Debug_Event_Array events;
i32 dbg_procing_start;
i32 dbg_procing_end;
i32 index;
i32 first_key;
};
Profile_Frame profile_frame;
#define PAST_PROFILE_COUNT 30
Profile_Frame past_frames[PAST_PROFILE_COUNT];
extern const i32 INTERNAL_event_index_count;
extern u32 INTERNAL_event_hits[];
i64 INTERNAL_frame_start_time;
bool32 INTERNAL_collecting_events;
inline u32
post_debug_event(char *name, Debug_Event_Type type, i32 event_index, i32 thread_index, u32 which_hit){
u32 result = 0;
if (INTERNAL_collecting_events){
u32 index =
InterlockedIncrement(&profile_frame.events.count);
--index;
Assert(index < ArrayCount(profile_frame.events.e));
Debug_Event ev;
ev.time = system_time() - INTERNAL_frame_start_time;
ev.name = name;
ev.type = type;
ev.event_index = event_index;
ev.thread_index = thread_index;
if (type == DBGEV_END){
ev.which_hit = which_hit;
}
else{
ev.which_hit = InterlockedIncrement(INTERNAL_event_hits + event_index) - 1;
}
profile_frame.events.e[index] = ev;
result = ev.which_hit;
}
return result;
}
internal u32
quick_partition(Debug_Event *es, u32 start, u32 pivot){
Debug_Event *p = es + pivot;
i32 m = (start + pivot) >> 1;
Swap(*p, es[m]);
i32 pn = p->thread_index;
i32 pe = p->event_index;
i32 ph = p->which_hit;
i32 pt = p->type;
for (u32 i = start; i < pivot; ++i){
Debug_Event *e = es + i;
bool32 smaller = 0;
if (e->thread_index < pn) smaller = 1;
else if (e->thread_index == pn){
if (e->type != DBGEV_MOMENT && pt == DBGEV_MOMENT) smaller = 1;
else if (e->type != DBGEV_MOMENT){
if (e->event_index < pe) smaller = 1;
else if (e->event_index == pe){
if (e->which_hit < ph) smaller = 1;
else if (e->which_hit == ph){
if (e->type < pt) smaller = 1;
}
}
}
else if (pt == DBGEV_MOMENT){
if (e->time < p->time) smaller = 1;
}
}
if (smaller){
Swap(*e, es[start]);
++start;
}
}
Swap(*p, es[start]);
return start;
}
internal void
quick_sort(Debug_Event *e, u32 start, u32 pivot){
u32 mid = quick_partition(e, start, pivot);
if (start + 1 < mid) quick_sort(e, start, mid - 1);
if (mid + 1 < pivot) quick_sort(e, mid + 1, pivot);
}
inline void
sort(Debug_Event_Array *events){
quick_sort(events->e, 0, events->count - 1);
}
globalvar i32 INTERNAL_frame_index;
globalvar bool32 INTERNAL_updating_profile;
#define ProfileStart_(name, start, counter, hit, thread, n, c)\
name = n; counter = c; start = system_time(); hit = post_debug_event(n, DBGEV_START, counter, thread, 0)
#define ProfileEnd_(name, start, counter, hit, thread) post_debug_event(name, DBGEV_END, counter, thread, hit)
#define ProfileMoment_(name, counter, thread) post_debug_event(name, DBGEV_MOMENT, counter, thread, 0)
struct INTERNAL_Profile_Block{
char *name;
i64 start;
i32 counter;
i32 thread;
i32 hit;
INTERNAL_Profile_Block(char *n, i32 c, i32 t){
ProfileStart_(name, start, counter, hit, t, n, c);
thread = t;
}
~INTERNAL_Profile_Block(){
ProfileEnd_(name, start, counter, hit, thread);
}
};
#define ProfileBlock(name, thread) INTERNAL_Profile_Block name(#name, __COUNTER__, thread)
#define ProfileBlockFunction() INTERNAL_Profile_Block name(__FUNCTION__, __COUNTER__, 0)
#define ProfileStart(name) char *_pname_##name; i64 _pstart_##name; i32 _pcounter_##name; u32 _phit_##name; \
ProfileStart_(_pname_##name, _pstart_##name, _pcounter_##name, _phit_##name, system_thread_get_id(thread), #name, __COUNTER__)
#define ProfileEnd(name) ProfileEnd_(_pname_##name, _pstart_##name, _pcounter_##name, _phit_##name, system_thread_get_id(thread))
#define ProfileMoment(name, thread) ProfileMoment_(#name, __COUNTER__, thread)
#define ProfileMomentFunction() ProfileMoment_(__FUNCTION__, __COUNTER__, 0)
#else
#define ProfileBlock(name)
#define ProfileStart(name)
#define ProfileEnd(name)
#define ProfileMoment(name)
#define ProfileMomentFunction()
#endif