196dcc73bSPawel Dziepak/*
296dcc73bSPawel Dziepak * Copyright 2013, Pawe�� Dziepak, pdziepak@quarnos.org.
396dcc73bSPawel Dziepak * Distributed under the terms of the MIT License.
496dcc73bSPawel Dziepak */
596dcc73bSPawel Dziepak#ifndef KERNEL_SCHEDULER_PROFILER_H
696dcc73bSPawel Dziepak#define KERNEL_SCHEDULER_PROFILER_H
796dcc73bSPawel Dziepak
896dcc73bSPawel Dziepak
996dcc73bSPawel Dziepak#include <smp.h>
1096dcc73bSPawel Dziepak
1196dcc73bSPawel Dziepak
1296dcc73bSPawel Dziepak//#define SCHEDULER_PROFILING
1396dcc73bSPawel Dziepak#ifdef SCHEDULER_PROFILING
1496dcc73bSPawel Dziepak
1596dcc73bSPawel Dziepak
1696dcc73bSPawel Dziepak#define SCHEDULER_ENTER_FUNCTION()	\
1796dcc73bSPawel Dziepak	Scheduler::Profiling::Function schedulerProfiler(__PRETTY_FUNCTION__)
1896dcc73bSPawel Dziepak
190269dd28SPawel Dziepak#define SCHEDULER_EXIT_FUNCTION()	\
200269dd28SPawel Dziepak	schedulerProfiler.Exit()
210269dd28SPawel Dziepak
2296dcc73bSPawel Dziepak
2396dcc73bSPawel Dziepaknamespace Scheduler {
2496dcc73bSPawel Dziepak
2596dcc73bSPawel Dziepaknamespace Profiling {
2696dcc73bSPawel Dziepak
2796dcc73bSPawel Dziepakclass Profiler {
2896dcc73bSPawel Dziepakpublic:
2996dcc73bSPawel Dziepak							Profiler();
3096dcc73bSPawel Dziepak
3196dcc73bSPawel Dziepak			void			EnterFunction(int32 cpu, const char* function);
3296dcc73bSPawel Dziepak			void			ExitFunction(int32 cpu, const char* function);
3396dcc73bSPawel Dziepak
3496dcc73bSPawel Dziepak			void			DumpCalled(uint32 count);
3596dcc73bSPawel Dziepak			void			DumpTimeInclusive(uint32 count);
3696dcc73bSPawel Dziepak			void			DumpTimeExclusive(uint32 count);
3796dcc73bSPawel Dziepak			void			DumpTimeInclusivePerCall(uint32 count);
3896dcc73bSPawel Dziepak			void			DumpTimeExclusivePerCall(uint32 count);
3996dcc73bSPawel Dziepak
4096dcc73bSPawel Dziepak			status_t		GetStatus() const	{ return fStatus; }
4196dcc73bSPawel Dziepak
4296dcc73bSPawel Dziepak	static	Profiler*		Get();
4396dcc73bSPawel Dziepak	static	void			Initialize();
4496dcc73bSPawel Dziepak
4596dcc73bSPawel Dziepakprivate:
4696dcc73bSPawel Dziepak	struct FunctionData {
4796dcc73bSPawel Dziepak			const char*		fFunction;
4896dcc73bSPawel Dziepak
4996dcc73bSPawel Dziepak			uint32			fCalled;
5096dcc73bSPawel Dziepak
5196dcc73bSPawel Dziepak			bigtime_t		fTimeInclusive;
5296dcc73bSPawel Dziepak			bigtime_t		fTimeExclusive;
5396dcc73bSPawel Dziepak	};
5496dcc73bSPawel Dziepak
5596dcc73bSPawel Dziepak	struct FunctionEntry {
5696dcc73bSPawel Dziepak			FunctionData*	fFunction;
5796dcc73bSPawel Dziepak
58712f37e1SPawel Dziepak			nanotime_t		fEntryTime;
59712f37e1SPawel Dziepak			nanotime_t		fOthersTime;
60712f37e1SPawel Dziepak			nanotime_t		fProfilerTime;
6196dcc73bSPawel Dziepak	};
6296dcc73bSPawel Dziepak
6396dcc73bSPawel Dziepak			uint32			_FunctionCount() const;
6496dcc73bSPawel Dziepak			void			_Dump(uint32 count);
6596dcc73bSPawel Dziepak
6696dcc73bSPawel Dziepak			FunctionData*	_FindFunction(const char* function);
6796dcc73bSPawel Dziepak
6896dcc73bSPawel Dziepak			template<typename Type, Type FunctionData::*Member>
6996dcc73bSPawel Dziepak	static	int				_CompareFunctions(const void* a, const void* b);
7096dcc73bSPawel Dziepak
7196dcc73bSPawel Dziepak			template<typename Type, Type FunctionData::*Member>
7296dcc73bSPawel Dziepak	static	int				_CompareFunctionsPerCall(const void* a,
7396dcc73bSPawel Dziepak								const void* b);
7496dcc73bSPawel Dziepak
7596dcc73bSPawel Dziepak			const uint32	kMaxFunctionEntries;
7696dcc73bSPawel Dziepak			const uint32	kMaxFunctionStackEntries;
7796dcc73bSPawel Dziepak
7896dcc73bSPawel Dziepak			FunctionEntry*	fFunctionStacks[SMP_MAX_CPUS];
7996dcc73bSPawel Dziepak			uint32			fFunctionStackPointers[SMP_MAX_CPUS];
8096dcc73bSPawel Dziepak
8196dcc73bSPawel Dziepak			FunctionData*	fFunctionData;
8296dcc73bSPawel Dziepak			spinlock		fFunctionLock;
8396dcc73bSPawel Dziepak
8496dcc73bSPawel Dziepak			status_t		fStatus;
8596dcc73bSPawel Dziepak};
8696dcc73bSPawel Dziepak
8796dcc73bSPawel Dziepakclass Function {
8896dcc73bSPawel Dziepakpublic:
8996dcc73bSPawel Dziepak	inline					Function(const char* functionName);
9096dcc73bSPawel Dziepak	inline					~Function();
9196dcc73bSPawel Dziepak
9296dcc73bSPawel Dziepak	inline	void			Exit();
9396dcc73bSPawel Dziepak
9496dcc73bSPawel Dziepakprivate:
9596dcc73bSPawel Dziepak			const char*		fFunctionName;
9696dcc73bSPawel Dziepak};
9796dcc73bSPawel Dziepak
9896dcc73bSPawel Dziepak
9996dcc73bSPawel DziepakFunction::Function(const char* functionName)
10096dcc73bSPawel Dziepak	:
10196dcc73bSPawel Dziepak	fFunctionName(functionName)
10296dcc73bSPawel Dziepak{
10396dcc73bSPawel Dziepak	Profiler::Get()->EnterFunction(smp_get_current_cpu(), fFunctionName);
10496dcc73bSPawel Dziepak}
10596dcc73bSPawel Dziepak
10696dcc73bSPawel Dziepak
10796dcc73bSPawel DziepakFunction::~Function()
10896dcc73bSPawel Dziepak{
10996dcc73bSPawel Dziepak	if (fFunctionName != NULL)
11096dcc73bSPawel Dziepak		Exit();
11196dcc73bSPawel Dziepak}
11296dcc73bSPawel Dziepak
11396dcc73bSPawel Dziepak
11496dcc73bSPawel Dziepakvoid
11596dcc73bSPawel DziepakFunction::Exit()
11696dcc73bSPawel Dziepak{
11796dcc73bSPawel Dziepak	Profiler::Get()->ExitFunction(smp_get_current_cpu(), fFunctionName);
11896dcc73bSPawel Dziepak	fFunctionName = NULL;
11996dcc73bSPawel Dziepak}
12096dcc73bSPawel Dziepak
12196dcc73bSPawel Dziepak
12296dcc73bSPawel Dziepak}	// namespace Profiling
12396dcc73bSPawel Dziepak
12496dcc73bSPawel Dziepak}	// namespace Scheduler
12596dcc73bSPawel Dziepak
12696dcc73bSPawel Dziepak
12796dcc73bSPawel Dziepak#else	// SCHEDULER_PROFILING
12896dcc73bSPawel Dziepak
12996dcc73bSPawel Dziepak#define SCHEDULER_ENTER_FUNCTION()	(void)0
1300269dd28SPawel Dziepak#define SCHEDULER_EXIT_FUNCTION()	(void)0
13196dcc73bSPawel Dziepak
13296dcc73bSPawel Dziepak#endif	// !SCHEDULER_PROFILING
13396dcc73bSPawel Dziepak
13496dcc73bSPawel Dziepak
13596dcc73bSPawel Dziepak#endif	// KERNEL_SCHEDULER_PROFILER_H
13696dcc73bSPawel Dziepak
137