dbexec.c revision 217365
1/******************************************************************************* 2 * 3 * Module Name: dbexec - debugger control method execution 4 * 5 ******************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2011, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 45#include <contrib/dev/acpica/include/acpi.h> 46#include <contrib/dev/acpica/include/accommon.h> 47#include <contrib/dev/acpica/include/acdebug.h> 48#include <contrib/dev/acpica/include/acnamesp.h> 49 50#ifdef ACPI_DEBUGGER 51 52#define _COMPONENT ACPI_CA_DEBUGGER 53 ACPI_MODULE_NAME ("dbexec") 54 55 56static ACPI_DB_METHOD_INFO AcpiGbl_DbMethodInfo; 57 58/* Local prototypes */ 59 60static ACPI_STATUS 61AcpiDbExecuteMethod ( 62 ACPI_DB_METHOD_INFO *Info, 63 ACPI_BUFFER *ReturnObj); 64 65static void 66AcpiDbExecuteSetup ( 67 ACPI_DB_METHOD_INFO *Info); 68 69static UINT32 70AcpiDbGetOutstandingAllocations ( 71 void); 72 73static void ACPI_SYSTEM_XFACE 74AcpiDbMethodThread ( 75 void *Context); 76 77static ACPI_STATUS 78AcpiDbExecutionWalk ( 79 ACPI_HANDLE ObjHandle, 80 UINT32 NestingLevel, 81 void *Context, 82 void **ReturnValue); 83 84 85/******************************************************************************* 86 * 87 * FUNCTION: AcpiDbExecuteMethod 88 * 89 * PARAMETERS: Info - Valid info segment 90 * ReturnObj - Where to put return object 91 * 92 * RETURN: Status 93 * 94 * DESCRIPTION: Execute a control method. 95 * 96 ******************************************************************************/ 97 98static ACPI_STATUS 99AcpiDbExecuteMethod ( 100 ACPI_DB_METHOD_INFO *Info, 101 ACPI_BUFFER *ReturnObj) 102{ 103 ACPI_STATUS Status; 104 ACPI_OBJECT_LIST ParamObjects; 105 ACPI_OBJECT Params[ACPI_METHOD_NUM_ARGS]; 106 ACPI_HANDLE Handle; 107 UINT32 i; 108 ACPI_DEVICE_INFO *ObjInfo; 109 110 111 ACPI_FUNCTION_TRACE (DbExecuteMethod); 112 113 114 if (AcpiGbl_DbOutputToFile && !AcpiDbgLevel) 115 { 116 AcpiOsPrintf ("Warning: debug output is not enabled!\n"); 117 } 118 119 /* Get the NS node, determines existence also */ 120 121 Status = AcpiGetHandle (NULL, Info->Pathname, &Handle); 122 if (ACPI_FAILURE (Status)) 123 { 124 return_ACPI_STATUS (Status); 125 } 126 127 /* Get the object info for number of method parameters */ 128 129 Status = AcpiGetObjectInfo (Handle, &ObjInfo); 130 if (ACPI_FAILURE (Status)) 131 { 132 return_ACPI_STATUS (Status); 133 } 134 135 ParamObjects.Pointer = NULL; 136 ParamObjects.Count = 0; 137 138 if (ObjInfo->Type == ACPI_TYPE_METHOD) 139 { 140 /* Are there arguments to the method? */ 141 142 if (Info->Args && Info->Args[0]) 143 { 144 for (i = 0; Info->Args[i] && 145 (i < ACPI_METHOD_NUM_ARGS) && 146 (i < ObjInfo->ParamCount); 147 i++) 148 { 149 Params[i].Type = ACPI_TYPE_INTEGER; 150 Params[i].Integer.Value = ACPI_STRTOUL (Info->Args[i], NULL, 16); 151 } 152 153 ParamObjects.Pointer = Params; 154 ParamObjects.Count = i; 155 } 156 else 157 { 158 /* Setup default parameters */ 159 160 for (i = 0; i < ObjInfo->ParamCount; i++) 161 { 162 switch (i) 163 { 164 case 0: 165 166 Params[0].Type = ACPI_TYPE_INTEGER; 167 Params[0].Integer.Value = 0x01020304; 168 break; 169 170 case 1: 171 172 Params[1].Type = ACPI_TYPE_STRING; 173 Params[1].String.Length = 12; 174 Params[1].String.Pointer = "AML Debugger"; 175 break; 176 177 default: 178 179 Params[i].Type = ACPI_TYPE_INTEGER; 180 Params[i].Integer.Value = i * (UINT64) 0x1000; 181 break; 182 } 183 } 184 185 ParamObjects.Pointer = Params; 186 ParamObjects.Count = ObjInfo->ParamCount; 187 } 188 } 189 190 ACPI_FREE (ObjInfo); 191 192 /* Prepare for a return object of arbitrary size */ 193 194 ReturnObj->Pointer = AcpiGbl_DbBuffer; 195 ReturnObj->Length = ACPI_DEBUG_BUFFER_SIZE; 196 197 /* Do the actual method execution */ 198 199 AcpiGbl_MethodExecuting = TRUE; 200 Status = AcpiEvaluateObject (NULL, 201 Info->Pathname, &ParamObjects, ReturnObj); 202 203 AcpiGbl_CmSingleStep = FALSE; 204 AcpiGbl_MethodExecuting = FALSE; 205 206 if (ACPI_FAILURE (Status)) 207 { 208 ACPI_EXCEPTION ((AE_INFO, Status, 209 "while executing %s from debugger", Info->Pathname)); 210 211 if (Status == AE_BUFFER_OVERFLOW) 212 { 213 ACPI_ERROR ((AE_INFO, 214 "Possible overflow of internal debugger buffer (size 0x%X needed 0x%X)", 215 ACPI_DEBUG_BUFFER_SIZE, (UINT32) ReturnObj->Length)); 216 } 217 } 218 219 return_ACPI_STATUS (Status); 220} 221 222 223/******************************************************************************* 224 * 225 * FUNCTION: AcpiDbExecuteSetup 226 * 227 * PARAMETERS: Info - Valid method info 228 * 229 * RETURN: None 230 * 231 * DESCRIPTION: Setup info segment prior to method execution 232 * 233 ******************************************************************************/ 234 235static void 236AcpiDbExecuteSetup ( 237 ACPI_DB_METHOD_INFO *Info) 238{ 239 240 /* Catenate the current scope to the supplied name */ 241 242 Info->Pathname[0] = 0; 243 if ((Info->Name[0] != '\\') && 244 (Info->Name[0] != '/')) 245 { 246 ACPI_STRCAT (Info->Pathname, AcpiGbl_DbScopeBuf); 247 } 248 249 ACPI_STRCAT (Info->Pathname, Info->Name); 250 AcpiDbPrepNamestring (Info->Pathname); 251 252 AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 253 AcpiOsPrintf ("Executing %s\n", Info->Pathname); 254 255 if (Info->Flags & EX_SINGLE_STEP) 256 { 257 AcpiGbl_CmSingleStep = TRUE; 258 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 259 } 260 261 else 262 { 263 /* No single step, allow redirection to a file */ 264 265 AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT); 266 } 267} 268 269 270#ifdef ACPI_DBG_TRACK_ALLOCATIONS 271UINT32 272AcpiDbGetCacheInfo ( 273 ACPI_MEMORY_LIST *Cache) 274{ 275 276 return (Cache->TotalAllocated - Cache->TotalFreed - Cache->CurrentDepth); 277} 278#endif 279 280/******************************************************************************* 281 * 282 * FUNCTION: AcpiDbGetOutstandingAllocations 283 * 284 * PARAMETERS: None 285 * 286 * RETURN: Current global allocation count minus cache entries 287 * 288 * DESCRIPTION: Determine the current number of "outstanding" allocations -- 289 * those allocations that have not been freed and also are not 290 * in one of the various object caches. 291 * 292 ******************************************************************************/ 293 294static UINT32 295AcpiDbGetOutstandingAllocations ( 296 void) 297{ 298 UINT32 Outstanding = 0; 299 300#ifdef ACPI_DBG_TRACK_ALLOCATIONS 301 302 Outstanding += AcpiDbGetCacheInfo (AcpiGbl_StateCache); 303 Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeCache); 304 Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeExtCache); 305 Outstanding += AcpiDbGetCacheInfo (AcpiGbl_OperandCache); 306#endif 307 308 return (Outstanding); 309} 310 311 312/******************************************************************************* 313 * 314 * FUNCTION: AcpiDbExecutionWalk 315 * 316 * PARAMETERS: WALK_CALLBACK 317 * 318 * RETURN: Status 319 * 320 * DESCRIPTION: Execute a control method. Name is relative to the current 321 * scope. 322 * 323 ******************************************************************************/ 324 325static ACPI_STATUS 326AcpiDbExecutionWalk ( 327 ACPI_HANDLE ObjHandle, 328 UINT32 NestingLevel, 329 void *Context, 330 void **ReturnValue) 331{ 332 ACPI_OPERAND_OBJECT *ObjDesc; 333 ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 334 ACPI_BUFFER ReturnObj; 335 ACPI_STATUS Status; 336 337 338 ObjDesc = AcpiNsGetAttachedObject (Node); 339 if (ObjDesc->Method.ParamCount) 340 { 341 return (AE_OK); 342 } 343 344 ReturnObj.Pointer = NULL; 345 ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 346 347 AcpiNsPrintNodePathname (Node, "Execute"); 348 349 /* Do the actual method execution */ 350 351 AcpiOsPrintf ("\n"); 352 AcpiGbl_MethodExecuting = TRUE; 353 354 Status = AcpiEvaluateObject (Node, NULL, NULL, &ReturnObj); 355 356 AcpiOsPrintf ("[%4.4s] returned %s\n", AcpiUtGetNodeName (Node), 357 AcpiFormatException (Status)); 358 AcpiGbl_MethodExecuting = FALSE; 359 360 return (AE_OK); 361} 362 363 364/******************************************************************************* 365 * 366 * FUNCTION: AcpiDbExecute 367 * 368 * PARAMETERS: Name - Name of method to execute 369 * Args - Parameters to the method 370 * Flags - single step/no single step 371 * 372 * RETURN: None 373 * 374 * DESCRIPTION: Execute a control method. Name is relative to the current 375 * scope. 376 * 377 ******************************************************************************/ 378 379void 380AcpiDbExecute ( 381 char *Name, 382 char **Args, 383 UINT32 Flags) 384{ 385 ACPI_STATUS Status; 386 ACPI_BUFFER ReturnObj; 387 char *NameString; 388 389 390#ifdef ACPI_DEBUG_OUTPUT 391 UINT32 PreviousAllocations; 392 UINT32 Allocations; 393 394 395 /* Memory allocation tracking */ 396 397 PreviousAllocations = AcpiDbGetOutstandingAllocations (); 398#endif 399 400 if (*Name == '*') 401 { 402 (void) AcpiWalkNamespace (ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT, 403 ACPI_UINT32_MAX, AcpiDbExecutionWalk, NULL, NULL, NULL); 404 return; 405 } 406 else 407 { 408 NameString = ACPI_ALLOCATE (ACPI_STRLEN (Name) + 1); 409 if (!NameString) 410 { 411 return; 412 } 413 414 ACPI_MEMSET (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); 415 416 ACPI_STRCPY (NameString, Name); 417 AcpiUtStrupr (NameString); 418 AcpiGbl_DbMethodInfo.Name = NameString; 419 AcpiGbl_DbMethodInfo.Args = Args; 420 AcpiGbl_DbMethodInfo.Flags = Flags; 421 422 ReturnObj.Pointer = NULL; 423 ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 424 425 AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo); 426 Status = AcpiDbExecuteMethod (&AcpiGbl_DbMethodInfo, &ReturnObj); 427 ACPI_FREE (NameString); 428 } 429 430 /* 431 * Allow any handlers in separate threads to complete. 432 * (Such as Notify handlers invoked from AML executed above). 433 */ 434 AcpiOsSleep ((UINT64) 10); 435 436 437#ifdef ACPI_DEBUG_OUTPUT 438 439 /* Memory allocation tracking */ 440 441 Allocations = AcpiDbGetOutstandingAllocations () - PreviousAllocations; 442 443 AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 444 445 if (Allocations > 0) 446 { 447 AcpiOsPrintf ("Outstanding: 0x%X allocations after execution\n", 448 Allocations); 449 } 450#endif 451 452 if (ACPI_FAILURE (Status)) 453 { 454 AcpiOsPrintf ("Execution of %s failed with status %s\n", 455 AcpiGbl_DbMethodInfo.Pathname, AcpiFormatException (Status)); 456 } 457 else 458 { 459 /* Display a return object, if any */ 460 461 if (ReturnObj.Length) 462 { 463 AcpiOsPrintf ("Execution of %s returned object %p Buflen %X\n", 464 AcpiGbl_DbMethodInfo.Pathname, ReturnObj.Pointer, 465 (UINT32) ReturnObj.Length); 466 AcpiDbDumpExternalObject (ReturnObj.Pointer, 1); 467 } 468 else 469 { 470 AcpiOsPrintf ("No return object from execution of %s\n", 471 AcpiGbl_DbMethodInfo.Pathname); 472 } 473 } 474 475 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 476} 477 478 479/******************************************************************************* 480 * 481 * FUNCTION: AcpiDbMethodThread 482 * 483 * PARAMETERS: Context - Execution info segment 484 * 485 * RETURN: None 486 * 487 * DESCRIPTION: Debugger execute thread. Waits for a command line, then 488 * simply dispatches it. 489 * 490 ******************************************************************************/ 491 492static void ACPI_SYSTEM_XFACE 493AcpiDbMethodThread ( 494 void *Context) 495{ 496 ACPI_STATUS Status; 497 ACPI_DB_METHOD_INFO *Info = Context; 498 ACPI_DB_METHOD_INFO LocalInfo; 499 UINT32 i; 500 UINT8 Allow; 501 ACPI_BUFFER ReturnObj; 502 503 504 /* 505 * AcpiGbl_DbMethodInfo.Arguments will be passed as method arguments. 506 * Prevent AcpiGbl_DbMethodInfo from being modified by multiple threads 507 * concurrently. 508 * 509 * Note: The arguments we are passing are used by the ASL test suite 510 * (aslts). Do not change them without updating the tests. 511 */ 512 (void) AcpiOsWaitSemaphore (Info->InfoGate, 1, ACPI_WAIT_FOREVER); 513 514 if (Info->InitArgs) 515 { 516 AcpiDbUInt32ToHexString (Info->NumCreated, Info->IndexOfThreadStr); 517 AcpiDbUInt32ToHexString ((UINT32) AcpiOsGetThreadId (), Info->IdOfThreadStr); 518 } 519 520 if (Info->Threads && (Info->NumCreated < Info->NumThreads)) 521 { 522 Info->Threads[Info->NumCreated++] = AcpiOsGetThreadId(); 523 } 524 525 LocalInfo = *Info; 526 LocalInfo.Args = LocalInfo.Arguments; 527 LocalInfo.Arguments[0] = LocalInfo.NumThreadsStr; 528 LocalInfo.Arguments[1] = LocalInfo.IdOfThreadStr; 529 LocalInfo.Arguments[2] = LocalInfo.IndexOfThreadStr; 530 LocalInfo.Arguments[3] = NULL; 531 532 (void) AcpiOsSignalSemaphore (Info->InfoGate, 1); 533 534 for (i = 0; i < Info->NumLoops; i++) 535 { 536 Status = AcpiDbExecuteMethod (&LocalInfo, &ReturnObj); 537 if (ACPI_FAILURE (Status)) 538 { 539 AcpiOsPrintf ("%s During execution of %s at iteration %X\n", 540 AcpiFormatException (Status), Info->Pathname, i); 541 if (Status == AE_ABORT_METHOD) 542 { 543 break; 544 } 545 } 546 547#if 0 548 if ((i % 100) == 0) 549 { 550 AcpiOsPrintf ("%u executions, Thread 0x%x\n", i, AcpiOsGetThreadId ()); 551 } 552 553 if (ReturnObj.Length) 554 { 555 AcpiOsPrintf ("Execution of %s returned object %p Buflen %X\n", 556 Info->Pathname, ReturnObj.Pointer, (UINT32) ReturnObj.Length); 557 AcpiDbDumpExternalObject (ReturnObj.Pointer, 1); 558 } 559#endif 560 } 561 562 /* Signal our completion */ 563 564 Allow = 0; 565 (void) AcpiOsWaitSemaphore (Info->ThreadCompleteGate, 1, ACPI_WAIT_FOREVER); 566 Info->NumCompleted++; 567 568 if (Info->NumCompleted == Info->NumThreads) 569 { 570 /* Do signal for main thread once only */ 571 Allow = 1; 572 } 573 574 (void) AcpiOsSignalSemaphore (Info->ThreadCompleteGate, 1); 575 576 if (Allow) 577 { 578 Status = AcpiOsSignalSemaphore (Info->MainThreadGate, 1); 579 if (ACPI_FAILURE (Status)) 580 { 581 AcpiOsPrintf ("Could not signal debugger thread sync semaphore, %s\n", 582 AcpiFormatException (Status)); 583 } 584 } 585} 586 587 588/******************************************************************************* 589 * 590 * FUNCTION: AcpiDbCreateExecutionThreads 591 * 592 * PARAMETERS: NumThreadsArg - Number of threads to create 593 * NumLoopsArg - Loop count for the thread(s) 594 * MethodNameArg - Control method to execute 595 * 596 * RETURN: None 597 * 598 * DESCRIPTION: Create threads to execute method(s) 599 * 600 ******************************************************************************/ 601 602void 603AcpiDbCreateExecutionThreads ( 604 char *NumThreadsArg, 605 char *NumLoopsArg, 606 char *MethodNameArg) 607{ 608 ACPI_STATUS Status; 609 UINT32 NumThreads; 610 UINT32 NumLoops; 611 UINT32 i; 612 UINT32 Size; 613 ACPI_MUTEX MainThreadGate; 614 ACPI_MUTEX ThreadCompleteGate; 615 ACPI_MUTEX InfoGate; 616 617 618 /* Get the arguments */ 619 620 NumThreads = ACPI_STRTOUL (NumThreadsArg, NULL, 0); 621 NumLoops = ACPI_STRTOUL (NumLoopsArg, NULL, 0); 622 623 if (!NumThreads || !NumLoops) 624 { 625 AcpiOsPrintf ("Bad argument: Threads %X, Loops %X\n", 626 NumThreads, NumLoops); 627 return; 628 } 629 630 /* 631 * Create the semaphore for synchronization of 632 * the created threads with the main thread. 633 */ 634 Status = AcpiOsCreateSemaphore (1, 0, &MainThreadGate); 635 if (ACPI_FAILURE (Status)) 636 { 637 AcpiOsPrintf ("Could not create semaphore for synchronization with the main thread, %s\n", 638 AcpiFormatException (Status)); 639 return; 640 } 641 642 /* 643 * Create the semaphore for synchronization 644 * between the created threads. 645 */ 646 Status = AcpiOsCreateSemaphore (1, 1, &ThreadCompleteGate); 647 if (ACPI_FAILURE (Status)) 648 { 649 AcpiOsPrintf ("Could not create semaphore for synchronization between the created threads, %s\n", 650 AcpiFormatException (Status)); 651 (void) AcpiOsDeleteSemaphore (MainThreadGate); 652 return; 653 } 654 655 Status = AcpiOsCreateSemaphore (1, 1, &InfoGate); 656 if (ACPI_FAILURE (Status)) 657 { 658 AcpiOsPrintf ("Could not create semaphore for synchronization of AcpiGbl_DbMethodInfo, %s\n", 659 AcpiFormatException (Status)); 660 (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 661 (void) AcpiOsDeleteSemaphore (MainThreadGate); 662 return; 663 } 664 665 ACPI_MEMSET (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); 666 667 /* Array to store IDs of threads */ 668 669 AcpiGbl_DbMethodInfo.NumThreads = NumThreads; 670 Size = sizeof (ACPI_THREAD_ID) * AcpiGbl_DbMethodInfo.NumThreads; 671 AcpiGbl_DbMethodInfo.Threads = AcpiOsAllocate (Size); 672 if (AcpiGbl_DbMethodInfo.Threads == NULL) 673 { 674 AcpiOsPrintf ("No memory for thread IDs array\n"); 675 (void) AcpiOsDeleteSemaphore (MainThreadGate); 676 (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 677 (void) AcpiOsDeleteSemaphore (InfoGate); 678 return; 679 } 680 ACPI_MEMSET (AcpiGbl_DbMethodInfo.Threads, 0, Size); 681 682 /* Setup the context to be passed to each thread */ 683 684 AcpiGbl_DbMethodInfo.Name = MethodNameArg; 685 AcpiGbl_DbMethodInfo.Flags = 0; 686 AcpiGbl_DbMethodInfo.NumLoops = NumLoops; 687 AcpiGbl_DbMethodInfo.MainThreadGate = MainThreadGate; 688 AcpiGbl_DbMethodInfo.ThreadCompleteGate = ThreadCompleteGate; 689 AcpiGbl_DbMethodInfo.InfoGate = InfoGate; 690 691 /* Init arguments to be passed to method */ 692 693 AcpiGbl_DbMethodInfo.InitArgs = 1; 694 AcpiGbl_DbMethodInfo.Args = AcpiGbl_DbMethodInfo.Arguments; 695 AcpiGbl_DbMethodInfo.Arguments[0] = AcpiGbl_DbMethodInfo.NumThreadsStr; 696 AcpiGbl_DbMethodInfo.Arguments[1] = AcpiGbl_DbMethodInfo.IdOfThreadStr; 697 AcpiGbl_DbMethodInfo.Arguments[2] = AcpiGbl_DbMethodInfo.IndexOfThreadStr; 698 AcpiGbl_DbMethodInfo.Arguments[3] = NULL; 699 AcpiDbUInt32ToHexString (NumThreads, AcpiGbl_DbMethodInfo.NumThreadsStr); 700 701 AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo); 702 703 /* Create the threads */ 704 705 AcpiOsPrintf ("Creating %X threads to execute %X times each\n", 706 NumThreads, NumLoops); 707 708 for (i = 0; i < (NumThreads); i++) 709 { 710 Status = AcpiOsExecute (OSL_DEBUGGER_THREAD, AcpiDbMethodThread, 711 &AcpiGbl_DbMethodInfo); 712 if (ACPI_FAILURE (Status)) 713 { 714 break; 715 } 716 } 717 718 /* Wait for all threads to complete */ 719 720 (void) AcpiOsWaitSemaphore (MainThreadGate, 1, ACPI_WAIT_FOREVER); 721 722 AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 723 AcpiOsPrintf ("All threads (%X) have completed\n", NumThreads); 724 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 725 726 /* Cleanup and exit */ 727 728 (void) AcpiOsDeleteSemaphore (MainThreadGate); 729 (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 730 (void) AcpiOsDeleteSemaphore (InfoGate); 731 732 AcpiOsFree (AcpiGbl_DbMethodInfo.Threads); 733 AcpiGbl_DbMethodInfo.Threads = NULL; 734} 735 736#endif /* ACPI_DEBUGGER */ 737 738 739