1/* 2 * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include "Thread.h" 8 9#include <algorithm> 10#include <new> 11 12#include <debug_support.h> 13 14#include "debug_utils.h" 15 16#include "Image.h" 17#include "Options.h" 18#include "Team.h" 19 20 21// #pragma mark - ThreadImage 22 23 24ThreadImage::ThreadImage(Image* image, ImageProfileResult* result) 25 : 26 fImage(image), 27 fResult(result) 28{ 29 fImage->AcquireReference(); 30 fResult->AcquireReference(); 31} 32 33 34ThreadImage::~ThreadImage() 35{ 36 fImage->ReleaseReference(); 37 fResult->ReleaseReference(); 38} 39 40 41// #pragma mark - ThreadI 42 43 44Thread::Thread(thread_id threadID, const char* name, Team* team) 45 : 46 fID(threadID), 47 fName(name), 48 fTeam(team), 49 fSampleArea(-1), 50 fSamples(NULL), 51 fProfileResult(NULL), 52 fLazyImages(true) 53{ 54 fTeam->AcquireReference(); 55} 56 57 58Thread::~Thread() 59{ 60 if (fSampleArea >= 0) 61 delete_area(fSampleArea); 62 63 if (fProfileResult != NULL) 64 fProfileResult->ReleaseReference(); 65 66 while (ThreadImage* image = fImages.RemoveHead()) 67 delete image; 68 while (ThreadImage* image = fOldImages.RemoveHead()) 69 delete image; 70 71 fTeam->ReleaseReference(); 72} 73 74 75int32 76Thread::EntityID() const 77{ 78 return ID(); 79} 80 81 82const char* 83Thread::EntityName() const 84{ 85 return Name(); 86} 87 88 89const char* 90Thread::EntityType() const 91{ 92 return "thread"; 93} 94 95 96void 97Thread::SetProfileResult(ProfileResult* result) 98{ 99 ProfileResult* oldResult = fProfileResult; 100 101 fProfileResult = result; 102 if (fProfileResult != NULL) 103 fProfileResult->AcquireReference(); 104 105 if (oldResult) 106 oldResult->ReleaseReference(); 107} 108 109 110void 111Thread::UpdateInfo(const char* name) 112{ 113 fName = name; 114} 115 116 117void 118Thread::SetSampleArea(area_id area, addr_t* samples) 119{ 120 fSampleArea = area; 121 fSamples = samples; 122} 123 124 125void 126Thread::SetInterval(bigtime_t interval) 127{ 128 fProfileResult->SetInterval(interval); 129} 130 131 132void 133Thread::SetLazyImages(bool lazy) 134{ 135 fLazyImages = lazy; 136} 137 138 139status_t 140Thread::AddImage(Image* image) 141{ 142 ImageProfileResult* result; 143 status_t error = fProfileResult->GetImageProfileResult( 144 image->GetSharedImage(), image->ID(), result); 145 if (error != B_OK) 146 return error; 147 148 BReference<ImageProfileResult> resultReference(result, true); 149 150 ThreadImage* threadImage = new(std::nothrow) ThreadImage(image, result); 151 if (threadImage == NULL) 152 return B_NO_MEMORY; 153 154 if (fLazyImages) 155 fNewImages.Add(threadImage); 156 else 157 fImages.Add(threadImage); 158 159 return B_OK; 160} 161 162 163void 164Thread::RemoveImage(Image* image) 165{ 166 ImageList::Iterator it = fImages.GetIterator(); 167 while (ThreadImage* threadImage = it.Next()) { 168 if (threadImage->GetImage() == image) { 169 it.Remove(); 170 if (threadImage->Result()->TotalHits() > 0) 171 fOldImages.Add(threadImage); 172 else 173 delete threadImage; 174 break; 175 } 176 } 177} 178 179 180void 181Thread::AddSamples(int32 count, int32 dropped, int32 stackDepth, 182 bool variableStackDepth, int32 event) 183{ 184 _SynchronizeImages(event); 185 186 if (variableStackDepth) { 187 addr_t* samples = fSamples; 188 189 while (count > 0) { 190 addr_t sampleCount = *(samples++); 191 192 if (sampleCount >= B_DEBUG_PROFILE_EVENT_BASE) { 193 int32 eventParameterCount 194 = sampleCount & B_DEBUG_PROFILE_EVENT_PARAMETER_MASK; 195 if (sampleCount == B_DEBUG_PROFILE_IMAGE_EVENT) { 196 _SynchronizeImages((int32)samples[0]); 197 } else { 198 fprintf(stderr, "unknown profile event: %#lx\n", 199 sampleCount); 200 } 201 202 samples += eventParameterCount; 203 count -= eventParameterCount + 1; 204 continue; 205 } 206 207 fProfileResult->AddSamples(this, samples, sampleCount); 208 209 samples += sampleCount; 210 count -= sampleCount + 1; 211 } 212 } else { 213 count = count / stackDepth * stackDepth; 214 215 for (int32 i = 0; i < count; i += stackDepth) 216 fProfileResult->AddSamples(this, fSamples + i, stackDepth); 217 } 218 219 fProfileResult->AddDroppedTicks(dropped); 220} 221 222 223void 224Thread::AddSamples(addr_t* samples, int32 sampleCount) 225{ 226 fProfileResult->AddSamples(this, samples, sampleCount); 227} 228 229 230void 231Thread::PrintResults() 232{ 233 fProfileResult->PrintResults(this); 234} 235 236 237int32 238Thread::CountImages() const 239{ 240 return fImages.Count() + fOldImages.Count(); 241} 242 243 244ImageProfileResult* 245Thread::VisitImages(Visitor& visitor) const 246{ 247 ImageList::ConstIterator it = fOldImages.GetIterator(); 248 while (ThreadImage* image = it.Next()) { 249 if (visitor.VisitImage(image->Result())) 250 return image->Result(); 251 } 252 253 it = fImages.GetIterator(); 254 while (ThreadImage* image = it.Next()) { 255 if (visitor.VisitImage(image->Result())) 256 return image->Result(); 257 } 258 259 return NULL; 260} 261 262 263ImageProfileResult* 264Thread::FindImage(addr_t address, addr_t& _loadDelta) const 265{ 266 ImageList::ConstIterator it = fImages.GetIterator(); 267 while (ThreadImage* image = it.Next()) { 268 if (image->GetImage()->ContainsAddress(address)) { 269 _loadDelta = image->GetImage()->LoadDelta(); 270 return image->Result(); 271 } 272 } 273 return NULL; 274} 275 276 277void 278Thread::_SynchronizeImages(int32 event) 279{ 280 // remove obsolete images 281 ImageList::Iterator it = fImages.GetIterator(); 282 while (ThreadImage* image = it.Next()) { 283 int32 deleted = image->GetImage()->DeletionEvent(); 284 if (deleted >= 0 && event >= deleted) { 285 it.Remove(); 286 if (image->Result()->TotalHits() > 0) 287 fOldImages.Add(image); 288 else 289 delete image; 290 } 291 } 292 293 // add new images 294 it = fNewImages.GetIterator(); 295 while (ThreadImage* image = it.Next()) { 296 if (image->GetImage()->CreationEvent() <= event) { 297 it.Remove(); 298 int32 deleted = image->GetImage()->DeletionEvent(); 299 if (deleted >= 0 && event >= deleted) { 300 // image already deleted 301 delete image; 302 } else 303 fImages.Add(image); 304 } 305 } 306} 307