xref: /haiku/src/bin/debug/profile/Thread.h (revision 0562493379cd52eb7103531f895f10bb8e77c085)
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