1120cfc62SIngo Weinhold/*
25fc675d5SIngo Weinhold * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3120cfc62SIngo Weinhold * Distributed under the terms of the MIT License.
4120cfc62SIngo Weinhold */
5120cfc62SIngo Weinhold
65fc675d5SIngo Weinhold
7120cfc62SIngo Weinhold#include "Thread.h"
8120cfc62SIngo Weinhold
9120cfc62SIngo Weinhold#include <algorithm>
10120cfc62SIngo Weinhold#include <new>
11120cfc62SIngo Weinhold
12120cfc62SIngo Weinhold#include <debug_support.h>
13120cfc62SIngo Weinhold
14120cfc62SIngo Weinhold#include "debug_utils.h"
15120cfc62SIngo Weinhold
166a28c22fSIngo Weinhold#include "Image.h"
17120cfc62SIngo Weinhold#include "Options.h"
18120cfc62SIngo Weinhold#include "Team.h"
19120cfc62SIngo Weinhold
20120cfc62SIngo Weinhold
216a28c22fSIngo Weinhold// #pragma mark - ThreadImage
226a28c22fSIngo Weinhold
236a28c22fSIngo Weinhold
246a28c22fSIngo WeinholdThreadImage::ThreadImage(Image* image, ImageProfileResult* result)
256a28c22fSIngo Weinhold	:
266a28c22fSIngo Weinhold	fImage(image),
276a28c22fSIngo Weinhold	fResult(result)
286a28c22fSIngo Weinhold{
296a28c22fSIngo Weinhold	fImage->AcquireReference();
3028f88875SIngo Weinhold	fResult->AcquireReference();
316a28c22fSIngo Weinhold}
326a28c22fSIngo Weinhold
336a28c22fSIngo Weinhold
346a28c22fSIngo WeinholdThreadImage::~ThreadImage()
356a28c22fSIngo Weinhold{
366a28c22fSIngo Weinhold	fImage->ReleaseReference();
3728f88875SIngo Weinhold	fResult->ReleaseReference();
386a28c22fSIngo Weinhold}
396a28c22fSIngo Weinhold
406a28c22fSIngo Weinhold
416a28c22fSIngo Weinhold// #pragma mark - ThreadI
426a28c22fSIngo Weinhold
43120cfc62SIngo Weinhold
441b9d2885SIngo WeinholdThread::Thread(thread_id threadID, const char* name, Team* team)
45120cfc62SIngo Weinhold	:
461b9d2885SIngo Weinhold	fID(threadID),
471b9d2885SIngo Weinhold	fName(name),
48120cfc62SIngo Weinhold	fTeam(team),
49120cfc62SIngo Weinhold	fSampleArea(-1),
50120cfc62SIngo Weinhold	fSamples(NULL),
516a28c22fSIngo Weinhold	fProfileResult(NULL),
526a28c22fSIngo Weinhold	fLazyImages(true)
53120cfc62SIngo Weinhold{
5475064315SIngo Weinhold	fTeam->AcquireReference();
55120cfc62SIngo Weinhold}
56120cfc62SIngo Weinhold
57120cfc62SIngo Weinhold
58120cfc62SIngo WeinholdThread::~Thread()
59120cfc62SIngo Weinhold{
60120cfc62SIngo Weinhold	if (fSampleArea >= 0)
61120cfc62SIngo Weinhold		delete_area(fSampleArea);
62ed2fc873SIngo Weinhold
6328f88875SIngo Weinhold	if (fProfileResult != NULL)
6428f88875SIngo Weinhold		fProfileResult->ReleaseReference();
656a28c22fSIngo Weinhold
666a28c22fSIngo Weinhold	while (ThreadImage* image = fImages.RemoveHead())
676a28c22fSIngo Weinhold		delete image;
686a28c22fSIngo Weinhold	while (ThreadImage* image = fOldImages.RemoveHead())
696a28c22fSIngo Weinhold		delete image;
7075064315SIngo Weinhold
7175064315SIngo Weinhold	fTeam->ReleaseReference();
72ed2fc873SIngo Weinhold}
73ed2fc873SIngo Weinhold
74ed2fc873SIngo Weinhold
755fc675d5SIngo Weinholdint32
765fc675d5SIngo WeinholdThread::EntityID() const
775fc675d5SIngo Weinhold{
785fc675d5SIngo Weinhold	return ID();
795fc675d5SIngo Weinhold}
805fc675d5SIngo Weinhold
815fc675d5SIngo Weinhold
825fc675d5SIngo Weinholdconst char*
835fc675d5SIngo WeinholdThread::EntityName() const
845fc675d5SIngo Weinhold{
855fc675d5SIngo Weinhold	return Name();
865fc675d5SIngo Weinhold}
875fc675d5SIngo Weinhold
885fc675d5SIngo Weinhold
895fc675d5SIngo Weinholdconst char*
905fc675d5SIngo WeinholdThread::EntityType() const
915fc675d5SIngo Weinhold{
925fc675d5SIngo Weinhold	return "thread";
935fc675d5SIngo Weinhold}
945fc675d5SIngo Weinhold
955fc675d5SIngo Weinhold
96ed2fc873SIngo Weinholdvoid
975fc675d5SIngo WeinholdThread::SetProfileResult(ProfileResult* result)
98ed2fc873SIngo Weinhold{
9928f88875SIngo Weinhold	ProfileResult* oldResult = fProfileResult;
10028f88875SIngo Weinhold
101ed2fc873SIngo Weinhold	fProfileResult = result;
10228f88875SIngo Weinhold	if (fProfileResult != NULL)
10328f88875SIngo Weinhold		fProfileResult->AcquireReference();
10428f88875SIngo Weinhold
10528f88875SIngo Weinhold	if (oldResult)
10628f88875SIngo Weinhold		oldResult->ReleaseReference();
107120cfc62SIngo Weinhold}
108120cfc62SIngo Weinhold
109120cfc62SIngo Weinhold
110120cfc62SIngo Weinholdvoid
1111b9d2885SIngo WeinholdThread::UpdateInfo(const char* name)
112120cfc62SIngo Weinhold{
1131b9d2885SIngo Weinhold	fName = name;
114120cfc62SIngo Weinhold}
115120cfc62SIngo Weinhold
116120cfc62SIngo Weinhold
117120cfc62SIngo Weinholdvoid
118120cfc62SIngo WeinholdThread::SetSampleArea(area_id area, addr_t* samples)
119120cfc62SIngo Weinhold{
120120cfc62SIngo Weinhold	fSampleArea = area;
121120cfc62SIngo Weinhold	fSamples = samples;
122120cfc62SIngo Weinhold}
123120cfc62SIngo Weinhold
124120cfc62SIngo Weinhold
125120cfc62SIngo Weinholdvoid
126120cfc62SIngo WeinholdThread::SetInterval(bigtime_t interval)
127120cfc62SIngo Weinhold{
128ed2fc873SIngo Weinhold	fProfileResult->SetInterval(interval);
129120cfc62SIngo Weinhold}
130120cfc62SIngo Weinhold
131120cfc62SIngo Weinhold
1326a28c22fSIngo Weinholdvoid
1336a28c22fSIngo WeinholdThread::SetLazyImages(bool lazy)
1346a28c22fSIngo Weinhold{
1356a28c22fSIngo Weinhold	fLazyImages = lazy;
1366a28c22fSIngo Weinhold}
1376a28c22fSIngo Weinhold
1386a28c22fSIngo Weinhold
1396a28c22fSIngo Weinholdstatus_t
1406a28c22fSIngo WeinholdThread::AddImage(Image* image)
1416a28c22fSIngo Weinhold{
14228f88875SIngo Weinhold	ImageProfileResult* result;
14328f88875SIngo Weinhold	status_t error = fProfileResult->GetImageProfileResult(
14428f88875SIngo Weinhold		image->GetSharedImage(), image->ID(), result);
14528f88875SIngo Weinhold	if (error != B_OK)
1466a28c22fSIngo Weinhold		return error;
14728f88875SIngo Weinhold
14828f88875SIngo Weinhold	BReference<ImageProfileResult> resultReference(result, true);
1496a28c22fSIngo Weinhold
1506a28c22fSIngo Weinhold	ThreadImage* threadImage = new(std::nothrow) ThreadImage(image, result);
15128f88875SIngo Weinhold	if (threadImage == NULL)
1526a28c22fSIngo Weinhold		return B_NO_MEMORY;
1536a28c22fSIngo Weinhold
1546a28c22fSIngo Weinhold	if (fLazyImages)
1556a28c22fSIngo Weinhold		fNewImages.Add(threadImage);
1566a28c22fSIngo Weinhold	else
1576a28c22fSIngo Weinhold		fImages.Add(threadImage);
1586a28c22fSIngo Weinhold
1596a28c22fSIngo Weinhold	return B_OK;
1606a28c22fSIngo Weinhold}
1616a28c22fSIngo Weinhold
1626a28c22fSIngo Weinhold
1636a28c22fSIngo Weinholdvoid
1646a28c22fSIngo WeinholdThread::RemoveImage(Image* image)
1656a28c22fSIngo Weinhold{
1666a28c22fSIngo Weinhold	ImageList::Iterator it = fImages.GetIterator();
1676a28c22fSIngo Weinhold	while (ThreadImage* threadImage = it.Next()) {
1686a28c22fSIngo Weinhold		if (threadImage->GetImage() == image) {
1696a28c22fSIngo Weinhold			it.Remove();
1706a28c22fSIngo Weinhold			if (threadImage->Result()->TotalHits() > 0)
1716a28c22fSIngo Weinhold				fOldImages.Add(threadImage);
1726a28c22fSIngo Weinhold			else
1736a28c22fSIngo Weinhold				delete threadImage;
1746a28c22fSIngo Weinhold			break;
1756a28c22fSIngo Weinhold		}
1766a28c22fSIngo Weinhold	}
1776a28c22fSIngo Weinhold}
1786a28c22fSIngo Weinhold
1796a28c22fSIngo Weinhold
180ed2fc873SIngo Weinholdvoid
181ed2fc873SIngo WeinholdThread::AddSamples(int32 count, int32 dropped, int32 stackDepth,
182ed2fc873SIngo Weinhold	bool variableStackDepth, int32 event)
183ed2fc873SIngo Weinhold{
1846a28c22fSIngo Weinhold	_SynchronizeImages(event);
185ed2fc873SIngo Weinhold
186ed2fc873SIngo Weinhold	if (variableStackDepth) {
187ed2fc873SIngo Weinhold		addr_t* samples = fSamples;
188ed2fc873SIngo Weinhold
189ed2fc873SIngo Weinhold		while (count > 0) {
190ed2fc873SIngo Weinhold			addr_t sampleCount = *(samples++);
191ed2fc873SIngo Weinhold
192ed2fc873SIngo Weinhold			if (sampleCount >= B_DEBUG_PROFILE_EVENT_BASE) {
193ed2fc873SIngo Weinhold				int32 eventParameterCount
194ed2fc873SIngo Weinhold					= sampleCount & B_DEBUG_PROFILE_EVENT_PARAMETER_MASK;
195ed2fc873SIngo Weinhold				if (sampleCount == B_DEBUG_PROFILE_IMAGE_EVENT) {
1966a28c22fSIngo Weinhold					_SynchronizeImages((int32)samples[0]);
197ed2fc873SIngo Weinhold				} else {
198ed2fc873SIngo Weinhold					fprintf(stderr, "unknown profile event: %#lx\n",
199ed2fc873SIngo Weinhold						sampleCount);
200ed2fc873SIngo Weinhold				}
201ed2fc873SIngo Weinhold
202ed2fc873SIngo Weinhold				samples += eventParameterCount;
203ed2fc873SIngo Weinhold				count -= eventParameterCount + 1;
204ed2fc873SIngo Weinhold				continue;
205ed2fc873SIngo Weinhold			}
206ed2fc873SIngo Weinhold
2076a28c22fSIngo Weinhold			fProfileResult->AddSamples(this, samples, sampleCount);
208ed2fc873SIngo Weinhold
209ed2fc873SIngo Weinhold			samples += sampleCount;
210ed2fc873SIngo Weinhold			count -= sampleCount + 1;
211ed2fc873SIngo Weinhold		}
212ed2fc873SIngo Weinhold	} else {
213ed2fc873SIngo Weinhold		count = count / stackDepth * stackDepth;
214ed2fc873SIngo Weinhold
215ed2fc873SIngo Weinhold		for (int32 i = 0; i < count; i += stackDepth)
2166a28c22fSIngo Weinhold			fProfileResult->AddSamples(this, fSamples + i, stackDepth);
217ed2fc873SIngo Weinhold	}
218ed2fc873SIngo Weinhold
219ed2fc873SIngo Weinhold	fProfileResult->AddDroppedTicks(dropped);
220ed2fc873SIngo Weinhold}
221ed2fc873SIngo Weinhold
222ed2fc873SIngo Weinhold
2230f379156SIngo Weinholdvoid
2240f379156SIngo WeinholdThread::AddSamples(addr_t* samples, int32 sampleCount)
2250f379156SIngo Weinhold{
2266a28c22fSIngo Weinhold	fProfileResult->AddSamples(this, samples, sampleCount);
2270f379156SIngo Weinhold}
2280f379156SIngo Weinhold
2290f379156SIngo Weinhold
230ed2fc873SIngo Weinholdvoid
2316a28c22fSIngo WeinholdThread::PrintResults()
2326a28c22fSIngo Weinhold{
2336a28c22fSIngo Weinhold	fProfileResult->PrintResults(this);
2346a28c22fSIngo Weinhold}
2356a28c22fSIngo Weinhold
2366a28c22fSIngo Weinhold
2376a28c22fSIngo Weinholdint32
2386a28c22fSIngo WeinholdThread::CountImages() const
2396a28c22fSIngo Weinhold{
2406a28c22fSIngo Weinhold	return fImages.Count() + fOldImages.Count();
2416a28c22fSIngo Weinhold}
2426a28c22fSIngo Weinhold
2436a28c22fSIngo Weinhold
2446a28c22fSIngo WeinholdImageProfileResult*
2456a28c22fSIngo WeinholdThread::VisitImages(Visitor& visitor) const
246ed2fc873SIngo Weinhold{
2476a28c22fSIngo Weinhold	ImageList::ConstIterator it = fOldImages.GetIterator();
2486a28c22fSIngo Weinhold	while (ThreadImage* image = it.Next()) {
2496a28c22fSIngo Weinhold		if (visitor.VisitImage(image->Result()))
2506a28c22fSIngo Weinhold			return image->Result();
2516a28c22fSIngo Weinhold	}
2526a28c22fSIngo Weinhold
2536a28c22fSIngo Weinhold	it = fImages.GetIterator();
2546a28c22fSIngo Weinhold	while (ThreadImage* image = it.Next()) {
2556a28c22fSIngo Weinhold		if (visitor.VisitImage(image->Result()))
2566a28c22fSIngo Weinhold			return image->Result();
2576a28c22fSIngo Weinhold	}
2586a28c22fSIngo Weinhold
2596a28c22fSIngo Weinhold	return NULL;
2606a28c22fSIngo Weinhold}
2616a28c22fSIngo Weinhold
2626a28c22fSIngo Weinhold
2636a28c22fSIngo WeinholdImageProfileResult*
2646a28c22fSIngo WeinholdThread::FindImage(addr_t address, addr_t& _loadDelta) const
2656a28c22fSIngo Weinhold{
2666a28c22fSIngo Weinhold	ImageList::ConstIterator it = fImages.GetIterator();
2676a28c22fSIngo Weinhold	while (ThreadImage* image = it.Next()) {
2686a28c22fSIngo Weinhold		if (image->GetImage()->ContainsAddress(address)) {
2696a28c22fSIngo Weinhold			_loadDelta = image->GetImage()->LoadDelta();
2706a28c22fSIngo Weinhold			return image->Result();
2716a28c22fSIngo Weinhold		}
2726a28c22fSIngo Weinhold	}
2736a28c22fSIngo Weinhold	return NULL;
2746a28c22fSIngo Weinhold}
2756a28c22fSIngo Weinhold
2766a28c22fSIngo Weinhold
2776a28c22fSIngo Weinholdvoid
2786a28c22fSIngo WeinholdThread::_SynchronizeImages(int32 event)
2796a28c22fSIngo Weinhold{
2806a28c22fSIngo Weinhold	// remove obsolete images
2816a28c22fSIngo Weinhold	ImageList::Iterator it = fImages.GetIterator();
2826a28c22fSIngo Weinhold	while (ThreadImage* image = it.Next()) {
2836a28c22fSIngo Weinhold		int32 deleted = image->GetImage()->DeletionEvent();
2846a28c22fSIngo Weinhold		if (deleted >= 0 && event >= deleted) {
2856a28c22fSIngo Weinhold			it.Remove();
2866a28c22fSIngo Weinhold			if (image->Result()->TotalHits() > 0)
2876a28c22fSIngo Weinhold				fOldImages.Add(image);
2886a28c22fSIngo Weinhold			else
2896a28c22fSIngo Weinhold				delete image;
2906a28c22fSIngo Weinhold		}
2916a28c22fSIngo Weinhold	}
2926a28c22fSIngo Weinhold
2936a28c22fSIngo Weinhold	// add new images
2946a28c22fSIngo Weinhold	it = fNewImages.GetIterator();
2956a28c22fSIngo Weinhold	while (ThreadImage* image = it.Next()) {
2966a28c22fSIngo Weinhold		if (image->GetImage()->CreationEvent() <= event) {
2976a28c22fSIngo Weinhold			it.Remove();
2986a28c22fSIngo Weinhold			int32 deleted = image->GetImage()->DeletionEvent();
2996a28c22fSIngo Weinhold			if (deleted >= 0 && event >= deleted) {
3006a28c22fSIngo Weinhold				// image already deleted
3016a28c22fSIngo Weinhold				delete image;
3026a28c22fSIngo Weinhold			} else
3036a28c22fSIngo Weinhold				fImages.Add(image);
3046a28c22fSIngo Weinhold		}
3056a28c22fSIngo Weinhold	}
306ed2fc873SIngo Weinhold}
307