13bb3ab83SIngo Weinhold/*
23bb3ab83SIngo Weinhold * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
33bb3ab83SIngo Weinhold * Copyright 2008, Axel D��rfler, axeld@pinc-software.de.
43bb3ab83SIngo Weinhold * Distributed under the terms of the MIT License.
53bb3ab83SIngo Weinhold */
6ab23dfa7SIngo Weinhold#ifndef KERNEL_TRACING_H
7ab23dfa7SIngo Weinhold#define KERNEL_TRACING_H
8aa5d2a2dSAxel Dörfler
9aa5d2a2dSAxel Dörfler
10aa5d2a2dSAxel Dörfler#include <SupportDefs.h>
11416458e9SAxel Dörfler#include <KernelExport.h>
12aa5d2a2dSAxel Dörfler
13328df922SIngo Weinhold#include <stdarg.h>
148e43ece8SAxel Dörfler#include <stdio.h>
158e43ece8SAxel Dörfler
16071f9c3aSIngo Weinhold#include "tracing_config.h"
17aa5d2a2dSAxel Dörfler
18aa5d2a2dSAxel Dörfler
19aa5d2a2dSAxel Dörflerstruct trace_entry {
203fccf067SIngo Weinhold	uint32	size			: 13;		// actual size is *4
213fccf067SIngo Weinhold	uint32	previous_size	: 13;		// actual size is *4
223fccf067SIngo Weinhold	uint32	flags			: 6;
23aa5d2a2dSAxel Dörfler};
24aa5d2a2dSAxel Dörfler
2569d7ad7dSIngo Weinholdstruct tracing_stack_trace {
2669d7ad7dSIngo Weinhold	int32	depth;
2769d7ad7dSIngo Weinhold	addr_t	return_addresses[0];
2869d7ad7dSIngo Weinhold};
2969d7ad7dSIngo Weinhold
3065f40152SIngo Weinhold
31aa5d2a2dSAxel Dörfler#ifdef __cplusplus
32aa5d2a2dSAxel Dörfler
33aa5d2a2dSAxel Dörfler#include <new>
34aa5d2a2dSAxel Dörfler
35350b6dbcSIngo Weinhold
36350b6dbcSIngo Weinhold// trace output flags
37350b6dbcSIngo Weinhold#define TRACE_OUTPUT_TEAM_ID	0x01
38350b6dbcSIngo Weinhold	// print the team ID
39350b6dbcSIngo Weinhold#define TRACE_OUTPUT_DIFF_TIME	0x02
40350b6dbcSIngo Weinhold	// print the difference time to the previously printed entry instead of the
41350b6dbcSIngo Weinhold	// absolute time
42350b6dbcSIngo Weinhold
43350b6dbcSIngo Weinhold
44f1047a1cSIngo Weinholdclass TraceOutput {
45328df922SIngo Weinholdpublic:
46328df922SIngo Weinhold	TraceOutput(char* buffer, size_t bufferSize, uint32 flags);
47f1047a1cSIngo Weinhold
48328df922SIngo Weinhold	void Clear();
49328df922SIngo Weinhold	void Print(const char* format,...)
50328df922SIngo Weinhold		__attribute__ ((format (__printf__, 2, 3)));
51328df922SIngo Weinhold	void PrintArgs(const char* format, va_list args);
52328df922SIngo Weinhold	void PrintStackTrace(tracing_stack_trace* stackTrace);
53328df922SIngo Weinhold	bool IsFull() const	{ return fSize >= fCapacity; }
54f1047a1cSIngo Weinhold
55328df922SIngo Weinhold	char* Buffer() const	{ return fBuffer; }
56328df922SIngo Weinhold	size_t Capacity() const	{ return fCapacity; }
57328df922SIngo Weinhold	size_t Size() const		{ return fSize; }
584c4b14c3SIngo Weinhold
59328df922SIngo Weinhold	uint32 Flags() const	{ return fFlags; }
60350b6dbcSIngo Weinhold
61328df922SIngo Weinhold	void SetLastEntryTime(bigtime_t time);
62328df922SIngo Weinhold	bigtime_t LastEntryTime() const;
63350b6dbcSIngo Weinhold
64328df922SIngo Weinholdprivate:
65328df922SIngo Weinhold	char*		fBuffer;
66328df922SIngo Weinhold	size_t		fCapacity;
67328df922SIngo Weinhold	size_t		fSize;
68328df922SIngo Weinhold	uint32		fFlags;
69328df922SIngo Weinhold	bigtime_t	fLastEntryTime;
70f1047a1cSIngo Weinhold};
71f1047a1cSIngo Weinhold
72ef7102faSIngo Weinhold
73b3d6c12dSIngo Weinholdclass TraceEntry {
74aa5d2a2dSAxel Dörfler	public:
75aa5d2a2dSAxel Dörfler		TraceEntry();
76aa5d2a2dSAxel Dörfler		virtual ~TraceEntry();
77aa5d2a2dSAxel Dörfler
78f7a5d9c5SIngo Weinhold		virtual void Dump(TraceOutput& out);
7965f40152SIngo Weinhold		virtual void DumpStackTrace(TraceOutput& out);
80aa5d2a2dSAxel Dörfler
81b3d6c12dSIngo Weinhold		size_t Size() const		{ return ToTraceEntry()->size; }
82b3d6c12dSIngo Weinhold		uint16 Flags() const	{ return ToTraceEntry()->flags; }
83aa5d2a2dSAxel Dörfler
84aa5d2a2dSAxel Dörfler		void Initialized();
85aa5d2a2dSAxel Dörfler
86416458e9SAxel Dörfler		void* operator new(size_t size, const std::nothrow_t&) throw();
87b3d6c12dSIngo Weinhold
88b3d6c12dSIngo Weinhold		trace_entry* ToTraceEntry() const
89b3d6c12dSIngo Weinhold		{
90b3d6c12dSIngo Weinhold			return (trace_entry*)this - 1;
91b3d6c12dSIngo Weinhold		}
92b3d6c12dSIngo Weinhold
93b3d6c12dSIngo Weinhold		static TraceEntry* FromTraceEntry(trace_entry* entry)
94b3d6c12dSIngo Weinhold		{
95b3d6c12dSIngo Weinhold			return (TraceEntry*)(entry + 1);
96b3d6c12dSIngo Weinhold		}
97416458e9SAxel Dörfler};
98416458e9SAxel Dörfler
99ef7102faSIngo Weinhold
100416458e9SAxel Dörflerclass AbstractTraceEntry : public TraceEntry {
101fe8f0f46SMichael Lotzpublic:
102fe8f0f46SMichael Lotz	AbstractTraceEntry()
103fe8f0f46SMichael Lotz	{
104fe8f0f46SMichael Lotz		_Init();
105fe8f0f46SMichael Lotz	}
1068e43ece8SAxel Dörfler
107fe8f0f46SMichael Lotz	// dummy, ignores all arguments
108fe8f0f46SMichael Lotz	AbstractTraceEntry(size_t, size_t, bool)
109fe8f0f46SMichael Lotz	{
110fe8f0f46SMichael Lotz		_Init();
111fe8f0f46SMichael Lotz	}
112f1047a1cSIngo Weinhold
113fe8f0f46SMichael Lotz	virtual ~AbstractTraceEntry();
114416458e9SAxel Dörfler
115fe8f0f46SMichael Lotz	virtual void Dump(TraceOutput& out);
116416458e9SAxel Dörfler
117fe8f0f46SMichael Lotz	virtual void AddDump(TraceOutput& out);
118fe8f0f46SMichael Lotz
119fe8f0f46SMichael Lotz	thread_id ThreadID() const	{ return fThread; }
120fe8f0f46SMichael Lotz	thread_id TeamID() const	{ return fTeam; }
121fe8f0f46SMichael Lotz	bigtime_t Time() const		{ return fTime; }
122fe8f0f46SMichael Lotz
123fe8f0f46SMichael Lotzprotected:
124fe8f0f46SMichael Lotz	typedef AbstractTraceEntry TraceEntryBase;
125fe8f0f46SMichael Lotz
126fe8f0f46SMichael Lotzprivate:
127fe8f0f46SMichael Lotz	void _Init();
128fe8f0f46SMichael Lotz
129fe8f0f46SMichael Lotzprotected:
130fe8f0f46SMichael Lotz	thread_id	fThread;
131fe8f0f46SMichael Lotz	team_id		fTeam;
132fe8f0f46SMichael Lotz	bigtime_t	fTime;
133fe8f0f46SMichael Lotz};
134fe8f0f46SMichael Lotz
135fe8f0f46SMichael Lotz
136fe8f0f46SMichael Lotzclass AbstractTraceEntryWithStackTrace : public AbstractTraceEntry {
137fe8f0f46SMichael Lotzpublic:
138fe8f0f46SMichael Lotz	AbstractTraceEntryWithStackTrace(size_t stackTraceDepth,
139fe8f0f46SMichael Lotz		size_t skipFrames, bool kernelOnly);
140fe8f0f46SMichael Lotz
141fe8f0f46SMichael Lotz	virtual void DumpStackTrace(TraceOutput& out);
142fe8f0f46SMichael Lotz
14369d7ad7dSIngo Weinhold	tracing_stack_trace* StackTrace() const
14469d7ad7dSIngo Weinhold	{
14569d7ad7dSIngo Weinhold		return fStackTrace;
14669d7ad7dSIngo Weinhold	}
14769d7ad7dSIngo Weinhold
148fe8f0f46SMichael Lotzprotected:
149fe8f0f46SMichael Lotz	typedef AbstractTraceEntryWithStackTrace TraceEntryBase;
150fe8f0f46SMichael Lotz
151fe8f0f46SMichael Lotzprivate:
152fe8f0f46SMichael Lotz	tracing_stack_trace* fStackTrace;
153fe8f0f46SMichael Lotz};
154fe8f0f46SMichael Lotz
155fe8f0f46SMichael Lotz
156fe8f0f46SMichael Lotztemplate<bool stackTraceDepth>
157fe8f0f46SMichael Lotzstruct AbstractTraceEntrySelector {
158fe8f0f46SMichael Lotz	typedef AbstractTraceEntryWithStackTrace Type;
159aa5d2a2dSAxel Dörfler};
160aa5d2a2dSAxel Dörfler
161ef7102faSIngo Weinhold
162fe8f0f46SMichael Lotztemplate<>
163fe8f0f46SMichael Lotzstruct AbstractTraceEntrySelector<0> {
164fe8f0f46SMichael Lotz	typedef AbstractTraceEntry Type;
165fe8f0f46SMichael Lotz};
166fe8f0f46SMichael Lotz
167fe8f0f46SMichael Lotz
168fe8f0f46SMichael Lotz#define TRACE_ENTRY_SELECTOR(stackTraceDepth) \
169fe8f0f46SMichael Lotz	AbstractTraceEntrySelector<stackTraceDepth>::Type
170fe8f0f46SMichael Lotz
171fe8f0f46SMichael Lotz
172f97199edSIngo Weinholdclass LazyTraceOutput : public TraceOutput {
173f97199edSIngo Weinholdpublic:
174f97199edSIngo Weinhold	LazyTraceOutput(char* buffer, size_t bufferSize, uint32 flags)
175f97199edSIngo Weinhold		: TraceOutput(buffer, bufferSize, flags)
176f97199edSIngo Weinhold	{
177f97199edSIngo Weinhold	}
178f97199edSIngo Weinhold
179f97199edSIngo Weinhold	const char* DumpEntry(const TraceEntry* entry)
180f97199edSIngo Weinhold	{
181f97199edSIngo Weinhold		if (Size() == 0) {
182f97199edSIngo Weinhold			const_cast<TraceEntry*>(entry)->Dump(*this);
183f97199edSIngo Weinhold				// Dump() should probably be const
184f97199edSIngo Weinhold		}
185f97199edSIngo Weinhold
186f97199edSIngo Weinhold		return Buffer();
187f97199edSIngo Weinhold	}
188f97199edSIngo Weinhold};
189f97199edSIngo Weinhold
190ef7102faSIngo Weinhold
191f97199edSIngo Weinholdclass TraceFilter {
192f97199edSIngo Weinholdpublic:
193f97199edSIngo Weinhold	virtual ~TraceFilter();
194f97199edSIngo Weinhold
195f97199edSIngo Weinhold	virtual bool Filter(const TraceEntry* entry, LazyTraceOutput& out);
196f97199edSIngo Weinhold
197f97199edSIngo Weinholdpublic:
198f97199edSIngo Weinhold	union {
199f97199edSIngo Weinhold		thread_id	fThread;
200f97199edSIngo Weinhold		team_id		fTeam;
201f97199edSIngo Weinhold		const char*	fString;
202f97199edSIngo Weinhold		uint64		fValue;
203f97199edSIngo Weinhold		struct {
204f97199edSIngo Weinhold			TraceFilter*	first;
205f97199edSIngo Weinhold			TraceFilter*	second;
206f97199edSIngo Weinhold		} fSubFilters;
207f97199edSIngo Weinhold	};
208f97199edSIngo Weinhold};
209f97199edSIngo Weinhold
210ef7102faSIngo Weinhold
211f97199edSIngo Weinholdclass WrapperTraceFilter : public TraceFilter {
212f97199edSIngo Weinholdpublic:
213f97199edSIngo Weinhold	virtual void Init(TraceFilter* filter, int direction, bool continued) = 0;
214f97199edSIngo Weinhold};
215f97199edSIngo Weinhold
216ef7102faSIngo Weinhold
217ef7102faSIngo Weinholdclass TraceEntryIterator {
218ef7102faSIngo Weinholdpublic:
219ef7102faSIngo Weinhold	TraceEntryIterator()
220ef7102faSIngo Weinhold		:
221ef7102faSIngo Weinhold 		fEntry(NULL),
222ef7102faSIngo Weinhold		fIndex(0)
223ef7102faSIngo Weinhold	{
224ef7102faSIngo Weinhold	}
225ef7102faSIngo Weinhold
226ef7102faSIngo Weinhold	void Reset()
227ef7102faSIngo Weinhold	{
228ef7102faSIngo Weinhold		fEntry = NULL;
229ef7102faSIngo Weinhold		fIndex = 0;
230ef7102faSIngo Weinhold	}
231ef7102faSIngo Weinhold
232ef7102faSIngo Weinhold	int32 Index() const
233ef7102faSIngo Weinhold	{
234ef7102faSIngo Weinhold		return fIndex;
235ef7102faSIngo Weinhold	}
236ef7102faSIngo Weinhold
237ef7102faSIngo Weinhold	TraceEntry* Current() const
238ef7102faSIngo Weinhold	{
239ef7102faSIngo Weinhold		return fEntry != NULL ? TraceEntry::FromTraceEntry(fEntry) : NULL;
240ef7102faSIngo Weinhold	}
241ef7102faSIngo Weinhold
242ef7102faSIngo Weinhold	TraceEntry* Next();
243ef7102faSIngo Weinhold	TraceEntry* Previous();
244ef7102faSIngo Weinhold	TraceEntry* MoveTo(int32 index);
245ef7102faSIngo Weinhold
246ef7102faSIngo Weinholdprivate:
247ef7102faSIngo Weinhold	trace_entry* _NextNonBufferEntry(trace_entry* entry);
248ef7102faSIngo Weinhold	trace_entry* _PreviousNonBufferEntry(trace_entry* entry);
249ef7102faSIngo Weinhold
250ef7102faSIngo Weinholdprivate:
251ef7102faSIngo Weinhold	trace_entry*	fEntry;
252ef7102faSIngo Weinhold	int32			fIndex;
253ef7102faSIngo Weinhold};
254ef7102faSIngo Weinhold
255ef7102faSIngo Weinhold
256328df922SIngo Weinholdinline void
257328df922SIngo WeinholdTraceOutput::Print(const char* format,...)
258328df922SIngo Weinhold{
259328df922SIngo Weinhold	va_list args;
260328df922SIngo Weinhold	va_start(args, format);
261328df922SIngo Weinhold	PrintArgs(format, args);
262328df922SIngo Weinhold	va_end(args);
263328df922SIngo Weinhold}
264328df922SIngo Weinhold
265328df922SIngo Weinhold
26631ffd653SOliver Tappeint dump_tracing(int argc, char** argv, WrapperTraceFilter* wrapperFilter);
26731ffd653SOliver Tappe
2689a79e531SMichael Lotzbool tracing_is_entry_valid(AbstractTraceEntry* entry,
2699a79e531SMichael Lotz	bigtime_t entryTime = -1);
27069d7ad7dSIngo Weinhold
271aa5d2a2dSAxel Dörfler#endif	// __cplusplus
272aa5d2a2dSAxel Dörfler
27369d7ad7dSIngo Weinhold
274aa5d2a2dSAxel Dörfler#ifdef __cplusplus
2758e43ece8SAxel Dörflerextern "C" {
276aa5d2a2dSAxel Dörfler#endif
2778e43ece8SAxel Dörfler
2788e43ece8SAxel Dörfleruint8* alloc_tracing_buffer(size_t size);
2790b60583fSIngo Weinholduint8* alloc_tracing_buffer_memcpy(const void* source, size_t size, bool user);
2800b60583fSIngo Weinholdchar* alloc_tracing_buffer_strcpy(const char* source, size_t maxSize,
2810b60583fSIngo Weinhold			bool user);
28269d7ad7dSIngo Weinhold
28331ffd653SOliver Tappestruct tracing_stack_trace* capture_tracing_stack_trace(int32 maxCount,
284a38f8503SIngo Weinhold			int32 skipFrames, bool kernelOnly);
28569d7ad7dSIngo Weinholdaddr_t tracing_find_caller_in_stack_trace(
28669d7ad7dSIngo Weinhold	struct tracing_stack_trace* stackTrace, const addr_t excludeRanges[],
28769d7ad7dSIngo Weinhold	uint32 excludeRangeCount);
288328df922SIngo Weinholdvoid tracing_print_stack_trace(struct tracing_stack_trace* stackTrace);
28969d7ad7dSIngo Weinhold
290aa1a64f3SIngo Weinholdvoid lock_tracing_buffer();
291aa1a64f3SIngo Weinholdvoid unlock_tracing_buffer();
292aa5d2a2dSAxel Dörflerstatus_t tracing_init(void);
293aa5d2a2dSAxel Dörfler
294a54c125eSIngo Weinholdvoid _user_ktrace_output(const char *message);
295a54c125eSIngo Weinhold
2968e43ece8SAxel Dörfler#ifdef __cplusplus
2978e43ece8SAxel Dörfler}
2988e43ece8SAxel Dörfler#endif
2998e43ece8SAxel Dörfler
300ab23dfa7SIngo Weinhold#endif	/* KERNEL_TRACING_H */
301