VirtualBox

Changeset 44487 in vbox for trunk/src/VBox/Runtime/r3/os2


Ignore:
Timestamp:
Jan 31, 2013 12:37:42 PM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
83507
Message:

IPRT: Poll on OS/2.

Location:
trunk/src/VBox/Runtime/r3/os2
Files:
1 deleted
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/os2/pipe-os2.cpp

    r44462 r44487  
    763763    if (RT_FAILURE(rc))
    764764        return rc;
     765
    765766    rc = rtPipeOs2EnsureSem(pThis);
     767    if (RT_SUCCESS(rc) && cMillies > 0)
     768    {
     769        /* Stop polling attempts if we might block. */
     770        if (pThis->hPollSet == NIL_RTPOLLSET)
     771            pThis->hPollSet = (RTPOLLSET)(uintptr_t)0xbeef0042;
     772        else
     773            rc = VERR_WRONG_ORDER;
     774    }
    766775    if (RT_SUCCESS(rc))
    767776    {
     
    771780             * Check the handle state.
    772781             */
     782            APIRET orc;
     783            if (cMillies > 0)
     784            {
     785                ULONG ulIgnore;
     786                orc = DosResetEventSem(pThis->hev, &ulIgnore);
     787                AssertMsg(orc == NO_ERROR || orc == ERROR_ALREADY_RESET, ("%d\n", orc));
     788            }
     789
    773790            PIPESEMSTATE aStates[4]; RT_ZERO(aStates);
    774             APIRET orc = DosQueryNPipeSemState((HSEM)pThis->hev, &aStates[0], sizeof(aStates));
     791            orc = DosQueryNPipeSemState((HSEM)pThis->hev, &aStates[0], sizeof(aStates));
    775792            if (orc != NO_ERROR)
    776793            {
     
    789806            Assert(aStates[i].fStatus == NPSS_WSPACE || aStates[i].fStatus == NPSS_RDATA || aStates[i].fStatus == NPSS_EOI);
    790807            if (   aStates[i].fStatus != NPSS_EOI
    791                 && aStates[0].usAvail > 0)
     808                && aStates[i].usAvail > 0)
    792809                break;
    793810
     
    822839        if (rc == VERR_BROKEN_PIPE)
    823840            pThis->fBrokenPipe = true;
     841        if (cMillies > 0)
     842            pThis->hPollSet = NIL_RTPOLLSET;
    824843    }
    825844
     
    860879
    861880
    862 #if 0
    863 /**
    864  * Internal RTPollSetAdd helper that returns the handle that should be added to
    865  * the pollset.
    866  *
    867  * @returns Valid handle on success, INVALID_HANDLE_VALUE on failure.
    868  * @param   hPipe               The pipe handle.
    869  * @param   fEvents             The events we're polling for.
    870  * @param   ph                  where to put the primary handle.
    871  */
    872 int rtPipePollGetHandle(RTPIPE hPipe, uint32_t fEvents, PHANDLE ph)
     881int rtPipePollGetHandle(RTPIPE hPipe, uint32_t fEvents, PRTHCINTPTR phNative)
    873882{
    874883    RTPIPEINTERNAL *pThis = hPipe;
     
    876885    AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, VERR_INVALID_HANDLE);
    877886
    878     AssertReturn(!(fEvents & RTPOLL_EVT_READ) || pThis->fRead, VERR_INVALID_PARAMETER);
     887    AssertReturn(!(fEvents & RTPOLL_EVT_READ)  || pThis->fRead, VERR_INVALID_PARAMETER);
    879888    AssertReturn(!(fEvents & RTPOLL_EVT_WRITE) || !pThis->fRead, VERR_INVALID_PARAMETER);
    880889
    881     /* Later: Try register an event handle with the pipe like on OS/2, there is
    882        a file control for doing this obviously intended for the OS/2 subsys.
    883        The question is whether this still exists on Vista and W7. */
    884     *ph = pThis->Overlapped.hEvent;
    885     return VINF_SUCCESS;
     890    int rc = RTCritSectEnter(&pThis->CritSect);
     891    if (RT_SUCCESS(rc))
     892    {
     893        rc = rtPipeOs2EnsureSem(pThis);
     894        if (RT_SUCCESS(rc))
     895            *phNative = (RTHCINTPTR)pThis->hev;
     896        RTCritSectLeave(&pThis->CritSect);
     897    }
     898    return rc;
    886899}
    887900
     
    893906 * @param   pThis               The pipe handle.
    894907 * @param   fEvents             The desired events.
     908 * @param   fResetEvtSem        Whether to reset the event semaphore.
    895909 */
    896 static uint32_t rtPipePollCheck(RTPIPEINTERNAL *pThis, uint32_t fEvents)
    897 {
     910static uint32_t rtPipePollCheck(RTPIPEINTERNAL *pThis, uint32_t fEvents, bool fResetEvtSem)
     911{
     912    /*
     913     * Reset the event semaphore if we're gonna wait.
     914     */
     915    APIRET orc;
     916    ULONG ulIgnore;
     917    if (fResetEvtSem)
     918    {
     919        orc = DosResetEventSem(pThis->hev, &ulIgnore);
     920        AssertMsg(orc == NO_ERROR || orc == ERROR_ALREADY_RESET, ("%d\n", orc));
     921    }
     922
     923    /*
     924     * Check for events.
     925     */
    898926    uint32_t fRetEvents = 0;
    899927    if (pThis->fBrokenPipe)
     
    901929    else if (pThis->fRead)
    902930    {
    903         if (!pThis->fIOPending)
    904         {
    905             DWORD cbAvailable;
    906             if (PeekNamedPipe(pThis->hPipe, NULL, 0, NULL, &cbAvailable, NULL))
    907             {
    908                 if (   (fEvents & RTPOLL_EVT_READ)
    909                     && cbAvailable > 0)
    910                     fRetEvents |= RTPOLL_EVT_READ;
    911             }
    912             else
    913             {
    914                 if (GetLastError() == ERROR_BROKEN_PIPE)
    915                     pThis->fBrokenPipe = true;
     931        ULONG       cbActual = 0;
     932        ULONG       ulState  = 0;
     933        AVAILDATA   Avail    = { 0, 0 };
     934        orc = DosPeekNPipe(pThis->hPipe, NULL, 0, &cbActual, &Avail, &ulState);
     935        if (orc != NO_ERROR)
     936        {
     937            fRetEvents |= RTPOLL_EVT_ERROR;
     938            if (orc == ERROR_BROKEN_PIPE || orc == ERROR_PIPE_NOT_CONNECTED)
     939                pThis->fBrokenPipe = true;
     940        }
     941        else if (Avail.cbpipe > 0)
     942            fRetEvents |= RTPOLL_EVT_READ;
     943        else if (ulState != NP_STATE_CONNECTED)
     944        {
     945            fRetEvents |= RTPOLL_EVT_ERROR;
     946            pThis->fBrokenPipe = true;
     947        }
     948    }
     949    else
     950    {
     951        PIPESEMSTATE aStates[4]; RT_ZERO(aStates);
     952        orc = DosQueryNPipeSemState((HSEM)pThis->hev, &aStates[0], sizeof(aStates));
     953        if (orc == NO_ERROR)
     954        {
     955            int i = 0;
     956            while (aStates[i].fStatus == NPSS_RDATA)
     957                i++;
     958            if (aStates[i].fStatus == NPSS_CLOSE)
     959            {
    916960                fRetEvents |= RTPOLL_EVT_ERROR;
    917             }
    918         }
    919     }
    920     else
    921     {
    922         if (pThis->fIOPending)
    923         {
    924             rtPipeWriteCheckCompletion(pThis);
    925             if (pThis->fBrokenPipe)
    926                 fRetEvents |= RTPOLL_EVT_ERROR;
    927         }
    928         if (   !pThis->fIOPending
    929             && !fRetEvents)
    930         {
    931             FILE_PIPE_LOCAL_INFORMATION Info;
    932             if (rtPipeQueryInfo(pThis, &Info))
    933             {
    934                 /* Check for broken pipe. */
    935                 if (Info.NamedPipeState == FILE_PIPE_CLOSING_STATE)
    936                 {
    937                     fRetEvents = RTPOLL_EVT_ERROR;
    938                     pThis->fBrokenPipe = true;
    939                 }
    940 
    941                 /* Check if there is available buffer space. */
    942                 if (   !fRetEvents
    943                     && (fEvents & RTPOLL_EVT_WRITE)
    944                     && (   Info.WriteQuotaAvailable > 0
    945                         || Info.OutboundQuota == 0)
    946                     )
    947                     fRetEvents |= RTPOLL_EVT_WRITE;
    948             }
    949             else if (fEvents & RTPOLL_EVT_WRITE)
     961                pThis->fBrokenPipe = true;
     962            }
     963            else if (   aStates[i].fStatus == NPSS_WSPACE
     964                     && aStates[i].usAvail > 0)
    950965                fRetEvents |= RTPOLL_EVT_WRITE;
    951966        }
    952     }
    953 
    954     return fRetEvents;
    955 }
    956 
    957 
    958 /**
    959  * Internal RTPoll helper that polls the pipe handle and, if @a fNoWait is
    960  * clear, starts whatever actions we've got running during the poll call.
    961  *
    962  * @returns 0 if no pending events, actions initiated if @a fNoWait is clear.
    963  *          Event mask (in @a fEvents) and no actions if the handle is ready
    964  *          already.
    965  *          UINT32_MAX (asserted) if the pipe handle is busy in I/O or a
    966  *          different poll set.
    967  *
    968  * @param   hPipe               The pipe handle.
    969  * @param   hPollSet            The poll set handle (for access checks).
    970  * @param   fEvents             The events we're polling for.
    971  * @param   fFinalEntry         Set if this is the final entry for this handle
    972  *                              in this poll set.  This can be used for dealing
    973  *                              with duplicate entries.
    974  * @param   fNoWait             Set if it's a zero-wait poll call.  Clear if
    975  *                              we'll wait for an event to occur.
    976  */
     967        else
     968        {
     969            fRetEvents |= RTPOLL_EVT_ERROR;
     970            if (orc == ERROR_BROKEN_PIPE || orc == ERROR_PIPE_NOT_CONNECTED)
     971                pThis->fBrokenPipe = true;
     972        }
     973    }
     974
     975    return fRetEvents & (fEvents | RTPOLL_EVT_ERROR);
     976}
     977
     978
    977979uint32_t rtPipePollStart(RTPIPE hPipe, RTPOLLSET hPollSet, uint32_t fEvents, bool fFinalEntry, bool fNoWait)
    978980{
    979     /** @todo All this polling code could be optimized to make fewer system
    980      *        calls; like for instance the ResetEvent calls. */
    981981    RTPIPEINTERNAL *pThis = hPipe;
    982982    AssertPtrReturn(pThis, UINT32_MAX);
     
    989989    uint32_t fRetEvents;
    990990    if (   pThis->cUsers   == 0
    991         || pThis->hPollSet == hPollSet)
    992     {
    993         /* Check what the current events are. */
    994         fRetEvents = rtPipePollCheck(pThis, fEvents);
    995         if (   !fRetEvents
    996             && !fNoWait)
    997         {
    998             /* Make sure the event semaphore has been reset. */
    999             if (!pThis->fIOPending)
    1000             {
    1001                 rc = ResetEvent(pThis->Overlapped.hEvent);
    1002                 Assert(rc == TRUE);
    1003             }
    1004 
    1005             /* Kick off the zero byte read thing if applicable. */
    1006             if (   !pThis->fIOPending
    1007                 && pThis->fRead
    1008                 && (fEvents & RTPOLL_EVT_READ)
    1009                )
    1010             {
    1011                 DWORD cbRead = 0;
    1012                 if (ReadFile(pThis->hPipe, pThis->abBuf, 0, &cbRead, &pThis->Overlapped))
    1013                     fRetEvents = rtPipePollCheck(pThis, fEvents);
    1014                 else if (GetLastError() == ERROR_IO_PENDING)
    1015                 {
    1016                     pThis->fIOPending    = true;
    1017                     pThis->fZeroByteRead = true;
    1018                 }
    1019                 else
    1020                     fRetEvents = RTPOLL_EVT_ERROR;
    1021             }
    1022 
    1023             /* If we're still set for the waiting, record the poll set and
    1024                mark the pipe used. */
    1025             if (!fRetEvents)
    1026             {
    1027                 pThis->cUsers++;
    1028                 pThis->hPollSet = hPollSet;
    1029             }
     991        || pThis->hPollSet == NIL_RTPOLLSET)
     992    {
     993        fRetEvents = rtPipePollCheck(pThis, fEvents, fNoWait);
     994        if (!fRetEvents && !fNoWait)
     995        {
     996            /* Mark the set busy while waiting. */
     997            pThis->cUsers++;
     998            pThis->hPollSet = hPollSet;
    1030999        }
    10311000    }
     
    10411010
    10421011
    1043 /**
    1044  * Called after a WaitForMultipleObjects returned in order to check for pending
    1045  * events and stop whatever actions that rtPipePollStart() initiated.
    1046  *
    1047  * @returns Event mask or 0.
    1048  *
    1049  * @param   hPipe               The pipe handle.
    1050  * @param   fEvents             The events we're polling for.
    1051  * @param   fFinalEntry         Set if this is the final entry for this handle
    1052  *                              in this poll set.  This can be used for dealing
    1053  *                              with duplicate entries.  Only keep in mind that
    1054  *                              this method is called in reverse order, so the
    1055  *                              first call will have this set (when the entire
    1056  *                              set was processed).
    1057  * @param   fHarvestEvents      Set if we should check for pending events.
    1058  */
    10591012uint32_t rtPipePollDone(RTPIPE hPipe, uint32_t fEvents, bool fFinalEntry, bool fHarvestEvents)
    10601013{
     
    10681021    Assert(pThis->cUsers > 0);
    10691022
    1070 
    1071     /* Cancel the zero byte read. */
    1072     uint32_t fRetEvents = 0;
    1073     if (pThis->fZeroByteRead)
    1074     {
    1075         CancelIo(pThis->hPipe);
    1076         DWORD cbRead = 0;
    1077         if (   !GetOverlappedResult(pThis->hPipe, &pThis->Overlapped, &cbRead, TRUE /*fWait*/)
    1078             && GetLastError() != ERROR_OPERATION_ABORTED)
    1079             fRetEvents = RTPOLL_EVT_ERROR;
    1080 
    1081         pThis->fIOPending    = false;
    1082         pThis->fZeroByteRead = false;
    1083     }
    1084 
    10851023    /* harvest events. */
    1086     fRetEvents |= rtPipePollCheck(pThis, fEvents);
     1024    uint32_t fRetEvents = rtPipePollCheck(pThis, fEvents, false);
    10871025
    10881026    /* update counters. */
    10891027    pThis->cUsers--;
    1090     if (!pThis->cUsers)
    1091         pThis->hPollSet = NIL_RTPOLLSET;
     1028    pThis->hPollSet = NIL_RTPOLLSET;
    10921029
    10931030    RTCritSectLeave(&pThis->CritSect);
    10941031    return fRetEvents;
    10951032}
    1096 #endif
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette