vfs: check userland buffers before reading them.
[haiku.git] / src / bin / debug / profile / Thread.cpp
blobb8cec22651d5c8766036fb0a28f9064267c22243
1 /*
2 * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include "Thread.h"
9 #include <algorithm>
10 #include <new>
12 #include <debug_support.h>
14 #include "debug_utils.h"
16 #include "Image.h"
17 #include "Options.h"
18 #include "Team.h"
21 // #pragma mark - ThreadImage
24 ThreadImage::ThreadImage(Image* image, ImageProfileResult* result)
26 fImage(image),
27 fResult(result)
29 fImage->AcquireReference();
30 fResult->AcquireReference();
34 ThreadImage::~ThreadImage()
36 fImage->ReleaseReference();
37 fResult->ReleaseReference();
41 // #pragma mark - ThreadI
44 Thread::Thread(thread_id threadID, const char* name, Team* team)
46 fID(threadID),
47 fName(name),
48 fTeam(team),
49 fSampleArea(-1),
50 fSamples(NULL),
51 fProfileResult(NULL),
52 fLazyImages(true)
54 fTeam->AcquireReference();
58 Thread::~Thread()
60 if (fSampleArea >= 0)
61 delete_area(fSampleArea);
63 if (fProfileResult != NULL)
64 fProfileResult->ReleaseReference();
66 while (ThreadImage* image = fImages.RemoveHead())
67 delete image;
68 while (ThreadImage* image = fOldImages.RemoveHead())
69 delete image;
71 fTeam->ReleaseReference();
75 int32
76 Thread::EntityID() const
78 return ID();
82 const char*
83 Thread::EntityName() const
85 return Name();
89 const char*
90 Thread::EntityType() const
92 return "thread";
96 void
97 Thread::SetProfileResult(ProfileResult* result)
99 ProfileResult* oldResult = fProfileResult;
101 fProfileResult = result;
102 if (fProfileResult != NULL)
103 fProfileResult->AcquireReference();
105 if (oldResult)
106 oldResult->ReleaseReference();
110 void
111 Thread::UpdateInfo(const char* name)
113 fName = name;
117 void
118 Thread::SetSampleArea(area_id area, addr_t* samples)
120 fSampleArea = area;
121 fSamples = samples;
125 void
126 Thread::SetInterval(bigtime_t interval)
128 fProfileResult->SetInterval(interval);
132 void
133 Thread::SetLazyImages(bool lazy)
135 fLazyImages = lazy;
139 status_t
140 Thread::AddImage(Image* image)
142 ImageProfileResult* result;
143 status_t error = fProfileResult->GetImageProfileResult(
144 image->GetSharedImage(), image->ID(), result);
145 if (error != B_OK)
146 return error;
148 BReference<ImageProfileResult> resultReference(result, true);
150 ThreadImage* threadImage = new(std::nothrow) ThreadImage(image, result);
151 if (threadImage == NULL)
152 return B_NO_MEMORY;
154 if (fLazyImages)
155 fNewImages.Add(threadImage);
156 else
157 fImages.Add(threadImage);
159 return B_OK;
163 void
164 Thread::RemoveImage(Image* image)
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;
180 void
181 Thread::AddSamples(int32 count, int32 dropped, int32 stackDepth,
182 bool variableStackDepth, int32 event)
184 _SynchronizeImages(event);
186 if (variableStackDepth) {
187 addr_t* samples = fSamples;
189 while (count > 0) {
190 addr_t sampleCount = *(samples++);
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);
202 samples += eventParameterCount;
203 count -= eventParameterCount + 1;
204 continue;
207 fProfileResult->AddSamples(this, samples, sampleCount);
209 samples += sampleCount;
210 count -= sampleCount + 1;
212 } else {
213 count = count / stackDepth * stackDepth;
215 for (int32 i = 0; i < count; i += stackDepth)
216 fProfileResult->AddSamples(this, fSamples + i, stackDepth);
219 fProfileResult->AddDroppedTicks(dropped);
223 void
224 Thread::AddSamples(addr_t* samples, int32 sampleCount)
226 fProfileResult->AddSamples(this, samples, sampleCount);
230 void
231 Thread::PrintResults()
233 fProfileResult->PrintResults(this);
237 int32
238 Thread::CountImages() const
240 return fImages.Count() + fOldImages.Count();
244 ImageProfileResult*
245 Thread::VisitImages(Visitor& visitor) const
247 ImageList::ConstIterator it = fOldImages.GetIterator();
248 while (ThreadImage* image = it.Next()) {
249 if (visitor.VisitImage(image->Result()))
250 return image->Result();
253 it = fImages.GetIterator();
254 while (ThreadImage* image = it.Next()) {
255 if (visitor.VisitImage(image->Result()))
256 return image->Result();
259 return NULL;
263 ImageProfileResult*
264 Thread::FindImage(addr_t address, addr_t& _loadDelta) const
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();
273 return NULL;
277 void
278 Thread::_SynchronizeImages(int32 event)
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;
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);