# MacOS LockAudio patch, take 2:

**URL:** <https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298>\
**Category:** SDL Development\
**Created:** [March 27, 2002, 3:19pm UTC](https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298 "2002-03-27T15:19:00Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![icculus](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/icculus/32/81_2.png) [@icculus](https://discourse.libsdl.org/u/icculus)\
**Post date:** [March 27, 2002, 3:19pm UTC](https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298/1 "2002-03-27T15:19:00Z")

</div>

Okay, I cleaned up the patch, and it appears to run correctly now, but I haven’t tested it too heavily. I’ll need some Mac people to pound on this.

Debugging was exasperated by the fact that SDL\_mixer was calling SDL\_LockAudio() from it’s audio callback. Who could have introduced THAT stupid bug?! (_whistles_)

Anyhow, attached is a hopefully fully functional patch to SDL CVS for the Mac audio code and a patch to SDL\_mixer CVS to fix my dumbass bug.

Do not apply the previous patch; this one is better.

–ryan.

```
-------------- next part --------------
diff -u -r1.34 mixer.c
--- mixer.c	2002/01/14 19:35:45	1.34
+++ mixer.c	2002/03/27 23:05:00
@@ -41,6 +41,9 @@
 
 static int audio_opened = 0;
 
+/* rcg03272002 prevent SDL_LockAudio() calls from inside the audio callback. */
+static volatile int in_mixer_callback = 0;+
 static SDL_AudioSpec mixer;
 static SDL_mutex *mixer_lock;
 
@@ -148,6 +151,8 @@
 	int i, mixable, volume;
 	Uint32 sdl_ticks;
 
+	in_mixer_callback = 1;
+
 	/* Mix the music (must be done before the channels are added) */
 	if ( music_active || (mix_music != music_mixer) ) {
 		mix_music(music_data, stream, len);
@@ -236,6 +241,8 @@
 		mix_postmix(mix_postmix_data, stream, len);
 	}
 	SDL_mutexV(mixer_lock);
+
+	in_mixer_callback = 0;
 }
 
 static void PrintFormat(char *title, SDL_AudioSpec *fmt)
@@ -1137,7 +1144,9 @@
 		return(0);
 	}
 
-	SDL_LockAudio();
+	if (!in_mixer_callback)
+ SDL_LockAudio();
+
 	for (cur = *e; cur != NULL; cur = next) {
 		next = cur->next;
 		if (cur->done_callback != NULL) {
@@ -1146,7 +1155,9 @@
 		free(cur);
 	}
 	*e = NULL;
-	SDL_UnlockAudio();
+
+	if (!in_mixer_callback)
+ SDL_UnlockAudio();
 
 	return(1);
 }
-------------- next part --------------
diff -u -r1.13 SDL_audio.c
--- src/audio/SDL_audio.c	2002/03/06 11:23:02	1.13
+++ src/audio/SDL_audio.c	2002/03/27 23:01:59
@@ -503,6 +503,15 @@
 
 void SDL_LockAudio (void)
 {
+/*
+ * !!! FIXME: Ideally, a LockAudio function pointer should be part
+ * !!! FIXME: of the SDL_AudioDevice struct, even if most can just use a
+ * !!! FIXME: default implementation. --ryan.
+ */
+#if ((defined __MACOS__ ) || (defined __MACOSX__ ))
+	void SDL_LockAudio_MacOS(void);
+	SDL_LockAudio_MacOS();
+#else
 	SDL_AudioDevice *audio = current_audio;
 
 	/* Obtain a lock on the mixing buffers */
@@ -512,10 +521,20 @@
 		}
 		SDL_mutexP(audio->mixer_lock);
 	}
+#endif
 }
 
 void SDL_UnlockAudio (void)
 {
+/*
+ * !!! FIXME: Ideally, an UnlockAudio function pointer should be part
+ * !!! FIXME: of the SDL_AudioDevice struct, even if most can just use a
+ * !!! FIXME: default implementation. --ryan.
+ */
+#if ((defined __MACOS__ ) || (defined __MACOSX__ ))
+	void SDL_UnlockAudio_MacOS(void);
+	SDL_UnlockAudio_MacOS();
+#else
 	SDL_AudioDevice *audio = current_audio;
 
 	/* Release lock on the mixing buffers */
@@ -525,6 +544,7 @@
 		}
 		SDL_mutexV(audio->mixer_lock);
 	}
+#endif
 }
 
 void SDL_CloseAudio (void)
diff -u -r1.5 SDL_romaudio.c
--- src/audio/macrom/SDL_romaudio.c	2002/03/06 11:23:02	1.5
+++ src/audio/macrom/SDL_romaudio.c	2002/03/27 23:02:00
@@ -30,6 +30,7 @@
 #else
 # include <Sound.h> /* SoundManager interface */
 # include <Gestalt.h>
+# include <DriverServices.h>
 #endif
 
 #include <stdlib.h>
@@ -94,35 +95,20 @@
 	Audio_Available, Audio_CreateDevice
 };
 
-#if TARGET_API_MAC_CARBON
+#if 1 /*TARGET_API_MAC_CARBON*/
 
+#pragma options align=power
+
+static volatile SInt32 audio_is_locked = 0;
+static volatile SInt32 need_to_mix = 0;
+
 static UInt8 *buffer[2];
 static volatile UInt32 running = 0;
 static CmpSoundHeader header;
+static volatile Uint32 fill_me = 0;
 
-static void callBackProc (SndChannel *chan, SndCommand *cmd_passed ) {
-   
- UInt32 fill_me, play_me;
- SndCommand cmd; 
- SDL_AudioDevice *audio = (SDL_AudioDevice *)chan->userInfo;
-   
- fill_me = cmd_passed->param2; /* buffer that has just finished playing, so fill it */      
- play_me = ! fill_me; /* filled buffer to play _now_ */
-
- if ( ! audio->enabled ) {
- return;
- }
-   
- header.samplePtr = (Ptr)buffer[play_me];
-   
- cmd.cmd = bufferCmd;
- cmd.param1 = 0; 
- cmd.param2 = (long)&header;
-
- SndDoCommand (chan, &cmd, 0);
-   
- memset (buffer[fill_me], 0, audio->spec.size);
-   
+static void mix_buffer(SDL_AudioDevice *audio, UInt8 *buffer)
+{
    if ( ! audio->paused ) {
         if ( audio->convert.needed ) {
             #if MACOSX
@@ -139,29 +125,85 @@
                 /* Uh oh... probably crashes here; */
             }
 #endif
- memcpy(buffer[fill_me], audio->convert.buf,
- audio->convert.len_cvt);
+ memcpy(buffer, audio->convert.buf, audio->convert.len_cvt);
         } else {
             #if MACOSX
                 SDL_mutexP(audio->mixer_lock);
             #endif
- audio->spec.callback(audio->spec.userdata,
- (Uint8 *)buffer[fill_me], audio->spec.size);
+ audio->spec.callback(audio->spec.userdata, buffer, audio->spec.size);
             #if MACOSX
                 SDL_mutexV(audio->mixer_lock);
             #endif
         }
     }
 
- if ( running ) {
+ DecrementAtomic((SInt32 *) &need_to_mix);
+}
+
+void SDL_LockAudio_MacOS(void)
+{
+ IncrementAtomic((SInt32 *) &audio_is_locked);
+}
+
+
+void SDL_UnlockAudio_MacOS(void)
+{
+ SInt32 oldval;
          
+ oldval = DecrementAtomic((SInt32 *) &audio_is_locked);
+ if ( oldval != 1 ) /* != 1 means audio is still locked. */
+ return;
+
+ /* Did we miss the chance to mix in an interrupt? Do it now. */
+ if ( BitAndAtomic (0xFFFFFFFF, &need_to_mix) ) {
+ /*
+ * Note that this could be a problem if you missed an interrupt
+ * while the audio was locked, and get preempted by a second
+ * interrupt here, but that means you locked for way too long anyhow.
+ */
+ mix_buffer (current_audio, buffer[fill_me]);
+ }
+}
+
+static void callBackProc (SndChannel *chan, SndCommand *cmd_passed ) {
+ UInt32 play_me;
+ SndCommand cmd; 
+ SDL_AudioDevice *audio = (SDL_AudioDevice *)chan->userInfo;
+
+ IncrementAtomic((SInt32 *) &need_to_mix);
+
+ fill_me = cmd_passed->param2; /* buffer that has just finished playing, so fill it */      
+ play_me = ! fill_me; /* filled buffer to play _now_ */
+
+ if ( ! audio->enabled ) {
+ return;
+ }
+   
+ /* queue previously mixed buffer for playback. */
+ header.samplePtr = (Ptr)buffer[play_me];
+ cmd.cmd = bufferCmd;
+ cmd.param1 = 0; 
+ cmd.param2 = (long)&header;
+ SndDoCommand (chan, &cmd, 0);
+
+ memset (buffer[fill_me], 0, audio->spec.size);
+
+ /*
+ * if audio device isn't locked, mix the next buffer to be queued in
+ * the memory block that just finished playing.
+ */
+ if ( ! BitAndAtomic(0xFFFFFFFF, &audio_is_locked) ) {
+ mix_buffer (audio, buffer[fill_me]);
+ } 
+
+ /* set this callback to run again when current buffer drains. */
+ if ( running ) {
       cmd.cmd = callBackCmd;
       cmd.param1 = 0;
       cmd.param2 = play_me;
    
       SndDoCommand (chan, &cmd, 0);
    }
-
 }
 
 static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec) {
@@ -170,7 +212,7 @@
    int sample_bits;
    int i;
    long initOptions;
-   
+      
    /* Very few conversions are required, but... */
     switch (spec->format) {
         case AUDIO_S8:
@@ -231,8 +273,7 @@
     }
     channel->userInfo = (long)this;
     channel->qLength = 128;
- if ( SndNewChannel(&channel, sampledSynth, initOptions, callback) !=
-noErr ) {
+ if ( SndNewChannel(&channel, sampledSynth, initOptions, callback) != noErr ) {
         SDL_SetError("Unable to create audio channel");
         free(channel);
         channel = NULL;
@@ -271,6 +312,17 @@
 }
 
 #else /* !TARGET_API_MAC_CARBON */
+
+void SDL_LockAudio_MacOS(void)
+{
+ /* no-op. */
+}
+
+void SDL_UnlockAudio_MacOS(void)
+{
+ /* no-op. */
+}
+
 
 /* This function is called by Sound Manager when it has exhausted one of
    the buffers, so we'll zero it to silence and fill it with audio if
```

---

<div class="post-metadata">

**Author:** ![Darrell\_Walisser](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/darrell_walisser/32/588_2.png) [@Darrell\_Walisser](https://discourse.libsdl.org/u/Darrell_Walisser)\
**Post date:** [March 27, 2002, 8:09pm UTC](https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298/2 "2002-03-27T20:09:02Z")

</div>

> Okay, I cleaned up the patch, and it appears to run correctly now, but I  
> haven’t tested it too heavily. I’ll need some Mac people to pound on this.

I did some quick unit tests and it appears to work so far. One should not  
hear any clicks or pops if the time between lock() and unlock() is smaller  
than the time to play the buffer, which seems to be the case:

for (i = 0; i \< 10; i++) {

SDL\_LockAudio();  
SDL\_Delay (185); // 22050 samples/sec with buffer size of 4096 samples  
// takes 185.76… ms to exhaust a buffer  
SDL\_UnlockAudio();  
}

With 185ms I listened for a few minutes and didn’t get any clicks or pops.  
With 186ms I got pops/clicks after 10s or so.  
Higher values produced pronounced clicks.  
Lower values did not cause clicks or pops.

The one issue (and a minor one at that) I’ve noticed is mentioned in the  
code - what is the correct thing to do when someone has locked for too  
long? The current code will send partially mixed audio, then if still  
locked after that buffer plays, you get silence. Or would it be better to  
send nothing at all or silence instead of that initial messed up buffer?  
I’m willing to live with the current implementation, but I thought I’d  
make note of this in case there was some predefined, undocumented behavior  
that other targets are using.

Besides this, looks great. Nice work Ryan ;-)On Wed, 27 Mar 2002, Ryan C. Gordon wrote:

---

<div class="post-metadata">

**Author:** ![icculus](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/icculus/32/81_2.png) [@icculus](https://discourse.libsdl.org/u/icculus)\
**Post date:** [March 27, 2002, 8:20pm UTC](https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298/3 "2002-03-27T20:20:00Z")

</div>

> The one issue (and a minor one at that) I’ve noticed is mentioned in the  
> code - what is the correct thing to do when someone has locked for too  
> long? The current code will send partially mixed audio, then if still  
> locked after that buffer plays, you get silence. Or would it be better to  
> send nothing at all or silence instead of that initial messed up buffer?  
> I’m willing to live with the current implementation, but I thought I’d  
> make note of this in case there was some predefined, undocumented behavior  
> that other targets are using.

My thought is that this method gives every possible chance to keep the  
audio sane; if you delay too long, you still might get most of your sound  
out (or all of it out, if your application’s callback beats the clock in  
SDL\_UnlockAudio), and, at worse, there’s silence written to the chip where  
one doesn’t beat the clock. I’m not married to the idea, if there’s a  
better solution.

> Besides this, looks great. Nice work Ryan 😉

Thanks for the idea in the first place. 🙂

–ryan.

---

<div class="post-metadata">

**Author:** ![slouken](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/s/ec9cab/32.png) [@slouken](https://discourse.libsdl.org/u/slouken)\
**Post date:** [March 27, 2002, 9:09pm UTC](https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298/4 "2002-03-27T21:09:02Z")

</div>

> Anyhow, attached is a hopefully fully functional patch to SDL CVS for the  
> Mac audio code and a patch to SDL\_mixer CVS to fix my dumbass bug.

Okay, is this good enough to apply to CVS replacing the existing code?  
I suppose I could go ahead and test it on my iBook. 🙂

Darrell, would you say this is production quality? Do we need new  
CarbonLib or anything for the atomic API calls?

See ya,  
-Sam Lantinga, Software Engineer, Blizzard Entertainment

---

<div class="post-metadata">

**Author:** ![Darrell\_Walisser](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/darrell_walisser/32/588_2.png) [@Darrell\_Walisser](https://discourse.libsdl.org/u/Darrell_Walisser)\
**Post date:** [March 27, 2002, 10:40pm UTC](https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298/5 "2002-03-27T22:40:01Z")

</div>

> > Anyhow, attached is a hopefully fully functional patch to SDL CVS for  
> > the  
> > Mac audio code and a patch to SDL\_mixer CVS to fix my dumbass bug.
> 
> Okay, is this good enough to apply to CVS replacing the existing code?  
> I suppose I could go ahead and test it on my iBook. 🙂

I think more rigorous testing is in order since we are dealing with an  
interrupt - if we have made a mistake we might crash/hang people’s  
systems.

> Darrell, would you say this is production quality?

I don’t know about production quality since I haven’t tested on any apps  
yet. I don’t have any/know of any apps that use SDL\_LockAudio (except  
for SDL\_Mixer, which worked fine before). Of course we modified things  
substantially so even code that doesn’t call this function deserves a  
once-over. I’m going to test with GLTron (doesn’t use locking) and  
perhaps dig up some old ports and see if they still work as well.

> Do we need new  
> CarbonLib or anything for the atomic API calls?

The calls used are DecrementAtomic() IncrementAtomic() and  
BitAndAtomic(), these all require Mac OS 8.5 or CarbonLib 1.0.

So we don’t need anything new, we just have to increase our system  
version requirement. If someone is really clever, they could  
find/write/hack the necessary PPC assembler for these routines.

-DOn Thursday, March 28, 2002, at 12:08 AM, Sam Lantinga wrote:

---

<div class="post-metadata">

**Author:** ![icculus](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/icculus/32/81_2.png) [@icculus](https://discourse.libsdl.org/u/icculus)\
**Post date:** [March 28, 2002, 1:36am UTC](https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298/6 "2002-03-28T01:36:00Z")

</div>

> Darrell, would you say this is production quality? Do we need new  
> CarbonLib or anything for the atomic API calls?

The Atomic stuff is supported in CarbonLib, but is part of  
DriverServicesLib, available since System 6, so that should be good to go.

–ryan.

---

<div class="post-metadata">

**Author:** ![icculus](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/icculus/32/81_2.png) [@icculus](https://discourse.libsdl.org/u/icculus)\
**Post date:** [March 28, 2002, 1:42am UTC](https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298/7 "2002-03-28T01:42:01Z")

</div>

> The calls used are DecrementAtomic() IncrementAtomic() and  
> BitAndAtomic(), these all require Mac OS 8.5 or CarbonLib 1.0.
> 
> So we don’t need anything new, we just have to increase our system  
> version requirement. If someone is really clever, they could  
> find/write/hack the necessary PPC assembler for these routines.

Wait, I’m retard; the calls aren’t available in System 6, like I just  
said. Apple technote 2006:

([Technotes | Apple Developer Documentation](http://developer.apple.com/technotes/tn/tn2006.html))

“All of the atomic operations originally introduced in DriverServicesLib  
(and exported by InterfaceLib since Mac OS 8.5) are MP-safe. Specifically,  
all of the routines declared in “DriverSynchronization.h” are MP-safe.”

That being said, the old double buffer code still exists, and  
_should_ work (albeit without locking). Perhaps we can check if atomic  
routines are available and drop back to the double buffer code on \< 8.5?

As for PowerPC assembly, this is also in technote 2006:

“WARNING:  
Do not use the PowerPC instructions Load Reserved (lwarx) and Store  
Conditional (stwcx) to implement atomicity in your preemptively threaded  
application. As described in DTS Technote 1137 Disabling Interrupts on the  
Traditional Mac OS, these instructions are non-portable and are tricky to  
use correctly across the full spectrum of PowerPC implementations.”

That being said, someone on a mac developer list sent me code to do just  
that (lwarx/stwcx), so if we’re brave, I’ve got it here.

–ryan.

---

<div class="post-metadata">

**Author:** ![Darrell\_Walisser](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/darrell_walisser/32/588_2.png) [@Darrell\_Walisser](https://discourse.libsdl.org/u/Darrell_Walisser)\
**Post date:** [March 28, 2002, 7:21am UTC](https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298/8 "2002-03-28T07:21:01Z")

</div>

> > So we don’t need anything new, we just have to increase our system  
> > version requirement. If someone is really clever, they could  
> > find/write/hack the necessary PPC assembler for these routines.
> 
> Wait, I’m retard; the calls aren’t available in System 6, like I just  
> said. Apple technote 2006:
> 
> ([Technotes | Apple Developer Documentation](http://developer.apple.com/technotes/tn/tn2006.html))
> 
> “All of the atomic operations originally introduced in DriverServicesLib  
> (and exported by InterfaceLib since Mac OS 8.5) are MP-safe.  
> Specifically,  
> all of the routines declared in “DriverSynchronization.h” are MP-safe.”

I think we both misinterpreted the docs. I think these functions are in  
earlier versions of Mac OS (I haven’t been able to find out just how  
early), but they are originally in DriverServicesLib. If we dynamically  
load the atomic functions from DriverServicesLib instead of linking them  
from InterfaceLib, this might increase our compatibility back to 8.0 or  
8.1. DriverServicesSynchronization.h says “Technology: Mac OS 8” which  
is what I’m basing this prediction on.

There is code to do just this in Matt Slot’s FastTimes implementation.

> That being said, the old double buffer code still exists, and  
> _should_ work (albeit without locking). Perhaps we can check if atomic  
> routines are available and drop back to the double buffer code on \< 8.5?

We can simply make the atomic functions a noop instead if we choose to  
use function pointers for them. Both versions (SndPlayDoubleBuffer() and  
bufferCmd) accomplish (practically) the exact same thing, so  
SoundPlayDoubleBuffer() could be scrapped.

> That being said, someone on a mac developer list sent me code to do just  
> that (lwarx/stwcx), so if we’re brave, I’ve got it here.

We probably don’t want to go down that road then. The solution I  
proposed above seems like a good tradeoff to me.

-DOn Thursday, March 28, 2002, at 04:45 AM, Ryan C. Gordon wrote:

---

<div class="post-metadata">

**Author:** ![slouken](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/s/ec9cab/32.png) [@slouken](https://discourse.libsdl.org/u/slouken)\
**Post date:** [March 28, 2002, 8:27am UTC](https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298/9 "2002-03-28T08:27:00Z")

</div>

> We probably don’t want to go down that road then. The solution I  
> proposed above seems like a good tradeoff to me.

Make it so.

```
-Sam Lantinga, Software Engineer, Blizzard Entertainment

```

---

<div class="post-metadata">

**Author:** ![Jason\_Hoffoss](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/j/a9adbd/32.png) [@Jason\_Hoffoss](https://discourse.libsdl.org/u/Jason_Hoffoss)\
**Post date:** [March 28, 2002, 8:58am UTC](https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298/10 "2002-03-28T08:58:00Z")

</div>

> > > We probably don’t want to go down that road then. The solution I  
> > > proposed above seems like a good tradeoff to me.
> > 
> > Make it so.
> 
> And don’t forget the hand gesture whenever you say “engage”.
> 
> > ----- Original Message -----  
> > From: [slouken@devolution.com](mailto:slouken@devolution.com) (Sam Lantinga)  
> > To:   
> > Sent: Thursday, March 28, 2002 11:26 AM  
> > Subject: Re: [SDL] MacOS LockAudio patch, take 2:

---

<div class="post-metadata">

**Author:** ![David\_Olofson](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/david_olofson/32/115_2.png) [@David\_Olofson](https://discourse.libsdl.org/u/David_Olofson)\
**Post date:** [March 28, 2002, 9:25am UTC](https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298/11 "2002-03-28T09:25:01Z")

</div>

Better in what way? It seems like your solution is just as good as that  
used by ALSA, which means that it’s way better than the “looping” that  
DirectX, OSS and many other APIs do when you’re late in memory mapped  
mode… Looks great.

Theoretically, the only solution that would be better is to implement an  
intelligent “click eliminator” that will attempt to “guess” what missing  
data should sound like. Basically analyze the frequency spectrum of all  
data from the callback, and then generate something similar when the  
callback cannot be used because audio is locked.

Obviously, that’s rather insanely heavy DSP stuff - and it doesn’t even  
really solve the problem!

Just never lock real time resources from non real time context. That’s  
all there is to it, if you want to make sure there are no drop-outs.  
There’s no way that SDL can “fix” broken applications.

//David Olofson — Programmer, Reologica Instruments AB

.- M A I A -------------------------------------------------.  
| Multimedia Application Integration Architecture |  
| A Free/Open Source Plugin API for Professional Multimedia |  
`----------------------------> http://www.linuxdj.com/maia -' .- David Olofson -------------------------------------------. | Audio Hacker - Open Source Advocate - Singer - Songwriter | `-------------------------------------\> [http://olofson.net](http://olofson.net) -'On Thursday 28 March 2002 05:23, Ryan C. Gordon wrote:

> > The one issue (and a minor one at that) I’ve noticed is mentioned in  
> > the code - what is the correct thing to do when someone has locked  
> > for too long? The current code will send partially mixed audio, then  
> > if still locked after that buffer plays, you get silence. Or would it  
> > be better to send nothing at all or silence instead of that initial  
> > messed up buffer? I’m willing to live with the current  
> > implementation, but I thought I’d make note of this in case there was  
> > some predefined, undocumented behavior that other targets are using.
> 
> My thought is that this method gives every possible chance to keep the  
> audio sane; if you delay too long, you still might get most of your  
> sound out (or all of it out, if your application’s callback beats the  
> clock in SDL\_UnlockAudio), and, at worse, there’s silence written to  
> the chip where one doesn’t beat the clock. I’m not married to the idea,  
> if there’s a better solution.

---

<div class="post-metadata">

**Author:** ![David\_Olofson](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/david_olofson/32/115_2.png) [@David\_Olofson](https://discourse.libsdl.org/u/David_Olofson)\
**Post date:** [March 28, 2002, 9:36am UTC](https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298/12 "2002-03-28T09:36:01Z")

</div>

[…]

> “WARNING:  
> Do not use the PowerPC instructions Load Reserved (lwarx) and Store  
> Conditional (stwcx) to implement atomicity in your preemptively  
> threaded application. As described in DTS Technote 1137 Disabling  
> Interrupts on the Traditional Mac OS, these instructions are  
> non-portable and are tricky to use correctly across the full spectrum  
> of PowerPC implementations.”
> 
> That being said, someone on a mac developer list sent me code to do  
> just that (lwarx/stwcx), so if we’re brave, I’ve got it here.

Do you really need those operations here? Are there more than two  
“threads” (main program + IRQ) involved?

(Tings like my lock-free FIFO, which is single-reader/single-writer, rely  
only on reads and writes of integers of a certain size being atomic.  
Atomic read-modify-write operations are not required.)

//David Olofson — Programmer, Reologica Instruments AB

.- M A I A -------------------------------------------------.  
| Multimedia Application Integration Architecture |  
| A Free/Open Source Plugin API for Professional Multimedia |  
`----------------------------> http://www.linuxdj.com/maia -' .- David Olofson -------------------------------------------. | Audio Hacker - Open Source Advocate - Singer - Songwriter | `-------------------------------------\> [http://olofson.net](http://olofson.net) -'On Thursday 28 March 2002 10:45, Ryan C. Gordon wrote:

---

<div class="post-metadata">

**Author:** ![icculus](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/icculus/32/81_2.png) [@icculus](https://discourse.libsdl.org/u/icculus)\
**Post date:** [March 28, 2002, 1:26pm UTC](https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298/13 "2002-03-28T13:26:01Z")

</div>

> We probably don’t want to go down that road then. The solution I  
> proposed above seems like a good tradeoff to me.

Agreed.

–ryan.

---

<div class="post-metadata">

**Author:** ![slouken](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/s/ec9cab/32.png) [@slouken](https://discourse.libsdl.org/u/slouken)\
**Post date:** [March 30, 2002, 11:32am UTC](https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298/14 "2002-03-30T11:32:01Z")

</div>

> Debugging was exasperated by the fact that SDL\_mixer was calling  
> SDL\_LockAudio() from it’s audio callback. Who could have introduced THAT  
> stupid bug?! (_whistles_)

There’s a race condition in your SDL\_mixer patch.

Step 1. The mixer callback runs, setting in\_mixer\_callback to 1.  
Step 2. The app code runs, sees in\_mixer\_callback, and doesn’t lock audio  
Step 3. Both the mixer and the app are stomping on effects data. 🙂

What you probably want to do is pass a parameter to an internal function  
and call that with in\_mixer == false from the API function.

I’m backing out your patch for now…

```
-Sam Lantinga, Software Engineer, Blizzard Entertainment

```

---

<div class="post-metadata">

**Author:** ![slouken](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/s/ec9cab/32.png) [@slouken](https://discourse.libsdl.org/u/slouken)\
**Post date:** [March 30, 2002, 12:08pm UTC](https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298/15 "2002-03-30T12:08:01Z")

</div>

> Okay, I cleaned up the patch, and it appears to run correctly now, but I  
> haven’t tested it too heavily. I’ll need some Mac people to pound on this.

I’ve moved the lock/unlock functions into the driver (with the old code  
as a default implementation), updated your patch to reflect that, and  
comitted it to CVS.

The atomic variable stuff should work instead of thread locking on MacOS X,  
right?

I’ll be running basic tests shortly. 🙂

Thanks!  
-Sam Lantinga, Software Engineer, Blizzard Entertainment

---

<div class="post-metadata">

**Author:** ![Darrell\_Walisser](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/darrell_walisser/32/588_2.png) [@Darrell\_Walisser](https://discourse.libsdl.org/u/Darrell_Walisser)\
**Post date:** [March 30, 2002, 1:35pm UTC](https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298/16 "2002-03-30T13:35:01Z")

</div>

> > Okay, I cleaned up the patch, and it appears to run correctly now, but I  
> > haven’t tested it too heavily. I’ll need some Mac people to pound on this.
> 
> I’ve moved the lock/unlock functions into the driver (with the old code  
> as a default implementation), updated your patch to reflect that, and  
> comitted it to CVS.
> 
> The atomic variable stuff should work instead of thread locking on MacOS X,  
> right?

Yep.On Sat, 30 Mar 2002, Sam Lantinga wrote:

---

<div class="post-metadata">

**Author:** ![Darrell\_Walisser](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/darrell_walisser/32/588_2.png) [@Darrell\_Walisser](https://discourse.libsdl.org/u/Darrell_Walisser)\
**Post date:** [March 30, 2002, 1:42pm UTC](https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298/17 "2002-03-30T13:42:01Z")

</div>

> > Debugging was exasperated by the fact that SDL\_mixer was calling  
> > SDL\_LockAudio() from it’s audio callback. Who could have introduced THAT  
> > stupid bug?! (_whistles_)
> 
> There’s a race condition in your SDL\_mixer patch.
> 
> Step 1. The mixer callback runs, setting in\_mixer\_callback to 1.  
> Step 2. The app code runs, sees in\_mixer\_callback, and doesn’t lock audio  
> Step 3. Both the mixer and the app are stomping on effects data. 🙂
> 
> What you probably want to do is pass a parameter to an internal function  
> and call that with in\_mixer == false from the API function.

Maybe I’m confused here, but I think that this can’t happen because the  
app can’t preempt the callback (On OS 9, on OS X it can).

I forgot about this point in my previous message, we should keep using  
the mutexes for Mac OS X unless you’ve already changed the code to remedy  
this.

Cheers,  
DarrellOn Sat, 30 Mar 2002, Sam Lantinga wrote:

---

<div class="post-metadata">

**Author:** ![slouken](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/s/ec9cab/32.png) [@slouken](https://discourse.libsdl.org/u/slouken)\
**Post date:** [March 30, 2002, 1:48pm UTC](https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298/18 "2002-03-30T13:48:01Z")

</div>

> > There’s a race condition in your SDL\_mixer patch.
> > 
> > Step 1. The mixer callback runs, setting in\_mixer\_callback to 1.  
> > Step 2. The app code runs, sees in\_mixer\_callback, and doesn’t lock audio  
> > Step 3. Both the mixer and the app are stomping on effects data. 🙂
> > 
> > What you probably want to do is pass a parameter to an internal function  
> > and call that with in\_mixer == false from the API function.

> Maybe I’m confused here, but I think that this can’t happen because the  
> app can’t preempt the callback (On OS 9, on OS X it can).

This is not a Mac-specific comment - it deals with any of the SDL audio  
implementations.

> I forgot about this point in my previous message, we should keep using  
> the mutexes for Mac OS X unless you’ve already changed the code to remedy  
> this.

Erm… Ryan? Should we use the default lock/unlock calls on MacOS X?

```
-Sam Lantinga, Software Engineer, Blizzard Entertainment

```

---

<div class="post-metadata">

**Author:** ![icculus](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/icculus/32/81_2.png) [@icculus](https://discourse.libsdl.org/u/icculus)\
**Post date:** [March 30, 2002, 2:26pm UTC](https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298/19 "2002-03-30T14:26:01Z")

</div>

> This is not a Mac-specific comment - it deals with any of the SDL audio  
> implementations.

(Doh!)

Yeah, that was stupid of me. I’ll write a cleaner SDL\_mixer patch tonight.

> > I forgot about this point in my previous message, we should keep using  
> > the mutexes for Mac OS X unless you’ve already changed the code to remedy  
> > this.
> 
> Erm… Ryan? Should we use the default lock/unlock calls on MacOS X?

You’re asking the wrong guy here, but my assumption was that the  
non-default stuff was only absolutely needed for the MacOS Classic target.  
Then again, if it works on OS X, that’s a couple less ifdefs we need.

I’ll bow to Darrell’s better judgement on this one, because I’m really not  
certain.

–ryan.

---

<div class="post-metadata">

**Author:** ![Robert\_Sadedin](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/r/41988e/32.png) [@Robert\_Sadedin](https://discourse.libsdl.org/u/Robert_Sadedin)\
**Post date:** [March 30, 2002, 4:43pm UTC](https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298/20 "2002-03-30T16:43:00Z")

</div>

Hey dude.  
Just back.  
Had a pretty ordinary night.  
I’d drunk too much and got too stoned with Damien on Friday (and haven’t  
done that for about eight months before), so last night I felt sick and  
bored.  
Got in about half an hour ago, and had a minor emergency when I found out  
that Rocket Rat had escaped somewhere. Found her eventually snuggled up  
peacefully in the bottom of the sock drawer.

I think I shall pike on the footy. It’s just too damned expensive for me,  
and I think I’ll try and get rid of the final Deep Wars bug I’m aware of  
(I’m sure we can find more :), of course).  
I shall give you a call in ten minutes, anway.

Hmmm … Actually, is your phone number 95303410?

If it isn’t, you won’t get a call from me, and had better call instead :)\> ----- Original Message -----

> From: [slouken@devolution.com](mailto:slouken@devolution.com) (Sam Lantinga)  
> To:   
> Sent: Sunday, March 31, 2002 7:46 AM  
> Subject: Re: [SDL] MacOS LockAudio patch, take 2:
> 
> > > > There’s a race condition in your SDL\_mixer patch.
> > > > 
> > > > Step 1. The mixer callback runs, setting in\_mixer\_callback to 1.  
> > > > Step 2. The app code runs, sees in\_mixer\_callback, and doesn’t lock  
> > > > audio  
> > > > Step 3. Both the mixer and the app are stomping on effects data. 🙂
> > > > 
> > > > What you probably want to do is pass a parameter to an internal  
> > > > function  
> > > > and call that with in\_mixer == false from the API function.
> > 
> > > Maybe I’m confused here, but I think that this can’t happen because the  
> > > app can’t preempt the callback (On OS 9, on OS X it can).
> > 
> > This is not a Mac-specific comment - it deals with any of the SDL audio  
> > implementations.
> > 
> > > I forgot about this point in my previous message, we should keep using  
> > > the mutexes for Mac OS X unless you’ve already changed the code to  
> > > remedy  
> > > this.
> > 
> > Erm… Ryan? Should we use the default lock/unlock calls on MacOS X?
> > 
> > -Sam Lantinga, Software Engineer, Blizzard Entertainment
> > 
> > * * *
> > 
> > SDL mailing list  
> > SDL at [libsdl.org](http://libsdl.org)  
> > [http://www.libsdl.org/mailman/listinfo/sdl](http://www.libsdl.org/mailman/listinfo/sdl)

[Next page](https://discourse.libsdl.org/t/macos-lockaudio-patch-take-2/6298.md?page=2)
