VirtualBox

Changeset 70964 in vbox


Ignore:
Timestamp:
Feb 11, 2018 9:25:29 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
120809
Message:

Audio/HDA: Implemented separate timers for per audio stream to a) remove a lot of complexity when it comes to synchronizing data when recording and playing back at the same time and b) to make recording a lot smoother while playing back audio.

Location:
trunk/src/VBox/Devices
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/DevHDA.cpp

    r70931 r70964  
    99
    1010/*
    11  * Copyright (C) 2006-2017 Oracle Corporation
     11 * Copyright (C) 2006-2018 Oracle Corporation
    1212 *
    1313 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    504504 * Acquires the TM lock and HDA lock, returns on failure.
    505505 */
    506 #define DEVHDA_LOCK_BOTH_RETURN_VOID(a_pThis) \
     506#define DEVHDA_LOCK_BOTH_RETURN_VOID(a_pThis, a_SD) \
    507507    do { \
    508         int rcLock = TMTimerLock((a_pThis)->pTimer, VERR_IGNORED); \
     508        int rcLock = TMTimerLock((a_pThis)->pTimer[a_SD], VERR_IGNORED); \
    509509        if (rcLock != VINF_SUCCESS) \
    510510        { \
     
    516516        { \
    517517            AssertRC(rcLock); \
    518             TMTimerUnlock((a_pThis)->pTimer); \
     518            TMTimerUnlock((a_pThis)->pTimer[a_SD]); \
    519519            return; \
    520520        } \
     
    524524 * Acquires the TM lock and HDA lock, returns on failure.
    525525 */
    526 #define DEVHDA_LOCK_BOTH_RETURN(a_pThis, a_rcBusy) \
     526#define DEVHDA_LOCK_BOTH_RETURN(a_pThis, a_SD, a_rcBusy) \
    527527    do { \
    528         int rcLock = TMTimerLock((a_pThis)->pTimer, (a_rcBusy)); \
     528        int rcLock = TMTimerLock((a_pThis)->pTimer[a_SD], (a_rcBusy)); \
    529529        if (rcLock != VINF_SUCCESS) \
    530530            return rcLock; \
     
    533533        { \
    534534            AssertRC(rcLock); \
    535             TMTimerUnlock((a_pThis)->pTimer); \
     535            TMTimerUnlock((a_pThis)->pTimer[a_SD]); \
    536536            return rcLock; \
    537537        } \
     
    541541 * Releases the HDA lock and TM lock.
    542542 */
    543 #define DEVHDA_UNLOCK_BOTH(a_pThis) \
     543#define DEVHDA_UNLOCK_BOTH(a_pThis, a_SD) \
    544544    do { \
    545545        PDMCritSectLeave(&(a_pThis)->CritSect); \
    546         TMTimerUnlock((a_pThis)->pTimer); \
     546        TMTimerUnlock((a_pThis)->pTimer[a_SD]); \
    547547    } while (0)
    548548
     
    13061306{
    13071307#ifdef IN_RING3
    1308     DEVHDA_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_MMIO_WRITE);
     1308    /* Get the stream descriptor. */
     1309    const uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, CTL, iReg);
     1310
     1311    DEVHDA_LOCK_BOTH_RETURN(pThis, uSD, VINF_IOM_R3_MMIO_WRITE);
    13091312
    13101313    /*
     
    13191322    bool fReset    = RT_BOOL(u32Value & HDA_SDCTL_SRST);
    13201323    bool fInReset  = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_SDCTL_SRST);
    1321 
    1322     /* Get the stream descriptor. */
    1323     uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, CTL, iReg);
    13241324
    13251325    LogFunc(("[SD%RU8] fRun=%RTbool, fInRun=%RTbool, fReset=%RTbool, fInReset=%RTbool, %R[sdctl]\n",
     
    13381338        LogFunc(("[SD%RU8] Warning: Invalid stream tag %RU8 specified!\n", uSD, uTag));
    13391339
    1340         DEVHDA_UNLOCK_BOTH(pThis);
     1340        DEVHDA_UNLOCK_BOTH(pThis, uSD);
    13411341        return hdaRegWriteU24(pThis, iReg, u32Value);
    13421342    }
     
    14441444                AssertRC(rc2);
    14451445
    1446                 rc2 = hdaTimerSet(pThis, TMTimerGet(pThis->pTimer) + pStream->State.cTransferTicks, false /* fForce */);
     1446                rc2 = hdaTimerSet(pThis, pStream, TMTimerGet(pThis->pTimer[pStream->u8SD]) + pStream->State.cTransferTicks, false /* fForce */);
    14471447                AssertRC(rc2);
    14481448            }
     
    14721472    AssertRC(rc2);
    14731473
    1474     DEVHDA_UNLOCK_BOTH(pThis);
    1475 
     1474    DEVHDA_UNLOCK_BOTH(pThis, uSD);
    14761475    return VINF_SUCCESS; /* Always return success to the MMIO handler. */
    14771476#else  /* !IN_RING3 */
     
    14841483{
    14851484#ifdef IN_RING3
    1486     DEVHDA_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_MMIO_WRITE);
    1487 
    1488     PHDASTREAM pStream = hdaGetStreamFromSD(pThis, HDA_SD_NUM_FROM_REG(pThis, STS, iReg));
     1485    const uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, STS, iReg);
     1486
     1487    DEVHDA_LOCK_BOTH_RETURN(pThis, uSD, VINF_IOM_R3_MMIO_WRITE);
     1488
     1489    PHDASTREAM pStream = hdaGetStreamFromSD(pThis, uSD);
    14891490    if (!pStream)
    14901491    {
     
    14921493                         HDA_SD_NUM_FROM_REG(pThis, STS, iReg), u32Value));
    14931494
    1494         DEVHDA_UNLOCK_BOTH(pThis);
     1495        DEVHDA_UNLOCK_BOTH(pThis, uSD);
    14951496        return hdaRegWriteU16(pThis, iReg, u32Value);
    14961497    }
     
    15401541#endif
    15411542
    1542     const uint64_t tsNow = TMTimerGet(pThis->pTimer);
     1543    const uint64_t tsNow = TMTimerGet(pThis->pTimer[uSD]);
    15431544    Assert(tsNow >= pStream->State.tsTransferLast);
    15441545
     
    15681569            LogRelMax2(64, ("HDA: Stream #%RU8 interrupt lagging behind (expected %uus, got %uus), trying to catch up ...\n",
    15691570                            pStream->u8SD,
    1570                             (TMTimerGetFreq(pThis->pTimer) / pThis->u16TimerHz) / 1000, (tsNow - pStream->State.tsTransferLast) / 1000));
     1571                            (TMTimerGetFreq(pThis->pTimer[pStream->u8SD]) / pThis->u16TimerHz) / 1000,(tsNow - pStream->State.tsTransferLast) / 1000));
    15711572
    15721573            cTicksToNext = 0;
     
    15871588
    15881589            /* Re-arm the timer. */
    1589             hdaTimerSet(pThis, tsNow + cTicksToNext, false /* fForce */);
     1590            LogFunc(("Timer set SD%RU8\n", pStream->u8SD));
     1591            hdaTimerSet(pThis, pStream, tsNow + cTicksToNext, false /* fForce */);
    15901592        }
    15911593    }
     
    15931595    hdaStreamUnlock(pStream);
    15941596
    1595     DEVHDA_UNLOCK_BOTH(pThis);
     1597    DEVHDA_UNLOCK_BOTH(pThis, uSD);
    15961598    return VINF_SUCCESS;
    15971599#else /* IN_RING3 */
     
    27822784
    27832785/**
    2784  * Main routine for the device timer.
     2786 * Main routine for the stream's timer.
    27852787 *
    2786  * @param   pThis               HDA state.
    2787  */
    2788 static void hdaTimerMain(PHDASTATE pThis)
    2789 {
    2790     AssertPtrReturnVoid(pThis);
    2791 
    2792     STAM_PROFILE_START(&pThis->StatTimer, a);
    2793 
    2794     DEVHDA_LOCK_BOTH_RETURN_VOID(pThis);
    2795 
    2796     /* Do all transfers from/to DMA. */
    2797     hdaDoTransfers(pThis);
     2788 * @param   pDevIns             Device instance.
     2789 * @param   pTimer              Timer this callback was called for.
     2790 * @param   pvUser              Pointer to associated HDASTREAM.
     2791 */
     2792DECLCALLBACK(void) hdaTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
     2793{
     2794    RT_NOREF(pDevIns, pTimer);
     2795
     2796    PHDASTREAM pStream = (PHDASTREAM)pvUser;
     2797    AssertPtr(pStream);
     2798
     2799    PHDASTATE  pThis   = pStream->pHDAState;
     2800
     2801    DEVHDA_LOCK_BOTH_RETURN_VOID(pStream->pHDAState, pStream->u8SD);
     2802
     2803    hdaStreamUpdate(pStream, true /* fInTimer */);
    27982804
    27992805    /* Flag indicating whether to kick the timer again for a
    28002806     * new data processing round. */
    2801     bool fSinksActive = false;
    2802 
    2803     /* Do we need to kick the timer again? */
    2804     if (   AudioMixerSinkIsActive(pThis->SinkFront.pMixSink)
    2805 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
    2806         || AudioMixerSinkIsActive(pThis->SinkCenterLFE.pMixSink)
    2807         || AudioMixerSinkIsActive(pThis->SinkRear.pMixSink)
    2808 #endif
    2809         || AudioMixerSinkIsActive(pThis->SinkLineIn.pMixSink)
    2810 #ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
    2811         || AudioMixerSinkIsActive(pThis->SinkMicIn.pMixSink)
    2812 #endif
    2813         )
    2814     {
    2815         fSinksActive = true;
    2816     }
    2817 
    2818     bool fTimerScheduled = false;
    2819     if (   hdaStreamTransferIsScheduled(hdaGetStreamFromSink(pThis, &pThis->SinkFront))
    2820 #ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
    2821         || hdaStreamTransferIsScheduled(hdaGetStreamFromSink(pThis, &pThis->SinkMicIn))
    2822 #endif
    2823         || hdaStreamTransferIsScheduled(hdaGetStreamFromSink(pThis, &pThis->SinkLineIn)))
    2824     {
    2825         fTimerScheduled = true;
    2826     }
    2827 
    2828     Log3Func(("fSinksActive=%RTbool, fTimerScheduled=%RTbool\n", fSinksActive, fTimerScheduled));
    2829 
    2830     if (    fSinksActive
     2807    const bool fSinkActive     = AudioMixerSinkIsActive(pStream->pMixSink->pMixSink);
     2808    const bool fTimerScheduled = hdaStreamTransferIsScheduled(pStream);
     2809
     2810    Log3Func(("fSinksActive=%RTbool, fTimerScheduled=%RTbool\n", fSinkActive, fTimerScheduled));
     2811
     2812    if (    fSinkActive
    28312813        && !fTimerScheduled)
    28322814    {
    2833         hdaTimerSet(pThis, TMTimerGet(pThis->pTimer) + TMTimerGetFreq(pThis->pTimer) / pThis->u16TimerHz, true /* fForce */);
    2834     }
    2835 
    2836     DEVHDA_UNLOCK_BOTH(pThis);
    2837 
    2838     STAM_PROFILE_STOP(&pThis->StatTimer, a);
     2815        hdaTimerSet(pThis, pStream,
     2816                    TMTimerGet(pThis->pTimer[pStream->u8SD]) + TMTimerGetFreq(pThis->pTimer[pStream->u8SD]) / pStream->pHDAState->u16TimerHz,
     2817                    true /* fForce */);
     2818    }
     2819
     2820    DEVHDA_UNLOCK_BOTH(pThis, pStream->u8SD);
    28392821}
    28402822
     
    30823064
    30833065/**
    3084  * Timer callback which handles the audio data transfers on a periodic basis.
    3085  *
    3086  * @param   pDevIns             Device instance.
    3087  * @param   pTimer              Timer which was used when calling this.
    3088  * @param   pvUser              User argument as PHDASTATE.
    3089  */
    3090 static DECLCALLBACK(void) hdaTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
    3091 {
    3092     RT_NOREF(pDevIns, pTimer);
    3093 
    3094     PHDASTATE pThis = (PHDASTATE)pvUser;
    3095     Assert(pThis == PDMINS_2_DATA(pDevIns, PHDASTATE));
    3096     AssertPtr(pThis);
    3097 
    3098     hdaTimerMain(pThis);
    3099 }
    3100 
    3101 /**
    31023066 * Main routine to perform the actual audio data transfers from the HDA streams
    31033067 * to the backend(s) and vice versa.
     
    36413605    int rc = VINF_SUCCESS;
    36423606
    3643     uint64_t tsExpire = 0; /* Timestamp of new timer expiration time / Whether to resume the device timer. */
    3644 
    36453607    /*
    36463608     * Enable all previously active streams.
     
    36793641                hdaStreamRegisterDMAHandlers(pThis, pStream);
    36803642#endif
    3681                 /* Determine the earliest timing slot we need to use. */
    3682                 if (tsExpire)
    3683                     tsExpire = RT_MIN(tsExpire, hdaStreamTransferGetNext(pStream));
    3684                 else
    3685                     tsExpire = hdaStreamTransferGetNext(pStream);
    3686 
    3687                 Log2Func(("[SD%RU8] tsExpire=%RU64\n", pStream->u8SD, tsExpire));
     3643                if (hdaStreamTransferIsScheduled(pStream))
     3644                    hdaTimerSet(pThis, pStream, hdaStreamTransferGetNext(pStream), true /* fForce */);
    36883645
    36893646                /* Also keep track of the currently active streams. */
     
    36913648            }
    36923649        }
    3693     }
    3694 
    3695     /* Start the timer if one of the above streams were active during taking the saved state. */
    3696     if (tsExpire)
    3697     {
    3698         LogFunc(("Resuming timer at %RU64\n", tsExpire));
    3699         hdaTimerSet(pThis, tsExpire, true /* fForce */);
    37003650    }
    37013651
     
    51375087        for (uint8_t i = 0; i < HDA_MAX_STREAMS; ++i)
    51385088        {
     5089            /* Create the emulation timer (per stream).
     5090             *
     5091             * Note:  Use TMCLOCK_VIRTUAL_SYNC here, as the guest's HDA driver
     5092             *        relies on exact (virtual) DMA timing and uses DMA Position Buffers
     5093             *        instead of the LPIB registers.
     5094             */
     5095            char szTimer[16];
     5096            RTStrPrintf2(szTimer, sizeof(szTimer), "HDA SD%RU8", i);
     5097
     5098            rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, hdaTimer, &pThis->aStreams[i],
     5099                                        TMTIMER_FLAGS_NO_CRIT_SECT, szTimer, &pThis->pTimer[i]);
     5100            AssertRCReturn(rc, rc);
     5101
     5102            /* Use our own critcal section for the device timer.
     5103             * That way we can control more fine-grained when to lock what. */
     5104            rc = TMR3TimerSetCritSect(pThis->pTimer[i], &pThis->CritSect);
     5105            AssertRCReturn(rc, rc);
     5106
    51395107            rc = hdaStreamCreate(&pThis->aStreams[i], pThis, i /* u8SD */);
    51405108            AssertRC(rc);
     
    53265294                             ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
    53275295        }
    5328     }
    5329 
    5330     if (RT_SUCCESS(rc))
    5331     {
    5332         /* Create the emulation timer.
    5333          *
    5334          * Note:  Use TMCLOCK_VIRTUAL_SYNC here, as the guest's HDA driver
    5335          *        relies on exact (virtual) DMA timing and uses DMA Position Buffers
    5336          *        instead of the LPIB registers.
    5337          */
    5338         rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, hdaTimer, pThis,
    5339                                     TMTIMER_FLAGS_NO_CRIT_SECT, "HDA Timer", &pThis->pTimer);
    5340         AssertRCReturn(rc, rc);
    5341 
    5342         /* Use our own critcal section for the device timer.
    5343          * That way we can control more fine-grained when to lock what. */
    5344         rc = TMR3TimerSetCritSect(pThis->pTimer, &pThis->CritSect);
    5345         AssertRCReturn(rc, rc);
    53465296    }
    53475297
  • trunk/src/VBox/Devices/Audio/DevHDA.h

    r70252 r70964  
    55
    66/*
    7  * Copyright (C) 2016-2017 Oracle Corporation
     7 * Copyright (C) 2016-2018 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    157157    /** Number of active (running) SDn streams. */
    158158    uint8_t                            cStreamsActive;
    159     /** The timer for pumping data thru the attached LUN drivers. */
    160     PTMTIMERR3                         pTimer;
     159    /** The stream timers for pumping data thru the attached LUN drivers. */
     160    PTMTIMERR3                         pTimer[HDA_MAX_STREAMS];
    161161#ifdef VBOX_WITH_STATISTICS
    162162    STAMPROFILE                        StatTimer;
  • trunk/src/VBox/Devices/Audio/DevHDACommon.cpp

    r70295 r70964  
    55
    66/*
    7  * Copyright (C) 2017 Oracle Corporation
     7 * Copyright (C) 2017-2018 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    404404        /* Sanity checks. */
    405405        Assert(cbChunk <= pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff);
    406         Assert(cbChunk % pStream->State.cbFrameSize == 0);
    407         Assert((cbChunk >> 1) >= 1);
    408406
    409407        if (pStream->Dbg.Runtime.fEnabled)
     
    677675 * @returns Whether the new expiration time was set or not.
    678676 * @param   pThis               HDA state.
     677 * @param   pStream             HDA stream to set timer for.
    679678 * @param   tsExpire            New (virtual) expiration time to set.
    680679 * @param   fForce              Whether to force setting the expiration time or not.
     
    689688 *          Forcing a new expiration time will override the above mechanism.
    690689 */
    691 bool hdaTimerSet(PHDASTATE pThis, uint64_t tsExpire, bool fForce)
    692 {
    693     AssertPtr(pThis->pTimer);
     690bool hdaTimerSet(PHDASTATE pThis, PHDASTREAM pStream, uint64_t tsExpire, bool fForce)
     691{
     692    AssertPtr(pThis);
     693    AssertPtr(pStream);
    694694
    695695    uint64_t tsExpireMin = tsExpire;
     
    697697    if (!fForce)
    698698    {
    699         for (uint8_t i = 0; i < HDA_MAX_STREAMS; i++)
    700         {
    701             PHDASTREAM pStream = &pThis->aStreams[i];
    702 
    703             if (hdaStreamTransferIsScheduled(pStream))
    704                 tsExpireMin = RT_MIN(tsExpireMin, hdaStreamTransferGetNext(pStream));
    705         }
    706     }
    707 
    708     const uint64_t tsNow = TMTimerGet(pThis->pTimer);
     699        if (hdaStreamTransferIsScheduled(pStream))
     700            tsExpireMin = RT_MIN(tsExpireMin, hdaStreamTransferGetNext(pStream));
     701    }
     702
     703    AssertPtr(pThis->pTimer[pStream->u8SD]);
     704
     705#ifdef VBOX_STRICT
     706    const uint64_t tsNow = TMTimerGet(pThis->pTimer[pStream->u8SD]);
    709707
    710708    if (tsExpireMin < tsNow) /* Make sure to not go backwards in time. */
    711709        tsExpireMin = tsNow;
    712 
    713     Log3Func(("u64Epxire=%RU64 -> u64ExpireMin=%RU64, fForce=%RTbool [%s]\n",
    714               tsExpire, tsExpireMin, fForce, tsExpireMin == tsExpire ? "OK" : "DELAYED"));
    715 
    716     int rc2 = TMTimerSet(pThis->pTimer, tsExpireMin);
    717     AssertRC(rc2);
    718 
    719     return tsExpireMin == tsExpire;
     710#endif
     711
     712      int rc2 = TMTimerSet(pThis->pTimer[pStream->u8SD], tsExpireMin);
     713      AssertRC(rc2);
     714
     715    return true;
    720716}
    721717#endif /* IN_RING3 */
    722 
  • trunk/src/VBox/Devices/Audio/DevHDACommon.h

    r70250 r70964  
    55
    66/*
    7  * Copyright (C) 2016-2017 Oracle Corporation
     7 * Copyright (C) 2016-2018 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    636636 */
    637637#ifdef IN_RING3
    638 bool          hdaTimerSet(PHDASTATE pThis, uint64_t u64Expire, bool fForce);
     638bool          hdaTimerSet(PHDASTATE pThis, PHDASTREAM pStream, uint64_t u64Expire, bool fForce);
    639639#endif /* IN_RING3 */
    640640/** @} */
  • trunk/src/VBox/Devices/Audio/HDAStream.cpp

    r70933 r70964  
    55
    66/*
    7  * Copyright (C) 2017 Oracle Corporation
     7 * Copyright (C) 2017-2018 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    5353    pStream->pMixSink       = NULL;
    5454    pStream->pHDAState      = pThis;
     55    pStream->pTimer         = pThis->pTimer[u8SD];
     56    AssertPtr(pStream->pTimer);
    5557
    5658    pStream->State.fInReset = false;
     
    6062#endif
    6163
    62     int rc = RTCircBufCreate(&pStream->State.pCircBuf, _64K); /** @todo Make this configurable. */
    63     if (RT_SUCCESS(rc))
    64     {
    65         rc = hdaStreamPeriodCreate(&pStream->State.Period);
    66         if (RT_SUCCESS(rc))
    67             rc = RTCritSectInit(&pStream->State.CritSect);
    68     }
    69 
    70     int rc2;
     64    int rc = RTCritSectInit(&pStream->CritSect);
     65    AssertRCReturn(rc, rc);
     66
     67    rc = RTCircBufCreate(&pStream->State.pCircBuf, _64K); /** @todo Make this configurable. */
     68    AssertRCReturn(rc, rc);
     69
     70    rc = hdaStreamPeriodCreate(&pStream->State.Period);
     71    AssertRCReturn(rc, rc);
    7172
    7273#ifdef DEBUG
    73     rc2 = RTCritSectInit(&pStream->Dbg.CritSect);
    74     AssertRC(rc2);
     74    rc = RTCritSectInit(&pStream->Dbg.CritSect);
     75    AssertRCReturn(rc, rc);
    7576#endif
    7677
     
    8788
    8889        char szPath[RTPATH_MAX + 1];
    89         rc2 = DrvAudioHlpGetFileName(szPath, sizeof(szPath), pThis->Dbg.szOutPath, szFile,
    90                                      0 /* uInst */, PDMAUDIOFILETYPE_WAV, PDMAUDIOFILENAME_FLAG_NONE);
     90        int rc2 = DrvAudioHlpGetFileName(szPath, sizeof(szPath), pThis->Dbg.szOutPath, szFile,
     91                                         0 /* uInst */, PDMAUDIOFILETYPE_WAV, PDMAUDIOFILENAME_FLAG_NONE);
    9192        AssertRC(rc2);
    9293        rc2 = DrvAudioHlpFileCreate(PDMAUDIOFILETYPE_WAV, szPath, PDMAUDIOFILE_FLAG_NONE, &pStream->Dbg.Runtime.pFileStream);
     
    133134#endif
    134135
    135     if (RTCritSectIsInitialized(&pStream->State.CritSect))
    136     {
    137         rc2 = RTCritSectDelete(&pStream->State.CritSect);
     136    if (RTCritSectIsInitialized(&pStream->CritSect))
     137    {
     138        rc2 = RTCritSectDelete(&pStream->CritSect);
    138139        AssertRC(rc2);
    139140    }
     
    366367        pStream->State.cbDMALeft                  = 0;
    367368
    368         const uint64_t cTicksPerHz = TMTimerGetFreq(pThis->pTimer) / pThis->u16TimerHz;
     369        const uint64_t cTicksPerHz = TMTimerGetFreq(pStream->pTimer) / pThis->u16TimerHz;
    369370
    370371        /* Calculate the timer ticks per byte for this stream. */
     
    374375        /* Calculate timer ticks per transfer. */
    375376        pStream->State.cTransferTicks     = pStream->State.cbTransferChunk * pStream->State.cTicksPerByte;
     377        Assert(pStream->State.cTransferTicks);
    376378
    377379        /* Initialize the transfer timestamps. */
     
    626628    AssertPtrReturn(pStream->pHDAState, false);
    627629
     630    const uint64_t tsNow = TMTimerGet(pStream->pTimer);
     631
    628632    const bool fScheduled =    pStream->State.fRunning
    629633                            && (   pStream->State.cTransferPendingInterrupts
    630                                 || pStream->State.tsTransferNext > TMTimerGet(pStream->pHDAState->pTimer));
    631 
    632     Log3Func(("[SD%RU8] tsTransferNext=%RU64, cTransferPendingInterrupts=%RU8 -> %RTbool\n",
    633               pStream->u8SD, pStream->State.tsTransferNext, pStream->State.cTransferPendingInterrupts, fScheduled));
     634                                || pStream->State.tsTransferNext > tsNow);
     635
     636#ifdef LOG_ENABLED
     637    if (fScheduled)
     638    {
     639        if (pStream->State.cTransferPendingInterrupts)
     640            Log3Func(("[SD%RU8] Scheduled (%RU8 IRQs pending)\n",
     641                      pStream->u8SD, pStream->State.cTransferPendingInterrupts));
     642        else
     643            Log3Func(("[SD%RU8] Scheduled in %RU64\n",
     644                      pStream->u8SD, pStream->State.tsTransferNext - tsNow));
     645    }
     646#endif
    634647
    635648    return fScheduled;
     
    708721    }
    709722
     723    Log3Func(("cbWrittenTotal=%RU32\n", cbWrittenTotal));
     724
    710725    if (pcbWritten)
    711726        *pcbWritten = cbWrittenTotal;
     
    832847    }
    833848
    834     const uint64_t tsNow = TMTimerGet(pThis->pTimer);
     849    const uint64_t tsNow = TMTimerGet(pStream->pTimer);
    835850
    836851    if (!pStream->State.tsTransferLast)
     
    12191234        Log3Func(("[SD%RU8] Scheduling timer\n", pStream->u8SD));
    12201235
    1221         TMTimerUnlock(pThis->pTimer);
    1222 
    1223         hdaTimerSet(pThis, tsTransferNext, false /* fForce */);
    1224 
    1225         TMTimerLock(pThis->pTimer, VINF_SUCCESS);
     1236        TMTimerUnlock(pStream->pTimer);
     1237
     1238        LogFunc(("Timer set SD%RU8\n", pStream->u8SD));
     1239        hdaTimerSet(pStream->pHDAState, pStream, tsTransferNext, false /* fForce */);
     1240
     1241        TMTimerLock(pStream->pTimer, VINF_SUCCESS);
    12261242
    12271243        pStream->State.tsTransferNext = tsTransferNext;
     
    13241340    {
    13251341#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    1326         if (fInTimer)
     1342        if (!fInTimer)
    13271343        {
    13281344#endif
     
    13881404            }
    13891405        #endif
     1406#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
     1407        }
     1408        else /* fInTimer */
     1409        {
     1410#endif
     1411            const uint64_t tsNow = RTTimeMilliTS();
     1412            static uint64_t s_lasti = 0;
     1413            if (s_lasti == 0)
     1414                s_lasti = tsNow;
     1415
     1416            if (tsNow - s_lasti >= 10) /** @todo Fix this properly. */
     1417            {
     1418                rc2 = hdaStreamAsyncIONotify(pStream);
     1419                AssertRC(rc2);
     1420
     1421                s_lasti = tsNow;
     1422            }
    13901423
    13911424            const uint32_t cbToTransfer = hdaStreamGetUsed(pStream);
     
    13961429            }
    13971430#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    1398         } /* fInTimer */
     1431        }
    13991432#endif
    14001433    }
     
    14101443{
    14111444    AssertPtrReturnVoid(pStream);
    1412     int rc2 = RTCritSectEnter(&pStream->State.CritSect);
     1445    int rc2 = RTCritSectEnter(&pStream->CritSect);
    14131446    AssertRC(rc2);
    14141447}
     
    14231456{
    14241457    AssertPtrReturnVoid(pStream);
    1425     int rc2 = RTCritSectLeave(&pStream->State.CritSect);
     1458    int rc2 = RTCritSectLeave(&pStream->CritSect);
    14261459    AssertRC(rc2);
    14271460}
  • trunk/src/VBox/Devices/Audio/HDAStream.h

    r70594 r70964  
    55
    66/*
    7  * Copyright (C) 2017 Oracle Corporation
     7 * Copyright (C) 2017-2018 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    122122    /** Unused, padding. */
    123123    uint8_t                 Padding0[3];
    124     /** Critical section to serialize access. */
    125     RTCRITSECT              CritSect;
    126124#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    127125    /** Asynchronous I/O state members. */
     
    222220    /** Pointer to HDA sink this stream is attached to. */
    223221    R3PTRTYPE(PHDAMIXERSINK) pMixSink;
     222    /** The stream'S critical section to serialize access. */
     223    RTCRITSECT               CritSect;
     224    /** Pointer to the stream's timer. */
     225    PTMTIMERR3               pTimer;
    224226    /** Internal state of this stream. */
    225227    HDASTREAMSTATE           State;
     
    267269/** @} */
    268270
     271/** @name Timer functions.
     272 * @{
     273 */
     274DECLCALLBACK(void) hdaStreamTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser);
     275/** @} */
     276
     277
    269278/** @name Async I/O stream functions.
    270279 * @{
     
    282291
    283292#endif /* IN_RING3 */
    284 
    285293#endif /* !HDA_STREAM_H */
    286294
  • trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp

    r70013 r70964  
    18421842    GEN_CHECK_OFF(HDASTREAMSTATE, uCurBDLE);
    18431843    GEN_CHECK_OFF(HDASTREAMSTATE, fInReset);
    1844     GEN_CHECK_OFF(HDASTREAMSTATE, CritSect);
    18451844    GEN_CHECK_OFF(HDASTREAMSTATE, Mapping);
    18461845    GEN_CHECK_OFF(HDASTREAMSTATE, BDLE);
     
    18601859    GEN_CHECK_OFF(HDASTREAM, State);
    18611860    GEN_CHECK_OFF(HDASTREAM, Dbg);
     1861    GEN_CHECK_OFF(HDASTREAM, CritSect);
    18621862
    18631863    GEN_CHECK_SIZE(HDASTATE);
     
    18821882    GEN_CHECK_OFF(HDASTATE, fRCEnabled);
    18831883#ifndef VBOX_WITH_AUDIO_CALLBACKS
    1884     GEN_CHECK_OFF(HDASTATE, pTimer);
    18851884#endif
    18861885#ifdef VBOX_WITH_STATISTICS
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