From: Rhythmic F. <rfi...@gm...> - 2006-01-25 00:31:37
|
On 1/25/06, skaller <sk...@us...> wrote: > On Tue, 2006-01-24 at 22:28 +1100, Rhythmic Fistman wrote: > > > Seriously, though - that sound mixing callback is asynchronous, > > so you'll have to felix threads executing concurrently. Won't > > that corrupt the garbage collector? > > How can it possibly be asynchronous? There's only two > ways that's possible: > > (a) driven from a signal > (b) operating in a pthread That's exactly how it is. grepping SDL src shows that most/all the implementations use threads to do audio. > Hard to know from the non-existent documentation ;( Have you looked? The SDL doco's great: libsdl.org -> Doc Project -> SDL API -> Audio. From http://www.libsdl.org/cgi/docwiki.cgi/SDL_5fOpenAudio """ his should be set to a function that will be called when the audio device is ready for more data. It is passed a pointer to the audio buffer, and the length in bytes of the audio buffer. This function usually runs in a separate thread, and so you should protect data structures that it accesses by calling SDL_LockAudio and SDL_UnlockAudio in your code. """ I've hacked the mac version of sdl100 to link and run, but it crashes in the mixing callback (with video disabled I get perfect sound). This could be a reentrancy problem. I don't know whether it's felix level or c++ level. If c++ SDL_LockAudio/ SDL_UnlockAudio *might* help, but I'm not sure where and when they would be called from. looks like src pointer is NULL Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_PROTECTION_FAILURE at address: 0x00000001 [Switching to process 17379 thread 0x7507] SDL_MixAudio (dst=3D0x1849800 "", src=3D0x0, len=3D20, volume=3D128) at SDL= _mixer.c:213 213 ADJUST_VOLUME(src1, volume); (gdb) bt #0 SDL_MixAudio (dst=3D0x1849800 "", src=3D0x0, len=3D20, volume=3D128) at SDL_mixer.c:213 #1 0x00004b94 in flxusr::sdl100::flx_mixaudio::resume () #2 0x00004110 in SDL_audio_callback () #3 0x0020a85c in audioCallback (inRefCon=3D0x44b8f0, inActionFlags=3D0, inTimeStamp=3D0x14, inBusNumber=3D128, ioData=3D0x4) at SDL_coreaudio.c:131 #4 0x9b53a3bc in DefaultOutputAUEntry () #5 0x9b605078 in dyld_stub__keymgr_get_and_lock_processwide_ptr () #6 0x9b604da8 in dyld_stub__keymgr_get_and_lock_processwide_ptr () #7 0x940f7e78 in AudioConverterChain::CallInputProc () #8 0x940f7ac8 in AudioConverterChain::FillBufferFromInputProc () #9 0x940f7290 in BufferedAudioConverter::GetInputBytes () #10 0x940f70e8 in CBRConverter::RenderOutput () #11 0x940f6e5c in BufferedAudioConverter::FillBuffer () #12 0x940f7a18 in BufferedInputAudioConverter::CallInputProc () #13 0x940f77d8 in BufferedInputAudioConverter::GetAllInputBytes () #14 0x940f7458 in Resampler2Wrapper::RenderOutput () #15 0x940f6e5c in BufferedAudioConverter::FillBuffer () #16 0x940f6fd8 in AudioConverterChain::RenderOutput () #17 0x940f6e5c in BufferedAudioConverter::FillBuffer () #18 0x940f6ce8 in AudioConverterFillComplexBuffer () #19 0x9b539fa4 in DefaultOutputAUEntry () #20 0x9b60490c in dyld_stub__keymgr_get_and_lock_processwide_ptr () #21 0x9b53be78 in DefaultOutputAUEntry () #22 0x9b539384 in DefaultOutputAUEntry () #23 0x91414ac8 in IOA_Device::CallIOProcs () #24 0x914147dc in HP_IOThread::PerformIO () #25 0x914127ec in HP_IOThread::WorkLoop () #26 0x91412354 in HP_IOThread::ThreadEntry () #27 0x914031d4 in CAPThread::Entry () #28 0x9002b200 in _pthread_body () Current language: auto; currently c [...] > and the clone procedure DOES call the gc: > > //PROC flx_mixaudio<2464>: Clone method > flx_mixaudio* flx_mixaudio::clone()const { > return new(*PTF gc,flx_mixaudio_ptr_map) flx_mixaudio(*this); > } > > which is BAD! You're right this could screw up if the callback > is invoked sequentially. > > The procedure itself is safe, it doesn't call the gc: That could easily changed if the callback were modified. Could there be a way to banish the gc from some parts of the code? [...] > > but that's just luck in this case :) > > SO -- some possible solutions: mark the procedure > > NOCLONE -- don't clone the procedure > > NOHEAP -- inline, stack call, or C call all calls, > bug out if not possible Right - way ahead of me. > Note this STILL leaves the problem asynchronous access > to user data: SDL_LockAudio and SDL_UnlockAudio solve > that but they cost. > > Another solution is to use .. GASP .. polling. > Here the callback copies some data in a fixed > location and sets a flag, and a Felix routine > polls that flag on a timeout, and fills the data, > then resets the flag. > > Of course this will NOT work if the callback > runs on another CPU than the polling routine, > since the caches won't be synchronised. So you're back to the equivalent of Lock/Unlock Audio. |