xref: /haiku/headers/private/kernel/tracing.h (revision 58481f0f6ef1a61ba07283f012cafbc2ed874ead)
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			: 14;		// actual size is *4
20 	uint32	previous_size	: 14;		// actual size is *4
21 	uint32	flags			: 4;
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 		virtual ~AbstractTraceEntry();
98 
99 		virtual void Dump(TraceOutput& out);
100 
101 		virtual void AddDump(TraceOutput& out);
102 
103 		thread_id Thread() const { return fThread; }
104 		thread_id Team() const { return fTeam; }
105 		bigtime_t Time() const { return fTime; }
106 
107 	protected:
108 		thread_id	fThread;
109 		team_id		fTeam;
110 		bigtime_t	fTime;
111 };
112 
113 
114 class LazyTraceOutput : public TraceOutput {
115 public:
116 	LazyTraceOutput(char* buffer, size_t bufferSize, uint32 flags)
117 		: TraceOutput(buffer, bufferSize, flags)
118 	{
119 	}
120 
121 	const char* DumpEntry(const TraceEntry* entry)
122 	{
123 		if (Size() == 0) {
124 			const_cast<TraceEntry*>(entry)->Dump(*this);
125 				// Dump() should probably be const
126 		}
127 
128 		return Buffer();
129 	}
130 };
131 
132 
133 class TraceFilter {
134 public:
135 	virtual ~TraceFilter();
136 
137 	virtual bool Filter(const TraceEntry* entry, LazyTraceOutput& out);
138 
139 public:
140 	union {
141 		thread_id	fThread;
142 		team_id		fTeam;
143 		const char*	fString;
144 		uint64		fValue;
145 		struct {
146 			TraceFilter*	first;
147 			TraceFilter*	second;
148 		} fSubFilters;
149 	};
150 };
151 
152 
153 class WrapperTraceFilter : public TraceFilter {
154 public:
155 	virtual void Init(TraceFilter* filter, int direction, bool continued) = 0;
156 };
157 
158 
159 class TraceEntryIterator {
160 public:
161 	TraceEntryIterator()
162 		:
163  		fEntry(NULL),
164 		fIndex(0)
165 	{
166 	}
167 
168 	void Reset()
169 	{
170 		fEntry = NULL;
171 		fIndex = 0;
172 	}
173 
174 	int32 Index() const
175 	{
176 		return fIndex;
177 	}
178 
179 	TraceEntry* Current() const
180 	{
181 		return fEntry != NULL ? TraceEntry::FromTraceEntry(fEntry) : NULL;
182 	}
183 
184 	TraceEntry* Next();
185 	TraceEntry* Previous();
186 	TraceEntry* MoveTo(int32 index);
187 
188 private:
189 	trace_entry* _NextNonBufferEntry(trace_entry* entry);
190 	trace_entry* _PreviousNonBufferEntry(trace_entry* entry);
191 
192 private:
193 	trace_entry*	fEntry;
194 	int32			fIndex;
195 };
196 
197 
198 int dump_tracing(int argc, char** argv, WrapperTraceFilter* wrapperFilter);
199 
200 #endif	// __cplusplus
201 
202 #ifdef __cplusplus
203 extern "C" {
204 #endif
205 
206 uint8* alloc_tracing_buffer(size_t size);
207 uint8* alloc_tracing_buffer_memcpy(const void* source, size_t size, bool user);
208 char* alloc_tracing_buffer_strcpy(const char* source, size_t maxSize,
209 			bool user);
210 struct tracing_stack_trace* capture_tracing_stack_trace(int32 maxCount,
211 			int32 skipFrames, bool userOnly);
212 void lock_tracing_buffer();
213 void unlock_tracing_buffer();
214 status_t tracing_init(void);
215 
216 void _user_ktrace_output(const char *message);
217 
218 #ifdef __cplusplus
219 }
220 #endif
221 
222 #endif	/* KERNEL_TRACING_H */
223