VirtualBox

Ticket #812: DrvHostSerial.2.diff

File DrvHostSerial.2.diff, 4.5 KB (added by Lawrence Rust, 16 years ago)

Linux TIOCMIWAIT workaround #2

  • .cpp

    old new  
    356356
    357357    tcsetattr(pThis->DeviceFile, TCSANOW, termiosSetup);
    358358    RTMemTmpFree(termiosSetup);
     359
     360#ifdef RT_OS_LINUX
     361    /* BUGBUG: In Linux 2.6.24 and earlier, if a thread calls tcsetattr while the monitor
     362     * thread is waiting in ioctl for a modem status change then 8250.c wrongly disables
     363     * modem irqs and so the monitor thread never gets released.  The workaround is to send
     364     * a signal after each tcsetattr
     365     */
     366    RTThreadPoke( pThis->pMonitorThread->Thread);
     367#endif
     368
    359369#elif defined(RT_OS_WINDOWS)
    360370    comSetup = (LPDCB)RTMemTmpAllocZ(sizeof(DCB));
    361371
     
    943953{
    944954    PDRVHOSTSERIAL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTSERIAL);
    945955    int rc = VINF_SUCCESS;
    946     unsigned uStatusLinesToCheck = 0;
    947 
    948     uStatusLinesToCheck = TIOCM_CAR | TIOCM_RNG | TIOCM_LE | TIOCM_CTS;
     956    unsigned long const uStatusLinesToCheck = TIOCM_CAR | TIOCM_RNG | TIOCM_DSR | TIOCM_CTS;
    949957
    950     if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
     958    if ( PDMTHREADSTATE_INITIALIZING == pThread->enmState)
    951959        return VINF_SUCCESS;
    952 
    953     while (pThread->enmState == PDMTHREADSTATE_RUNNING)
     960    do
    954961    {
    955         uint32_t newStatusLine = 0;
    956962        unsigned int statusLines;
    957 
    958 # ifdef RT_OS_LINUX
    959         /*
    960          * Wait for status line change.
    961          */
    962         rc = ioctl(pThis->DeviceFile, TIOCMIWAIT, &uStatusLinesToCheck);
    963         if (pThread->enmState != PDMTHREADSTATE_RUNNING)
    964             break;
    965         if (rc < 0)
    966         {
    967 ioctl_error:
    968             PDMDrvHlpVMSetRuntimeError(pDrvIns, false, "DrvHostSerialFail",
    969                                        N_("Ioctl failed for serial host device '%s' (%Rrc). The device will not work properly"),
    970                                        pThis->pszDevicePath, RTErrConvertFromErrno(errno));
    971             break;
    972         }
    973 
    974         rc = ioctl(pThis->DeviceFile, TIOCMGET, &statusLines);
    975         if (rc < 0)
    976             goto ioctl_error;
    977 # else  /* !RT_OS_LINUX */
    978         /*
    979          * Poll for the status line change.
    980          */
    981         rc = ioctl(pThis->DeviceFile, TIOCMGET, &statusLines);
    982         if (rc < 0)
     963        if ( 0 > (rc = ioctl( pThis->DeviceFile, TIOCMGET, &statusLines)))
    983964        {
    984965            PDMDrvHlpVMSetRuntimeError(pDrvIns, false, "DrvHostSerialFail",
    985966                                       N_("Ioctl failed for serial host device '%s' (%Rrc). The device will not work properly"),
    986                                        pThis->pszDevicePath, RTErrConvertFromErrno(errno));
     967                pThis->pszDevicePath, RTErrConvertFromErrno(errno)
     968            );
    987969            break;
    988970        }
    989         if (!((statusLines ^ pThis->fStatusLines) & uStatusLinesToCheck))
    990         {
    991             PDMR3ThreadSleep(pThread, 500); /* 0.5 sec */
    992             continue;
    993         }
    994         pThis->fStatusLines = statusLines;
    995 # endif /* !RT_OS_LINUX */
    996971
     972        uint32_t newStatusLine = 0;
    997973        if (statusLines & TIOCM_CAR)
    998974            newStatusLine |= PDM_ICHAR_STATUS_LINES_DCD;
    999975        if (statusLines & TIOCM_RNG)
    1000976            newStatusLine |= PDM_ICHAR_STATUS_LINES_RI;
    1001         if (statusLines & TIOCM_LE)
     977        if ( statusLines & TIOCM_DSR)
    1002978            newStatusLine |= PDM_ICHAR_STATUS_LINES_DSR;
    1003979        if (statusLines & TIOCM_CTS)
    1004980            newStatusLine |= PDM_ICHAR_STATUS_LINES_CTS;
    1005         rc = pThis->pDrvCharPort->pfnNotifyStatusLinesChanged(pThis->pDrvCharPort, newStatusLine);
     981        pThis->pDrvCharPort->pfnNotifyStatusLinesChanged( pThis->pDrvCharPort, newStatusLine);
     982
     983        if ( PDMTHREADSTATE_RUNNING != pThread->enmState)
     984            break;
     985# ifdef RT_OS_LINUX
     986        /* Wait for status line change. */
     987        /* BUGBUG: In Linux 2.6.24 and earlier, if a thread calls tcsetattr while the monitor
     988         * thread is waiting in ioctl for a modem status change then 8250.c wrongly disables
     989         * modem irqs and so the monitor thread never gets released.  The workaround is to send
     990         * a signal after each tcsetattr
     991         */
     992        ioctl( pThis->DeviceFile, TIOCMIWAIT, uStatusLinesToCheck);
     993# else
     994        /* Poll for status line change. */
     995        if (!((statusLines ^ pThis->fStatusLines) & uStatusLinesToCheck))
     996            PDMR3ThreadSleep( pThread, 500); /* 0.5 sec */
     997        pThis->fStatusLines = statusLines;
     998# endif
    1006999    }
     1000    while ( PDMTHREADSTATE_RUNNING == pThread->enmState);
    10071001
    1008     return VINF_SUCCESS;
     1002    return rc;
    10091003}
    10101004
    10111005/**

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy