xref: /haiku/headers/private/kernel/tracing.h (revision a84e14ca84d32e9469c91372d71556488bd3d48b)
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 
19 struct 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 
25 struct 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 
44 class TraceOutput {
45 public:
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);
IsFull()53 	bool IsFull() const	{ return fSize >= fCapacity; }
54 
Buffer()55 	char* Buffer() const	{ return fBuffer; }
Capacity()56 	size_t Capacity() const	{ return fCapacity; }
Size()57 	size_t Size() const		{ return fSize; }
58 
Flags()59 	uint32 Flags() const	{ return fFlags; }
60 
61 	void SetLastEntryTime(bigtime_t time);
62 	bigtime_t LastEntryTime() const;
63 
64 private:
65 	char*		fBuffer;
66 	size_t		fCapacity;
67 	size_t		fSize;
68 	uint32		fFlags;
69 	bigtime_t	fLastEntryTime;
70 };
71 
72 
73 class TraceEntry {
74 	public:
75 		TraceEntry();
76 		virtual ~TraceEntry();
77 
78 		virtual void Dump(TraceOutput& out);
79 		virtual void DumpStackTrace(TraceOutput& out);
80 
Size()81 		size_t Size() const		{ return ToTraceEntry()->size; }
Flags()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 
ToTraceEntry()88 		trace_entry* ToTraceEntry() const
89 		{
90 			return (trace_entry*)this - 1;
91 		}
92 
FromTraceEntry(trace_entry * entry)93 		static TraceEntry* FromTraceEntry(trace_entry* entry)
94 		{
95 			return (TraceEntry*)(entry + 1);
96 		}
97 };
98 
99 
100 class AbstractTraceEntry : public TraceEntry {
101 public:
AbstractTraceEntry()102 	AbstractTraceEntry()
103 	{
104 		_Init();
105 	}
106 
107 	// dummy, ignores all arguments
AbstractTraceEntry(size_t,size_t,bool)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 
ThreadID()119 	thread_id ThreadID() const	{ return fThread; }
TeamID()120 	thread_id TeamID() const	{ return fTeam; }
Time()121 	bigtime_t Time() const		{ return fTime; }
122 
123 protected:
124 	typedef AbstractTraceEntry TraceEntryBase;
125 
126 private:
127 	void _Init();
128 
129 protected:
130 	thread_id	fThread;
131 	team_id		fTeam;
132 	bigtime_t	fTime;
133 };
134 
135 
136 class AbstractTraceEntryWithStackTrace : public AbstractTraceEntry {
137 public:
138 	AbstractTraceEntryWithStackTrace(size_t stackTraceDepth,
139 		size_t skipFrames, bool kernelOnly);
140 
141 	virtual void DumpStackTrace(TraceOutput& out);
142 
StackTrace()143 	tracing_stack_trace* StackTrace() const
144 	{
145 		return fStackTrace;
146 	}
147 
148 protected:
149 	typedef AbstractTraceEntryWithStackTrace TraceEntryBase;
150 
151 private:
152 	tracing_stack_trace* fStackTrace;
153 };
154 
155 
156 template<bool stackTraceDepth>
157 struct AbstractTraceEntrySelector {
158 	typedef AbstractTraceEntryWithStackTrace Type;
159 };
160 
161 
162 template<>
163 struct AbstractTraceEntrySelector<0> {
164 	typedef AbstractTraceEntry Type;
165 };
166 
167 
168 #define TRACE_ENTRY_SELECTOR(stackTraceDepth) \
169 	AbstractTraceEntrySelector<stackTraceDepth>::Type
170 
171 
172 class LazyTraceOutput : public TraceOutput {
173 public:
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 
191 class TraceFilter {
192 public:
193 	virtual ~TraceFilter();
194 
195 	virtual bool Filter(const TraceEntry* entry, LazyTraceOutput& out);
196 
197 public:
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 
211 class WrapperTraceFilter : public TraceFilter {
212 public:
213 	virtual void Init(TraceFilter* filter, int direction, bool continued) = 0;
214 };
215 
216 
217 class TraceEntryIterator {
218 public:
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 
246 private:
247 	trace_entry* _NextNonBufferEntry(trace_entry* entry);
248 	trace_entry* _PreviousNonBufferEntry(trace_entry* entry);
249 
250 private:
251 	trace_entry*	fEntry;
252 	int32			fIndex;
253 };
254 
255 
256 inline void
257 TraceOutput::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 
266 int dump_tracing(int argc, char** argv, WrapperTraceFilter* wrapperFilter);
267 
268 bool tracing_is_entry_valid(AbstractTraceEntry* entry,
269 	bigtime_t entryTime = -1);
270 
271 #endif	// __cplusplus
272 
273 
274 #ifdef __cplusplus
275 extern "C" {
276 #endif
277 
278 uint8* alloc_tracing_buffer(size_t size);
279 uint8* alloc_tracing_buffer_memcpy(const void* source, size_t size, bool user);
280 char* alloc_tracing_buffer_strcpy(const char* source, size_t maxSize,
281 			bool user);
282 
283 struct tracing_stack_trace* capture_tracing_stack_trace(int32 maxCount,
284 			int32 skipFrames, bool kernelOnly);
285 addr_t tracing_find_caller_in_stack_trace(
286 	struct tracing_stack_trace* stackTrace, const addr_t excludeRanges[],
287 	uint32 excludeRangeCount);
288 void tracing_print_stack_trace(struct tracing_stack_trace* stackTrace);
289 
290 void lock_tracing_buffer();
291 void unlock_tracing_buffer();
292 status_t tracing_init(void);
293 
294 void _user_ktrace_output(const char *message);
295 
296 #ifdef __cplusplus
297 }
298 #endif
299 
300 #endif	/* KERNEL_TRACING_H */
301