Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

722 lines
20 KiB

  1. /*** ctxt.c - Context Block handling functions
  2. *
  3. * Copyright (c) 1996,1997 Microsoft Corporation
  4. * Author: Michael Tsang (MikeTs)
  5. * Created 06/13/97
  6. *
  7. * MODIFICATION HISTORY
  8. */
  9. #include "pch.h"
  10. #ifdef LOCKABLE_PRAGMA
  11. #pragma ACPI_LOCKABLE_DATA
  12. #pragma ACPI_LOCKABLE_CODE
  13. #endif
  14. NTSTATUS
  15. LOCAL
  16. NewContext(
  17. PPCTXT ppctxt
  18. )
  19. /*++
  20. Routine Description:
  21. Allocate a new context structure from tne NonPaged Lookaside
  22. List. Also keep track of the high water marks so that the OS
  23. can intelligently decide what the "appropriate" number of
  24. contexts that it should allocate.
  25. Note that this code raises the possibility that if we detect
  26. an out-of-memory error, we might be able to save a registry
  27. key that includes a new larger number (to prevent this problem
  28. in the first place). Adaptive recovery?
  29. Arguments:
  30. ppctxt - address of to hold the newly created context
  31. Return Value:
  32. NTSTATUS
  33. --*/
  34. {
  35. TRACENAME("NEWCONTEXT")
  36. KIRQL oldIrql;
  37. NTSTATUS rc = STATUS_SUCCESS;
  38. ENTER(2, ("NewContext(ppctxt=%x)\n", ppctxt));
  39. *ppctxt = ExAllocateFromNPagedLookasideList(
  40. &AMLIContextLookAsideList
  41. );
  42. if (*ppctxt == NULL) {
  43. AMLI_WARN(("NewContext: Could not Allocate New Context"));
  44. rc = AMLIERR_OUT_OF_MEM;
  45. } else {
  46. //
  47. // Bookkeeping for memory resources to determine the high
  48. // water mark
  49. //
  50. KeAcquireSpinLock(&gdwGContextSpinLock, &oldIrql );
  51. gdwcCTObjs++;
  52. if (gdwcCTObjs > 0 &&
  53. (ULONG) gdwcCTObjs > gdwcCTObjsMax) {
  54. gdwcCTObjsMax = gdwcCTObjs;
  55. }
  56. KeReleaseSpinLock(&gdwGContextSpinLock, oldIrql );
  57. //
  58. // Context Initialization
  59. //
  60. InitContext(*ppctxt, gdwCtxtBlkSize);
  61. AcquireMutex(&gmutCtxtList);
  62. ListInsertTail(&(*ppctxt)->listCtxt, &gplistCtxtHead);
  63. ReleaseMutex(&gmutCtxtList);
  64. }
  65. EXIT(2, ("NewContext=%x (pctxt=%x)\n", rc, *ppctxt));
  66. return rc;
  67. } //NewContext
  68. VOID
  69. LOCAL
  70. FreeContext(
  71. PCTXT pctxt
  72. )
  73. /*++
  74. Routine Description:
  75. This is routine is called when a context is no longer required
  76. and should be returned to the system's LookAside list
  77. Arguments:
  78. pctxt - Address of the context to be freed
  79. Return Value:
  80. None
  81. --*/
  82. {
  83. TRACENAME("FREECONTEXT")
  84. KIRQL oldIrql;
  85. ENTER(2, ("FreeContext(pctxt=%x)\n", pctxt));
  86. ASSERT(pctxt->powner == NULL);
  87. //
  88. // Need to hold the proper mutex to touch the global ctxt list
  89. //
  90. AcquireMutex(&gmutCtxtList);
  91. ListRemoveEntry(&pctxt->listCtxt, &gplistCtxtHead);
  92. if (pctxt->pplistCtxtQueue != NULL) {
  93. ListRemoveEntry(&pctxt->listQueue, pctxt->pplistCtxtQueue);
  94. }
  95. //
  96. // Done with the global mutex
  97. //
  98. ReleaseMutex(&gmutCtxtList);
  99. //
  100. // Release any allocated storage that might not have been cleaned up
  101. //
  102. FreeDataBuffs(&pctxt->Result, 1);
  103. //
  104. // Bookkeeping for memory resources to determine the high
  105. // water mark
  106. //
  107. KeAcquireSpinLock(&gdwGContextSpinLock, &oldIrql );
  108. gdwcCTObjs--;
  109. ASSERT(gdwcCTObjs >= 0);
  110. KeReleaseSpinLock(&gdwGContextSpinLock, oldIrql );
  111. //
  112. // Log the end of a method
  113. //
  114. ACPIWMILOGEVENT((1,
  115. EVENT_TRACE_TYPE_END,
  116. GUID_List[AMLI_LOG_GUID],
  117. "Object = %s",
  118. GetObjectPath(pctxt->pnsObj)
  119. ));
  120. //
  121. // Return the context to the nonpaged lookaside list
  122. //
  123. ExFreeToNPagedLookasideList(&AMLIContextLookAsideList, pctxt);
  124. EXIT(2, ("FreeContext!\n"));
  125. } //FreeContext
  126. /***LP InitContext - initialize a given context block
  127. *
  128. * ENTRY
  129. * pctxt -> CTXT
  130. * dwLen - length of context block
  131. *
  132. * EXIT
  133. * None
  134. */
  135. VOID LOCAL InitContext(PCTXT pctxt, ULONG dwLen)
  136. {
  137. TRACENAME("INITCONTEXT")
  138. ENTER(2, ("InitContext(pctxt=%x,Len=%d)\n", pctxt, dwLen));
  139. MEMZERO(pctxt, sizeof(CTXT) - sizeof(HEAP));
  140. pctxt->dwSig = SIG_CTXT;
  141. pctxt->pbCtxtEnd = (PUCHAR)pctxt + dwLen;
  142. pctxt->pheapCurrent = &pctxt->LocalHeap;
  143. // #ifdef DEBUGGER
  144. // KeQuerySystemTime(&pctxt->Timestamp);
  145. // #endif
  146. KeInitializeDpc(&pctxt->Dpc, TimeoutCallback, pctxt);
  147. KeInitializeTimer(&pctxt->Timer);
  148. InitHeap(&pctxt->LocalHeap,
  149. (ULONG)(pctxt->pbCtxtEnd - (PUCHAR)&pctxt->LocalHeap));
  150. pctxt->LocalHeap.pheapHead = &pctxt->LocalHeap;
  151. EXIT(2, ("InitContext!\n"));
  152. } //InitContext
  153. /***LP IsStackEmpty - determine if the stack is empty
  154. *
  155. * ENTRY
  156. * pctxt -> CTXT
  157. *
  158. * EXIT-SUCCESS
  159. * returns TRUE - stack is empty
  160. * EXIT-FAILURE
  161. * returns FALSE
  162. */
  163. BOOLEAN LOCAL IsStackEmpty(PCTXT pctxt)
  164. {
  165. TRACENAME("ISSTACKEMPTY")
  166. BOOLEAN rc;
  167. ENTER(2, ("IsStackEmpty(pctxt=%p)\n", pctxt));
  168. rc = (BOOLEAN)(pctxt->LocalHeap.pbHeapEnd == pctxt->pbCtxtEnd);
  169. EXIT(2, ("IsStackEmpty=%x\n", rc));
  170. return rc;
  171. } //IsStackEmpty
  172. /***LP PushFrame - Push a new frame on the stack
  173. *
  174. * ENTRY
  175. * pctxt -> CTXT
  176. * dwSig - frame object signature
  177. * dwLen - size of the frame object
  178. * pfnParse -> frame object parse function
  179. * ppvFrame -> to hold pointer to the newly pushed frame (can be NULL)
  180. *
  181. * EXIT-SUCCESS
  182. * returns STATUS_SUCCESS
  183. * EXIT-FAILURE
  184. * returns AMLIERR_ code
  185. */
  186. NTSTATUS LOCAL PushFrame(PCTXT pctxt, ULONG dwSig, ULONG dwLen,
  187. PFNPARSE pfnParse, PVOID *ppvFrame)
  188. {
  189. TRACENAME("PUSHFRAME")
  190. NTSTATUS rc = STATUS_SUCCESS;
  191. ENTER(2, ("PushFrame(pctxt=%p,Sig=%s,Len=%d,pfnParse=%p,ppvFrame=%p)\n",
  192. pctxt, NameSegString(dwSig), dwLen, pfnParse, ppvFrame));
  193. //
  194. // Check to see if we have enough space, make sure it doesn't run into the
  195. // heap.
  196. //
  197. if (pctxt->LocalHeap.pbHeapEnd - dwLen >= pctxt->LocalHeap.pbHeapTop)
  198. {
  199. PFRAMEHDR pfh;
  200. pctxt->LocalHeap.pbHeapEnd -= dwLen;
  201. pfh = (PFRAMEHDR)pctxt->LocalHeap.pbHeapEnd;
  202. MEMZERO(pfh, dwLen);
  203. pfh->dwSig = dwSig;
  204. pfh->dwLen = dwLen;
  205. pfh->pfnParse = pfnParse;
  206. if (ppvFrame != NULL)
  207. {
  208. *ppvFrame = pfh;
  209. }
  210. #ifdef DEBUG
  211. if ((ULONG)(pctxt->pbCtxtEnd - pctxt->LocalHeap.pbHeapEnd) >
  212. gdwLocalStackMax)
  213. {
  214. gdwLocalStackMax = (ULONG)(pctxt->pbCtxtEnd -
  215. pctxt->LocalHeap.pbHeapEnd);
  216. }
  217. #endif
  218. }
  219. else
  220. {
  221. rc = AMLI_LOGERR(AMLIERR_STACK_OVERFLOW,
  222. ("PushFrame: stack ran out of space"));
  223. }
  224. EXIT(2, ("PushFrame=%x (StackTop=%x)\n", rc, pctxt->LocalHeap.pbHeapEnd));
  225. return rc;
  226. } //PushFrame
  227. /***LP PopFrame - Pop a frame off the stack
  228. *
  229. * ENTRY
  230. * pctxt -> CTXT
  231. *
  232. * EXIT
  233. * None
  234. */
  235. VOID LOCAL PopFrame(PCTXT pctxt)
  236. {
  237. TRACENAME("POPFRAME")
  238. ENTER(2, ("PopFrame(pctxt=%p)\n", pctxt));
  239. ASSERT(!IsStackEmpty(pctxt));
  240. ASSERT(((PFRAMEHDR)pctxt->LocalHeap.pbHeapEnd)->dwSig != 0);
  241. pctxt->LocalHeap.pbHeapEnd +=
  242. ((PFRAMEHDR)pctxt->LocalHeap.pbHeapEnd)->dwLen;
  243. EXIT(2, ("PopFrame! (StackTop=%p)\n", pctxt->LocalHeap.pbHeapEnd));
  244. } //PopFrame
  245. /***LP PushPost - Push a Post frame on the stack
  246. *
  247. * ENTRY
  248. * pctxt -> CTXT
  249. * pfnPost -> post processing function
  250. * uipData1 - data1
  251. * uipData2 - data2
  252. * pdataResult -> result object
  253. *
  254. * EXIT-SUCCESS
  255. * returns STATUS_SUCCESS
  256. * EXIT-FAILURE
  257. * returns AMLIERR_ code
  258. */
  259. NTSTATUS LOCAL PushPost(PCTXT pctxt, PFNPARSE pfnPost, ULONG_PTR uipData1,
  260. ULONG_PTR uipData2, POBJDATA pdataResult)
  261. {
  262. TRACENAME("PUSHPOST")
  263. NTSTATUS rc = STATUS_SUCCESS;
  264. PPOST ppost;
  265. ENTER(2, ("PushPost(pctxt=%x,pfnPost=%x,Data1=%x,Data2=%x,pdataResult=%x)\n",
  266. pctxt, pfnPost, uipData1, uipData2, pdataResult));
  267. if ((rc = PushFrame(pctxt, SIG_POST, sizeof(POST), pfnPost, &ppost)) ==
  268. STATUS_SUCCESS)
  269. {
  270. ppost->uipData1 = uipData1;
  271. ppost->uipData2 = uipData2;
  272. ppost->pdataResult = pdataResult;
  273. }
  274. EXIT(2, ("PushPost=%x (ppost=%x)\n", rc, ppost));
  275. return rc;
  276. } //PushPost
  277. /***LP PushScope - Push a ParseScope frame on the stack
  278. *
  279. * ENTRY
  280. * pctxt -> CTXT
  281. * pbOpBegin -> beginning of scope
  282. * pbOpEnd -> end of scope
  283. * pbOpRet -> return address after end of scope (NULL if continue on)
  284. * pnsScope -> new scope
  285. * powner -> new owner
  286. * pheap -> new heap
  287. * pdataResult -> result object
  288. *
  289. * EXIT-SUCCESS
  290. * returns STATUS_SUCCESS
  291. * EXIT-FAILURE
  292. * returns AMLIERR_ code
  293. */
  294. NTSTATUS LOCAL PushScope(PCTXT pctxt, PUCHAR pbOpBegin, PUCHAR pbOpEnd,
  295. PUCHAR pbOpRet, PNSOBJ pnsScope, POBJOWNER powner,
  296. PHEAP pheap, POBJDATA pdataResult)
  297. {
  298. TRACENAME("PUSHSCOPE")
  299. NTSTATUS rc = STATUS_SUCCESS;
  300. PSCOPE pscope;
  301. ENTER(2, ("PushScope(pctxt=%x,pbOpBegin=%x,pbOpEnd=%x,pbOpRet=%x,pnsScope=%x,pheap=%x,pdataResult=%x)\n",
  302. pctxt, pbOpBegin, pbOpEnd, pbOpRet, pnsScope, pheap,
  303. pdataResult));
  304. if ((rc = PushFrame(pctxt, SIG_SCOPE, sizeof(SCOPE), ParseScope, &pscope))
  305. == STATUS_SUCCESS)
  306. {
  307. pctxt->pbOp = pbOpBegin;
  308. pscope->pbOpEnd = pbOpEnd;
  309. pscope->pbOpRet = pbOpRet;
  310. pscope->pnsPrevScope = pctxt->pnsScope;
  311. pctxt->pnsScope = pnsScope;
  312. pscope->pownerPrev = pctxt->powner;
  313. pctxt->powner = powner;
  314. pscope->pheapPrev = pctxt->pheapCurrent;
  315. pctxt->pheapCurrent = pheap;
  316. pscope->pdataResult = pdataResult;
  317. }
  318. EXIT(2, ("PushScope=%x (pscope=%x)\n", rc, pscope));
  319. return rc;
  320. } //PushScope
  321. /***LP PushCall - Push a Call frame on the stack
  322. *
  323. * ENTRY
  324. * pctxt -> CTXT
  325. * pnsMethod -> method object
  326. * pdataResult -> result object
  327. *
  328. * EXIT-SUCCESS
  329. * returns STATUS_SUCCESS
  330. * EXIT-FAILURE
  331. * returns AMLIERR_ code
  332. */
  333. NTSTATUS LOCAL PushCall(PCTXT pctxt, PNSOBJ pnsMethod, POBJDATA pdataResult)
  334. {
  335. TRACENAME("PUSHCALL")
  336. NTSTATUS rc = STATUS_SUCCESS;
  337. PCALL pcall;
  338. ENTER(2, ("PushCall(pctxt=%x,pnsMethod=%s,pdataResult=%x)\n",
  339. pctxt, GetObjectPath(pnsMethod), pdataResult));
  340. ASSERT((pnsMethod == NULL) ||
  341. (pnsMethod->ObjData.dwDataType == OBJTYPE_METHOD));
  342. if ((rc = PushFrame(pctxt, SIG_CALL, sizeof(CALL), ParseCall, &pcall))
  343. == STATUS_SUCCESS)
  344. {
  345. if (pnsMethod != NULL)
  346. {
  347. PMETHODOBJ pm = (PMETHODOBJ)pnsMethod->ObjData.pbDataBuff;
  348. pcall->pnsMethod = pnsMethod;
  349. if (pm->bMethodFlags & METHOD_SERIALIZED)
  350. {
  351. pcall->FrameHdr.dwfFrame |= CALLF_NEED_MUTEX;
  352. }
  353. pcall->icArgs = (int)(pm->bMethodFlags & METHOD_NUMARG_MASK);
  354. if (pcall->icArgs > 0)
  355. {
  356. if ((pcall->pdataArgs = NEWODOBJ(pctxt->pheapCurrent,
  357. sizeof(OBJDATA)*pcall->icArgs))
  358. == NULL)
  359. {
  360. rc = AMLI_LOGERR(AMLIERR_OUT_OF_MEM,
  361. ("PushCall: failed to allocate argument objects"));
  362. }
  363. else
  364. {
  365. MEMZERO(pcall->pdataArgs, sizeof(OBJDATA)*pcall->icArgs);
  366. }
  367. }
  368. }
  369. else
  370. {
  371. //
  372. // This is a dummy call frame for AMLILoadDDB. We just need it
  373. // for its Locals array in case there is ASL referencing them.
  374. // But we don't really want to parse a call frame, so let's set
  375. // it to final clean up stage.
  376. //
  377. ASSERT(pctxt->pcall == NULL);
  378. pctxt->pcall = pcall;
  379. pcall->FrameHdr.dwfFrame = 4;
  380. }
  381. pcall->pdataResult = pdataResult;
  382. }
  383. EXIT(2, ("PushCall=%x (pcall=%x)\n", rc, pcall));
  384. return rc;
  385. } //PushCall
  386. /***LP PushTerm - Push a Term frame on the stack
  387. *
  388. * ENTRY
  389. * pctxt -> CTXT
  390. * pbOpTerm -> term opcode
  391. * pbScopeEnd -> end of current scope
  392. * pamlterm -> AMLTERM
  393. * pdataResult -> result object
  394. *
  395. * EXIT-SUCCESS
  396. * returns STATUS_SUCCESS
  397. * EXIT-FAILURE
  398. * returns AMLIERR_ code
  399. */
  400. NTSTATUS LOCAL PushTerm(PCTXT pctxt, PUCHAR pbOpTerm, PUCHAR pbScopeEnd,
  401. PAMLTERM pamlterm, POBJDATA pdataResult)
  402. {
  403. TRACENAME("PUSHTERM")
  404. NTSTATUS rc = STATUS_SUCCESS;
  405. PTERM pterm;
  406. ENTER(2, ("PushTerm(pctxt=%x,pbOpTerm=%x,pbScopeEnd=%x,pamlterm=%x,pdataResult=%x)\n",
  407. pctxt, pbOpTerm, pbScopeEnd, pamlterm, pdataResult));
  408. if ((rc = PushFrame(pctxt, SIG_TERM, sizeof(TERM), ParseTerm, &pterm)) ==
  409. STATUS_SUCCESS)
  410. {
  411. pterm->pbOpTerm = pbOpTerm;
  412. pterm->pbScopeEnd = pbScopeEnd;
  413. pterm->pamlterm = pamlterm;
  414. pterm->pdataResult = pdataResult;
  415. pterm->icArgs = pamlterm->pszArgTypes? STRLEN(pamlterm->pszArgTypes): 0;
  416. if (pterm->icArgs > 0)
  417. {
  418. if ((pterm->pdataArgs = NEWODOBJ(pctxt->pheapCurrent,
  419. sizeof(OBJDATA)*pterm->icArgs)) ==
  420. NULL)
  421. {
  422. rc = AMLI_LOGERR(AMLIERR_OUT_OF_MEM,
  423. ("PushTerm: failed to allocate argument objects"));
  424. }
  425. else
  426. {
  427. MEMZERO(pterm->pdataArgs, sizeof(OBJDATA)*pterm->icArgs);
  428. }
  429. }
  430. }
  431. EXIT(2, ("PushTerm=%x (pterm=%x)\n", rc, pterm));
  432. return rc;
  433. } //PushTerm
  434. /***LP RunContext - Run a context
  435. *
  436. * ENTRY
  437. * pctxt -> CTXT
  438. *
  439. * EXIT-SUCCESS
  440. * returns STATUS_SUCCESS
  441. * EXIT-FAILURE
  442. * returns AMLIERR_ code
  443. *
  444. * NOTE
  445. * Caller must own the scheduler lock such that the context flags can
  446. * be updated properly. The lock is dropped and re-obtain around
  447. * execution of the target context.
  448. */
  449. NTSTATUS LOCAL RunContext(PCTXT pctxt)
  450. {
  451. TRACENAME("RUNCONTEXT")
  452. NTSTATUS rc;
  453. PFRAMEHDR pfh;
  454. PKTHREAD pkthSave = gReadyQueue.pkthCurrent;
  455. PCTXT pctxtSave = gReadyQueue.pctxtCurrent;
  456. ENTER(2, ("RunContext(pctxt=%x)\n", pctxt));
  457. //
  458. // Better be a Ready Context structure.
  459. //
  460. ASSERT(pctxt->dwSig == SIG_CTXT);
  461. ASSERT(pctxt->dwfCtxt & CTXTF_READY);
  462. //
  463. // Remember previous context and thread.
  464. //
  465. gReadyQueue.pctxtCurrent = pctxt;
  466. gReadyQueue.pkthCurrent = KeGetCurrentThread();
  467. LOGSCHEDEVENT('RUNC', (ULONG_PTR)pctxt, (ULONG_PTR)
  468. (pctxt->pnctxt? pctxt->pnctxt->pnsObj: pctxt->pnsObj),
  469. (ULONG_PTR)pctxt->dwfCtxt);
  470. //
  471. // As long as the context is ready, execute it.
  472. //
  473. for (;;)
  474. {
  475. //
  476. // Transistion context from Ready to Running.
  477. //
  478. rc = STATUS_SUCCESS;
  479. pctxt->dwfCtxt &= ~CTXTF_READY;
  480. pctxt->dwfCtxt |= CTXTF_RUNNING;
  481. //
  482. // Drop scheduler lock and execute context.
  483. //
  484. ReleaseMutex(&gReadyQueue.mutCtxtQ);
  485. //
  486. // Go for as long as there's work to perform.
  487. //
  488. while (!IsStackEmpty(pctxt))
  489. {
  490. CHKDEBUGGERREQ();
  491. pfh = (PFRAMEHDR)pctxt->LocalHeap.pbHeapEnd;
  492. ASSERT(pfh->pfnParse != NULL);
  493. rc = pfh->pfnParse(pctxt, pfh, rc);
  494. if ((rc == AMLISTA_PENDING) || (rc == AMLISTA_DONE))
  495. {
  496. break;
  497. }
  498. }
  499. //
  500. // Get the scheduler lock, and clear the running flag.
  501. //
  502. AcquireMutex(&gReadyQueue.mutCtxtQ);
  503. //
  504. // If we are in nested eval and the nested context is done,
  505. // we must not clear the running flag because the parent thread
  506. // is still running.
  507. //
  508. if (!(pctxt->dwfCtxt & CTXTF_NEST_EVAL) || (rc != AMLISTA_DONE))
  509. {
  510. pctxt->dwfCtxt &= ~CTXTF_RUNNING;
  511. }
  512. //
  513. // If the context is no longer ready, we're done.
  514. //
  515. if (!(pctxt->dwfCtxt & CTXTF_READY))
  516. {
  517. break;
  518. }
  519. //
  520. // Context became Ready during a pending operation, keep
  521. // dispatching.
  522. //
  523. ASSERT (rc == AMLISTA_PENDING);
  524. }
  525. if (rc == AMLISTA_PENDING)
  526. {
  527. pctxt->dwfCtxt |= CTXTF_NEED_CALLBACK;
  528. }
  529. else if (rc == AMLISTA_DONE)
  530. {
  531. if (pctxt->pnctxt == NULL)
  532. {
  533. pctxt->dwfCtxt &= ~CTXTF_NEST_EVAL;
  534. }
  535. rc = STATUS_SUCCESS;
  536. }
  537. else
  538. {
  539. ReleaseMutex(&gReadyQueue.mutCtxtQ);
  540. if ((rc == STATUS_SUCCESS) && (pctxt->pdataCallBack != NULL))
  541. {
  542. rc = DupObjData(gpheapGlobal, pctxt->pdataCallBack, &pctxt->Result);
  543. }
  544. if (pctxt->dwfCtxt & CTXTF_NEED_CALLBACK)
  545. {
  546. AsyncCallBack(pctxt, rc);
  547. if(pctxt->dwfCtxt & CTXTF_ASYNC_EVAL)
  548. {
  549. rc = AMLISTA_PENDING;
  550. }
  551. }
  552. //
  553. // Free any owned resources the context may not have freed.
  554. //
  555. while (pctxt->plistResources != NULL)
  556. {
  557. PRESOURCE pres;
  558. pres = CONTAINING_RECORD(pctxt->plistResources, RESOURCE, list);
  559. ASSERT (pres->pctxtOwner == pctxt);
  560. //
  561. // Note that it is the responsibility of the corresponding
  562. // resource release functions (e.g. ReleaseASLMutex) to dequeue
  563. // the resource from the list and free it.
  564. //
  565. switch (pres->dwResType)
  566. {
  567. case RESTYPE_MUTEX:
  568. ReleaseASLMutex(pctxt, pres->pvResObj);
  569. break;
  570. default:
  571. //
  572. // We should never come here. In case we do, we need to
  573. // dequeue the unknown resource object and free it.
  574. //
  575. pres = CONTAINING_RECORD(
  576. ListRemoveHead(&pctxt->plistResources),
  577. RESOURCE, list);
  578. ASSERT(pres == NULL);
  579. FREECROBJ(pres);
  580. }
  581. }
  582. FreeContext(pctxt);
  583. AcquireMutex(&gReadyQueue.mutCtxtQ);
  584. }
  585. //
  586. // Restore previous context and thread.
  587. //
  588. gReadyQueue.pkthCurrent = pkthSave;
  589. gReadyQueue.pctxtCurrent = pctxtSave;
  590. if ((gReadyQueue.dwfCtxtQ & CQF_FLUSHING) && (gplistCtxtHead == NULL))
  591. {
  592. //
  593. // We just flushed the last pending ctxt, let's go into paused state.
  594. //
  595. gReadyQueue.dwfCtxtQ &= ~CQF_FLUSHING;
  596. gReadyQueue.dwfCtxtQ |= CQF_PAUSED;
  597. if (gReadyQueue.pfnPauseCallback != NULL)
  598. {
  599. //
  600. // We are in paused state and all pending contexts are flushed,
  601. // tell core driver that we are done flushing.
  602. //
  603. gReadyQueue.pfnPauseCallback(gReadyQueue.PauseCBContext);
  604. LOGSCHEDEVENT('PACB', (ULONG_PTR)pctxt, (ULONG_PTR)rc, 0);
  605. }
  606. }
  607. LOGSCHEDEVENT('RUN!', (ULONG_PTR)pctxt, (ULONG_PTR)rc, 0);
  608. EXIT(2, ("RunContext=%x\n", rc));
  609. return rc;
  610. } //RunContext