Diff markup
1 /********************************************* 1 /******************************************************************************
2 * 2 *
3 * Module Name: dsmethod - Parser/Interpreter 3 * Module Name: dsmethod - Parser/Interpreter interface - control method parsing
4 * 4 *
5 ********************************************* 5 *****************************************************************************/
6 6
7 /* 7 /*
8 * Copyright (C) 2000 - 2007, R. Byron Moore !! 8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * Redistribution and use in source and binary 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that t 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must reta 14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the 15 * notice, this list of conditions, and the following disclaimer,
16 * without modification. 16 * without modification.
17 * 2. Redistributions in binary form must repr 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANT 18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution mu 19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Discla 20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution. 21 * binary redistribution.
22 * 3. Neither the names of the above-listed co 22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endor 23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prio 24 * from this software without specific prior written permission.
25 * 25 *
26 * Alternatively, this software may be distrib 26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation. 28 * Software Foundation.
29 * 29 *
30 * NO WARRANTY 30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTI 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCH 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECI 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PRO 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILI 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIG 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES. 41 * POSSIBILITY OF SUCH DAMAGES.
42 */ 42 */
43 43
>> 44
44 #include <acpi/acpi.h> 45 #include <acpi/acpi.h>
45 #include <acpi/acparser.h> 46 #include <acpi/acparser.h>
46 #include <acpi/amlcode.h> 47 #include <acpi/amlcode.h>
47 #include <acpi/acdispat.h> 48 #include <acpi/acdispat.h>
48 #include <acpi/acinterp.h> 49 #include <acpi/acinterp.h>
49 #include <acpi/acnamesp.h> 50 #include <acpi/acnamesp.h>
50 #include <acpi/acdisasm.h> !! 51
51 52
52 #define _COMPONENT ACPI_DISPATCHER 53 #define _COMPONENT ACPI_DISPATCHER
53 ACPI_MODULE_NAME("dsmethod") !! 54 ACPI_MODULE_NAME ("dsmethod")
54 55
55 /* Local prototypes */ <<
56 static acpi_status <<
57 acpi_ds_create_method_mutex(union acpi_operand <<
58 56
59 /********************************************* 57 /*******************************************************************************
60 * 58 *
61 * FUNCTION: acpi_ds_method_error !! 59 * FUNCTION: acpi_ds_parse_method
62 * 60 *
63 * PARAMETERS: Status - Execution st !! 61 * PARAMETERS: obj_handle - Method node
64 * walk_state - Current stat <<
65 * 62 *
66 * RETURN: Status 63 * RETURN: Status
67 * 64 *
68 * DESCRIPTION: Called on method error. Invoke !! 65 * DESCRIPTION: Call the parser and parse the AML that is associated with the
69 * present, dump the method data !! 66 * method.
70 * 67 *
71 * Note: Allows the exception han !! 68 * MUTEX: Assumes parser is locked
72 * 69 *
73 ********************************************* 70 ******************************************************************************/
74 71
75 acpi_status 72 acpi_status
76 acpi_ds_method_error(acpi_status status, struc !! 73 acpi_ds_parse_method (
>> 74 acpi_handle obj_handle)
77 { 75 {
78 ACPI_FUNCTION_ENTRY(); !! 76 acpi_status status;
>> 77 union acpi_operand_object *obj_desc;
>> 78 union acpi_parse_object *op;
>> 79 struct acpi_namespace_node *node;
>> 80 acpi_owner_id owner_id;
>> 81 struct acpi_walk_state *walk_state;
79 82
80 /* Ignore AE_OK and control exception <<
81 83
82 if (ACPI_SUCCESS(status) || (status & !! 84 ACPI_FUNCTION_TRACE_PTR ("ds_parse_method", obj_handle);
83 return (status); <<
84 } <<
85 85
86 /* Invoke the global exception handler <<
87 86
88 if (acpi_gbl_exception_handler) { !! 87 /* Parameter Validation */
89 88
90 /* Exit the interpreter, allow !! 89 if (!obj_handle) {
>> 90 return_ACPI_STATUS (AE_NULL_ENTRY);
>> 91 }
91 92
92 acpi_ex_exit_interpreter(); !! 93 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Parsing [%4.4s] **** named_obj=%p\n",
>> 94 acpi_ut_get_node_name (obj_handle), obj_handle));
93 95
94 /* !! 96 /* Extract the method object from the method Node */
95 * Handler can map the excepti !! 97
96 * AE_OK, in which case the ex !! 98 node = (struct acpi_namespace_node *) obj_handle;
97 */ !! 99 obj_desc = acpi_ns_get_attached_object (node);
98 status = acpi_gbl_exception_ha !! 100 if (!obj_desc) {
99 !! 101 return_ACPI_STATUS (AE_NULL_OBJECT);
100 <<
101 <<
102 <<
103 <<
104 <<
105 (void)acpi_ex_enter_interprete <<
106 } 102 }
107 #ifdef ACPI_DISASSEMBLER <<
108 if (ACPI_FAILURE(status)) { <<
109 103
110 /* Display method locals/args !! 104 /* Create a mutex for the method if there is a concurrency limit */
111 105
112 acpi_dm_dump_method_info(statu !! 106 if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) &&
>> 107 (!obj_desc->method.semaphore)) {
>> 108 status = acpi_os_create_semaphore (obj_desc->method.concurrency,
>> 109 obj_desc->method.concurrency,
>> 110 &obj_desc->method.semaphore);
>> 111 if (ACPI_FAILURE (status)) {
>> 112 return_ACPI_STATUS (status);
>> 113 }
113 } 114 }
114 #endif <<
115 115
116 return (status); !! 116 /*
117 } !! 117 * Allocate a new parser op to be the root of the parsed
>> 118 * method tree
>> 119 */
>> 120 op = acpi_ps_alloc_op (AML_METHOD_OP);
>> 121 if (!op) {
>> 122 return_ACPI_STATUS (AE_NO_MEMORY);
>> 123 }
118 124
119 /********************************************* !! 125 /* Init new op with the method name and pointer back to the Node */
120 * <<
121 * FUNCTION: acpi_ds_create_method_mutex <<
122 * <<
123 * PARAMETERS: obj_desc - The meth <<
124 * <<
125 * RETURN: Status <<
126 * <<
127 * DESCRIPTION: Create a mutex object for a se <<
128 * <<
129 ********************************************* <<
130 126
131 static acpi_status !! 127 acpi_ps_set_name (op, node->name.integer);
132 acpi_ds_create_method_mutex(union acpi_operand !! 128 op->common.node = node;
133 { <<
134 union acpi_operand_object *mutex_desc; <<
135 acpi_status status; <<
136 129
137 ACPI_FUNCTION_TRACE(ds_create_method_m !! 130 /*
>> 131 * Get a new owner_id for objects created by this method. Namespace
>> 132 * objects (such as Operation Regions) can be created during the
>> 133 * first pass parse.
>> 134 */
>> 135 owner_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD);
>> 136 obj_desc->method.owning_id = owner_id;
138 137
139 /* Create the new mutex object */ !! 138 /* Create and initialize a new walk state */
140 139
141 mutex_desc = acpi_ut_create_internal_o !! 140 walk_state = acpi_ds_create_walk_state (owner_id, NULL, NULL, NULL);
142 if (!mutex_desc) { !! 141 if (!walk_state) {
143 return_ACPI_STATUS(AE_NO_MEMOR !! 142 return_ACPI_STATUS (AE_NO_MEMORY);
>> 143 }
>> 144
>> 145 status = acpi_ds_init_aml_walk (walk_state, op, node,
>> 146 obj_desc->method.aml_start,
>> 147 obj_desc->method.aml_length, NULL, 1);
>> 148 if (ACPI_FAILURE (status)) {
>> 149 acpi_ds_delete_walk_state (walk_state);
>> 150 return_ACPI_STATUS (status);
144 } 151 }
145 152
146 /* Create the actual OS Mutex */ !! 153 /*
147 !! 154 * Parse the method, first pass
148 status = acpi_os_create_mutex(&mutex_d !! 155 *
149 if (ACPI_FAILURE(status)) { !! 156 * The first pass load is where newly declared named objects are
150 return_ACPI_STATUS(status); !! 157 * added into the namespace. Actual evaluation of
>> 158 * the named objects (what would be called a "second
>> 159 * pass") happens during the actual execution of the
>> 160 * method so that operands to the named objects can
>> 161 * take on dynamic run-time values.
>> 162 */
>> 163 status = acpi_ps_parse_aml (walk_state);
>> 164 if (ACPI_FAILURE (status)) {
>> 165 return_ACPI_STATUS (status);
151 } 166 }
152 167
153 mutex_desc->mutex.sync_level = method_ !! 168 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
154 method_desc->method.mutex = mutex_desc !! 169 "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n",
155 return_ACPI_STATUS(AE_OK); !! 170 acpi_ut_get_node_name (obj_handle), obj_handle, op));
>> 171
>> 172 acpi_ps_delete_parse_tree (op);
>> 173 return_ACPI_STATUS (status);
156 } 174 }
157 175
>> 176
158 /********************************************* 177 /*******************************************************************************
159 * 178 *
160 * FUNCTION: acpi_ds_begin_method_execution 179 * FUNCTION: acpi_ds_begin_method_execution
161 * 180 *
162 * PARAMETERS: method_node - Node of 181 * PARAMETERS: method_node - Node of the method
163 * obj_desc - The meth 182 * obj_desc - The method object
164 * walk_state - current !! 183 * calling_method_node - Caller of this method (if non-null)
165 * a method <<
166 * 184 *
167 * RETURN: Status 185 * RETURN: Status
168 * 186 *
169 * DESCRIPTION: Prepare a method for execution 187 * DESCRIPTION: Prepare a method for execution. Parses the method if necessary,
170 * increments the thread count, a 188 * increments the thread count, and waits at the method semaphore
171 * for clearance to execute. 189 * for clearance to execute.
172 * 190 *
173 ********************************************* 191 ******************************************************************************/
174 192
175 acpi_status 193 acpi_status
176 acpi_ds_begin_method_execution(struct acpi_nam !! 194 acpi_ds_begin_method_execution (
177 union acpi_oper !! 195 struct acpi_namespace_node *method_node,
178 struct acpi_wal !! 196 union acpi_operand_object *obj_desc,
>> 197 struct acpi_namespace_node *calling_method_node)
179 { 198 {
180 acpi_status status = AE_OK; !! 199 acpi_status status = AE_OK;
181 200
182 ACPI_FUNCTION_TRACE_PTR(ds_begin_metho <<
183 201
184 if (!method_node) { !! 202 ACPI_FUNCTION_TRACE_PTR ("ds_begin_method_execution", method_node);
185 return_ACPI_STATUS(AE_NULL_ENT <<
186 } <<
187 203
188 /* Prevent wraparound of thread count <<
189 204
190 if (obj_desc->method.thread_count == A !! 205 if (!method_node) {
191 ACPI_ERROR((AE_INFO, !! 206 return_ACPI_STATUS (AE_NULL_ENTRY);
192 "Method reached ma <<
193 return_ACPI_STATUS(AE_AML_METH <<
194 } 207 }
195 208
196 /* 209 /*
197 * If this method is serialized, we ne !! 210 * If there is a concurrency limit on this method, we need to
>> 211 * obtain a unit from the method semaphore.
198 */ 212 */
199 if (obj_desc->method.method_flags & AM !! 213 if (obj_desc->method.semaphore) {
200 /* <<
201 * Create a mutex for the meth <<
202 * and a mutex has not already <<
203 * until a method is actually <<
204 */ <<
205 if (!obj_desc->method.mutex) { <<
206 status = acpi_ds_creat <<
207 if (ACPI_FAILURE(statu <<
208 return_ACPI_ST <<
209 } <<
210 } <<
211 <<
212 /* 214 /*
213 * The current_sync_level (per !! 215 * Allow recursive method calls, up to the reentrancy/concurrency
214 * the sync level of the metho !! 216 * limit imposed by the SERIALIZED rule and the sync_level method
215 * deadlock prevention !! 217 * parameter.
216 * 218 *
217 * Top-level method invocation !! 219 * The point of this code is to avoid permanently blocking a
>> 220 * thread that is making recursive method calls.
218 */ 221 */
219 if (walk_state && !! 222 if (method_node == calling_method_node) {
220 (walk_state->thread->curre !! 223 if (obj_desc->method.thread_count >= obj_desc->method.concurrency) {
221 obj_desc->method.mutex->m !! 224 return_ACPI_STATUS (AE_AML_METHOD_LIMIT);
222 ACPI_ERROR((AE_INFO, !! 225 }
223 "Cannot ac <<
224 acpi_ut_ge <<
225 walk_state <<
226 <<
227 return_ACPI_STATUS(AE_ <<
228 } 226 }
229 227
230 /* 228 /*
231 * Obtain the method mutex if !! 229 * Get a unit from the method semaphore. This releases the
232 * recursive call. !! 230 * interpreter if we block
233 */ 231 */
234 if (!walk_state || !! 232 status = acpi_ex_system_wait_semaphore (obj_desc->method.semaphore,
235 !obj_desc->method.mutex->m !! 233 ACPI_WAIT_FOREVER);
236 (walk_state->thread != <<
237 obj_desc->method.mutex->m <<
238 /* <<
239 * Acquire the method <<
240 * block (and reacquir <<
241 */ <<
242 status = <<
243 acpi_ex_system_wai <<
244 <<
245 <<
246 if (ACPI_FAILURE(statu <<
247 return_ACPI_ST <<
248 } <<
249 <<
250 /* Update the mutex an <<
251 <<
252 if (walk_state) { <<
253 obj_desc->meth <<
254 original_s <<
255 walk_state <<
256 <<
257 obj_desc->meth <<
258 walk_state <<
259 walk_state->th <<
260 obj_desc-> <<
261 } else { <<
262 obj_desc->meth <<
263 original_s <<
264 obj_desc-> <<
265 } <<
266 } <<
267 <<
268 /* Always increase acquisition <<
269 <<
270 obj_desc->method.mutex->mutex. <<
271 } <<
272 <<
273 /* <<
274 * Allocate an Owner ID for this metho <<
275 * to begin concurrent execution. We o <<
276 * method is invoked recursively. <<
277 */ <<
278 if (!obj_desc->method.owner_id) { <<
279 status = acpi_ut_allocate_owne <<
280 if (ACPI_FAILURE(status)) { <<
281 goto cleanup; <<
282 } <<
283 } 234 }
284 235
285 /* 236 /*
286 * Increment the method parse tree thr 237 * Increment the method parse tree thread count since it has been
287 * reentered one more time (even if it 238 * reentered one more time (even if it is the same thread)
288 */ 239 */
289 obj_desc->method.thread_count++; 240 obj_desc->method.thread_count++;
290 return_ACPI_STATUS(status); !! 241 return_ACPI_STATUS (status);
291 <<
292 cleanup: <<
293 /* On error, must release the method m <<
294 <<
295 if (obj_desc->method.mutex) { <<
296 acpi_os_release_mutex(obj_desc <<
297 } <<
298 return_ACPI_STATUS(status); <<
299 } 242 }
300 243
>> 244
301 /********************************************* 245 /*******************************************************************************
302 * 246 *
303 * FUNCTION: acpi_ds_call_control_method 247 * FUNCTION: acpi_ds_call_control_method
304 * 248 *
305 * PARAMETERS: Thread - Info for 249 * PARAMETERS: Thread - Info for this thread
306 * this_walk_state - Current 250 * this_walk_state - Current walk state
307 * Op - Current 251 * Op - Current Op to be walked
308 * 252 *
309 * RETURN: Status 253 * RETURN: Status
310 * 254 *
311 * DESCRIPTION: Transfer execution to a called 255 * DESCRIPTION: Transfer execution to a called control method
312 * 256 *
313 ********************************************* 257 ******************************************************************************/
314 258
315 acpi_status 259 acpi_status
316 acpi_ds_call_control_method(struct acpi_thread !! 260 acpi_ds_call_control_method (
317 struct acpi_walk_s !! 261 struct acpi_thread_state *thread,
318 union acpi_parse_o !! 262 struct acpi_walk_state *this_walk_state,
>> 263 union acpi_parse_object *op)
319 { 264 {
320 acpi_status status; !! 265 acpi_status status;
321 struct acpi_namespace_node *method_nod !! 266 struct acpi_namespace_node *method_node;
322 struct acpi_walk_state *next_walk_stat !! 267 struct acpi_walk_state *next_walk_state;
323 union acpi_operand_object *obj_desc; !! 268 union acpi_operand_object *obj_desc;
324 struct acpi_evaluate_info *info; !! 269 struct acpi_parameter_info info;
325 u32 i; !! 270 u32 i;
326 !! 271
327 ACPI_FUNCTION_TRACE_PTR(ds_call_contro !! 272
328 !! 273 ACPI_FUNCTION_TRACE_PTR ("ds_call_control_method", this_walk_state);
329 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, !! 274
330 "Calling method %p, !! 275 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Execute method %p, currentstate=%p\n",
331 this_walk_state->pre !! 276 this_walk_state->prev_op, this_walk_state));
332 277
333 /* 278 /*
334 * Get the namespace entry for the con 279 * Get the namespace entry for the control method we are about to call
335 */ 280 */
336 method_node = this_walk_state->method_ 281 method_node = this_walk_state->method_call_node;
337 if (!method_node) { 282 if (!method_node) {
338 return_ACPI_STATUS(AE_NULL_ENT !! 283 return_ACPI_STATUS (AE_NULL_ENTRY);
339 } 284 }
340 285
341 obj_desc = acpi_ns_get_attached_object !! 286 obj_desc = acpi_ns_get_attached_object (method_node);
342 if (!obj_desc) { 287 if (!obj_desc) {
343 return_ACPI_STATUS(AE_NULL_OBJ !! 288 return_ACPI_STATUS (AE_NULL_OBJECT);
344 } 289 }
345 290
346 /* Init for new method, possibly wait !! 291 obj_desc->method.owning_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD);
>> 292
>> 293 /* Init for new method, wait on concurrency semaphore */
347 294
348 status = acpi_ds_begin_method_executio !! 295 status = acpi_ds_begin_method_execution (method_node, obj_desc,
349 !! 296 this_walk_state->method_node);
350 if (ACPI_FAILURE(status)) { !! 297 if (ACPI_FAILURE (status)) {
351 return_ACPI_STATUS(status); !! 298 return_ACPI_STATUS (status);
352 } 299 }
353 300
354 /* Begin method parse/execution. Creat !! 301 if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) {
>> 302 /* 1) Parse: Create a new walk state for the preempting walk */
>> 303
>> 304 next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
>> 305 op, obj_desc, NULL);
>> 306 if (!next_walk_state) {
>> 307 return_ACPI_STATUS (AE_NO_MEMORY);
>> 308 }
>> 309
>> 310 /* Create and init a Root Node */
>> 311
>> 312 op = acpi_ps_create_scope_op ();
>> 313 if (!op) {
>> 314 status = AE_NO_MEMORY;
>> 315 goto cleanup;
>> 316 }
355 317
356 next_walk_state = acpi_ds_create_walk_ !! 318 status = acpi_ds_init_aml_walk (next_walk_state, op, method_node,
357 !! 319 obj_desc->method.aml_start, obj_desc->method.aml_length,
>> 320 NULL, 1);
>> 321 if (ACPI_FAILURE (status)) {
>> 322 acpi_ds_delete_walk_state (next_walk_state);
>> 323 goto cleanup;
>> 324 }
>> 325
>> 326 /* Begin AML parse */
>> 327
>> 328 status = acpi_ps_parse_aml (next_walk_state);
>> 329 acpi_ps_delete_parse_tree (op);
>> 330 }
>> 331
>> 332 /* 2) Execute: Create a new state for the preempting walk */
>> 333
>> 334 next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
>> 335 NULL, obj_desc, thread);
358 if (!next_walk_state) { 336 if (!next_walk_state) {
359 status = AE_NO_MEMORY; 337 status = AE_NO_MEMORY;
360 goto cleanup; 338 goto cleanup;
361 } 339 }
362 <<
363 /* 340 /*
364 * The resolved arguments were put on 341 * The resolved arguments were put on the previous walk state's operand
365 * stack. Operands on the previous wal !! 342 * stack. Operands on the previous walk state stack always
366 * start at index 0. Also, null termin !! 343 * start at index 0.
>> 344 * Null terminate the list of arguments
367 */ 345 */
368 this_walk_state->operands[this_walk_st !! 346 this_walk_state->operands [this_walk_state->num_operands] = NULL;
369 347
370 /* !! 348 info.parameters = &this_walk_state->operands[0];
371 * Allocate and initialize the evaluat !! 349 info.parameter_type = ACPI_PARAM_ARGS;
372 * TBD: this is somewhat inefficient, <<
373 * ds_init_aml_walk. For now, keeps th <<
374 */ <<
375 info = ACPI_ALLOCATE_ZEROED(sizeof(str <<
376 if (!info) { <<
377 return_ACPI_STATUS(AE_NO_MEMOR <<
378 } <<
379 <<
380 info->parameters = &this_walk_state->o <<
381 info->parameter_type = ACPI_PARAM_ARGS <<
382 <<
383 status = acpi_ds_init_aml_walk(next_wa <<
384 obj_des <<
385 obj_des <<
386 ACPI_IM <<
387 350
388 ACPI_FREE(info); !! 351 status = acpi_ds_init_aml_walk (next_walk_state, NULL, method_node,
389 if (ACPI_FAILURE(status)) { !! 352 obj_desc->method.aml_start, obj_desc->method.aml_length,
>> 353 &info, 3);
>> 354 if (ACPI_FAILURE (status)) {
390 goto cleanup; 355 goto cleanup;
391 } 356 }
392 357
393 /* 358 /*
394 * Delete the operands on the previous 359 * Delete the operands on the previous walkstate operand stack
395 * (they were copied to new objects) 360 * (they were copied to new objects)
396 */ 361 */
397 for (i = 0; i < obj_desc->method.param 362 for (i = 0; i < obj_desc->method.param_count; i++) {
398 acpi_ut_remove_reference(this_ !! 363 acpi_ut_remove_reference (this_walk_state->operands [i]);
399 this_walk_state->operands[i] = !! 364 this_walk_state->operands [i] = NULL;
400 } 365 }
401 366
402 /* Clear the operand stack */ 367 /* Clear the operand stack */
403 368
404 this_walk_state->num_operands = 0; 369 this_walk_state->num_operands = 0;
405 370
406 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, !! 371 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
407 "**** Begin nested e !! 372 "Starting nested execution, newstate=%p\n", next_walk_state));
408 method_node->name.as <<
409 <<
410 /* Invoke an internal method if necess <<
411 373
412 if (obj_desc->method.method_flags & AM 374 if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
413 status = obj_desc->method.impl !! 375 status = obj_desc->method.implementation (next_walk_state);
>> 376 return_ACPI_STATUS (status);
414 } 377 }
415 378
416 return_ACPI_STATUS(status); !! 379 return_ACPI_STATUS (AE_OK);
417 380
418 cleanup: <<
419 381
420 /* On error, we must terminate the met !! 382 /* On error, we must delete the new walk state */
421 383
422 acpi_ds_terminate_control_method(obj_d !! 384 cleanup:
423 if (next_walk_state) { !! 385 if (next_walk_state && (next_walk_state->method_desc)) {
424 acpi_ds_delete_walk_state(next !! 386 /* Decrement the thread count on the method parse tree */
425 } <<
426 387
427 return_ACPI_STATUS(status); !! 388 next_walk_state->method_desc->method.thread_count--;
>> 389 }
>> 390 (void) acpi_ds_terminate_control_method (next_walk_state);
>> 391 acpi_ds_delete_walk_state (next_walk_state);
>> 392 return_ACPI_STATUS (status);
428 } 393 }
429 394
>> 395
430 /********************************************* 396 /*******************************************************************************
431 * 397 *
432 * FUNCTION: acpi_ds_restart_control_method 398 * FUNCTION: acpi_ds_restart_control_method
433 * 399 *
434 * PARAMETERS: walk_state - State fo 400 * PARAMETERS: walk_state - State for preempted method (caller)
435 * return_desc - Return v 401 * return_desc - Return value from the called method
436 * 402 *
437 * RETURN: Status 403 * RETURN: Status
438 * 404 *
439 * DESCRIPTION: Restart a method that was pree 405 * DESCRIPTION: Restart a method that was preempted by another (nested) method
440 * invocation. Handle the return 406 * invocation. Handle the return value (if any) from the callee.
441 * 407 *
442 ********************************************* 408 ******************************************************************************/
443 409
444 acpi_status 410 acpi_status
445 acpi_ds_restart_control_method(struct acpi_wal !! 411 acpi_ds_restart_control_method (
446 union acpi_oper !! 412 struct acpi_walk_state *walk_state,
>> 413 union acpi_operand_object *return_desc)
447 { 414 {
448 acpi_status status; !! 415 acpi_status status;
449 int same_as_implicit_return; <<
450 416
451 ACPI_FUNCTION_TRACE_PTR(ds_restart_con <<
452 417
453 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, !! 418 ACPI_FUNCTION_TRACE_PTR ("ds_restart_control_method", walk_state);
454 "****Restart [%4.4s] <<
455 acpi_ut_get_node_nam <<
456 walk_state->method_c <<
457 <<
458 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, <<
459 " ReturnFromThisM <<
460 walk_state->return_u <<
461 walk_state->results, <<
462 419
463 /* Did the called method return a valu <<
464 420
465 if (return_desc) { !! 421 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
>> 422 "****Restart [%4.4s] Op %p return_value_from_callee %p\n",
>> 423 (char *) &walk_state->method_node->name, walk_state->method_call_op,
>> 424 return_desc));
466 425
467 /* Is the implicit return obje !! 426 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
>> 427 " return_from_this_method_used?=%X res_stack %p Walk %p\n",
>> 428 walk_state->return_used,
>> 429 walk_state->results, walk_state));
468 430
469 same_as_implicit_return = !! 431 /* Did the called method return a value? */
470 (walk_state->implicit_retu <<
471 432
>> 433 if (return_desc) {
472 /* Are we actually going to us 434 /* Are we actually going to use the return value? */
473 435
474 if (walk_state->return_used) { 436 if (walk_state->return_used) {
475 <<
476 /* Save the return val 437 /* Save the return value from the previous method */
477 438
478 status = acpi_ds_resul !! 439 status = acpi_ds_result_push (return_desc, walk_state);
479 if (ACPI_FAILURE(statu !! 440 if (ACPI_FAILURE (status)) {
480 acpi_ut_remove !! 441 acpi_ut_remove_reference (return_desc);
481 return_ACPI_ST !! 442 return_ACPI_STATUS (status);
482 } 443 }
483 444
484 /* 445 /*
485 * Save as THIS method 446 * Save as THIS method's return value in case it is returned
486 * immediately to yet 447 * immediately to yet another method
487 */ 448 */
488 walk_state->return_des 449 walk_state->return_desc = return_desc;
489 } 450 }
490 !! 451 else {
491 /* <<
492 * The following code is the o <<
493 * "implicit return". Some AML <<
494 * method is "implicitly" retu <<
495 * explicit return value. <<
496 * <<
497 * Just save the last result o <<
498 * <<
499 * NOTE: this is optional beca <<
500 * support this behavior. <<
501 */ <<
502 else if (!acpi_ds_do_implicit_ <<
503 (return_desc, walk_st <<
504 || same_as_implicit_r <<
505 /* 452 /*
506 * Delete the return v 453 * Delete the return value if it will not be used by the
507 * calling method or r !! 454 * calling method
508 * is the same as the <<
509 */ 455 */
510 acpi_ut_remove_referen !! 456 acpi_ut_remove_reference (return_desc);
511 } 457 }
512 } 458 }
513 459
514 return_ACPI_STATUS(AE_OK); !! 460 return_ACPI_STATUS (AE_OK);
515 } 461 }
516 462
>> 463
517 /********************************************* 464 /*******************************************************************************
518 * 465 *
519 * FUNCTION: acpi_ds_terminate_control_meth 466 * FUNCTION: acpi_ds_terminate_control_method
520 * 467 *
521 * PARAMETERS: method_desc - Method o !! 468 * PARAMETERS: walk_state - State of the method
522 * walk_state - State as <<
523 * 469 *
524 * RETURN: None !! 470 * RETURN: Status
525 * 471 *
526 * DESCRIPTION: Terminate a control method. D 472 * DESCRIPTION: Terminate a control method. Delete everything that the method
527 * created, delete all locals and 473 * created, delete all locals and arguments, and delete the parse
528 * tree if requested. 474 * tree if requested.
529 * 475 *
530 * MUTEX: Interpreter is locked <<
531 * <<
532 ********************************************* 476 ******************************************************************************/
533 477
534 void !! 478 acpi_status
535 acpi_ds_terminate_control_method(union acpi_op !! 479 acpi_ds_terminate_control_method (
536 struct acpi_w !! 480 struct acpi_walk_state *walk_state)
537 { 481 {
538 struct acpi_namespace_node *method_nod !! 482 union acpi_operand_object *obj_desc;
539 acpi_status status; !! 483 struct acpi_namespace_node *method_node;
>> 484 acpi_status status;
540 485
541 ACPI_FUNCTION_TRACE_PTR(ds_terminate_c <<
542 486
543 /* method_desc is required, walk_state !! 487 ACPI_FUNCTION_TRACE_PTR ("ds_terminate_control_method", walk_state);
544 488
545 if (!method_desc) { <<
546 return_VOID; <<
547 } <<
548 489
549 if (walk_state) { !! 490 if (!walk_state) {
>> 491 return (AE_BAD_PARAMETER);
>> 492 }
550 493
551 /* Delete all arguments and lo !! 494 /* The current method object was saved in the walk state */
552 495
553 acpi_ds_method_data_delete_all !! 496 obj_desc = walk_state->method_desc;
>> 497 if (!obj_desc) {
>> 498 return_ACPI_STATUS (AE_OK);
554 } 499 }
555 500
>> 501 /* Delete all arguments and locals */
>> 502
>> 503 acpi_ds_method_data_delete_all (walk_state);
>> 504
556 /* 505 /*
557 * If method is serialized, release th !! 506 * Lock the parser while we terminate this method.
558 * current sync level for this thread !! 507 * If this is the last thread executing the method,
>> 508 * we have additional cleanup to perform
559 */ 509 */
560 if (method_desc->method.mutex) { !! 510 status = acpi_ut_acquire_mutex (ACPI_MTX_PARSER);
>> 511 if (ACPI_FAILURE (status)) {
>> 512 return_ACPI_STATUS (status);
>> 513 }
561 514
562 /* Acquisition Depth handles r !! 515 /* Signal completion of the execution of this method if necessary */
563 516
564 method_desc->method.mutex->mut !! 517 if (walk_state->method_desc->method.semaphore) {
565 if (!method_desc->method.mutex !! 518 status = acpi_os_signal_semaphore (
566 walk_state->thread->cu !! 519 walk_state->method_desc->method.semaphore, 1);
567 method_desc->metho !! 520 if (ACPI_FAILURE (status)) {
568 original_sync_leve !! 521 ACPI_REPORT_ERROR (("Could not signal method semaphore\n"));
>> 522 status = AE_OK;
569 523
570 acpi_os_release_mutex( !! 524 /* Ignore error and continue cleanup */
571 <<
572 method_desc->method.mu <<
573 } 525 }
574 } 526 }
575 527
576 if (walk_state) { !! 528 if (walk_state->method_desc->method.thread_count) {
577 /* !! 529 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
578 * Delete any objects created !! 530 "*** Not deleting method namespace, there are still %d threads\n",
579 * The method Node is stored i !! 531 walk_state->method_desc->method.thread_count));
580 */ <<
581 method_node = walk_state->meth <<
582 <<
583 /* <<
584 * Delete any namespace object <<
585 * the namespace by the execut <<
586 */ <<
587 acpi_ns_delete_namespace_by_ow <<
588 } <<
589 <<
590 /* Decrement the thread count on the m <<
591 <<
592 if (method_desc->method.thread_count) <<
593 method_desc->method.thread_cou <<
594 } else { <<
595 ACPI_ERROR((AE_INFO, "Invalid <<
596 } 532 }
597 533
598 /* Are there any other threads current !! 534 if (!walk_state->method_desc->method.thread_count) {
599 <<
600 if (method_desc->method.thread_count) <<
601 /* <<
602 * Additional threads. Do not <<
603 * we immediately reuse it for <<
604 */ <<
605 ACPI_DEBUG_PRINT((ACPI_DB_DISP <<
606 "*** Complet <<
607 method_desc- <<
608 } else { <<
609 /* This is the only executing <<
610 <<
611 /* 535 /*
612 * Support to dynamically chan 536 * Support to dynamically change a method from not_serialized to
613 * Serialized if it appears th !! 537 * Serialized if it appears that the method is written foolishly and
614 * does not support multiple t !! 538 * does not support multiple thread execution. The best example of this
615 * is if such a method creates !! 539 * is if such a method creates namespace objects and blocks. A second
616 * thread will fail with an AE 540 * thread will fail with an AE_ALREADY_EXISTS exception
617 * 541 *
618 * This code is here because w 542 * This code is here because we must wait until the last thread exits
619 * before creating the synchro 543 * before creating the synchronization semaphore.
620 */ 544 */
621 if ((method_desc->method.metho !! 545 if ((walk_state->method_desc->method.concurrency == 1) &&
622 && (!method_desc->method.m !! 546 (!walk_state->method_desc->method.semaphore)) {
623 status = acpi_ds_creat !! 547 status = acpi_os_create_semaphore (1,
>> 548 1,
>> 549 &walk_state->method_desc->method.semaphore);
624 } 550 }
625 551
626 /* No more threads, we can fre !! 552 /*
>> 553 * There are no more threads executing this method. Perform
>> 554 * additional cleanup.
>> 555 *
>> 556 * The method Node is stored in the walk state
>> 557 */
>> 558 method_node = walk_state->method_node;
>> 559
>> 560 /*
>> 561 * Delete any namespace entries created immediately underneath
>> 562 * the method
>> 563 */
>> 564 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
>> 565 if (ACPI_FAILURE (status)) {
>> 566 return_ACPI_STATUS (status);
>> 567 }
>> 568
>> 569 if (method_node->child) {
>> 570 acpi_ns_delete_namespace_subtree (method_node);
>> 571 }
627 572
628 acpi_ut_release_owner_id(&meth !! 573 /*
>> 574 * Delete any namespace entries created anywhere else within
>> 575 * the namespace
>> 576 */
>> 577 acpi_ns_delete_namespace_by_owner (walk_state->method_desc->method.owning_id);
>> 578 status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
>> 579 if (ACPI_FAILURE (status)) {
>> 580 return_ACPI_STATUS (status);
>> 581 }
629 } 582 }
630 583
631 return_VOID; !! 584 status = acpi_ut_release_mutex (ACPI_MTX_PARSER);
>> 585 return_ACPI_STATUS (status);
632 } 586 }
>> 587
>> 588
633 589
|
This page was automatically generated by the
LXR engine.
|