1/*
2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2008, Axel Dörfler, axeld@pinc-software.de.
4 * Distributed under the terms of the MIT License.
5 */
6#ifndef KERNEL_TRACING_H
7#define KERNEL_TRACING_H
8
9
10#include <SupportDefs.h>
11#include <KernelExport.h>
12
13#include <stdarg.h>
14#include <stdio.h>
15
16#include "tracing_config.h"
17
18
19struct trace_entry {
20	uint32	size			: 13;		// actual size is *4
21	uint32	previous_size	: 13;		// actual size is *4
22	uint32	flags			: 6;
23};
24
25struct tracing_stack_trace {
26	int32	depth;
27	addr_t	return_addresses[0];
28};
29
30
31#ifdef __cplusplus
32
33#include <new>
34
35
36// trace output flags
37#define TRACE_OUTPUT_TEAM_ID	0x01
38	// print the team ID
39#define TRACE_OUTPUT_DIFF_TIME	0x02
40	// print the difference time to the previously printed entry instead of the
41	// absolute time
42
43
44class TraceOutput {
45public:
46	TraceOutput(char* buffer, size_t bufferSize, uint32 flags);
47
48	void Clear();
49	void Print(const char* format,...)
50		__attribute__ ((format (__printf__, 2, 3)));
51	void PrintArgs(const char* format, va_list args);
52	void PrintStackTrace(tracing_stack_trace* stackTrace);
53	bool IsFull() const	{ return fSize >= fCapacity; }
54
55	char* Buffer() const	{ return fBuffer; }
56	size_t Capacity() const	{ return fCapacity; }
57	size_t Size() const		{ return fSize; }
58
59	uint32 Flags() const	{ return fFlags; }
60
61	void SetLastEntryTime(bigtime_t time);
62	bigtime_t LastEntryTime() const;
63
64private:
65	char*		fBuffer;
66	size_t		fCapacity;
67	size_t		fSize;
68	uint32		fFlags;
69	bigtime_t	fLastEntryTime;
70};
71
72
73class TraceEntry {
74	public:
75		TraceEntry();
76		virtual ~TraceEntry();
77
78		virtual void Dump(TraceOutput& out);
79		virtual void DumpStackTrace(TraceOutput& out);
80
81		size_t Size() const		{ return ToTraceEntry()->size; }
82		uint16 Flags() const	{ return ToTraceEntry()->flags; }
83
84		void Initialized();
85
86		void* operator new(size_t size, const std::nothrow_t&) throw();
87
88		trace_entry* ToTraceEntry() const
89		{
90			return (trace_entry*)this - 1;
91		}
92
93		static TraceEntry* FromTraceEntry(trace_entry* entry)
94		{
95			return (TraceEntry*)(entry + 1);
96		}
97};
98
99
100class AbstractTraceEntry : public TraceEntry {
101public:
102	AbstractTraceEntry()
103	{
104		_Init();
105	}
106
107	// dummy, ignores all arguments
108	AbstractTraceEntry(size_t, size_t, bool)
109	{
110		_Init();
111	}
112
113	virtual ~AbstractTraceEntry();
114
115	virtual void Dump(TraceOutput& out);
116
117	virtual void AddDump(TraceOutput& out);
118
119	thread_id ThreadID() const	{ return fThread; }
120	thread_id TeamID() const	{ return fTeam; }
121	bigtime_t Time() const		{ return fTime; }
122
123protected:
124	typedef AbstractTraceEntry TraceEntryBase;
125
126private:
127	void _Init();
128
129protected:
130	thread_id	fThread;
131	team_id		fTeam;
132	bigtime_t	fTime;
133};
134
135
136class AbstractTraceEntryWithStackTrace : public AbstractTraceEntry {
137public:
138	AbstractTraceEntryWithStackTrace(size_t stackTraceDepth,
139		size_t skipFrames, bool kernelOnly);
140
141	virtual void DumpStackTrace(TraceOutput& out);
142
143	tracing_stack_trace* StackTrace() const
144	{
145		return fStackTrace;
146	}
147
148protected:
149	typedef AbstractTraceEntryWithStackTrace TraceEntryBase;
150
151private:
152	tracing_stack_trace* fStackTrace;
153};
154
155
156template<bool stackTraceDepth>
157struct AbstractTraceEntrySelector {
158	typedef AbstractTraceEntryWithStackTrace Type;
159};
160
161
162template<>
163struct AbstractTraceEntrySelector<0> {
164	typedef AbstractTraceEntry Type;
165};
166
167
168#define TRACE_ENTRY_SELECTOR(stackTraceDepth) \
169	AbstractTraceEntrySelector<stackTraceDepth>::Type
170
171
172class LazyTraceOutput : public TraceOutput {
173public:
174	LazyTraceOutput(char* buffer, size_t bufferSize, uint32 flags)
175		: TraceOutput(buffer, bufferSize, flags)
176	{
177	}
178
179	const char* DumpEntry(const TraceEntry* entry)
180	{
181		if (Size() == 0) {
182			const_cast<TraceEntry*>(entry)->Dump(*this);
183				// Dump() should probably be const
184		}
185
186		return Buffer();
187	}
188};
189
190
191class TraceFilter {
192public:
193	virtual ~TraceFilter();
194
195	virtual bool Filter(const TraceEntry* entry, LazyTraceOutput& out);
196
197public:
198	union {
199		thread_id	fThread;
200		team_id		fTeam;
201		const char*	fString;
202		uint64		fValue;
203		struct {
204			TraceFilter*	first;
205			TraceFilter*	second;
206		} fSubFilters;
207	};
208};
209
210
211class WrapperTraceFilter : public TraceFilter {
212public:
213	virtual void Init(TraceFilter* filter, int direction, bool continued) = 0;
214};
215
216
217class TraceEntryIterator {
218public:
219	TraceEntryIterator()
220		:
221 		fEntry(NULL),
222		fIndex(0)
223	{
224	}
225
226	void Reset()
227	{
228		fEntry = NULL;
229		fIndex = 0;
230	}
231
232	int32 Index() const
233	{
234		return fIndex;
235	}
236
237	TraceEntry* Current() const
238	{
239		return fEntry != NULL ? TraceEntry::FromTraceEntry(fEntry) : NULL;
240	}
241
242	TraceEntry* Next();
243	TraceEntry* Previous();
244	TraceEntry* MoveTo(int32 index);
245
246private:
247	trace_entry* _NextNonBufferEntry(trace_entry* entry);
248	trace_entry* _PreviousNonBufferEntry(trace_entry* entry);
249
250private:
251	trace_entry*	fEntry;
252	int32			fIndex;
253};
254
255
256inline void
257TraceOutput::Print(const char* format,...)
258{
259	va_list args;
260	va_start(args, format);
261	PrintArgs(format, args);
262	va_end(args);
263}
264
265
266int dump_tracing(int argc, char** argv, WrapperTraceFilter* wrapperFilter);
267
268bool tracing_is_entry_valid(AbstractTraceEntry* entry,
269	bigtime_t entryTime = -1);
270
271#endif	// __cplusplus
272
273
274#ifdef __cplusplus
275extern "C" {
276#endif
277
278uint8* alloc_tracing_buffer(size_t size);
279uint8* alloc_tracing_buffer_memcpy(const void* source, size_t size, bool user);
280char* alloc_tracing_buffer_strcpy(const char* source, size_t maxSize,
281			bool user);
282
283struct tracing_stack_trace* capture_tracing_stack_trace(int32 maxCount,
284			int32 skipFrames, bool kernelOnly);
285addr_t tracing_find_caller_in_stack_trace(
286	struct tracing_stack_trace* stackTrace, const addr_t excludeRanges[],
287	uint32 excludeRangeCount);
288void tracing_print_stack_trace(struct tracing_stack_trace* stackTrace);
289
290void lock_tracing_buffer();
291void unlock_tracing_buffer();
292status_t tracing_init(void);
293
294void _user_ktrace_output(const char *message);
295
296#ifdef __cplusplus
297}
298#endif
299
300#endif	/* KERNEL_TRACING_H */
301