VirtualBox

Changeset 27932 in vbox


Ignore:
Timestamp:
Apr 1, 2010 12:39:15 PM (15 years ago)
Author:
vboxsync
Message:

DrvChar.cpp: Wait for all threads that have been created with the RTTHREADFLAGS_WAITABLE flag or well leak stuff. Don't try signal the semaphore if PDMDrvHlpAttach failed.

File:
1 edited

Legend:

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

    r26173 r27932  
    11/* $Id$ */
    22/** @file
    3  * VBox stream I/O devices: Generic char driver
     3 * Driver that PDMISTREAM into PDMICHARCONNECTOR / PDMICHARPORT.
     4 *
     5 * Converts synchronous calls (PDMICHARCONNECTOR::pfnWrite, PDMISTREAM::pfnRead)
     6 * into asynchronous ones.
    47 */
    58
    69/*
    7  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
     10 * Copyright (C) 2006-2010 Sun Microsystems, Inc.
    811 *
    912 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    7679    /** Internal send FIFO queue */
    7780    uint8_t                     aSendQueue[CHAR_MAX_SEND_QUEUE];
    78     uint32_t                    iSendQueueHead;
     81    uint32_t volatile           iSendQueueHead;
    7982    uint32_t                    iSendQueueTail;
    8083
     
    142145
    143146/**
    144  * Send thread loop.
     147 * Send thread loop - pushes data down thru the driver chain.
    145148 *
    146149 * @returns 0 on success.
     
    152155    PDRVCHAR pThis = (PDRVCHAR)pvUser;
    153156
    154     for(;;)
     157    while (!pThis->fShutdown)
    155158    {
    156159        int rc = RTSemEventWait(pThis->SendSem, RT_INDEFINITE_WAIT);
     
    161164         * Write the character to the attached stream (if present).
    162165         */
    163         if (    !pThis->fShutdown
    164             &&  pThis->pDrvStream)
     166        if (    pThis->fShutdown
     167            ||  !pThis->pDrvStream)
     168            break;
     169
     170        while (   pThis->iSendQueueTail != pThis->iSendQueueHead
     171               && !pThis->fShutdown)
    165172        {
    166             while (pThis->iSendQueueTail != pThis->iSendQueueHead)
    167             {
    168                 size_t cbProcessed = 1;
    169 
    170                 rc = pThis->pDrvStream->pfnWrite(pThis->pDrvStream, &pThis->aSendQueue[pThis->iSendQueueTail], &cbProcessed);
    171                 if (RT_SUCCESS(rc))
    172                 {
    173                     Assert(cbProcessed);
    174                     pThis->iSendQueueTail++;
    175                     pThis->iSendQueueTail &= CHAR_MAX_SEND_QUEUE_MASK;
    176                 }
    177                 else if (rc == VERR_TIMEOUT)
    178                 {
    179                     /* Normal case, just means that the stream didn't accept a new
    180                      * character before the timeout elapsed. Just retry. */
    181                     rc = VINF_SUCCESS;
    182                 }
    183                 else
    184                 {
    185                     LogFlow(("Write failed with %Rrc; skipping\n", rc));
    186                     break;
    187                 }
     173            size_t cbProcessed = 1;
     174
     175            rc = pThis->pDrvStream->pfnWrite(pThis->pDrvStream, &pThis->aSendQueue[pThis->iSendQueueTail], &cbProcessed);
     176            if (RT_SUCCESS(rc))
     177            {
     178                Assert(cbProcessed);
     179                pThis->iSendQueueTail++;
     180                pThis->iSendQueueTail &= CHAR_MAX_SEND_QUEUE_MASK;
     181            }
     182            else if (rc == VERR_TIMEOUT)
     183            {
     184                /* Normal case, just means that the stream didn't accept a new
     185                 * character before the timeout elapsed. Just retry. */
     186                rc = VINF_SUCCESS;
     187            }
     188            else
     189            {
     190                LogFlow(("Write failed with %Rrc; skipping\n", rc));
     191                break;
    188192            }
    189193        }
    190         else
    191             break;
    192     }
    193 
    194     pThis->SendThread = NIL_RTTHREAD;
     194    }
    195195
    196196    return VINF_SUCCESS;
     
    263263    }
    264264
    265     pThis->ReceiveThread = NIL_RTTHREAD;
    266 
    267265    return VINF_SUCCESS;
    268266}
     
    312310    PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
    313311
     312    /*
     313     * Tell the threads to shut down.
     314     */
    314315    pThis->fShutdown = true;
    315     if (pThis->ReceiveThread)
    316     {
    317         RTThreadWait(pThis->ReceiveThread, 1000, NULL);
    318         if (pThis->ReceiveThread != NIL_RTTHREAD)
    319             LogRel(("Char%d: receive thread did not terminate\n", pDrvIns->iInstance));
    320     }
    321 
    322     /* Empty the send queue */
    323     pThis->iSendQueueTail = pThis->iSendQueueHead = 0;
    324 
    325     RTSemEventSignal(pThis->SendSem);
    326     RTSemEventDestroy(pThis->SendSem);
    327     pThis->SendSem = NIL_RTSEMEVENT;
    328 
    329     if (pThis->SendThread)
    330     {
    331         RTThreadWait(pThis->SendThread, 1000, NULL);
    332         if (pThis->SendThread != NIL_RTTHREAD)
    333             LogRel(("Char%d: send thread did not terminate\n", pDrvIns->iInstance));
     316    if (pThis->SendSem != NIL_RTSEMEVENT)
     317    {
     318        RTSemEventSignal(pThis->SendSem);
     319        RTSemEventDestroy(pThis->SendSem);
     320        pThis->SendSem = NIL_RTSEMEVENT;
     321    }
     322
     323    /*
     324     * Wait for the threads.
     325     * ASSUMES that PDM destroys the driver chain from the the bottom and up.
     326     */
     327    if (pThis->ReceiveThread != NIL_RTTHREAD)
     328    {
     329        int rc = RTThreadWait(pThis->ReceiveThread, 300000, NULL);
     330        if (RT_SUCCESS(rc))
     331            pThis->ReceiveThread = NIL_RTTHREAD;
     332        else
     333            LogRel(("Char%d: receive thread did not terminate (%Rrc)\n", pDrvIns->iInstance, rc));
     334    }
     335
     336    if (pThis->SendThread != NIL_RTTHREAD)
     337    {
     338        int rc = RTThreadWait(pThis->SendThread, 30000, NULL);
     339        if (RT_SUCCESS(rc))
     340            pThis->SendThread = NIL_RTTHREAD;
     341        else
     342            LogRel(("Char%d: send thread did not terminate (%Rrc)\n", pDrvIns->iInstance, rc));
    334343    }
    335344}
     
    350359     * Init basic data members and interfaces.
    351360     */
     361    pThis->fShutdown                        = false;
    352362    pThis->ReceiveThread                    = NIL_RTTHREAD;
    353     pThis->fShutdown                        = false;
     363    pThis->SendThread                       = NIL_RTTHREAD;
     364    pThis->SendSem                          = NIL_RTSEMEVENT;
    354365    /* IBase. */
    355366    pDrvIns->IBase.pfnQueryInterface        = drvCharQueryInterface;
     
    383394    if (pThis->pDrvStream->pfnRead)
    384395    {
    385         rc = RTThreadCreate(&pThis->ReceiveThread, drvCharReceiveLoop, (void *)pThis, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "CharRecv");
     396        rc = RTThreadCreate(&pThis->ReceiveThread, drvCharReceiveLoop, (void *)pThis, 0,
     397                            RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "CharRecv");
    386398        if (RT_FAILURE(rc))
    387399            return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("Char#%d cannot create receive thread"), pDrvIns->iInstance);
     
    389401
    390402    rc = RTSemEventCreate(&pThis->SendSem);
    391     AssertRC(rc);
    392 
    393     rc = RTThreadCreate(&pThis->SendThread, drvCharSendLoop, (void *)pThis, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "CharSend");
     403    AssertRCReturn(rc, rc);
     404
     405    rc = RTThreadCreate(&pThis->SendThread, drvCharSendLoop, (void *)pThis, 0,
     406                        RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "CharSend");
    394407    if (RT_FAILURE(rc))
    395408        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("Char#%d cannot create send thread"), pDrvIns->iInstance);
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