test: taskman.c Source File

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

# taskman.c

Go to the documentation of this file.

    00001 /****************************** Module Header ******************************\
    00002 * Module Name: taskman.c
    00003 *
    00004 * Copyright (c) 1985 - 1999, Microsoft Corporation
    00005 *
    00006 * This module contains the core functions of the input sub-system
    00007 *
    00008 * History:
    00009 * 02-27-91 MikeHar      Created.
    00010 * 02-23-92 MattFe       rewrote sleeptask
    00011 * 09-07-93 DaveHart     Per-process nonpreemptive scheduler for
    00012 *                       multiple WOW VDM support.
    00013 \***************************************************************************/
    00014
    00015 #include "precomp.h"
    00016 #pragma hdrstop
    00017
    00018
    00019 /*
    00020  * WakeWowTask
    00021  *
    00022  * if needed the wowtask is woken by setting its event
    00023  * It is assumed that if any wow task is currently scheduled
    00024  * that it is a waste of time to wake the specified wow task
    00025  * since rescheduling will occur when the currently scheduled
    00026  * wow task enters xxxSleepTask
    00027  *
    00028  */
    00029 VOID
    00030 WakeWowTask(
    00031    PTHREADINFO pti
    00032    )
    00033 {
    00034    PWOWPROCESSINFO pwpi;
    00035
    00036    pwpi = pti->ppi->pwpi;
    00037    if (pwpi && !pwpi->ptiScheduled) {
    00038        KeSetEvent(pti->pEventQueueServer, EVENT_INCREMENT, FALSE);
    00039        }
    00040 }
    00041
    00042
    00043
    00044
    00045 /***************************************************************************\
    00046 * InsertTask
    00047 *
    00048 * This function removes a task from its old location and inserts
    00049 * in the proper prioritized location
    00050 *
    00051 * Find a place for this task such that it must be inserted
    00052 * after any task with greater or equal priority and must be
    00053 * before any task with higher priorty.  The higher the priority
    00054 * the less urgent the task.
    00055 *
    00056 * History:
    00057 * 19-Nov-1993 mikeke    Created
    00058 \***************************************************************************/
    00059
    00060 void InsertTask(
    00061     PPROCESSINFO ppi,
    00062     PTDB ptdbNew)
    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 }
    00120
    00121
    00122 /***************************************************************************\
    00123 * DestroyTask()
    00124 *
    00125 * History:
    00126 * 02-27-91 MikeHar      Created.
    00127 \***************************************************************************/
    00128
    00129 void DestroyTask(
    00130     PPROCESSINFO ppi,
    00131     PTHREADINFO ptiToRemove)
    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 }
    00233
    00234
    00235
    00236
    00237 /***************************************************************************\
    00238 * xxxSleepTask
    00239 *
    00240 * This function puts this task to sleep and wakes the next (if any)
    00241 * deserving task.
    00242 *
    00243 * BOOL   fInputIdle  - app is going idle, may do idle hooks
    00244 * HANDLE hEvent      - if nonzero, WowExec's event (client side) for
    00245 *                      virtual HW Interrupt HotPath.
    00246 * History:
    00247 * 02-27-91 MikeHar      Created.
    00248 * 02-23-91 MattFe       rewrote
    00249 * 12-17-93 Jonle        add wowexec hotpath for VirtualInterrupts
    00250 \***************************************************************************/
    00251
    00252 BOOL xxxSleepTask(
    00253     BOOL   fInputIdle,
    00254     HANDLE hEvent)
    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 }
    00525
    00526
    00527
    00528 /***************************************************************************\
    00529 * xxxUserYield
    00530 *
    00531 * Does exactly what Win3.1 UserYield does.
    00532 *
    00533 * History:
    00534 * 10-19-92 Scottlu      Created.
    00535 \***************************************************************************/
    00536
    00537 BOOL xxxUserYield(
    00538     PTHREADINFO pti)
    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 }
    00585
    00586
    00587 /***************************************************************************\
    00588 * DirectedScheduleTask
    00589 *
    00590 * History:
    00591 * 25-Jun-1992 mikeke    Created.
    00592 \***************************************************************************/
    00593
    00594 VOID DirectedScheduleTask(
    00595      PTHREADINFO ptiOld,
    00596      PTHREADINFO ptiNew,
    00597      BOOL bSendMsg,
    00598      PSMS psms
    00599      )
    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 }
    00680
    00681
    00682
    00683
    00684 /***************************************************************************\
    00685 * xxxDirectedYield
    00686 *
    00687 * History:
    00688 * 09-17-92 JimA         Created.
    00689 \***************************************************************************/
    00690
    00691 void xxxDirectedYield(
    00692     DWORD dwThreadId)
    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 }
    00733
    00734
    00735 /***************************************************************************\
    00736 * CurrentTaskLock
    00737 *
    00738 * Lock the current 16 bit task into the 16 bit scheduler
    00739 *
    00740 * Parameter:
    00741 *   hlck    if NULL, lock the current 16 bit task and return a lock handle
    00742 *           if valid lock handle, unlock the current task
    00743 *
    00744 * History:
    00745 * 13-Apr-1992 jonpa      Created.
    00746 \***************************************************************************/
    00747 #if 0 /* WOW is not using this but they might some day */
    00748 DWORD CurrentTaskLock(
    00749     DWORD hlck)
    00750 {
    00751     PWOWPROCESSINFO pwpi = PpiCurrent()->pwpi;
    00752
    00753     if (!pwpi)
    00754         return 0;
    00755
    00756     if (hlck == 0) {
    00757         pwpi->nTaskLock++;
    00758         return ~(DWORD)pwpi->ptiScheduled->ptdb;
    00759     } else if ((~hlck) == (DWORD)pwpi->ptiScheduled->ptdb) {
    00760         pwpi->nTaskLock--;
    00761     }
    00762
    00763     return 0;
    00764 }
    00765 #endif