1/*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "ThreadModel.h"
8
9#include <new>
10
11
12// #pragma mark - WaitObjectGroup
13
14
15ThreadModel::WaitObjectGroup::WaitObjectGroup(
16	Model::ThreadWaitObject** waitObjects, int32 count)
17	:
18	fWaitObjects(waitObjects),
19	fCount(count),
20	fWaits(0),
21	fTotalWaitTime(0)
22{
23	for (int32 i = 0; i < fCount; i++) {
24		fWaits += fWaitObjects[i]->Waits();
25		fTotalWaitTime += fWaitObjects[i]->TotalWaitTime();
26	}
27}
28
29
30ThreadModel::WaitObjectGroup::~WaitObjectGroup()
31{
32	delete[] fWaitObjects;
33}
34
35
36// #pragma mark - ThreadModel
37
38
39ThreadModel::ThreadModel(Model* model, Model::Thread* thread)
40	:
41	fModel(model),
42	fThread(thread),
43	fWaitObjectGroups(10, true)
44{
45}
46
47
48ThreadModel::~ThreadModel()
49{
50}
51
52
53ThreadModel::WaitObjectGroup*
54ThreadModel::AddWaitObjectGroup(
55	const BObjectList<Model::ThreadWaitObject>& waitObjects, int32 start,
56	int32 end)
57{
58	// check params
59	int32 count = end - start;
60	if (start < 0 || count <= 0 || waitObjects.CountItems() < end)
61		return NULL;
62
63	// create an array of the wait object
64	Model::ThreadWaitObject** objects
65		= new(std::nothrow) Model::ThreadWaitObject*[count];
66	if (objects == NULL)
67		return NULL;
68
69	for (int32 i = 0; i < count; i++)
70		objects[i] = waitObjects.ItemAt(start + i);
71
72	// create and add the group
73	WaitObjectGroup* group = new(std::nothrow) WaitObjectGroup(objects, count);
74	if (group == NULL) {
75		delete[] objects;
76		return NULL;
77	}
78
79	if (!fWaitObjectGroups.BinaryInsert(group,
80			&WaitObjectGroup::CompareByTypeName)) {
81		delete group;
82		return NULL;
83	}
84
85	return group;
86}
87
88
89bool
90ThreadModel::AddSchedulingEvent(const system_profiler_event_header* eventHeader)
91{
92	return fSchedulingEvents.AddItem(eventHeader);
93}
94
95
96int32
97ThreadModel::FindSchedulingEvent(nanotime_t time)
98{
99	if (time < 0)
100		return 0;
101
102	time += fModel->BaseTime();
103
104	int32 lower = 0;
105	int32 upper = CountSchedulingEvents() - 1;
106
107	while (lower < upper) {
108		int32 mid = (lower + upper) / 2;
109		const system_profiler_event_header* header = SchedulingEventAt(mid);
110		system_profiler_thread_scheduling_event* event
111			=  (system_profiler_thread_scheduling_event*)(header + 1);
112		if (event->time < time)
113			lower = mid + 1;
114		else
115			upper = mid;
116	}
117
118	// We've found the first event that has a time >= the given time. If its
119	// time is >, we rather return the previous event.
120	if (lower > 0) {
121		const system_profiler_event_header* header = SchedulingEventAt(lower);
122		system_profiler_thread_scheduling_event* event
123			=  (system_profiler_thread_scheduling_event*)(header + 1);
124		if (event->time > time)
125			lower--;
126	}
127
128	return lower;
129}
130