VirtualBox

Changeset 12361 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Sep 10, 2008 3:05:50 PM (16 years ago)
Author:
vboxsync
Message:

DrvHostSerial: volatile vars and atomic set/get is required on the send queue. darwin only: don't overwrite the tail.

File:
1 edited

Legend:

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

    r12355 r12361  
    132132
    133133    /** Internal send FIFO queue */
    134     uint8_t                     aSendQueue[CHAR_MAX_SEND_QUEUE];
    135     uint32_t                    iSendQueueHead;
    136     uint32_t                    iSendQueueTail;
     134    uint8_t volatile            aSendQueue[CHAR_MAX_SEND_QUEUE];
     135    uint32_t volatile           iSendQueueHead;
     136    uint32_t volatile           iSendQueueTail;
    137137
    138138    /** Read/write statistics */
     
    182182    LogFlow(("%s: pvBuf=%#p cbWrite=%d\n", __FUNCTION__, pvBuf, cbWrite));
    183183
    184     for (uint32_t i=0;i<cbWrite;i++)
     184    for (uint32_t i = 0; i < cbWrite; i++)
    185185    {
    186         uint32_t idx = pThis->iSendQueueHead;
     186#ifdef RT_OS_DARWIN /* don't wanna break the others here. */
     187        uint32_t iHead = ASMAtomicUoReadU32(&pThis->iSendQueueHead);
     188        uint32_t iTail = ASMAtomicUoReadU32(&pThis->iSendQueueTail);
     189        int32_t  cbAvail = iTail > iHead
     190                         ? iHead + CHAR_MAX_SEND_QUEUE - iTail - 1
     191                         : CHAR_MAX_SEND_QUEUE - (iHead - iTail) - 1;
     192        if (cbAvail <= 0)
     193        {
     194            Log(("%s: dropping %d chars (cbAvail=%d iHead=%d iTail=%d)\n", __FUNCTION__, cbWrite - i , cbAvial, iHead, iTail));
     195            break;
     196        }
     197
     198        pThis->aSendQueue[iHead] = pbBuffer[i];
     199        STAM_COUNTER_INC(&pThis->StatBytesWritten);
     200        ASMAtomicWriteU32(&pThis->iSendQueueHead, (iHead + 1) & CHAR_MAX_SEND_QUEUE_MASK);
     201        if (cbAvail < CHAR_MAX_SEND_QUEUE / 4)
     202        {
     203            RTSemEventSignal(pThis->SendSem);
     204            RTThreadYield();
     205        }
     206#else
     207        uint32_t idx = ASMAtomicUoReadU32(&pThis->iSendQueueHead);
    187208
    188209        pThis->aSendQueue[idx] = pbBuffer[i];
     
    190211
    191212        STAM_COUNTER_INC(&pThis->StatBytesWritten);
    192         ASMAtomicXchgU32(&pThis->iSendQueueHead, idx);
     213        ASMAtomicWriteU32(&pThis->iSendQueueHead, idx);
     214#endif
    193215    }
    194216    RTSemEventSignal(pThis->SendSem);
     
    450472         * Write the character to the host device.
    451473         */
     474        uint32_t iTail;
    452475        while (   pThread->enmState == PDMTHREADSTATE_RUNNING
    453                && pThis->iSendQueueTail != pThis->iSendQueueHead)
     476               && (iTail = ASMAtomicUoReadU32(&pThis->iSendQueueTail)) != ASMAtomicUoReadU32(&pThis->iSendQueueHead))
    454477        {
     478            /** @todo process more than one byte? */
    455479            unsigned cbProcessed = 1;
     480            uint8_t abBuf[1];
     481            abBuf[0] = pThis->aSendQueue[iTail];
    456482
    457483#if defined(RT_OS_LINUX) || defined(RT_OS_DARWIN)
    458484
    459             rc = RTFileWrite(pThis->DeviceFile, &pThis->aSendQueue[pThis->iSendQueueTail], cbProcessed, NULL);
     485            rc = RTFileWrite(pThis->DeviceFile, abBuf, cbProcessed, NULL);
    460486
    461487#elif defined(RT_OS_WINDOWS)
     
    465491            pThis->overlappedSend.hEvent = pThis->hEventSend;
    466492
    467             if (!WriteFile(pThis->hDeviceFile, &pThis->aSendQueue[pThis->iSendQueueTail], cbProcessed, &cbBytesWritten, &pThis->overlappedSend))
     493            if (!WriteFile(pThis->hDeviceFile, abBuf, cbProcessed, &cbBytesWritten, &pThis->overlappedSend))
    468494            {
    469495                dwRet = GetLastError();
     
    488514            if (RT_SUCCESS(rc))
    489515            {
    490                 Assert(cbProcessed);
    491                 pThis->iSendQueueTail++;
    492                 pThis->iSendQueueTail &= CHAR_MAX_SEND_QUEUE_MASK;
     516                Assert(cbProcessed == 1);
     517                ASMAtomicWriteU32(&pThis->iSendQueueTail, (iTail + 1) & CHAR_MAX_SEND_QUEUE_MASK);
    493518            }
    494519            else if (RT_FAILURE(rc))
    495520            {
    496521                LogRel(("HostSerial#%d: Serial Write failed with %Rrc; terminating send thread\n", pDrvIns->iInstance, rc));
    497                 return VINF_SUCCESS;
     522                return rc;
    498523            }
    499524        }
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