MacOS LockAudio patch, take 2:

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

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:

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 :wink:

Thanks for the idea in the first place. :slight_smile:

–ryan.

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. :slight_smile:

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

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. :slight_smile:

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:

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.

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:

(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.

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:

(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:

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

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 (Sam Lantinga)
To:
Sent: Thursday, March 28, 2002 11:26 AM
Subject: Re: [SDL] MacOS LockAudio patch, take 2:

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 -'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.

[…]

“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 -'On Thursday 28 March 2002 10:45, Ryan C. Gordon wrote:

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.

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. :slight_smile:

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

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. :slight_smile:

Thanks!
-Sam Lantinga, Software Engineer, Blizzard Entertainment

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:

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. :slight_smile:

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:

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. :slight_smile:

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

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.

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 (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. :slight_smile:

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://www.libsdl.org/mailman/listinfo/sdl