|
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
View previous topic :: View next topic |
Author |
Message |
sakya
Joined: 28 Apr 2006 Posts: 190
|
Posted: Sat Jan 05, 2008 2:30 am Post subject: BUG in pspAudioLib |
|
|
Hi! :)
I think I found a bug in pspAudioLib.
This code just init and then end the audio lib but after two init-end the init fails (cannot create callback threads).
Code: | int main(){
int count = 0;
pspDebugScreenInit();
SetupCallbacks();
pspDebugScreenPrintf("Eboot test\n");
pspDebugScreenPrintf("Press X to run pspAudioInit and pspAudioEnd\n");
SceCtrlData pad;
while(runningFlag){
sceCtrlReadBufferPositive(&pad, 1);
if (pad.Buttons & PSP_CTRL_CROSS){
pspDebugScreenSetXY(0, 5);
pspDebugScreenPrintf("Count: %i\n", ++count);
if (pspAudioInit())
pspDebugScreenPrintf("pspAudioInit ERROR!!!\n");
else
pspAudioEnd();
}
sceKernelDelayThread(200000);
}
sceKernelExitGame();
return 0;
} |
The problem (I think) is that pspAudioEnd isn't really deleting threads (so when the maximum is reached the init fails).
I fixed this by just adding a "flag" in this structure
Code: | typedef struct {
int threadhandle;
int threadactive; <-- THIS
int handle;
int volumeleft;
int volumeright;
pspAudioCallback_t callback;
void *pdata;
} psp_audio_channelinfo; |
I changed the AudioChannelCallback to manage the new flag:
Code: | static int AudioChannelThread(int args, void *argp)
{
volatile int bufidx=0;
int channel=*(int *)argp;
AudioStatus[channel].threadactive = 1; <-- HERE
while (audio_terminate==0) {
void *bufptr=&audio_sndbuf[channel][bufidx];
pspAudioCallback_t callback;
callback=AudioStatus[channel].callback;
if (callback) {
callback(bufptr, PSP_NUM_AUDIO_SAMPLES, AudioStatus[channel].pdata);
} else {
unsigned int *ptr=bufptr;
int i;
for (i=0; i<PSP_NUM_AUDIO_SAMPLES; ++i) *(ptr++)=0;
}
pspAudioOutBlocking(channel,AudioStatus[channel].volumeleft,AudioStatus[channel].volumeright,bufptr);
bufidx=(bufidx?0:1);
}
AudioStatus[channel].threadactive = 0; <-- HERE
sceKernelExitThread(0);
return 0;
} |
and waited for this flag in pspAudioEnd before sceKernelDeleteThread:
Code: | void pspAudioEnd()
{
int i;
audio_ready=0;
audio_terminate=1;
for (i=0; i<PSP_NUM_AUDIO_CHANNELS; i++) {
if (AudioStatus[i].threadhandle != -1) {
//sceKernelWaitThreadEnd(AudioStatus[i].threadhandle,NULL);
while (AudioStatus[i].threadactive) <-- HERE
sceKernelDelayThread(100000);
sceKernelDeleteThread(AudioStatus[i].threadhandle);
}
AudioStatus[i].threadhandle = -1;
}
for (i=0; i<PSP_NUM_AUDIO_CHANNELS; i++) {
if (AudioStatus[i].handle != -1) {
sceAudioChRelease(AudioStatus[i].handle);
AudioStatus[i].handle = -1;
}
}
} |
There's surely a more elegant way to fix this bug. :)
EDIT: I see now this commented line:
Code: | sceKernelWaitThreadEnd(AudioStatus[i].threadhandle,NULL); |
If this does what I think (wait for the thread to end) it could fix the problem (maybe I'll try later).
Why is commented?
I dind't mention that I found the bug on 3.52M33-u4, with a kernel 3.x eboot.
Ciaooo
Sakya |
|
Back to top |
|
|
NineByNine
Joined: 18 Jul 2008 Posts: 2
|
Posted: Fri Jul 18, 2008 8:47 am Post subject: |
|
|
Apologies for resurrection of this ancient thread, but I found the same behaviour recently. It's only likely to cause trouble if you start and stop the pspaudiolib stuff a couple times, but it does cause trouble in this case. Full explanation: the pspAudioEnd() code sets the flag that is supposed to allow the audio thread to terminate gracefully (audio_terminate), but doesn't actually wait for the audio threads to exit, so the calls to sceKernelDeleteThread() fail (silently; the returns aren't checked), and eventually, if you start and stop the lib a few times, the dead threads pile up and calls to create new threads start to fail.
I'm guessing the call to sceKernelWaitThreadEnd(...) was commented out because if someone supplies a buggy callback which would itself hang the audio thread(s), and then called pspAudioEnd() to shutdown, the thread calling pspAudioEnd() would hang in the call. But it's a nuisance that piles up dead threads if you leave the call out.
I note there's also a pspAudioEndPre() defined, presumably for this purpose. Calling this first, then sleeping the calling thread (to allow the audio threads slice time to terminate gracefully), and *then* calling pspAudioEnd() should also work... But note it's not quite guaranteed; you have to count on the audio threads actually getting scheduled, and getting out of the way in time for your call to pspAudioEnd(). The sceKernelWaitThreadEnd() from pspAudioEnd() is much safer from that point of view (tho', of course, a risk with regard to callbacks hanging).
My solution was to create a second call in the lib (pspAudioEnd_patient()) that does wait for the thread exit. Works fine for my app. Just a suggestion. |
|
Back to top |
|
|
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Fri Jul 18, 2008 10:26 am Post subject: |
|
|
Or you could just start the audio lib at the start of your app and stop it at the end... you know, like EVERYONE else does. ;) |
|
Back to top |
|
|
NineByNine
Joined: 18 Jul 2008 Posts: 2
|
Posted: Fri Jul 18, 2008 11:02 am Post subject: |
|
|
J.F. wrote: | Or you could just start the audio lib at the start of your app and stop it at the end... you know, like EVERYONE else does. ;) |
... Or, y'know, the SDK could contain code that cleans up after itself properly. Like anyone would expect.
Seriously, the reason I do it that way is only because attempts to reset the sample frequency (to use the built in rates the sce calls support) once the lib was up and running failed. So I modified the lib to allow me to set the sample frequency at init; that works; init with the rate you want, shut down, init again for another stream with a different rate; it's all good that way, provided you make sure those threads get put away properly. I do expect to revisit the issue, see what I can do about resetting the frequency without tearing down and restarting the thread; I don't like that either. But still, I did find that issue doing that. So here's yer notice, for what it's worth to you. |
|
Back to top |
|
|
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Fri Jul 18, 2008 11:07 am Post subject: |
|
|
NineByNine wrote: | J.F. wrote: | Or you could just start the audio lib at the start of your app and stop it at the end... you know, like EVERYONE else does. ;) |
... Or, y'know, the SDK could contain code that cleans up after itself properly. Like anyone would expect.
Seriously, the reason I do it that way is only because attempts to reset the sample frequency (to use the built in rates the sce calls support) once the lib was up and running failed. So I modified the lib to allow me to set the sample frequency at init; that works; init with the rate you want, shut down, init again for another stream with a different rate; it's all good that way, provided you make sure those threads get put away properly. I do expect to revisit the issue, see what I can do about resetting the frequency without tearing down and restarting the thread; I don't like that either. But still, I did find that issue doing that. So here's yer notice, for what it's worth to you. |
Or you can use the same method to set the sample rate that sakya uses in LightMP3. Seriously, it sounds like you should be using his code instead of the audiolib anyway. Too many people use the audiolib who don't really need to. |
|
Back to top |
|
|
nemesis
Joined: 10 May 2009 Posts: 6
|
Posted: Sun Aug 02, 2009 4:09 pm Post subject: |
|
|
ok.. this crap took me hours of bugsearching where everything was fine.. thanks to sakya for this hint.. jeez why isn't this commited yet? |
|
Back to top |
|
|
jimparis
Joined: 10 Jun 2005 Posts: 1179 Location: Boston
|
Posted: Tue Aug 11, 2009 12:56 pm Post subject: |
|
|
Because you haven't provided a proper patch in the "Patch Submissions" forum. |
|
Back to top |
|
|
willow :--)
Joined: 13 Jan 2007 Posts: 126
|
Posted: Sun Jul 18, 2010 10:57 pm Post subject: |
|
|
I ran into the issue this week while working on Half Byte Loader.
Even though half byte loader needs to clean up the mess after applications, it would be good if something was done for this issue.
In my specific case the "guilty" homebrew was my own, so I was able to replace the call to pspAudioEnd() with
pspAudioEndPre()
sceKernelDelayThread(100000)
pspAudioEnd()
as suggested by NineByNine (which, granted, does not give any guarantee, but seemed to do the trick for now), but nevertheless I have to find a long term solution for HBL.
Of course fixing the SDK now will not fix the homebrews that already have the bug, so I still have to find an HBL specific solution, but that's just an additional post to say that it's bad to assume that all homebrews have the same use case of "pspaudioinit" "pspaudioend" getting called only once at the beginning and end of the application respectively.
HBL is an example of homebrew that doesn't fit in the "usual" case. _________________ Wagic. Play that card game against an AI on your PSP |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|