Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

taskman.c File Reference

#include "precomp.h"

Go to the source code of this file.

Functions

VOID WakeWowTask (PTHREADINFO pti)
void InsertTask (PPROCESSINFO ppi, PTDB ptdbNew)
void DestroyTask (PPROCESSINFO ppi, PTHREADINFO ptiToRemove)
BOOL xxxSleepTask (BOOL fInputIdle, HANDLE hEvent)
BOOL xxxUserYield (PTHREADINFO pti)
VOID DirectedScheduleTask (PTHREADINFO ptiOld, PTHREADINFO ptiNew, BOOL bSendMsg, PSMS psms)
void xxxDirectedYield (DWORD dwThreadId)


Function Documentation

void DestroyTask PPROCESSINFO  ppi,
PTHREADINFO  ptiToRemove
 

Definition at line 129 of file taskman.c.

References _PostMessage(), BEGINATOMICCHECK, CheckCritIn, CLOSE_PSEUDO_EVENT, tagWOWPROCESSINFO::CSOwningThread, DTM_SETUPAPPRAN, ENDATOMICCHECK, EVENT_INCREMENT, ExitWowCritSect(), FALSE, GETDESKINFO, gpsi, gpwtiFirst, KeSetEvent(), tagTDB::nEvents, tagWOWPROCESSINFO::nTaskLock, NULL, tagTHREADINFO::pEventQueueServer, tagWOWPROCESSINFO::pEventWowExec, tagWOWTHREADINFO::pIdleEvent, tagTHREADINFO::ptdb, tagWOWPROCESSINFO::ptdbHead, tagTDB::ptdbNext, tagTDB::pti, tagWOWPROCESSINFO::ptiScheduled, tagPROCESSINFO::pwpi, tagTDB::pwti, tagWOWTHREADINFO::pwtiNext, tagDESKTOPINFO::spwndShell, tagTDB::TDB_Flags, and TDBF_SETUP.

Referenced by xxxDestroyThreadInfo().

00132 { 00133 PTDB ptdbToRemove = ptiToRemove->ptdb; 00134 PTDB ptdb; 00135 PTDB* pptdb; 00136 PWOWPROCESSINFO pwpi = ppi->pwpi; 00137 00138 // try to catch #150446 00139 CheckCritIn(); 00140 BEGINATOMICCHECK(); 00141 00142 UserAssert(pwpi != NULL); 00143 00144 if (ptdbToRemove != NULL) { 00145 00146 if (ptdbToRemove->TDB_Flags & TDBF_SETUP) { 00147 /* 00148 * This means that the WoW app was a setup app (checked in SetAppCompatFlags). 00149 * If so, the shell needs to be notified so it can clean up potential problems 00150 * caused by bad calls to DDE, etc. FritzS 00151 */ 00152 PDESKTOPINFO pdeskinfo = GETDESKINFO(ptiToRemove); 00153 if (pdeskinfo->spwndShell) { 00154 _PostMessage(pdeskinfo->spwndShell, DTM_SETUPAPPRAN, 0, 0); 00155 } 00156 } 00157 /* 00158 * Remove the WOW per thread info 00159 */ 00160 if (ptdbToRemove->pwti) { 00161 PWOWTHREADINFO *ppwti = &gpwtiFirst; 00162 while (*ppwti != ptdbToRemove->pwti && (*ppwti)->pwtiNext != NULL) { 00163 ppwti = &((*ppwti)->pwtiNext); 00164 } 00165 if (*ppwti == ptdbToRemove->pwti) { 00166 *ppwti = ptdbToRemove->pwti->pwtiNext; 00167 } 00168 CLOSE_PSEUDO_EVENT(&ptdbToRemove->pwti->pIdleEvent); 00169 UserFreePool(ptdbToRemove->pwti); 00170 } 00171 00172 gpsi->nEvents -= ptdbToRemove->nEvents; 00173 00174 /* 00175 * remove it from any lists 00176 */ 00177 pptdb = &pwpi->ptdbHead; 00178 while ((ptdb = *pptdb) != NULL) { 00179 /* 00180 * Remove it from it's old location 00181 */ 00182 if (ptdb == ptdbToRemove) { 00183 *pptdb = ptdb->ptdbNext; 00184 UserFreePool(ptdbToRemove); 00185 UserAssert(ptiToRemove->ptdb == ptdbToRemove); 00186 ptiToRemove->ptdb = NULL; 00187 break; 00188 } 00189 pptdb = &(ptdb->ptdbNext); 00190 } 00191 UserAssert(ptdb == ptdbToRemove); // #150446 check that we actually found it 00192 } 00193 ENDATOMICCHECK(); // #150446 00194 00195 /* 00196 * If the task being destroyed is the active task, make nobody active. 00197 * We will go through this code path for 32-bit threads that die while 00198 * Win16 threads are waiting for a SendMessage reply from them. 00199 */ 00200 if (pwpi->ptiScheduled == ptiToRemove) { 00201 pwpi->ptiScheduled = NULL; 00202 ExitWowCritSect(ptiToRemove, pwpi); 00203 00204 /* 00205 * If this active task was locked, remove lock so next guy can 00206 * run. 00207 */ 00208 pwpi->nTaskLock = 0; 00209 00210 00211 /* 00212 * Wake next task with events, or wowexec to run the scheduler 00213 */ 00214 if (pwpi->ptdbHead != NULL) { 00215 PTDB ptdb; 00216 00217 for (ptdb = pwpi->ptdbHead; ptdb; ptdb = ptdb->ptdbNext) { 00218 if (ptdb->nEvents > 0) { 00219 KeSetEvent(ptdb->pti->pEventQueueServer, 00220 EVENT_INCREMENT, FALSE); 00221 break; 00222 } 00223 } 00224 00225 if (!ptdb) { 00226 KeSetEvent(pwpi->pEventWowExec, EVENT_INCREMENT, FALSE); 00227 } 00228 } 00229 } 00230 UserAssert(ptiToRemove != pwpi->CSOwningThread); 00231 00232 }

VOID DirectedScheduleTask PTHREADINFO  ptiOld,
PTHREADINFO  ptiNew,
BOOL  bSendMsg,
PSMS  psms
 

Definition at line 594 of file taskman.c.

References BOOL, CheckCritIn, gpsi, InsertTask(), tagTDB::nEvents, tagTDB::nPriority, tagWOWPROCESSINFO::nRecvLock, tagWOWPROCESSINFO::nSendLock, tagTHREADINFO::ppi, tagTHREADINFO::psmsSent, tagTHREADINFO::ptdb, tagWOWPROCESSINFO::ptiScheduled, tagPROCESSINFO::pwpi, SMF_WOWRECEIVE, SMF_WOWSEND, TIF_16BIT, tagTHREADINFO::TIF_flags, VOID(), and WakeWowTask().

Referenced by _ReplyMessage(), ReceiverDied(), xxxInterSendMsgEx(), xxxReceiveMessage(), and xxxSleepTask().

00600 { 00601 PWOWPROCESSINFO pwpiOld; 00602 PWOWPROCESSINFO pwpiNew; 00603 00604 CheckCritIn(); 00605 00606 pwpiOld = ptiOld->ppi->pwpi; 00607 pwpiNew = ptiNew->ppi->pwpi; 00608 00609 00610 /* 00611 * If old task is 16 bit, reinsert the task in its wow scheduler list 00612 * so that it is lowest in priority. Note that ptiOld is always the 00613 * same as pwpiOld->ptiScheduled except when called from ReceiverDied. 00614 */ 00615 if (ptiOld->TIF_flags & TIF_16BIT) { 00616 00617 if (pwpiOld->ptiScheduled == ptiOld) { 00618 ptiOld->ptdb->nEvents++; 00619 gpsi->nEvents++; 00620 InsertTask(ptiOld->ppi, ptiOld->ptdb); 00621 } 00622 00623 00624 // Update the Send\Recv counts for interprocess scheduling in SleepTask 00625 00626 if (pwpiOld != pwpiNew || !(ptiNew->TIF_flags & TIF_16BIT)) { 00627 if (bSendMsg) { 00628 pwpiOld->nSendLock++; 00629 psms->flags |= SMF_WOWSEND; 00630 } 00631 else if (pwpiOld->nRecvLock && psms->flags & SMF_WOWRECEIVE) { 00632 pwpiOld->nRecvLock--; 00633 psms->flags &= ~SMF_WOWRECEIVE; 00634 } 00635 } 00636 00637 } 00638 00639 00640 /* 00641 * If the new task is 16 bit, reinsert into the wow scheduler list 00642 * so that it will run, if its a sendmsg raise priority of the receiver. 00643 * If its a reply and the sender is waiting for this psms or the sender 00644 * has a message to reply to raise priority of the sender. 00645 */ 00646 if (ptiNew->TIF_flags & TIF_16BIT) { 00647 BOOL bRaisePriority; 00648 00649 ptiNew->ptdb->nEvents++; 00650 gpsi->nEvents++; 00651 bRaisePriority = bSendMsg || psms == ptiNew->psmsSent; 00652 00653 if (bRaisePriority) { 00654 ptiNew->ptdb->nPriority--; 00655 } 00656 00657 InsertTask(ptiNew->ppi, ptiNew->ptdb); 00658 00659 if (bRaisePriority) { 00660 ptiNew->ptdb->nPriority++; 00661 WakeWowTask(ptiNew); 00662 } 00663 00664 00665 // Update the Send\Recv counts for interprocess scheduling in SleepTask 00666 00667 if (pwpiOld != pwpiNew || !(ptiOld->TIF_flags & TIF_16BIT)) { 00668 if (bSendMsg) { 00669 pwpiNew->nRecvLock++; 00670 psms->flags |= SMF_WOWRECEIVE; 00671 } 00672 else if (pwpiNew->nSendLock && psms->flags & SMF_WOWSEND) { 00673 pwpiNew->nSendLock--; 00674 psms->flags &= ~SMF_WOWSEND; 00675 } 00676 } 00677 00678 } 00679 }

void InsertTask PPROCESSINFO  ppi,
PTDB  ptdbNew
 

Definition at line 60 of file taskman.c.

References CheckCritIn, tagTDB::nPriority, NULL, tagWOWPROCESSINFO::ptdbHead, tagTDB::ptdbNext, and tagPROCESSINFO::pwpi.

Referenced by DirectedScheduleTask(), xxxDirectedYield(), xxxSleepTask(), xxxUserYield(), and zzzInitTask().

00063 { 00064 PTDB *pptdb; 00065 PTDB ptdb; 00066 int nPriority; 00067 PWOWPROCESSINFO pwpi = ppi->pwpi; 00068 00069 CheckCritIn(); 00070 00071 UserAssert(pwpi != NULL); 00072 00073 pptdb = &pwpi->ptdbHead; 00074 nPriority = ptdbNew->nPriority; 00075 00076 while ((ptdb = *pptdb) != NULL) { 00077 /* 00078 * Remove it from it's old location 00079 */ 00080 if (ptdb == ptdbNew) { 00081 *pptdb = ptdbNew->ptdbNext; 00082 00083 /* 00084 * continue to search for the place to insert it 00085 */ 00086 while ((ptdb = *pptdb) != NULL) { 00087 if (nPriority < ptdb->nPriority) { 00088 break; 00089 } 00090 00091 pptdb = &(ptdb->ptdbNext); 00092 } 00093 break; 00094 } 00095 00096 /* 00097 * if this is the place to insert continue to search for the 00098 * place to delete it from 00099 */ 00100 if (nPriority < ptdb->nPriority) { 00101 do { 00102 if (ptdb->ptdbNext == ptdbNew) { 00103 ptdb->ptdbNext = ptdbNew->ptdbNext; 00104 break; 00105 } 00106 ptdb = ptdb->ptdbNext; 00107 } while (ptdb != NULL); 00108 break; 00109 } 00110 00111 pptdb = &(ptdb->ptdbNext); 00112 } 00113 00114 /* 00115 * insert the new task 00116 */ 00117 ptdbNew->ptdbNext = *pptdb; 00118 *pptdb = ptdbNew; 00119 }

VOID WakeWowTask PTHREADINFO  pti  ) 
 

Definition at line 30 of file taskman.c.

References EVENT_INCREMENT, FALSE, KeSetEvent(), tagTHREADINFO::pEventQueueServer, tagTHREADINFO::ppi, tagWOWPROCESSINFO::ptiScheduled, and tagPROCESSINFO::pwpi.

Referenced by DirectedScheduleTask(), and SetWakeBit().

00033 { 00034 PWOWPROCESSINFO pwpi; 00035 00036 pwpi = pti->ppi->pwpi; 00037 if (pwpi && !pwpi->ptiScheduled) { 00038 KeSetEvent(pti->pEventQueueServer, EVENT_INCREMENT, FALSE); 00039 } 00040 }

void xxxDirectedYield DWORD  dwThreadId  ) 
 

Definition at line 691 of file taskman.c.

References CheckCritIn, gpsi, InsertTask(), tagTDB::nEvents, tagTDB::nPriority, NULL, tagTHREADINFO::ppi, tagTHREADINFO::ptdb, PtiCurrent, PtiFromThreadId(), tagPROCESSINFO::pwpi, TIF_16BIT, tagTHREADINFO::TIF_flags, TRUE, and xxxSleepTask().

Referenced by xxxInternalGetMessage(), and xxxPollAndWaitForSingleObject().

00693 { 00694 PTHREADINFO ptiOld; 00695 PTHREADINFO ptiNew; 00696 00697 CheckCritIn(); 00698 00699 ptiOld = PtiCurrent(); 00700 if (!(ptiOld->TIF_flags & TIF_16BIT) || !ptiOld->ppi->pwpi) { 00701 RIPMSG0(RIP_ERROR, "DirectedYield called from 32 bit thread!"); 00702 return; 00703 } 00704 00705 /* 00706 * If the old task is 16 bit, reinsert the task in its wow 00707 * scheduler list so that it is lowest in priority. 00708 */ 00709 ptiOld->ptdb->nEvents++; 00710 gpsi->nEvents++; 00711 InsertTask(ptiOld->ppi, ptiOld->ptdb); 00712 00713 /* 00714 * -1 supports Win 3.1 OldYield mechanics 00715 */ 00716 if (dwThreadId != DY_OLDYIELD) { 00717 00718 ptiNew = PtiFromThreadId(dwThreadId); 00719 if (ptiNew == NULL) 00720 return; 00721 00722 if (ptiNew->TIF_flags & TIF_16BIT) { 00723 ptiNew->ptdb->nEvents++; 00724 gpsi->nEvents++; 00725 ptiNew->ptdb->nPriority--; 00726 InsertTask(ptiNew->ppi, ptiNew->ptdb); 00727 ptiNew->ptdb->nPriority++; 00728 } 00729 } 00730 00731 xxxSleepTask(TRUE, NULL); 00732 }

BOOL xxxSleepTask BOOL  fInputIdle,
HANDLE  hEvent
 

Definition at line 252 of file taskman.c.

References tagTHREADINFO::apEvent, BOOL, CheckCritIn, CheckForClientDeath, ClientDeliverUserApc(), tagWOWPROCESSINFO::CSOwningThread, DirectedScheduleTask(), EnterCrit, EnterWowCritSect(), EVENT_INCREMENT, ExitWowCritSect(), FALSE, tagCLIENTTHREADINFO::fsChangeBits, tagCLIENTTHREADINFO::fsWakeMask, gpsi, HEVENT_REMOVEME, tagWOWPROCESSINFO::hEventWowExecClient, IEV_TASK, IEV_WOWEXEC, InsertTask(), IsHooked, KeClearEvent, KeSetEvent(), KeWaitForMultipleObjects(), LeaveCrit, tagTDB::nEvents, tagWOWPROCESSINFO::nRecvLock, tagWOWPROCESSINFO::nSendLock, tagWOWPROCESSINFO::nTaskLock, NTSTATUS(), NULL, tagTHREADINFO::pcti, tagTHREADINFO::pEventQueueServer, tagWOWPROCESSINFO::pEventWowExec, POLL_EVENT_CNT, tagTHREADINFO::ppi, PsGetCurrentThread, PsIsThreadTerminating, PSMS, tagTHREADINFO::psmsCurrent, tagTHREADINFO::ptdb, tagWOWPROCESSINFO::ptdbHead, tagTDB::ptdbNext, tagTDB::pti, PtiCurrent, tagWOWPROCESSINFO::ptiScheduled, tagPROCESSINFO::pwpi, SMF_RECEIVEDMESSAGE, SMF_RECEIVERBUSY, SMF_REPLY, Status, TIF_16BIT, tagTHREADINFO::TIF_flags, TIF_SHAREDWOW, TRUE, UserMode, WHF_FOREGROUNDIDLE, WrUserRequest, xxxCallHook(), and zzzWakeInputIdle().

Referenced by _ReplyMessage(), NtUserWaitForMsgAndEvent(), xxxDirectedYield(), xxxInternalGetMessage(), xxxPollAndWaitForSingleObject(), xxxReceiveMessage(), xxxSleepThread(), and xxxUserYield().

00255 { 00256 PTDB ptdb; 00257 PTHREADINFO pti; 00258 PPROCESSINFO ppi; 00259 PWOWPROCESSINFO pwpi; 00260 PSMS psms; 00261 NTSTATUS Status; 00262 int nHandles; 00263 BOOLEAN bWaitedAtLeastOnce; 00264 00265 /* 00266 * !!! 00267 * ClearSendMessages assumes that this function does NOT leave the 00268 * critical section when called with fInputIdle==FALSE and from a 00269 * 32bit thread! 00270 */ 00271 00272 CheckCritIn(); 00273 00274 pti = PtiCurrent(); 00275 ppi = pti->ppi; 00276 pwpi = ppi->pwpi; 00277 00278 /* 00279 * If this task has received a message from outside of the current 00280 * wow scheduler and hasn't yet replied to the message, the scheduler 00281 * will deadlock because the send\receive lock counts are updated 00282 * in ReplyMessage and not in receive message. Check for this 00283 * condition and do the DirectedSchedukeTask that normally occurs 00284 * in ReplyMessage. 16-Feb-1995 Jonle 00285 */ 00286 psms = pti->psmsCurrent; 00287 if (psms && psms->ptiReceiver == pti && 00288 psms->ptiSender && !(psms->flags & SMF_REPLY) && 00289 psms->flags & (SMF_RECEIVERBUSY | SMF_RECEIVEDMESSAGE) && 00290 psms->ptiSender->TIF_flags & TIF_16BIT && 00291 (pwpi != psms->ptiSender->ppi->pwpi || !(pti->TIF_flags & TIF_16BIT)) ) { 00292 DirectedScheduleTask(psms->ptiReceiver, psms->ptiSender, FALSE, psms); 00293 } 00294 00295 00296 /* 00297 * return immediately if we are not 16 bit (don't have a pwpi) 00298 */ 00299 if (!(pti->TIF_flags & TIF_16BIT)) { 00300 return FALSE; 00301 } 00302 00303 00304 /* 00305 * Deschedule the current task 00306 */ 00307 if (pti == pwpi->ptiScheduled) { 00308 ExitWowCritSect(pti, pwpi); 00309 if (!pwpi->nTaskLock) { 00310 pwpi->ptiScheduled = NULL; 00311 } 00312 } 00313 UserAssert(pti != pwpi->CSOwningThread); 00314 00315 00316 /* 00317 * If this is wowexec calling on WowWaitForMsgAndEvent 00318 * set up the WakeMask for all messages , and check for wake 00319 * bits set since the last time. Reinsert wowexec, at the end 00320 * of the list so other 16 bit tasks will be scheduled first. 00321 */ 00322 if (pwpi->hEventWowExecClient == hEvent) { 00323 InsertTask(ppi, pti->ptdb); 00324 pti->pcti->fsWakeMask = QS_ALLINPUT | QS_EVENT; 00325 if (pti->pcti->fsChangeBits & pti->pcti->fsWakeMask) { 00326 pti->ptdb->nEvents++; 00327 gpsi->nEvents++; 00328 } 00329 } 00330 00331 00332 bWaitedAtLeastOnce = FALSE; 00333 00334 do { 00335 00336 /* 00337 * If nobody is Active look for the highest priority task with 00338 * some events pending. if MsgWaitForMultiple call don't 00339 * reschedule self 00340 */ 00341 00342 if (pwpi->ptiScheduled == NULL) { 00343 rescan: 00344 if (pwpi->nRecvLock >= pwpi->nSendLock) { 00345 for (ptdb = pwpi->ptdbHead; ptdb; ptdb = ptdb->ptdbNext) { 00346 if (ptdb->nEvents > 0 && 00347 !(hEvent == HEVENT_REMOVEME && ptdb->pti == pti)) { 00348 pwpi->ptiScheduled = ptdb->pti; 00349 break; 00350 } 00351 } 00352 00353 if (bWaitedAtLeastOnce) { 00354 // 00355 // If not first entry into sleep task avoid waiting 00356 // more than needed, if the curr task is now scheduled. 00357 // 00358 if (pwpi->ptiScheduled == pti) { 00359 break; 00360 } 00361 00362 } else { 00363 // 00364 // On the first entry into sleep task input is going 00365 // idle if no tasks are ready to run. Call the idle 00366 // hook if there is one. 00367 // 00368 if (fInputIdle && 00369 pwpi->ptiScheduled == NULL && 00370 IsHooked(pti, WHF_FOREGROUNDIDLE)) { 00371 00372 /* 00373 * Make this the active task so that no other 00374 * task will become active while we're calling 00375 * the hook. 00376 */ 00377 pwpi->ptiScheduled = pti; 00378 xxxCallHook(HC_ACTION, 0, 0, WH_FOREGROUNDIDLE); 00379 00380 /* 00381 * Reset state so that no tasks are active. We 00382 * then need to rescan the task list to see if 00383 * a task was scheduled during the call to the 00384 * hook. Clear the input idle flag to ensure 00385 * that the hook won't be called again if there 00386 * are no tasks ready to run. 00387 */ 00388 pwpi->ptiScheduled = NULL; 00389 fInputIdle = FALSE; 00390 goto rescan; 00391 } 00392 } 00393 } 00394 00395 00396 /* 00397 * If there is a task ready, wake it up. 00398 */ 00399 if (pwpi->ptiScheduled != NULL) { 00400 KeSetEvent(pwpi->ptiScheduled->pEventQueueServer, 00401 EVENT_INCREMENT, 00402 FALSE 00403 ); 00404 00405 /* 00406 * There is no one to wake up, but we may have to wake 00407 * wowexec to service virtual hardware interrupts 00408 */ 00409 } else if (ppi->W32PF_Flags & W32PF_WAKEWOWEXEC) { 00410 if (pwpi->hEventWowExecClient == hEvent) { 00411 pwpi->ptiScheduled = pti; 00412 ppi->W32PF_Flags &= ~W32PF_WAKEWOWEXEC; 00413 InsertTask(ppi, pti->ptdb); 00414 EnterWowCritSect(pti, pwpi); 00415 UserAssert(pti == pwpi->ptiScheduled); 00416 return TRUE; 00417 } else { 00418 KeSetEvent(pwpi->pEventWowExec, EVENT_INCREMENT, FALSE); 00419 } 00420 } else if ((pti->TIF_flags & TIF_SHAREDWOW) && !bWaitedAtLeastOnce) { 00421 if (pwpi->hEventWowExecClient == hEvent) { 00422 /* 00423 * We have to call zzzWakeInputIdle only if this will 00424 * awake WowExec's thread and not other thread. Bug 44060. 00425 */ 00426 zzzWakeInputIdle(pti); // need to DeferWinEventNotify() ?? IANJA ?? 00427 } 00428 } 00429 00430 } else if (pwpi->nTaskLock > 0 && pwpi->ptiScheduled == pti 00431 && pti->ptdb->nEvents > 0) { 00432 KeSetEvent(pwpi->ptiScheduled->pEventQueueServer, 00433 EVENT_INCREMENT, FALSE); 00434 } 00435 /* 00436 * return if we are a 32 bit thread, or if we were called by 00437 * MsgWaitForMultiple to exit the wow scheduler 00438 */ 00439 if (!(pti->TIF_flags & TIF_16BIT)) { 00440 return FALSE; 00441 } else if (hEvent == HEVENT_REMOVEME) { 00442 InsertTask(ppi, pti->ptdb); 00443 KeClearEvent(pti->pEventQueueServer); 00444 return FALSE; 00445 } 00446 00447 if (pti->apEvent == NULL) { 00448 pti->apEvent = UserAllocPoolNonPaged(POLL_EVENT_CNT * sizeof(PKEVENT), TAG_EVENT); 00449 if (pti->apEvent == NULL) 00450 return FALSE; 00451 } 00452 00453 /* 00454 * Wait for input to this thread. 00455 */ 00456 pti->apEvent[IEV_TASK] = pti->pEventQueueServer; 00457 00458 /* 00459 * Add the WowExec, handle for virtual hw interrupts 00460 */ 00461 if (pwpi->hEventWowExecClient == hEvent) { 00462 pti->apEvent[IEV_WOWEXEC] = pwpi->pEventWowExec; 00463 nHandles = 2; 00464 } else { 00465 nHandles = 1; 00466 } 00467 00468 CheckForClientDeath(); 00469 LeaveCrit(); 00470 00471 Status = KeWaitForMultipleObjects(nHandles, 00472 &pti->apEvent[IEV_TASK], 00473 WaitAny, 00474 WrUserRequest, 00475 UserMode, 00476 TRUE, 00477 NULL, 00478 NULL); 00479 00480 CheckForClientDeath(); 00481 00482 EnterCrit(); 00483 00484 bWaitedAtLeastOnce = TRUE; 00485 00486 // remember if we woke up for wowexec 00487 if (Status == STATUS_WAIT_1) { 00488 ppi->W32PF_Flags |= W32PF_WAKEWOWEXEC; 00489 } else if (Status == STATUS_USER_APC) { 00490 00491 /* 00492 * An alert was received. This should only occur when the 00493 * thread has been terminated. 00494 * ClientDeliverUserApc() delivers User-mode APCs by calling back 00495 * to the client and immediately returning without doing anything: 00496 * KeUserModeCallback will automatically deliver any pending APCs. 00497 */ 00498 UserAssert(PsIsThreadTerminating(PsGetCurrentThread())); 00499 ClientDeliverUserApc(); 00500 } 00501 00502 } while (pwpi->ptiScheduled != pti); 00503 00504 00505 /* 00506 * We are the Active Task, reduce number of Events 00507 * Place ourselves at the far end of tasks in the same priority 00508 * so that next time we sleep someone else will run. 00509 */ 00510 pti->ptdb->nEvents--; 00511 gpsi->nEvents--; 00512 UserAssert(gpsi->nEvents >= 0); 00513 00514 InsertTask(ppi, pti->ptdb); 00515 00516 ppi->W32PF_Flags &= ~W32PF_WAKEWOWEXEC; 00517 00518 EnterWowCritSect(pti, pwpi); 00519 UserAssert(pti == pwpi->ptiScheduled); 00520 00521 00522 00523 return FALSE; 00524 }

BOOL xxxUserYield PTHREADINFO  pti  ) 
 

Definition at line 537 of file taskman.c.

References BOOL, gpsi, InsertTask(), tagTDB::nEvents, NULL, tagTHREADINFO::ppi, tagTHREADINFO::ptdb, tagWOWPROCESSINFO::ptiScheduled, tagPROCESSINFO::pwpi, TIF_16BIT, tagTHREADINFO::TIF_flags, TRUE, xxxReceiveMessages, and xxxSleepTask().

Referenced by NtUserYieldTask(), and xxxInternalGetMessage().

00539 { 00540 PPROCESSINFO ppi = pti->ppi; 00541 00542 /* 00543 * Deal with any pending messages. Only call it this first time if 00544 * this is the current running 16 bit app. In the case when starting 00545 * up a 16 bit app, the starter calls UserYield() to yield to the new 00546 * task, but at this time ppi->ptiScheduled is set to the new task. 00547 * Receiving messages at this point would be bad! 00548 */ 00549 if (pti->TIF_flags & TIF_16BIT) { 00550 if (pti == ppi->pwpi->ptiScheduled) { 00551 xxxReceiveMessages(pti); 00552 } 00553 } else { 00554 xxxReceiveMessages(pti); 00555 } 00556 00557 /* 00558 * If we are a 16 bit task 00559 * Mark our task so it comes back some time. Also, remove it and 00560 * re-add it to the list so that we are the last task of our priority 00561 * to run. 00562 */ 00563 if ((pti->TIF_flags & TIF_16BIT) && (pti->ptdb != NULL)) { 00564 if (pti->ptdb->nEvents == 0) { 00565 pti->ptdb->nEvents++; 00566 gpsi->nEvents++; 00567 } 00568 InsertTask(ppi, pti->ptdb); 00569 00570 /* 00571 * Sleep. Return right away if there are no higher priority tasks 00572 * in need of running. 00573 */ 00574 xxxSleepTask(TRUE, NULL); 00575 00576 /* 00577 * Deal with any that arrived since we weren't executing. 00578 */ 00579 xxxReceiveMessages(pti); 00580 } 00581 00582 00583 return TRUE; 00584 }


Generated on Sat May 15 19:45:44 2004 for test by doxygen 1.3.7