xref: /haiku/src/bin/debug/profile/Thread.h (revision b671e9bbdbd10268a042b4f4cc4317ccd03d105e)
1 /*
2  * Copyright 2008-2009, 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 <String.h>
9 
10 #include <util/DoublyLinkedList.h>
11 
12 #include "Image.h"
13 
14 
15 class Team;
16 class ThreadImage;
17 class ThreadProfileResult;
18 
19 
20 class ThreadImage {
21 public:
22 								ThreadImage(Image* image);
23 	virtual						~ThreadImage();
24 
25 	virtual	status_t			Init();
26 
27 	inline	image_id			ID() const;
28 	inline	Image*				GetImage() const;
29 
30 	inline	bool				ContainsAddress(addr_t address) const;
31 
32 	inline	int64				TotalHits() const;
33 
34 protected:
35 			Image*				fImage;
36 			int64				fTotalHits;
37 };
38 
39 
40 class Thread : public DoublyLinkedListLinkImpl<Thread> {
41 public:
42 								Thread(thread_id threadID, const char* name,
43 									Team* team);
44 								~Thread();
45 
46 	inline	thread_id			ID() const;
47 	inline	const char*			Name() const;
48 	inline	addr_t*				Samples() const;
49 	inline	Team*				GetTeam() const;
50 
51 	inline	ThreadProfileResult* ProfileResult() const;
52 			void				SetProfileResult(ThreadProfileResult* result);
53 
54 			void				UpdateInfo(const char* name);
55 
56 			void				SetSampleArea(area_id area, addr_t* samples);
57 			void				SetInterval(bigtime_t interval);
58 
59 	inline	status_t			AddImage(Image* image);
60 	inline	void				RemoveImage(Image* image);
61 
62 			void				AddSamples(int32 count, int32 dropped,
63 									int32 stackDepth, bool variableStackDepth,
64 									int32 event);
65 			void				AddSamples(addr_t* samples, int32 sampleCount);
66 			void				PrintResults() const;
67 
68 private:
69 	typedef DoublyLinkedList<ThreadImage>	ImageList;
70 
71 private:
72 			thread_id			fID;
73 			BString				fName;
74 			::Team*				fTeam;
75 			area_id				fSampleArea;
76 			addr_t*				fSamples;
77 			ThreadProfileResult* fProfileResult;
78 };
79 
80 
81 class ThreadProfileResult {
82 public:
83 								ThreadProfileResult();
84 	virtual						~ThreadProfileResult();
85 
86 	virtual	status_t			Init(Thread* thread);
87 
88 			void				SetInterval(bigtime_t interval);
89 
90 	virtual	void				SetLazyImages(bool lazy) = 0;
91 
92 	virtual	status_t			AddImage(Image* image) = 0;
93 	virtual	void				RemoveImage(Image* image) = 0;
94 	virtual	void				SynchronizeImages(int32 event) = 0;
95 
96 	virtual	void				AddSamples(addr_t* samples,
97 									int32 sampleCount) = 0;
98 	virtual	void				AddDroppedTicks(int32 dropped) = 0;
99 	virtual	void				PrintResults() = 0;
100 
101 protected:
102 			Thread*				fThread;
103 			bigtime_t			fInterval;
104 };
105 
106 
107 template<typename ThreadImageType>
108 class AbstractThreadProfileResult : public ThreadProfileResult {
109 public:
110 								AbstractThreadProfileResult();
111 	virtual						~AbstractThreadProfileResult();
112 
113 	virtual	void				SetLazyImages(bool lazy);
114 
115 	virtual	status_t			AddImage(Image* image);
116 	virtual	void				RemoveImage(Image* image);
117 	virtual	void				SynchronizeImages(int32 event);
118 
119 			ThreadImageType*	FindImage(addr_t address) const;
120 			int32				GetHitImages(ThreadImageType** images) const;
121 
122 	virtual	void				AddSamples(addr_t* samples,
123 									int32 sampleCount) = 0;
124 	virtual	void				AddDroppedTicks(int32 dropped) = 0;
125 	virtual	void				PrintResults() = 0;
126 
127 	virtual ThreadImageType*	CreateThreadImage(Image* image) = 0;
128 
129 protected:
130 	typedef DoublyLinkedList<ThreadImageType>	ImageList;
131 
132 			ImageList			fImages;
133 			ImageList			fNewImages;
134 			ImageList			fOldImages;
135 			bool				fLazyImages;
136 };
137 
138 
139 // #pragma mark -
140 
141 
142 image_id
143 ThreadImage::ID() const
144 {
145 	return fImage->ID();
146 }
147 
148 
149 bool
150 ThreadImage::ContainsAddress(addr_t address) const
151 {
152 	return fImage->ContainsAddress(address);
153 }
154 
155 
156 Image*
157 ThreadImage::GetImage() const
158 {
159 	return fImage;
160 }
161 
162 
163 int64
164 ThreadImage::TotalHits() const
165 {
166 	return fTotalHits;
167 }
168 
169 
170 // #pragma mark -
171 
172 
173 thread_id
174 Thread::ID() const
175 {
176 	return fID;
177 }
178 
179 
180 const char*
181 Thread::Name() const
182 {
183 	return fName.String();
184 }
185 
186 
187 addr_t*
188 Thread::Samples() const
189 {
190 	return fSamples;
191 }
192 
193 
194 Team*
195 Thread::GetTeam() const
196 {
197 	return fTeam;
198 }
199 
200 
201 ThreadProfileResult*
202 Thread::ProfileResult() const
203 {
204 	return fProfileResult;
205 }
206 
207 
208 status_t
209 Thread::AddImage(Image* image)
210 {
211 	return fProfileResult->AddImage(image);
212 }
213 
214 
215 void
216 Thread::RemoveImage(Image* image)
217 {
218 	fProfileResult->RemoveImage(image);
219 }
220 
221 
222 // #pragma mark - AbstractThreadProfileResult
223 
224 
225 template<typename ThreadImageType>
226 AbstractThreadProfileResult<ThreadImageType>::AbstractThreadProfileResult()
227 	:
228 	fImages(),
229 	fNewImages(),
230 	fOldImages(),
231 	fLazyImages(true)
232 {
233 }
234 
235 
236 template<typename ThreadImageType>
237 AbstractThreadProfileResult<ThreadImageType>::~AbstractThreadProfileResult()
238 {
239 	while (ThreadImageType* image = fImages.RemoveHead())
240 		delete image;
241 	while (ThreadImageType* image = fOldImages.RemoveHead())
242 		delete image;
243 }
244 
245 
246 template<typename ThreadImageType>
247 void
248 AbstractThreadProfileResult<ThreadImageType>::SetLazyImages(bool lazy)
249 {
250 	fLazyImages = lazy;
251 }
252 
253 
254 template<typename ThreadImageType>
255 status_t
256 AbstractThreadProfileResult<ThreadImageType>::AddImage(Image* image)
257 {
258 	ThreadImageType* threadImage = CreateThreadImage(image);
259 	if (threadImage == NULL)
260 		return B_NO_MEMORY;
261 
262 	status_t error = threadImage->Init();
263 	if (error != B_OK) {
264 		delete threadImage;
265 		return error;
266 	}
267 
268 	if (fLazyImages)
269 		fNewImages.Add(threadImage);
270 	else
271 		fImages.Add(threadImage);
272 
273 	return B_OK;
274 }
275 
276 
277 template<typename ThreadImageType>
278 void
279 AbstractThreadProfileResult<ThreadImageType>::RemoveImage(Image* image)
280 {
281 	typename ImageList::Iterator it = fImages.GetIterator();
282 	while (ThreadImageType* threadImage = it.Next()) {
283 		if (threadImage->GetImage() == image) {
284 			it.Remove();
285 			if (threadImage->TotalHits() > 0)
286 				fOldImages.Add(threadImage);
287 			else
288 				delete threadImage;
289 			break;
290 		}
291 	}
292 }
293 
294 
295 template<typename ThreadImageType>
296 void
297 AbstractThreadProfileResult<ThreadImageType>::SynchronizeImages(int32 event)
298 {
299 	// remove obsolete images
300 	typename ImageList::Iterator it = fImages.GetIterator();
301 	while (ThreadImageType* image = it.Next()) {
302 		int32 deleted = image->GetImage()->DeletionEvent();
303 		if (deleted >= 0 && event >= deleted) {
304 			it.Remove();
305 			if (image->TotalHits() > 0)
306 				fOldImages.Add(image);
307 			else
308 				delete image;
309 		}
310 	}
311 
312 	// add new images
313 	it = fNewImages.GetIterator();
314 	while (ThreadImageType* image = it.Next()) {
315 		if (image->GetImage()->CreationEvent() <= event) {
316 			it.Remove();
317 			int32 deleted = image->GetImage()->DeletionEvent();
318 			if (deleted >= 0 && event >= deleted) {
319 				// image already deleted
320 				delete image;
321 			} else
322 				fImages.Add(image);
323 		}
324 	}
325 }
326 
327 
328 template<typename ThreadImageType>
329 ThreadImageType*
330 AbstractThreadProfileResult<ThreadImageType>::FindImage(addr_t address) const
331 {
332 	typename ImageList::ConstIterator it = fImages.GetIterator();
333 	while (ThreadImageType* image = it.Next()) {
334 		if (image->ContainsAddress(address))
335 			return image;
336 	}
337 	return NULL;
338 }
339 
340 
341 template<typename ThreadImageType>
342 int32
343 AbstractThreadProfileResult<ThreadImageType>::GetHitImages(
344 	ThreadImageType** images) const
345 {
346 	int32 imageCount = 0;
347 
348 	typename ImageList::ConstIterator it = fOldImages.GetIterator();
349 	while (ThreadImageType* image = it.Next()) {
350 		if (image->TotalHits() > 0)
351 			images[imageCount++] = image;
352 	}
353 
354 	it = fImages.GetIterator();
355 	while (ThreadImageType* image = it.Next()) {
356 		if (image->TotalHits() > 0)
357 			images[imageCount++] = image;
358 	}
359 
360 	return imageCount;
361 }
362 
363 #endif	// THREAD_H
364