ReactOS 0.4.16-dev-92-g0c2cdca
dsmethod.c File Reference
#include "acpi.h"
#include "accommon.h"
#include "acdispat.h"
#include "acinterp.h"
#include "acnamesp.h"
#include "acparser.h"
#include "amlcode.h"
#include "acdebug.h"
Include dependency graph for dsmethod.c:

Go to the source code of this file.

Macros

#define _COMPONENT   ACPI_DISPATCHER
 

Functions

static ACPI_STATUS AcpiDsDetectNamedOpcodes (ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT **OutOp)
 
static ACPI_STATUS AcpiDsCreateMethodMutex (ACPI_OPERAND_OBJECT *MethodDesc)
 
ACPI_STATUS AcpiDsAutoSerializeMethod (ACPI_NAMESPACE_NODE *Node, ACPI_OPERAND_OBJECT *ObjDesc)
 
ACPI_STATUS AcpiDsMethodError (ACPI_STATUS Status, ACPI_WALK_STATE *WalkState)
 
ACPI_STATUS AcpiDsBeginMethodExecution (ACPI_NAMESPACE_NODE *MethodNode, ACPI_OPERAND_OBJECT *ObjDesc, ACPI_WALK_STATE *WalkState)
 
ACPI_STATUS AcpiDsCallControlMethod (ACPI_THREAD_STATE *Thread, ACPI_WALK_STATE *ThisWalkState, ACPI_PARSE_OBJECT *Op)
 
ACPI_STATUS AcpiDsRestartControlMethod (ACPI_WALK_STATE *WalkState, ACPI_OPERAND_OBJECT *ReturnDesc)
 
void AcpiDsTerminateControlMethod (ACPI_OPERAND_OBJECT *MethodDesc, ACPI_WALK_STATE *WalkState)
 

Macro Definition Documentation

◆ _COMPONENT

#define _COMPONENT   ACPI_DISPATCHER

Definition at line 54 of file dsmethod.c.

Function Documentation

◆ AcpiDsAutoSerializeMethod()

ACPI_STATUS AcpiDsAutoSerializeMethod ( ACPI_NAMESPACE_NODE Node,
ACPI_OPERAND_OBJECT ObjDesc 
)

Definition at line 94 of file dsmethod.c.

97{
100 ACPI_WALK_STATE *WalkState;
101
102
103 ACPI_FUNCTION_TRACE_PTR (DsAutoSerializeMethod, Node);
104
105
107 "Method auto-serialization parse [%4.4s] %p\n",
109
110 /* Create/Init a root op for the method parse tree */
111
113 if (!Op)
114 {
116 }
117
118 AcpiPsSetName (Op, Node->Name.Integer);
119 Op->Common.Node = Node;
120
121 /* Create and initialize a new walk state */
122
123 WalkState = AcpiDsCreateWalkState (Node->OwnerId, NULL, NULL, NULL);
124 if (!WalkState)
125 {
126 AcpiPsFreeOp (Op);
128 }
129
130 Status = AcpiDsInitAmlWalk (WalkState, Op, Node,
131 ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength, NULL, 0);
132 if (ACPI_FAILURE (Status))
133 {
134 AcpiDsDeleteWalkState (WalkState);
135 AcpiPsFreeOp (Op);
137 }
138
140
141 /* Parse the method, scan for creation of named objects */
142
143 Status = AcpiPsParseAml (WalkState);
144
147}
#define ACPI_FAILURE(a)
Definition: acexcep.h:95
#define AE_NO_MEMORY
Definition: acexcep.h:112
#define ACPI_DEBUG_PRINT(pl)
Definition: acoutput.h:475
#define ACPI_DB_PARSE
Definition: acoutput.h:162
#define ACPI_FUNCTION_TRACE_PTR(a, b)
Definition: acoutput.h:481
#define return_ACPI_STATUS(s)
Definition: acoutput.h:496
void AcpiPsSetName(ACPI_PARSE_OBJECT *op, UINT32 name)
Definition: psutils.c:281
void AcpiPsDeleteParseTree(ACPI_PARSE_OBJECT *root)
Definition: pswalk.c:67
void AcpiPsFreeOp(ACPI_PARSE_OBJECT *Op)
Definition: psutils.c:212
ACPI_STATUS AcpiPsParseAml(ACPI_WALK_STATE *WalkState)
Definition: psparse.c:453
ACPI_PARSE_OBJECT * AcpiPsAllocOp(UINT16 Opcode, UINT8 *Aml)
Definition: psutils.c:130
UINT32 ACPI_STATUS
Definition: actypes.h:460
const char * AcpiUtGetNodeName(void *Object)
Definition: utdecode.c:306
#define AML_METHOD_OP
Definition: amlcode.h:64
#define NULL
Definition: types.h:112
union node Node
Definition: types.h:1255
static ACPI_STATUS AcpiDsDetectNamedOpcodes(ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT **OutOp)
Definition: dsmethod.c:166
ACPI_WALK_STATE * AcpiDsCreateWalkState(ACPI_OWNER_ID OwnerId, ACPI_PARSE_OBJECT *Origin, ACPI_OPERAND_OBJECT *MethodDesc, ACPI_THREAD_STATE *Thread)
Definition: dswstate.c:600
ACPI_STATUS AcpiDsInitAmlWalk(ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op, ACPI_NAMESPACE_NODE *MethodNode, UINT8 *AmlStart, UINT32 AmlLength, ACPI_EVALUATE_INFO *Info, UINT8 PassNumber)
Definition: dswstate.c:662
void AcpiDsDeleteWalkState(ACPI_WALK_STATE *WalkState)
Definition: dswstate.c:780
Status
Definition: gdiplustypes.h:25
UINT8 * AmlStart
Definition: acobject.h:221
ACPI_PARSE_DOWNWARDS DescendingCallback
Definition: acstruct.h:128
ACPI_OBJECT_METHOD Method
Definition: acobject.h:525
ACPI_PARSE_OBJ_COMMON Common
Definition: aclocal.h:1078
Definition: dlist.c:348

Referenced by AcpiDsInitOneObject().

◆ AcpiDsBeginMethodExecution()

ACPI_STATUS AcpiDsBeginMethodExecution ( ACPI_NAMESPACE_NODE MethodNode,
ACPI_OPERAND_OBJECT ObjDesc,
ACPI_WALK_STATE WalkState 
)

Definition at line 352 of file dsmethod.c.

356{
358
359
360 ACPI_FUNCTION_TRACE_PTR (DsBeginMethodExecution, MethodNode);
361
362
363 if (!MethodNode)
364 {
366 }
367
368 AcpiExStartTraceMethod (MethodNode, ObjDesc, WalkState);
369
370 /* Prevent wraparound of thread count */
371
372 if (ObjDesc->Method.ThreadCount == ACPI_UINT8_MAX)
373 {
375 "Method reached maximum reentrancy limit (255)"));
377 }
378
379 /*
380 * If this method is serialized, we need to acquire the method mutex.
381 */
383 {
384 /*
385 * Create a mutex for the method if it is defined to be Serialized
386 * and a mutex has not already been created. We defer the mutex creation
387 * until a method is actually executed, to minimize the object count
388 */
389 if (!ObjDesc->Method.Mutex)
390 {
392 if (ACPI_FAILURE (Status))
393 {
395 }
396 }
397
398 /*
399 * The CurrentSyncLevel (per-thread) must be less than or equal to
400 * the sync level of the method. This mechanism provides some
401 * deadlock prevention.
402 *
403 * If the method was auto-serialized, we just ignore the sync level
404 * mechanism, because auto-serialization of methods can interfere
405 * with ASL code that actually uses sync levels.
406 *
407 * Top-level method invocation has no walk state at this point
408 */
409 if (WalkState &&
411 (WalkState->Thread->CurrentSyncLevel >
412 ObjDesc->Method.Mutex->Mutex.SyncLevel))
413 {
415 "Cannot acquire Mutex for method [%4.4s]"
416 ", current SyncLevel is too large (%u)",
417 AcpiUtGetNodeName (MethodNode),
418 WalkState->Thread->CurrentSyncLevel));
419
421 }
422
423 /*
424 * Obtain the method mutex if necessary. Do not acquire mutex for a
425 * recursive call.
426 */
427 if (!WalkState ||
428 !ObjDesc->Method.Mutex->Mutex.ThreadId ||
429 (WalkState->Thread->ThreadId !=
430 ObjDesc->Method.Mutex->Mutex.ThreadId))
431 {
432 /*
433 * Acquire the method mutex. This releases the interpreter if we
434 * block (and reacquires it before it returns)
435 */
438 if (ACPI_FAILURE (Status))
439 {
441 }
442
443 /* Update the mutex and walk info and save the original SyncLevel */
444
445 if (WalkState)
446 {
448 WalkState->Thread->CurrentSyncLevel;
449
450 ObjDesc->Method.Mutex->Mutex.ThreadId =
451 WalkState->Thread->ThreadId;
452
453 /*
454 * Update the current SyncLevel only if this is not an auto-
455 * serialized method. In the auto case, we have to ignore
456 * the sync level for the method mutex (created for the
457 * auto-serialization) because we have no idea of what the
458 * sync level should be. Therefore, just ignore it.
459 */
460 if (!(ObjDesc->Method.InfoFlags &
462 {
463 WalkState->Thread->CurrentSyncLevel =
464 ObjDesc->Method.SyncLevel;
465 }
466 }
467 else
468 {
470 ObjDesc->Method.Mutex->Mutex.SyncLevel;
471
472 ObjDesc->Method.Mutex->Mutex.ThreadId =
474 }
475 }
476
477 /* Always increase acquisition depth */
478
480 }
481
482 /*
483 * Allocate an Owner ID for this method, only if this is the first thread
484 * to begin concurrent execution. We only need one OwnerId, even if the
485 * method is invoked recursively.
486 */
487 if (!ObjDesc->Method.OwnerId)
488 {
490 if (ACPI_FAILURE (Status))
491 {
492 goto Cleanup;
493 }
494 }
495
496 /*
497 * Increment the method parse tree thread count since it has been
498 * reentered one more time (even if it is the same thread)
499 */
500 ObjDesc->Method.ThreadCount++;
501 AcpiMethodCount++;
503
504
505Cleanup:
506 /* On error, must release the method mutex (if present) */
507
508 if (ObjDesc->Method.Mutex)
509 {
511 }
513}
#define AE_NULL_ENTRY
Definition: acexcep.h:118
#define AE_AML_MUTEX_ORDER
Definition: acexcep.h:200
#define AE_AML_METHOD_LIMIT
Definition: acexcep.h:198
#define AE_OK
Definition: acexcep.h:97
#define ACPI_METHOD_IGNORE_SYNC_LEVEL
Definition: acobject.h:240
#define ACPI_METHOD_SERIALIZED
Definition: acobject.h:238
#define ACPI_ERROR(plist)
Definition: acoutput.h:240
#define AE_INFO
Definition: acoutput.h:230
ACPI_THREAD_ID AcpiOsGetThreadId(void)
Definition: osl.c:217
#define AcpiOsReleaseMutex(Handle)
Definition: actypes.h:277
#define ACPI_WAIT_FOREVER
Definition: actypes.h:501
#define ACPI_UINT8_MAX
Definition: actypes.h:64
ACPI_STATUS AcpiUtAllocateOwnerId(ACPI_OWNER_ID *OwnerId)
Definition: utownerid.c:68
static const WCHAR Cleanup[]
Definition: register.c:80
static ACPI_STATUS AcpiDsCreateMethodMutex(ACPI_OPERAND_OBJECT *MethodDesc)
Definition: dsmethod.c:301
ACPI_STATUS AcpiExSystemWaitMutex(ACPI_MUTEX Mutex, UINT16 Timeout)
Definition: exsystem.c:120
void AcpiExStartTraceMethod(ACPI_NAMESPACE_NODE *MethodNode, ACPI_OPERAND_OBJECT *ObjDesc, ACPI_WALK_STATE *WalkState)
Definition: extrace.c:224
ACPI_OWNER_ID OwnerId
Definition: acobject.h:229
ACPI_OBJECT_COMMON_HEADER UINT8 InfoFlags
Definition: acobject.h:216
union acpi_operand_object * Mutex
Definition: acobject.h:219
ACPI_OBJECT_COMMON_HEADER UINT8 SyncLevel
Definition: acobject.h:186
UINT16 AcquisitionDepth
Definition: acobject.h:187
ACPI_THREAD_ID ThreadId
Definition: acobject.h:189
ACPI_MUTEX OsMutex
Definition: acobject.h:188
UINT8 OriginalSyncLevel
Definition: acobject.h:194
ACPI_STATE_COMMON UINT8 CurrentSyncLevel
Definition: aclocal.h:764
ACPI_THREAD_ID ThreadId
Definition: aclocal.h:767
ACPI_THREAD_STATE * Thread
Definition: acstruct.h:127
ACPI_OBJECT_MUTEX Mutex
Definition: acobject.h:526

Referenced by AcpiDsCallControlMethod(), and AcpiPsExecuteMethod().

◆ AcpiDsCallControlMethod()

ACPI_STATUS AcpiDsCallControlMethod ( ACPI_THREAD_STATE Thread,
ACPI_WALK_STATE ThisWalkState,
ACPI_PARSE_OBJECT Op 
)

Definition at line 531 of file dsmethod.c.

535{
537 ACPI_NAMESPACE_NODE *MethodNode;
538 ACPI_WALK_STATE *NextWalkState = NULL;
539 ACPI_OPERAND_OBJECT *ObjDesc;
541 UINT32 i;
542
543
544 ACPI_FUNCTION_TRACE_PTR (DsCallControlMethod, ThisWalkState);
545
547 "Calling method %p, currentstate=%p\n",
548 ThisWalkState->PrevOp, ThisWalkState));
549
550 /*
551 * Get the namespace entry for the control method we are about to call
552 */
553 MethodNode = ThisWalkState->MethodCallNode;
554 if (!MethodNode)
555 {
557 }
558
559 ObjDesc = AcpiNsGetAttachedObject (MethodNode);
560 if (!ObjDesc)
561 {
563 }
564
565 /* Init for new method, possibly wait on method mutex */
566
568 MethodNode, ObjDesc, ThisWalkState);
569 if (ACPI_FAILURE (Status))
570 {
572 }
573
574 /* Begin method parse/execution. Create a new walk state */
575
576 NextWalkState = AcpiDsCreateWalkState (
577 ObjDesc->Method.OwnerId, NULL, ObjDesc, Thread);
578 if (!NextWalkState)
579 {
581 goto Cleanup;
582 }
583
584 /*
585 * The resolved arguments were put on the previous walk state's operand
586 * stack. Operands on the previous walk state stack always
587 * start at index 0. Also, null terminate the list of arguments
588 */
589 ThisWalkState->Operands [ThisWalkState->NumOperands] = NULL;
590
591 /*
592 * Allocate and initialize the evaluation information block
593 * TBD: this is somewhat inefficient, should change interface to
594 * DsInitAmlWalk. For now, keeps this struct off the CPU stack
595 */
597 if (!Info)
598 {
600 goto Cleanup;
601 }
602
603 Info->Parameters = &ThisWalkState->Operands[0];
604
605 Status = AcpiDsInitAmlWalk (NextWalkState, NULL, MethodNode,
606 ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength,
608
609 ACPI_FREE (Info);
610 if (ACPI_FAILURE (Status))
611 {
612 goto Cleanup;
613 }
614
615 NextWalkState->MethodNestingDepth = ThisWalkState->MethodNestingDepth + 1;
616
617 /*
618 * Delete the operands on the previous walkstate operand stack
619 * (they were copied to new objects)
620 */
621 for (i = 0; i < ObjDesc->Method.ParamCount; i++)
622 {
623 AcpiUtRemoveReference (ThisWalkState->Operands [i]);
624 ThisWalkState->Operands [i] = NULL;
625 }
626
627 /* Clear the operand stack */
628
629 ThisWalkState->NumOperands = 0;
630
632 "**** Begin nested execution of [%4.4s] **** WalkState=%p\n",
633 MethodNode->Name.Ascii, NextWalkState));
634
635 ThisWalkState->MethodPathname = AcpiNsGetNormalizedPathname (MethodNode, TRUE);
636 ThisWalkState->MethodIsNested = TRUE;
637
638 /* Optional object evaluation log */
639
641 "%-26s: %*s%s\n", " Nested method call",
642 NextWalkState->MethodNestingDepth * 3, " ",
643 &ThisWalkState->MethodPathname[1]));
644
645 /* Invoke an internal method if necessary */
646
648 {
649 Status = ObjDesc->Method.Dispatch.Implementation (NextWalkState);
650 if (Status == AE_OK)
651 {
653 }
654 }
655
657
658
659Cleanup:
660
661 /* On error, we must terminate the method properly */
662
663 AcpiDsTerminateControlMethod (ObjDesc, NextWalkState);
664 AcpiDsDeleteWalkState (NextWalkState);
665
667}
unsigned int UINT32
#define AE_CTRL_TERMINATE
Definition: acexcep.h:226
#define AE_NULL_OBJECT
Definition: acexcep.h:117
@ ACPI_IMODE_EXECUTE
Definition: aclocal.h:169
char * AcpiNsGetNormalizedPathname(ACPI_NAMESPACE_NODE *Node, BOOLEAN NoTrailing)
Definition: nsnames.c:367
ACPI_OPERAND_OBJECT * AcpiNsGetAttachedObject(ACPI_NAMESPACE_NODE *Node)
Definition: nsobject.c:308
#define ACPI_METHOD_INTERNAL_ONLY
Definition: acobject.h:237
#define ACPI_DB_DISPATCH
Definition: acoutput.h:163
#define ACPI_DEBUG_PRINT_RAW(pl)
Definition: acoutput.h:476
#define ACPI_DB_EVALUATION
Definition: acoutput.h:181
#define ACPI_FREE(a)
Definition: actypes.h:386
#define ACPI_ALLOCATE_ZEROED(a)
Definition: actypes.h:385
void AcpiUtRemoveReference(ACPI_OPERAND_OBJECT *Object)
Definition: utdelete.c:790
#define TRUE
Definition: types.h:120
void AcpiDsTerminateControlMethod(ACPI_OPERAND_OBJECT *MethodDesc, ACPI_WALK_STATE *WalkState)
Definition: dsmethod.c:779
ACPI_STATUS AcpiDsBeginMethodExecution(ACPI_NAMESPACE_NODE *MethodNode, ACPI_OPERAND_OBJECT *ObjDesc, ACPI_WALK_STATE *WalkState)
Definition: dsmethod.c:352
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
ACPI_NAME_UNION Name
Definition: aclocal.h:191
union acpi_object_method::@613 Dispatch
ACPI_INTERNAL_METHOD Implementation
Definition: acobject.h:224
union acpi_operand_object * Operands[ACPI_OBJ_NUM_OPERANDS+1]
Definition: acstruct.h:105
char * MethodPathname
Definition: acstruct.h:117
UINT16 MethodNestingDepth
Definition: acstruct.h:100
UINT8 MethodIsNested
Definition: acstruct.h:101
ACPI_PARSE_OBJECT * PrevOp
Definition: acstruct.h:125
UINT8 NumOperands
Definition: acstruct.h:80
struct acpi_namespace_node * MethodCallNode
Definition: acstruct.h:113
char Ascii[4]
Definition: actbl.h:394
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690

Referenced by AcpiPsParseAml().

◆ AcpiDsCreateMethodMutex()

static ACPI_STATUS AcpiDsCreateMethodMutex ( ACPI_OPERAND_OBJECT MethodDesc)
static

Definition at line 301 of file dsmethod.c.

303{
304 ACPI_OPERAND_OBJECT *MutexDesc;
306
307
308 ACPI_FUNCTION_TRACE (DsCreateMethodMutex);
309
310
311 /* Create the new mutex object */
312
314 if (!MutexDesc)
315 {
317 }
318
319 /* Create the actual OS Mutex */
320
321 Status = AcpiOsCreateMutex (&MutexDesc->Mutex.OsMutex);
322 if (ACPI_FAILURE (Status))
323 {
324 AcpiUtDeleteObjectDesc (MutexDesc);
326 }
327
328 MutexDesc->Mutex.SyncLevel = MethodDesc->Method.SyncLevel;
329 MethodDesc->Method.Mutex = MutexDesc;
331}
#define ACPI_FUNCTION_TRACE(a)
Definition: acoutput.h:480
#define ACPI_TYPE_MUTEX
Definition: actypes.h:696
#define AcpiOsCreateMutex(OutHandle)
Definition: actypes.h:274
#define AcpiUtCreateInternalObject(t)
Definition: acutils.h:681
void AcpiUtDeleteObjectDesc(ACPI_OPERAND_OBJECT *Object)
Definition: utobject.c:473

Referenced by AcpiDsBeginMethodExecution().

◆ AcpiDsDetectNamedOpcodes()

static ACPI_STATUS AcpiDsDetectNamedOpcodes ( ACPI_WALK_STATE WalkState,
ACPI_PARSE_OBJECT **  OutOp 
)
static

Definition at line 166 of file dsmethod.c.

169{
170
172
173
174 /* We are only interested in opcodes that create a new name */
175
176 if (!(WalkState->OpInfo->Flags & (AML_NAMED | AML_CREATE | AML_FIELD)))
177 {
178 return (AE_OK);
179 }
180
181 /*
182 * At this point, we know we have a Named object opcode.
183 * Mark the method as serialized. Later code will create a mutex for
184 * this method to enforce serialization.
185 *
186 * Note, ACPI_METHOD_IGNORE_SYNC_LEVEL flag means that we will ignore the
187 * Sync Level mechanism for this method, even though it is now serialized.
188 * Otherwise, there can be conflicts with existing ASL code that actually
189 * uses sync levels.
190 */
191 WalkState->MethodDesc->Method.SyncLevel = 0;
192 WalkState->MethodDesc->Method.InfoFlags |=
194
196 "Method serialized [%4.4s] %p - [%s] (%4.4X)\n",
197 WalkState->MethodNode->Name.Ascii, WalkState->MethodNode,
198 WalkState->OpInfo->Name, WalkState->Opcode));
199
200 /* Abort the parse, no need to examine this method any further */
201
202 return (AE_CTRL_TERMINATE);
203}
#define ACPI_DB_INFO
Definition: acoutput.h:153
#define ACPI_FUNCTION_NAME(a)
Definition: acoutput.h:479
#define AML_FIELD
Definition: amlcode.h:321
#define AML_CREATE
Definition: amlcode.h:320
#define AML_NAMED
Definition: amlcode.h:323
UINT16 Flags
Definition: aclocal.h:873
union acpi_operand_object * MethodDesc
Definition: acstruct.h:115
struct acpi_namespace_node * MethodNode
Definition: acstruct.h:116
UINT16 Opcode
Definition: acstruct.h:78
const ACPI_OPCODE_INFO * OpInfo
Definition: acstruct.h:119

Referenced by AcpiDsAutoSerializeMethod(), and AcpiDsDetectNamedOpcodes().

◆ AcpiDsMethodError()

ACPI_STATUS AcpiDsMethodError ( ACPI_STATUS  Status,
ACPI_WALK_STATE WalkState 
)

Definition at line 223 of file dsmethod.c.

226{
227 UINT32 AmlOffset;
228 ACPI_NAME Name = 0;
229
230
232
233
234 /* Ignore AE_OK and control exception codes */
235
236 if (ACPI_SUCCESS (Status) ||
238 {
239 return (Status);
240 }
241
242 /* Invoke the global exception handler */
243
244 if (AcpiGbl_ExceptionHandler)
245 {
246 /* Exit the interpreter, allow handler to execute methods */
247
249
250 /*
251 * Handler can map the exception code to anything it wants, including
252 * AE_OK, in which case the executing method will not be aborted.
253 */
254 AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->Aml,
255 WalkState->ParserState.AmlStart);
256
257 if (WalkState->MethodNode)
258 {
259 Name = WalkState->MethodNode->Name.Integer;
260 }
261 else if (WalkState->DeferredNode)
262 {
263 Name = WalkState->DeferredNode->Name.Integer;
264 }
265
266 Status = AcpiGbl_ExceptionHandler (Status, Name,
267 WalkState->Opcode, AmlOffset, NULL);
269 }
270
271 AcpiDsClearImplicitReturn (WalkState);
272
273 if (ACPI_FAILURE (Status))
274 {
275 AcpiDsDumpMethodStack (Status, WalkState, WalkState->Op);
276
277 /* Display method locals/args if debugger is present */
278
279#ifdef ACPI_DEBUGGER
280 AcpiDbDumpMethodInfo (Status, WalkState);
281#endif
282 }
283
284 return (Status);
285}
void AcpiDbDumpMethodInfo(ACPI_STATUS Status, ACPI_WALK_STATE *WalkState)
#define AE_CODE_CONTROL
Definition: acexcep.h:57
#define ACPI_SUCCESS(a)
Definition: acexcep.h:94
#define ACPI_FUNCTION_ENTRY()
Definition: acoutput.h:484
#define ACPI_PTR_DIFF(a, b)
Definition: actypes.h:548
UINT32 ACPI_NAME
Definition: actypes.h:461
void AcpiDsDumpMethodStack(ACPI_STATUS Status, ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op)
Definition: dsdebug.c:249
void AcpiDsClearImplicitReturn(ACPI_WALK_STATE *WalkState)
Definition: dsutils.c:73
void AcpiExExitInterpreter(void)
Definition: exutils.c:139
void AcpiExEnterInterpreter(void)
Definition: exutils.c:91
UINT8 * AmlStart
Definition: aclocal.h:1101
UINT8 * Aml
Definition: acstruct.h:91
ACPI_PARSE_OBJECT * Op
Definition: acstruct.h:118
struct acpi_namespace_node * DeferredNode
Definition: acstruct.h:111
ACPI_PARSE_STATE ParserState
Definition: acstruct.h:97

Referenced by AcpiDsExecBeginOp(), AcpiDsExecEndOp(), AcpiPsGetNextNamepath(), and AcpiPsParseAml().

◆ AcpiDsRestartControlMethod()

ACPI_STATUS AcpiDsRestartControlMethod ( ACPI_WALK_STATE WalkState,
ACPI_OPERAND_OBJECT ReturnDesc 
)

Definition at line 685 of file dsmethod.c.

688{
690 int SameAsImplicitReturn;
691
692
693 ACPI_FUNCTION_TRACE_PTR (DsRestartControlMethod, WalkState);
694
695
697 "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n",
698 AcpiUtGetNodeName (WalkState->MethodNode),
699 WalkState->MethodCallOp, ReturnDesc));
700
702 " ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n",
703 WalkState->ReturnUsed,
704 WalkState->Results, WalkState));
705
706 /* Did the called method return a value? */
707
708 if (ReturnDesc)
709 {
710 /* Is the implicit return object the same as the return desc? */
711
712 SameAsImplicitReturn = (WalkState->ImplicitReturnObj == ReturnDesc);
713
714 /* Are we actually going to use the return value? */
715
716 if (WalkState->ReturnUsed)
717 {
718 /* Save the return value from the previous method */
719
720 Status = AcpiDsResultPush (ReturnDesc, WalkState);
721 if (ACPI_FAILURE (Status))
722 {
723 AcpiUtRemoveReference (ReturnDesc);
725 }
726
727 /*
728 * Save as THIS method's return value in case it is returned
729 * immediately to yet another method
730 */
731 WalkState->ReturnDesc = ReturnDesc;
732 }
733
734 /*
735 * The following code is the optional support for the so-called
736 * "implicit return". Some AML code assumes that the last value of the
737 * method is "implicitly" returned to the caller, in the absence of an
738 * explicit return value.
739 *
740 * Just save the last result of the method as the return value.
741 *
742 * NOTE: this is optional because the ASL language does not actually
743 * support this behavior.
744 */
745 else if (!AcpiDsDoImplicitReturn (ReturnDesc, WalkState, FALSE) ||
746 SameAsImplicitReturn)
747 {
748 /*
749 * Delete the return value if it will not be used by the
750 * calling method or remove one reference if the explicit return
751 * is the same as the implicit return value.
752 */
753 AcpiUtRemoveReference (ReturnDesc);
754 }
755 }
756
758}
#define FALSE
Definition: types.h:117
BOOLEAN AcpiDsDoImplicitReturn(ACPI_OPERAND_OBJECT *ReturnDesc, ACPI_WALK_STATE *WalkState, BOOLEAN AddReference)
Definition: dsutils.c:123
ACPI_STATUS AcpiDsResultPush(ACPI_OPERAND_OBJECT *Object, ACPI_WALK_STATE *WalkState)
Definition: dswstate.c:160
union acpi_operand_object * ImplicitReturnObj
Definition: acstruct.h:112
ACPI_GENERIC_STATE * Results
Definition: acstruct.h:122
union acpi_operand_object * ReturnDesc
Definition: acstruct.h:123
ACPI_PARSE_OBJECT * MethodCallOp
Definition: acstruct.h:114
UINT8 ReturnUsed
Definition: acstruct.h:85

Referenced by AcpiPsParseAml().

◆ AcpiDsTerminateControlMethod()

void AcpiDsTerminateControlMethod ( ACPI_OPERAND_OBJECT MethodDesc,
ACPI_WALK_STATE WalkState 
)

Definition at line 779 of file dsmethod.c.

782{
783
784 ACPI_FUNCTION_TRACE_PTR (DsTerminateControlMethod, WalkState);
785
786
787 /* MethodDesc is required, WalkState is optional */
788
789 if (!MethodDesc)
790 {
792 }
793
794 if (WalkState)
795 {
796 /* Delete all arguments and locals */
797
798 AcpiDsMethodDataDeleteAll (WalkState);
799
800 /*
801 * Delete any namespace objects created anywhere within the
802 * namespace by the execution of this method. Unless:
803 * 1) This method is a module-level executable code method, in which
804 * case we want make the objects permanent.
805 * 2) There are other threads executing the method, in which case we
806 * will wait until the last thread has completed.
807 */
808 if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) &&
809 (MethodDesc->Method.ThreadCount == 1))
810 {
811 /* Delete any direct children of (created by) this method */
812
816
817 /*
818 * Delete any objects that were created by this method
819 * elsewhere in the namespace (if any were created).
820 * Use of the ACPI_METHOD_MODIFIED_NAMESPACE optimizes the
821 * deletion such that we don't have to perform an entire
822 * namespace walk for every control method execution.
823 */
825 {
829 MethodDesc->Method.InfoFlags &=
830 ~ACPI_METHOD_MODIFIED_NAMESPACE;
831 }
832 }
833
834 /*
835 * If method is serialized, release the mutex and restore the
836 * current sync level for this thread
837 */
838 if (MethodDesc->Method.Mutex)
839 {
840 /* Acquisition Depth handles recursive calls */
841
842 MethodDesc->Method.Mutex->Mutex.AcquisitionDepth--;
843 if (!MethodDesc->Method.Mutex->Mutex.AcquisitionDepth)
844 {
845 WalkState->Thread->CurrentSyncLevel =
846 MethodDesc->Method.Mutex->Mutex.OriginalSyncLevel;
847
849 MethodDesc->Method.Mutex->Mutex.OsMutex);
850 MethodDesc->Method.Mutex->Mutex.ThreadId = 0;
851 }
852 }
853 }
854
855 /* Decrement the thread count on the method */
856
857 if (MethodDesc->Method.ThreadCount)
858 {
859 MethodDesc->Method.ThreadCount--;
860 }
861 else
862 {
864 "Invalid zero thread count in method"));
865 }
866
867 /* Are there any other threads currently executing this method? */
868
869 if (MethodDesc->Method.ThreadCount)
870 {
871 /*
872 * Additional threads. Do not release the OwnerId in this case,
873 * we immediately reuse it for the next thread executing this method
874 */
876 "*** Completed execution of one thread, %u threads remaining\n",
877 MethodDesc->Method.ThreadCount));
878 }
879 else
880 {
881 /* This is the only executing thread for this method */
882
883 /*
884 * Support to dynamically change a method from NotSerialized to
885 * Serialized if it appears that the method is incorrectly written and
886 * does not support multiple thread execution. The best example of this
887 * is if such a method creates namespace objects and blocks. A second
888 * thread will fail with an AE_ALREADY_EXISTS exception.
889 *
890 * This code is here because we must wait until the last thread exits
891 * before marking the method as serialized.
892 */
894 {
895 if (WalkState)
896 {
897 ACPI_INFO ((
898 "Marking method %4.4s as Serialized "
899 "because of AE_ALREADY_EXISTS error",
900 WalkState->MethodNode->Name.Ascii));
901 }
902
903 /*
904 * Method tried to create an object twice and was marked as
905 * "pending serialized". The probable cause is that the method
906 * cannot handle reentrancy.
907 *
908 * The method was created as NotSerialized, but it tried to create
909 * a named object and then blocked, causing the second thread
910 * entrance to begin and then fail. Workaround this problem by
911 * marking the method permanently as Serialized when the last
912 * thread exits here.
913 */
914 MethodDesc->Method.InfoFlags &=
915 ~ACPI_METHOD_SERIALIZED_PENDING;
916
917 MethodDesc->Method.InfoFlags |=
919 MethodDesc->Method.SyncLevel = 0;
920 }
921
922 /* No more threads, we can free the OwnerId */
923
924 if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL))
925 {
926 AcpiUtReleaseOwnerId (&MethodDesc->Method.OwnerId);
927 }
928 }
929
931 MethodDesc, WalkState);
932
934}
void AcpiNsDeleteNamespaceSubtree(ACPI_NAMESPACE_NODE *ParentHandle)
Definition: nsalloc.c:399
void AcpiNsDeleteNamespaceByOwner(ACPI_OWNER_ID OwnerId)
Definition: nsalloc.c:497
#define ACPI_METHOD_MODIFIED_NAMESPACE
Definition: acobject.h:241
#define ACPI_METHOD_MODULE_LEVEL
Definition: acobject.h:236
#define ACPI_METHOD_SERIALIZED_PENDING
Definition: acobject.h:239
#define ACPI_INFO(plist)
Definition: acoutput.h:237
#define return_VOID
Definition: acoutput.h:495
void AcpiUtReleaseOwnerId(ACPI_OWNER_ID *OwnerId)
Definition: utownerid.c:190
void AcpiDsMethodDataDeleteAll(ACPI_WALK_STATE *WalkState)
Definition: dsmthdat.c:153
void AcpiExStopTraceMethod(ACPI_NAMESPACE_NODE *MethodNode, ACPI_OPERAND_OBJECT *ObjDesc, ACPI_WALK_STATE *WalkState)
Definition: extrace.c:290
union acpi_operand_object * Node
Definition: acobject.h:220

Referenced by AcpiDsCallControlMethod(), AcpiPsExecuteMethod(), and AcpiPsParseAml().