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