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 24 ThreadImage::ThreadImage(Image* image, ImageProfileResult* result) 25 : 26 fImage(image), 27 fResult(result) 28 { 29 fImage->AcquireReference(); 30 fResult->AcquireReference(); 31 } 32 33 34 ThreadImage::~ThreadImage() 35 { 36 fImage->ReleaseReference(); 37 fResult->ReleaseReference(); 38 } 39 40 41 // #pragma mark - ThreadI 42 43 44 Thread::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 58 Thread::~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 75 int32 76 Thread::EntityID() const 77 { 78 return ID(); 79 } 80 81 82 const char* 83 Thread::EntityName() const 84 { 85 return Name(); 86 } 87 88 89 const char* 90 Thread::EntityType() const 91 { 92 return "thread"; 93 } 94 95 96 void 97 Thread::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 110 void 111 Thread::UpdateInfo(const char* name) 112 { 113 fName = name; 114 } 115 116 117 void 118 Thread::SetSampleArea(area_id area, addr_t* samples) 119 { 120 fSampleArea = area; 121 fSamples = samples; 122 } 123 124 125 void 126 Thread::SetInterval(bigtime_t interval) 127 { 128 fProfileResult->SetInterval(interval); 129 } 130 131 132 void 133 Thread::SetLazyImages(bool lazy) 134 { 135 fLazyImages = lazy; 136 } 137 138 139 status_t 140 Thread::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 163 void 164 Thread::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 180 void 181 Thread::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 223 void 224 Thread::AddSamples(addr_t* samples, int32 sampleCount) 225 { 226 fProfileResult->AddSamples(this, samples, sampleCount); 227 } 228 229 230 void 231 Thread::PrintResults() 232 { 233 fProfileResult->PrintResults(this); 234 } 235 236 237 int32 238 Thread::CountImages() const 239 { 240 return fImages.Count() + fOldImages.Count(); 241 } 242 243 244 ImageProfileResult* 245 Thread::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 263 ImageProfileResult* 264 Thread::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 277 void 278 Thread::_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