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