1/*
2 * Copyright 2013, Paweł Dziepak, pdziepak@quarnos.org.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef KERNEL_SCHEDULER_PROFILER_H
6#define KERNEL_SCHEDULER_PROFILER_H
7
8
9#include <smp.h>
10
11
12//#define SCHEDULER_PROFILING
13#ifdef SCHEDULER_PROFILING
14
15
16#define SCHEDULER_ENTER_FUNCTION()	\
17	Scheduler::Profiling::Function schedulerProfiler(__PRETTY_FUNCTION__)
18
19#define SCHEDULER_EXIT_FUNCTION()	\
20	schedulerProfiler.Exit()
21
22
23namespace Scheduler {
24
25namespace Profiling {
26
27class Profiler {
28public:
29							Profiler();
30
31			void			EnterFunction(int32 cpu, const char* function);
32			void			ExitFunction(int32 cpu, const char* function);
33
34			void			DumpCalled(uint32 count);
35			void			DumpTimeInclusive(uint32 count);
36			void			DumpTimeExclusive(uint32 count);
37			void			DumpTimeInclusivePerCall(uint32 count);
38			void			DumpTimeExclusivePerCall(uint32 count);
39
40			status_t		GetStatus() const	{ return fStatus; }
41
42	static	Profiler*		Get();
43	static	void			Initialize();
44
45private:
46	struct FunctionData {
47			const char*		fFunction;
48
49			uint32			fCalled;
50
51			bigtime_t		fTimeInclusive;
52			bigtime_t		fTimeExclusive;
53	};
54
55	struct FunctionEntry {
56			FunctionData*	fFunction;
57
58			nanotime_t		fEntryTime;
59			nanotime_t		fOthersTime;
60			nanotime_t		fProfilerTime;
61	};
62
63			uint32			_FunctionCount() const;
64			void			_Dump(uint32 count);
65
66			FunctionData*	_FindFunction(const char* function);
67
68			template<typename Type, Type FunctionData::*Member>
69	static	int				_CompareFunctions(const void* a, const void* b);
70
71			template<typename Type, Type FunctionData::*Member>
72	static	int				_CompareFunctionsPerCall(const void* a,
73								const void* b);
74
75			const uint32	kMaxFunctionEntries;
76			const uint32	kMaxFunctionStackEntries;
77
78			FunctionEntry*	fFunctionStacks[SMP_MAX_CPUS];
79			uint32			fFunctionStackPointers[SMP_MAX_CPUS];
80
81			FunctionData*	fFunctionData;
82			spinlock		fFunctionLock;
83
84			status_t		fStatus;
85};
86
87class Function {
88public:
89	inline					Function(const char* functionName);
90	inline					~Function();
91
92	inline	void			Exit();
93
94private:
95			const char*		fFunctionName;
96};
97
98
99Function::Function(const char* functionName)
100	:
101	fFunctionName(functionName)
102{
103	Profiler::Get()->EnterFunction(smp_get_current_cpu(), fFunctionName);
104}
105
106
107Function::~Function()
108{
109	if (fFunctionName != NULL)
110		Exit();
111}
112
113
114void
115Function::Exit()
116{
117	Profiler::Get()->ExitFunction(smp_get_current_cpu(), fFunctionName);
118	fFunctionName = NULL;
119}
120
121
122}	// namespace Profiling
123
124}	// namespace Scheduler
125
126
127#else	// SCHEDULER_PROFILING
128
129#define SCHEDULER_ENTER_FUNCTION()	(void)0
130#define SCHEDULER_EXIT_FUNCTION()	(void)0
131
132#endif	// !SCHEDULER_PROFILING
133
134
135#endif	// KERNEL_SCHEDULER_PROFILER_H
136
137