2 * Copyright 2012-2015, Rene Gollent, rene@gollent.com.
3 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
4 * Distributed under the terms of the MIT License.
9 #include <AutoLocker.h>
11 #include "Architecture.h"
13 #include "DebuggerInterface.h"
14 #include "TeamTypeInformation.h"
17 #include "ValueLoader.h"
18 #include "ValueLocation.h"
19 #include "ValueNode.h"
20 #include "ValueNodeContainer.h"
22 #include "VariableValueNodeChild.h"
25 ResolveValueNodeValueJob::ResolveValueNodeValueJob(
26 DebuggerInterface
* debuggerInterface
, Architecture
* architecture
,
27 CpuState
* cpuState
, TeamTypeInformation
* typeInformation
,
28 ValueNodeContainer
* container
, ValueNode
* valueNode
)
30 fKey(valueNode
, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE
),
31 fDebuggerInterface(debuggerInterface
),
32 fArchitecture(architecture
),
34 fTypeInformation(typeInformation
),
35 fContainer(container
),
38 if (fCpuState
!= NULL
)
39 fCpuState
->AcquireReference();
40 fContainer
->AcquireReference();
41 fValueNode
->AcquireReference();
45 ResolveValueNodeValueJob::~ResolveValueNodeValueJob()
47 if (fCpuState
!= NULL
)
48 fCpuState
->ReleaseReference();
49 fContainer
->ReleaseReference();
50 fValueNode
->ReleaseReference();
55 ResolveValueNodeValueJob::Key() const
62 ResolveValueNodeValueJob::Do()
64 // check whether the node still belongs to the container
65 AutoLocker
<ValueNodeContainer
> containerLocker(fContainer
);
66 if (fValueNode
->Container() != fContainer
)
69 // if already resolved, we're done
70 status_t nodeResolutionState
71 = fValueNode
->LocationAndValueResolutionState();
72 if (nodeResolutionState
!= VALUE_NODE_UNRESOLVED
)
73 return nodeResolutionState
;
75 containerLocker
.Unlock();
78 status_t error
= _ResolveNodeValue();
80 nodeResolutionState
= fValueNode
->LocationAndValueResolutionState();
81 if (nodeResolutionState
!= VALUE_NODE_UNRESOLVED
)
82 return nodeResolutionState
;
84 containerLocker
.Lock();
85 fValueNode
->SetLocationAndValue(NULL
, NULL
, error
);
86 containerLocker
.Unlock();
94 ResolveValueNodeValueJob::_ResolveNodeValue()
96 // get the node child and parent node
97 AutoLocker
<ValueNodeContainer
> containerLocker(fContainer
);
98 ValueNodeChild
* nodeChild
= fValueNode
->NodeChild();
99 BReference
<ValueNodeChild
> nodeChildReference(nodeChild
);
101 ValueNode
* parentNode
= nodeChild
->Parent();
102 BReference
<ValueNode
> parentNodeReference(parentNode
);
104 // Check whether the node child location has been resolved already
106 status_t nodeChildResolutionState
= nodeChild
->LocationResolutionState();
107 bool nodeChildDone
= nodeChildResolutionState
!= VALUE_NODE_UNRESOLVED
;
108 if (nodeChildDone
&& nodeChildResolutionState
!= B_OK
)
109 return nodeChildResolutionState
;
111 // If the child node location has not been resolved yet, check whether the
112 // parent node location and value have been resolved already (successfully).
113 bool parentDone
= true;
114 if (!nodeChildDone
&& parentNode
!= NULL
) {
115 status_t parentResolutionState
116 = parentNode
->LocationAndValueResolutionState();
117 parentDone
= parentResolutionState
!= VALUE_NODE_UNRESOLVED
;
118 if (parentDone
&& parentResolutionState
!= B_OK
)
119 return parentResolutionState
;
122 containerLocker
.Unlock();
124 // resolve the parent node location and value, if necessary
126 status_t error
= _ResolveParentNodeValue(parentNode
);
128 TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
129 "node: %p (\"%s\"): _ResolveParentNodeValue(%p) failed\n",
130 fValueNode
, fValueNode
->Name().String(), parentNode
);
134 if (State() == JOB_STATE_WAITING
)
138 // resolve the node child location, if necessary
139 if (!nodeChildDone
) {
140 status_t error
= _ResolveNodeChildLocation(nodeChild
);
142 TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
143 "node: %p (\"%s\"): _ResolveNodeChildLocation(%p) failed\n",
144 fValueNode
, fValueNode
->Name().String(), nodeChild
);
149 CpuState
* variableCpuState
= NULL
;
150 VariableValueNodeChild
* variableChild
= dynamic_cast<
151 VariableValueNodeChild
*>(nodeChild
);
152 if (variableChild
!= NULL
)
153 variableCpuState
= variableChild
->GetVariable()->GetCpuState();
155 // resolve the node location and value
156 ValueLoader
valueLoader(fArchitecture
, fDebuggerInterface
,
157 variableCpuState
!= NULL
? variableCpuState
: fCpuState
);
158 ValueLocation
* location
;
160 status_t error
= fValueNode
->ResolvedLocationAndValue(&valueLoader
,
163 TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
164 "node: %p (\"%s\"): fValueNode->ResolvedLocationAndValue() "
165 "failed\n", fValueNode
, fValueNode
->Name().String());
168 BReference
<ValueLocation
> locationReference(location
, true);
169 BReference
<Value
> valueReference(value
, true);
171 // set location and value on the node
172 containerLocker
.Lock();
173 status_t nodeResolutionState
174 = fValueNode
->LocationAndValueResolutionState();
175 if (nodeResolutionState
!= VALUE_NODE_UNRESOLVED
)
176 return nodeResolutionState
;
177 fValueNode
->SetLocationAndValue(location
, value
, B_OK
);
178 containerLocker
.Unlock();
185 ResolveValueNodeValueJob::_ResolveNodeChildLocation(ValueNodeChild
* nodeChild
)
187 // resolve the location
188 ValueLoader
valueLoader(fArchitecture
, fDebuggerInterface
, fCpuState
);
189 ValueLocation
* location
= NULL
;
190 status_t error
= nodeChild
->ResolveLocation(&valueLoader
, location
);
191 BReference
<ValueLocation
> locationReference(location
, true);
193 // set the location on the node child
194 AutoLocker
<ValueNodeContainer
> containerLocker(fContainer
);
195 status_t nodeChildResolutionState
= nodeChild
->LocationResolutionState();
196 if (nodeChildResolutionState
== VALUE_NODE_UNRESOLVED
)
197 nodeChild
->SetLocation(location
, error
);
199 error
= nodeChildResolutionState
;
206 ResolveValueNodeValueJob::_ResolveParentNodeValue(ValueNode
* parentNode
)
208 AutoLocker
<ValueNodeContainer
> containerLocker(fContainer
);
210 if (parentNode
->Container() != fContainer
)
213 // if the parent node already has a value, we're done
214 status_t nodeResolutionState
215 = parentNode
->LocationAndValueResolutionState();
216 if (nodeResolutionState
!= VALUE_NODE_UNRESOLVED
)
217 return nodeResolutionState
;
219 // check whether a job is already in progress
220 AutoLocker
<Worker
> workerLocker(GetWorker());
221 SimpleJobKey
jobKey(parentNode
, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE
);
222 if (GetWorker()->GetJob(jobKey
) == NULL
) {
223 workerLocker
.Unlock();
226 status_t error
= GetWorker()->ScheduleJob(
227 new(std::nothrow
) ResolveValueNodeValueJob(fDebuggerInterface
,
228 fArchitecture
, fCpuState
, fTypeInformation
, fContainer
,
231 // scheduling failed -- set the value to invalid
232 parentNode
->SetLocationAndValue(NULL
, NULL
, error
);
237 // wait for the job to finish
238 workerLocker
.Unlock();
239 containerLocker
.Unlock();
241 switch (WaitFor(jobKey
)) {
242 case JOB_DEPENDENCY_SUCCEEDED
:
243 case JOB_DEPENDENCY_NOT_FOUND
:
244 // "Not found" can happen due to a race condition between
245 // unlocking the worker and starting to wait.
247 case JOB_DEPENDENCY_ACTIVE
:
249 case JOB_DEPENDENCY_FAILED
:
250 case JOB_DEPENDENCY_ABORTED
:
255 containerLocker
.Lock();
257 // now there should be a value for the node
258 nodeResolutionState
= parentNode
->LocationAndValueResolutionState();
259 return nodeResolutionState
!= VALUE_NODE_UNRESOLVED
260 ? nodeResolutionState
: B_ERROR
;