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