VirtualBox

Changeset 73712 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Aug 16, 2018 1:32:54 PM (6 years ago)
Author:
vboxsync
Message:

Devices/Serial: Remove giving the amount of available data to write from the UART core and let the drivers figure it out themselves when querying the data to write. Avoids unnecessary trips to R3 when the FIFO is enabled if the guest keeps the FIFO filled. Some other smaller fixes

Location:
trunk/src/VBox/Devices/Serial
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Serial/DrvCharNew.cpp

    r73331 r73712  
    5959    /** Flag to notify the receive thread it should terminate. */
    6060    volatile bool               fShutdown;
     61    /** Flag whether data is available from the device/driver above as notified by the driver. */
     62    volatile bool               fAvailWrExt;
     63    /** Internal copy of the flag which gets reset when there is no data anymore. */
     64    bool                        fAvailWrInt;
    6165    /** I/O thread. */
    6266    PPDMTHREAD                  pThrdIo;
    6367
    64     /** Amount of data available for sending from the device/driver above. */
    65     volatile size_t             cbAvailWr;
    6668    /** Small send buffer. */
    6769    uint8_t                     abTxBuf[16];
     
    112114 * @interface_method_impl{PDMISERIALCONNECTOR,pfnDataAvailWrNotify}
    113115 */
    114 static DECLCALLBACK(int) drvCharDataAvailWrNotify(PPDMISERIALCONNECTOR pInterface, size_t cbAvail)
    115 {
    116     LogFlowFunc(("pInterface=%#p cbAvail=%zu\n", pInterface, cbAvail));
     116static DECLCALLBACK(int) drvCharDataAvailWrNotify(PPDMISERIALCONNECTOR pInterface)
     117{
     118    LogFlowFunc(("pInterface=%#p\n", pInterface));
    117119    PDRVCHAR pThis = RT_FROM_MEMBER(pInterface, DRVCHAR, ISerialConnector);
    118120
    119121    int rc = VINF_SUCCESS;
    120     size_t cbAvailOld = ASMAtomicAddZ(&pThis->cbAvailWr, cbAvail);
    121     if (!cbAvailOld)
     122    bool fAvailOld = ASMAtomicXchgBool(&pThis->fAvailWrExt, true);
     123    if (!fAvailOld)
    122124        rc = pThis->pDrvStream->pfnPollInterrupt(pThis->pDrvStream);
    123125
     
    219221        uint32_t fEvts = 0;
    220222
     223        if (!pThis->fAvailWrInt)
     224            pThis->fAvailWrInt = ASMAtomicXchgBool(&pThis->fAvailWrExt, false);
     225
    221226        if (   !pThis->cbRemaining
    222227            && pThis->pDrvStream->pfnRead)
    223228            fEvts |= RTPOLL_EVT_READ;
    224         if (   pThis->cbAvailWr
     229        if (   pThis->fAvailWrInt
    225230            || pThis->cbTxUsed)
    226231            fEvts |= RTPOLL_EVT_WRITE;
     
    232237            if (fEvtsRecv & RTPOLL_EVT_WRITE)
    233238            {
    234                 if (pThis->cbAvailWr)
     239                if (pThis->fAvailWrInt)
    235240                {
    236241                    /* Stuff as much data into the TX buffer as we can. */
    237                     size_t cbToFetch = RT_MIN(RT_ELEMENTS(pThis->abTxBuf) - pThis->cbTxUsed, pThis->cbAvailWr);
     242                    size_t cbToFetch = RT_ELEMENTS(pThis->abTxBuf) - pThis->cbTxUsed;
    238243                    size_t cbFetched = 0;
    239244                    rc = pThis->pDrvSerialPort->pfnReadWr(pThis->pDrvSerialPort, &pThis->abTxBuf[pThis->cbTxUsed], cbToFetch,
     
    242247
    243248                    if (cbFetched > 0)
    244                     {
    245                         ASMAtomicSubZ(&pThis->cbAvailWr, cbFetched);
    246249                        pThis->cbTxUsed  += cbFetched;
    247                     }
    248250                    else
    249251                    {
    250                         /* The guest reset the send queue and there is no data available anymore. */
    251                         pThis->cbAvailWr = 0;
     252                        /* There is no data available anymore. */
     253                        pThis->fAvailWrInt = false;
    252254                    }
    253255                }
     
    331333
    332334    /* Reset TX and RX buffers. */
    333     pThis->cbAvailWr   = 0;
     335    pThis->fAvailWrExt = false;
     336    pThis->fAvailWrInt = false;
    334337    pThis->cbTxUsed    = 0;
    335338    pThis->cbRemaining = 0;
  • trunk/src/VBox/Devices/Serial/DrvHostSerialNew.cpp

    r73331 r73712  
    6363    char                        *pszDevicePath;
    6464
    65     /** Amount of data available for sending from the device/driver above. */
    66     volatile size_t             cbAvailWr;
     65    /** Flag whether data is available from the device/driver above as notified by the driver. */
     66    volatile bool               fAvailWrExt;
     67    /** Internal copy of the flag which gets reset when there is no data anymore. */
     68    bool                        fAvailWrInt;
    6769    /** Small send buffer. */
    6870    uint8_t                     abTxBuf[16];
     
    187189
    188190/** @interface_method_impl{PDMISERIALCONNECTOR,pfnDataAvailWrNotify} */
    189 static DECLCALLBACK(int) drvHostSerialDataAvailWrNotify(PPDMISERIALCONNECTOR pInterface, size_t cbAvail)
     191static DECLCALLBACK(int) drvHostSerialDataAvailWrNotify(PPDMISERIALCONNECTOR pInterface)
    190192{
    191193    PDRVHOSTSERIAL pThis = RT_FROM_MEMBER(pInterface, DRVHOSTSERIAL, ISerialConnector);
    192194
    193195    int rc = VINF_SUCCESS;
    194     size_t cbAvailOld = ASMAtomicAddZ(&pThis->cbAvailWr, cbAvail);
    195     if (!cbAvailOld)
     196    bool fAvailOld = ASMAtomicXchgBool(&pThis->fAvailWrExt, true);
     197    if (!fAvailOld)
    196198        rc = RTSerialPortEvtPollInterrupt(pThis->hSerialPort);
    197199
     
    376378        uint32_t fEvtFlags = RTSERIALPORT_EVT_F_STATUS_LINE_CHANGED | RTSERIALPORT_EVT_F_BREAK_DETECTED;
    377379
     380        if (!pThis->fAvailWrInt)
     381            pThis->fAvailWrInt = ASMAtomicXchgBool(&pThis->fAvailWrExt, false);
     382
    378383        /* Wait until there is room again if there is anyting to send. */
    379         if (   pThis->cbAvailWr
     384        if (   pThis->fAvailWrInt
    380385            || pThis->cbTxUsed)
    381386            fEvtFlags |= RTSERIALPORT_EVT_F_DATA_TX;
     
    391396            if (fEvtsRecv & RTSERIALPORT_EVT_F_DATA_TX)
    392397            {
    393                 if (pThis->cbAvailWr)
     398                if (pThis->fAvailWrInt)
    394399                {
    395400                    /* Stuff as much data into the TX buffer as we can. */
    396                     size_t cbToFetch = RT_MIN(RT_ELEMENTS(pThis->abTxBuf) - pThis->cbTxUsed, pThis->cbAvailWr);
     401                    size_t cbToFetch = RT_ELEMENTS(pThis->abTxBuf) - pThis->cbTxUsed;
    397402                    size_t cbFetched = 0;
    398403                    rc = pThis->pDrvSerialPort->pfnReadWr(pThis->pDrvSerialPort, &pThis->abTxBuf[pThis->cbTxUsed], cbToFetch,
     
    401406
    402407                    if (cbFetched > 0)
    403                     {
    404                         ASMAtomicSubZ(&pThis->cbAvailWr, cbFetched);
    405                         pThis->cbTxUsed  += cbFetched;
    406                     }
     408                        pThis->cbTxUsed += cbFetched;
    407409                    else
    408410                    {
    409                         /* The guest reset the send queue and there is no data available anymore. */
    410                         pThis->cbAvailWr = 0;
     411                        /* There is no data available anymore. */
     412                        pThis->fAvailWrInt = false;
    411413                    }
    412414                }
     
    565567    pThis->pDrvIns                               = pDrvIns;
    566568    pThis->hSerialPort                           = NIL_RTSERIALPORT;
    567     pThis->cbAvailWr                             = 0;
     569    pThis->fAvailWrExt                           = false;
     570    pThis->fAvailWrInt                           = false;
    568571    pThis->cbTxUsed                              = 0;
    569572    pThis->offWrite                              = 0;
  • trunk/src/VBox/Devices/Serial/UartCore.cpp

    r73636 r73712  
    7070# define UART_REG_IIR_ID_SET(a_Val)          (((a_Val) << 1) & UART_REG_IIR_ID_MASK)
    7171/** Gets the interrupt identification from the given IIR register value. */
    72 # define UART_REG_IIR_ID_GET(a_Val)          (((a_Val) >> 1) & UART_REG_IIR_ID_MASK)
     72# define UART_REG_IIR_ID_GET(a_Val)          (((a_Val) & UART_REG_IIR_ID_MASK) >> 1)
    7373/** Receiver Line Status interrupt. */
    7474#  define UART_REG_IIR_ID_RCL                0x3
     
    337337
    338338
     339/**
     340 * Returns the amount of bytes stored in the given FIFO.
     341 *
     342 * @retrusn Amount of bytes stored in the FIFO.
     343 * @param   pFifo               The FIFO.
     344 */
     345DECLINLINE(size_t) uartFifoUsedGet(PUARTFIFO pFifo)
     346{
     347    return pFifo->cbUsed;
     348}
     349
     350
     351/**
     352 * Puts a new character into the given FIFO.
     353 *
     354 * @returns Flag whether the FIFO overflowed.
     355 * @param   pFifo               The FIFO to put the data into.
     356 * @param   fOvrWr              Flag whether to overwrite data if the FIFO is full.
     357 * @param   bData               The data to add.
     358 */
     359DECLINLINE(bool) uartFifoPut(PUARTFIFO pFifo, bool fOvrWr, uint8_t bData)
     360{
     361    if (fOvrWr || pFifo->cbUsed < pFifo->cbMax)
     362    {
     363        pFifo->abBuf[pFifo->offWrite] = bData;
     364        pFifo->offWrite = (pFifo->offWrite + 1) % pFifo->cbMax;
     365    }
     366
     367    bool fOverFlow = false;
     368    if (pFifo->cbUsed < pFifo->cbMax)
     369        pFifo->cbUsed++;
     370    else
     371    {
     372        fOverFlow = true;
     373        if (fOvrWr) /* Advance the read position to account for the lost character. */
     374           pFifo->offRead = (pFifo->offRead + 1) % pFifo->cbMax;
     375    }
     376
     377    return fOverFlow;
     378}
     379
     380
     381/**
     382 * Returns the next character in the FIFO.
     383 *
     384 * @return Next byte in the FIFO.
     385 * @param   pFifo               The FIFO to get data from.
     386 */
     387DECLINLINE(uint8_t) uartFifoGet(PUARTFIFO pFifo)
     388{
     389    uint8_t bRet = 0;
     390
     391    if (pFifo->cbUsed)
     392    {
     393        bRet = pFifo->abBuf[pFifo->offRead];
     394        pFifo->offRead = (pFifo->offRead + 1) % pFifo->cbMax;
     395        pFifo->cbUsed--;
     396    }
     397
     398    return bRet;
     399}
     400
     401
    339402#ifdef IN_RING3
    340403/**
     
    365428
    366429
    367 /**
    368  * Puts a new character into the given FIFO.
    369  *
    370  * @returns Flag whether the FIFO overflowed.
    371  * @param   pFifo               The FIFO to put the data into.
    372  * @param   fOvrWr              Flag whether to overwrite data if the FIFO is full.
    373  * @param   bData               The data to add.
    374  */
    375 DECLINLINE(bool) uartFifoPut(PUARTFIFO pFifo, bool fOvrWr, uint8_t bData)
    376 {
    377     if (fOvrWr || pFifo->cbUsed < pFifo->cbMax)
    378     {
    379         pFifo->abBuf[pFifo->offWrite] = bData;
    380         pFifo->offWrite = (pFifo->offWrite + 1) % pFifo->cbMax;
    381     }
    382 
    383     bool fOverFlow = false;
    384     if (pFifo->cbUsed < pFifo->cbMax)
    385         pFifo->cbUsed++;
    386     else
    387     {
    388         fOverFlow = true;
    389         if (fOvrWr) /* Advance the read position to account for the lost character. */
    390            pFifo->offRead = (pFifo->offRead + 1) % pFifo->cbMax;
    391     }
    392 
    393     return fOverFlow;
    394 }
    395 #endif
    396 
    397 
    398 /**
    399  * Returns the next character in the FIFO.
    400  *
    401  * @return Next byte in the FIFO.
    402  * @param   pFifo               The FIFO to get data from.
    403  */
    404 DECLINLINE(uint8_t) uartFifoGet(PUARTFIFO pFifo)
    405 {
    406     uint8_t bRet = 0;
    407 
    408     if (pFifo->cbUsed)
    409     {
    410         bRet = pFifo->abBuf[pFifo->offRead];
    411         pFifo->offRead = (pFifo->offRead + 1) % pFifo->cbMax;
    412         pFifo->cbUsed--;
    413     }
    414 
    415     return bRet;
    416 }
    417 
    418 
    419 #ifdef IN_RING3
    420430/**
    421431 * Tries to copy the requested amount of data from the given FIFO into the provided buffer.
     
    748758        {
    749759#ifndef IN_RING3
    750             rc = VINF_IOM_R3_IOPORT_WRITE;
     760            if (!uartFifoUsedGet(&pThis->FifoXmit))
     761                rc = VINF_IOM_R3_IOPORT_WRITE;
     762            else
     763            {
     764                uartFifoPut(&pThis->FifoXmit, true /*fOvrWr*/, uVal);
     765                UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_THRE | UART_REG_LSR_TEMT);
     766            }
    751767#else
    752768            uartFifoPut(&pThis->FifoXmit, true /*fOvrWr*/, uVal);
     
    754770            pThis->fThreEmptyPending = false;
    755771            uartIrqUpdate(pThis);
    756             if (pThis->pDrvSerial)
     772            if (   pThis->pDrvSerial
     773                && uartFifoUsedGet(&pThis->FifoXmit) == 1)
    757774            {
    758                 int rc2 = pThis->pDrvSerial->pfnDataAvailWrNotify(pThis->pDrvSerial, 1);
     775                int rc2 = pThis->pDrvSerial->pfnDataAvailWrNotify(pThis->pDrvSerial);
    759776                if (RT_FAILURE(rc2))
    760777                    LogRelMax(10, ("Serial#%d: Failed to send data with %Rrc\n", pThis->pDevInsR3->iInstance, rc2));
     
    776793                if (pThis->pDrvSerial)
    777794                {
    778                     int rc2 = pThis->pDrvSerial->pfnDataAvailWrNotify(pThis->pDrvSerial, 1);
     795                    int rc2 = pThis->pDrvSerial->pfnDataAvailWrNotify(pThis->pDrvSerial);
    779796                    if (RT_FAILURE(rc2))
    780797                        LogRelMax(10, ("Serial#%d: Failed to send data with %Rrc\n", pThis->pDevInsR3->iInstance, rc2));
     
    821838        else
    822839            pThis->uRegIer = uVal & UART_REG_IER_MASK_WR_16750;
     840
     841        if (pThis->uRegLsr & UART_REG_LSR_THRE)
     842            pThis->fThreEmptyPending = true;
     843
    823844        uartIrqUpdate(pThis);
    824845    }
     
    16571678    pThis->uRegScr        = 0;
    16581679    pThis->fIrqCtiPending = false;
    1659     pThis->fThreEmptyPending = false;
     1680    pThis->fThreEmptyPending = true;
    16601681
    16611682    /* Standard FIFO size for 15550A. */
Note: See TracChangeset for help on using the changeset viewer.

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