1 /* 2 * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef THREAD_H 6 #define THREAD_H 7 8 #include <String.h> 9 10 #include <util/DoublyLinkedList.h> 11 12 #include "Image.h" 13 14 15 class Team; 16 class ThreadImage; 17 class ThreadProfileResult; 18 19 20 class ThreadImage { 21 public: 22 ThreadImage(Image* image); 23 virtual ~ThreadImage(); 24 25 virtual status_t Init(); 26 27 inline image_id ID() const; 28 inline Image* GetImage() const; 29 30 inline bool ContainsAddress(addr_t address) const; 31 32 inline int64 TotalHits() const; 33 34 protected: 35 Image* fImage; 36 int64 fTotalHits; 37 }; 38 39 40 class Thread : public DoublyLinkedListLinkImpl<Thread> { 41 public: 42 Thread(thread_id threadID, const char* name, 43 Team* team); 44 ~Thread(); 45 46 inline thread_id ID() const; 47 inline const char* Name() const; 48 inline addr_t* Samples() const; 49 inline Team* GetTeam() const; 50 51 inline ThreadProfileResult* ProfileResult() const; 52 void SetProfileResult(ThreadProfileResult* result); 53 54 void UpdateInfo(const char* name); 55 56 void SetSampleArea(area_id area, addr_t* samples); 57 void SetInterval(bigtime_t interval); 58 59 inline status_t AddImage(Image* image); 60 inline void RemoveImage(Image* image); 61 62 void AddSamples(int32 count, int32 dropped, 63 int32 stackDepth, bool variableStackDepth, 64 int32 event); 65 void AddSamples(addr_t* samples, int32 sampleCount); 66 void PrintResults() const; 67 68 private: 69 typedef DoublyLinkedList<ThreadImage> ImageList; 70 71 private: 72 thread_id fID; 73 BString fName; 74 ::Team* fTeam; 75 area_id fSampleArea; 76 addr_t* fSamples; 77 ThreadProfileResult* fProfileResult; 78 }; 79 80 81 class ThreadProfileResult { 82 public: 83 ThreadProfileResult(); 84 virtual ~ThreadProfileResult(); 85 86 virtual status_t Init(Thread* thread); 87 88 void SetInterval(bigtime_t interval); 89 90 virtual void SetLazyImages(bool lazy) = 0; 91 92 virtual status_t AddImage(Image* image) = 0; 93 virtual void RemoveImage(Image* image) = 0; 94 virtual void SynchronizeImages(int32 event) = 0; 95 96 virtual void AddSamples(addr_t* samples, 97 int32 sampleCount) = 0; 98 virtual void AddDroppedTicks(int32 dropped) = 0; 99 virtual void PrintResults() = 0; 100 101 protected: 102 Thread* fThread; 103 bigtime_t fInterval; 104 }; 105 106 107 template<typename ThreadImageType> 108 class AbstractThreadProfileResult : public ThreadProfileResult { 109 public: 110 AbstractThreadProfileResult(); 111 virtual ~AbstractThreadProfileResult(); 112 113 virtual void SetLazyImages(bool lazy); 114 115 virtual status_t AddImage(Image* image); 116 virtual void RemoveImage(Image* image); 117 virtual void SynchronizeImages(int32 event); 118 119 ThreadImageType* FindImage(addr_t address) const; 120 int32 GetHitImages(ThreadImageType** images) const; 121 122 virtual void AddSamples(addr_t* samples, 123 int32 sampleCount) = 0; 124 virtual void AddDroppedTicks(int32 dropped) = 0; 125 virtual void PrintResults() = 0; 126 127 virtual ThreadImageType* CreateThreadImage(Image* image) = 0; 128 129 protected: 130 typedef DoublyLinkedList<ThreadImageType> ImageList; 131 132 ImageList fImages; 133 ImageList fNewImages; 134 ImageList fOldImages; 135 bool fLazyImages; 136 }; 137 138 139 // #pragma mark - 140 141 142 image_id 143 ThreadImage::ID() const 144 { 145 return fImage->ID(); 146 } 147 148 149 bool 150 ThreadImage::ContainsAddress(addr_t address) const 151 { 152 return fImage->ContainsAddress(address); 153 } 154 155 156 Image* 157 ThreadImage::GetImage() const 158 { 159 return fImage; 160 } 161 162 163 int64 164 ThreadImage::TotalHits() const 165 { 166 return fTotalHits; 167 } 168 169 170 // #pragma mark - 171 172 173 thread_id 174 Thread::ID() const 175 { 176 return fID; 177 } 178 179 180 const char* 181 Thread::Name() const 182 { 183 return fName.String(); 184 } 185 186 187 addr_t* 188 Thread::Samples() const 189 { 190 return fSamples; 191 } 192 193 194 Team* 195 Thread::GetTeam() const 196 { 197 return fTeam; 198 } 199 200 201 ThreadProfileResult* 202 Thread::ProfileResult() const 203 { 204 return fProfileResult; 205 } 206 207 208 status_t 209 Thread::AddImage(Image* image) 210 { 211 return fProfileResult->AddImage(image); 212 } 213 214 215 void 216 Thread::RemoveImage(Image* image) 217 { 218 fProfileResult->RemoveImage(image); 219 } 220 221 222 // #pragma mark - AbstractThreadProfileResult 223 224 225 template<typename ThreadImageType> 226 AbstractThreadProfileResult<ThreadImageType>::AbstractThreadProfileResult() 227 : 228 fImages(), 229 fNewImages(), 230 fOldImages(), 231 fLazyImages(true) 232 { 233 } 234 235 236 template<typename ThreadImageType> 237 AbstractThreadProfileResult<ThreadImageType>::~AbstractThreadProfileResult() 238 { 239 while (ThreadImageType* image = fImages.RemoveHead()) 240 delete image; 241 while (ThreadImageType* image = fOldImages.RemoveHead()) 242 delete image; 243 } 244 245 246 template<typename ThreadImageType> 247 void 248 AbstractThreadProfileResult<ThreadImageType>::SetLazyImages(bool lazy) 249 { 250 fLazyImages = lazy; 251 } 252 253 254 template<typename ThreadImageType> 255 status_t 256 AbstractThreadProfileResult<ThreadImageType>::AddImage(Image* image) 257 { 258 ThreadImageType* threadImage = CreateThreadImage(image); 259 if (threadImage == NULL) 260 return B_NO_MEMORY; 261 262 status_t error = threadImage->Init(); 263 if (error != B_OK) { 264 delete threadImage; 265 return error; 266 } 267 268 if (fLazyImages) 269 fNewImages.Add(threadImage); 270 else 271 fImages.Add(threadImage); 272 273 return B_OK; 274 } 275 276 277 template<typename ThreadImageType> 278 void 279 AbstractThreadProfileResult<ThreadImageType>::RemoveImage(Image* image) 280 { 281 typename ImageList::Iterator it = fImages.GetIterator(); 282 while (ThreadImageType* threadImage = it.Next()) { 283 if (threadImage->GetImage() == image) { 284 it.Remove(); 285 if (threadImage->TotalHits() > 0) 286 fOldImages.Add(threadImage); 287 else 288 delete threadImage; 289 break; 290 } 291 } 292 } 293 294 295 template<typename ThreadImageType> 296 void 297 AbstractThreadProfileResult<ThreadImageType>::SynchronizeImages(int32 event) 298 { 299 // remove obsolete images 300 typename ImageList::Iterator it = fImages.GetIterator(); 301 while (ThreadImageType* image = it.Next()) { 302 int32 deleted = image->GetImage()->DeletionEvent(); 303 if (deleted >= 0 && event >= deleted) { 304 it.Remove(); 305 if (image->TotalHits() > 0) 306 fOldImages.Add(image); 307 else 308 delete image; 309 } 310 } 311 312 // add new images 313 it = fNewImages.GetIterator(); 314 while (ThreadImageType* image = it.Next()) { 315 if (image->GetImage()->CreationEvent() <= event) { 316 it.Remove(); 317 int32 deleted = image->GetImage()->DeletionEvent(); 318 if (deleted >= 0 && event >= deleted) { 319 // image already deleted 320 delete image; 321 } else 322 fImages.Add(image); 323 } 324 } 325 } 326 327 328 template<typename ThreadImageType> 329 ThreadImageType* 330 AbstractThreadProfileResult<ThreadImageType>::FindImage(addr_t address) const 331 { 332 typename ImageList::ConstIterator it = fImages.GetIterator(); 333 while (ThreadImageType* image = it.Next()) { 334 if (image->ContainsAddress(address)) 335 return image; 336 } 337 return NULL; 338 } 339 340 341 template<typename ThreadImageType> 342 int32 343 AbstractThreadProfileResult<ThreadImageType>::GetHitImages( 344 ThreadImageType** images) const 345 { 346 int32 imageCount = 0; 347 348 typename ImageList::ConstIterator it = fOldImages.GetIterator(); 349 while (ThreadImageType* image = it.Next()) { 350 if (image->TotalHits() > 0) 351 images[imageCount++] = image; 352 } 353 354 it = fImages.GetIterator(); 355 while (ThreadImageType* image = it.Next()) { 356 if (image->TotalHits() > 0) 357 images[imageCount++] = image; 358 } 359 360 return imageCount; 361 } 362 363 #endif // THREAD_H 364