 |
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
| View previous topic :: View next topic |
| Author |
Message |
jesil
Joined: 17 Feb 2009 Posts: 10
|
Posted: Mon Jun 01, 2009 10:40 pm Post subject: Multi-thread in PSP failed . Need help |
|
|
Hi ,I am writing an game engine on psp. I need to play music in my game . So i study the mp3 sample in the PSPSDK wrote by raphael.
Then i want to create a thread to deal with playing music while i can do something else in the game. But when i start the thread , it freeze . I don't know why. Please if you counld help me.Here is my part of code .
| Code: |
PSP_MODULE_INFO("LevolAVG", 0, 1, 6);
PSP_MAIN_THREAD_ATTR(0);
PSP_HEAP_SIZE_KB(18*1024);
/* Exit callback */
int exit_callback(int arg1, int arg2, void *common)
{
sceKernelExitGame();
return 0;
}
int CallbackThread(SceSize args, void *argp)
{
int cbid;
cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
sceKernelRegisterExitCallback(cbid);
sceKernelSleepThreadCB();
return 0;
}
/* Sets up the callback thread and returns its thread id */
int SetupCallbacks(void)
{
int thid = 0;
thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0x3F40, 0, 0);
if(thid >= 0)
{
sceKernelStartThread(thid, 0, 0);
}
return thid;
}
//Functions Definition and Variables Delaration
void show_menu(void);
void show_menu(void)
{
printf("Press circle to load a imge\n");
}
int main()
{
int errorInteger=0;
pspDebugScreenInit();
SetupCallbacks();
sceDisplaySetMode(0, SCREEN_WIDTH, SCREEN_HEIGHT);
EnableGU();
errorInteger=FreeTypeInitial();
if ( errorInteger == 0 )
{
ERRORMSG("Error Error in FreeTypeInitial\n");
}
errorInteger = MovieInitial();
if (errorInteger == 0)
{
ERRORMSG("Error in Movie Initial\n");
}
ScriptFlow("my.txt");
sceKernelSleepThread();
return 0;
}
|
The code above is my main thread. while in the ScriptFlow functions ,i start the thread as follows.
| Code: |
myAvgThread->MusicPlayThread=sceKernelCreateThread("playmusic",PlayMusicThread,0x8,0x10000,0,0);
if(myAvgThread->MusicPlayThread < 0)
{
ERRORMSG("ERROR: creat startPlay thread failed returned 0x%08X\n", myAvgThread->MusicPlayThread);
}
sceKernelStartThread(myAvgThread->MusicPlayThread,4,&myAvgThread);
sceKerneSleepThread();
|
It can play music but my program freeze.I can not do anything else while listening to the music i Played. But indeed i want do some display actions while playing music.
So counld somebody tell me my fault in this program. |
|
| Back to top |
|
 |
Torch

Joined: 28 May 2008 Posts: 842
|
Posted: Mon Jun 01, 2009 11:36 pm Post subject: |
|
|
| Priority of 0x8 is very high. Try reducing it less than the main thread. Is your music thread delaying to allow other threads to execute? |
|
| Back to top |
|
 |
jesil
Joined: 17 Feb 2009 Posts: 10
|
Posted: Tue Jun 02, 2009 12:20 am Post subject: |
|
|
THX for Torch reply.
So it means in the PSP,it cannot run two threads at the same time .should i add scekerneldelaythread or other functions to delay music thread and let main thread run.
i ajust my code . and the new code are as follows :
| Code: |
int PlayMusicThread(SceSize input_lenth, void *input)
{
volatile AvgThread *myAvgThread = *((void**) input);
SceCtrlData pad;
SceUID fd;
int status;
sceCtrlSetSamplingCycle(0);
sceCtrlSetSamplingMode(0);
LoadMp3Module();
// Open the input file
fd = sceIoOpen( myAvgThread->filename, PSP_O_RDONLY, 0777 );
status = sceMp3InitResource();
if (status<0)
{
ERRORMSG("ERROR: sceMp3InitResource returned 0x%08X\n", status);
}
// Reserve a mp3 handle for our playback
SceMp3InitArg mp3Init;
mp3Init.mp3StreamStart = 0;
mp3Init.mp3StreamEnd = sceIoLseek32( fd, 0, SEEK_END );
mp3Init.unk1 = 0;
mp3Init.unk2 = 0;
mp3Init.mp3Buf = mp3Buf;
mp3Init.mp3BufSize = sizeof(mp3Buf);
mp3Init.pcmBuf = pcmBuf;
mp3Init.pcmBufSize = sizeof(pcmBuf);
SceInt32 handle = sceMp3ReserveMp3Handle( &mp3Init );
// Fill the stream buffer with some data so that sceMp3Init has something to work with
FillMp3StreamBuffer( fd, handle );
status = sceMp3Init( handle );
int channel = -1;
int samplingRate = sceMp3GetSamplingRate( handle );
int numChannels = sceMp3GetMp3ChannelNum( handle );
int lastDecoded = 0;
int volume = PSP_AUDIO_VOLUME_MAX;
int numPlayed = 0;
int paused = 0;
while (1)
{
if (!paused)
{
sceKernelDelayThread(100000);
// Check if we need to fill our stream buffer
if (sceMp3CheckStreamDataNeeded( handle )>0)
{
FillMp3StreamBuffer( fd, handle );
}
short* buf;
int bytesDecoded;
int retries = 0;
// We retry in case it's just that we reached the end of the stream and need to loop
for (retries = 0;retries<1;retries++)
{
bytesDecoded = sceMp3Decode( handle, &buf );
if (bytesDecoded>0)
break;
if (sceMp3CheckStreamDataNeeded( handle )<=0)
break;
if (!FillMp3StreamBuffer( fd, handle ))
{
numPlayed = 0;
}
}
// Nothing more to decode? Must have reached end of input buffer
if (bytesDecoded==0 || bytesDecoded==0x80671402)
{
paused = 1;
sceMp3ResetPlayPosition( handle );
//numPlayed = 0;
}
else
{
// Reserve the Audio channel for our output if not yet done
if (channel<0 || lastDecoded!=bytesDecoded)
{
if (channel>=0)
sceAudioSRCChRelease();
channel = sceAudioSRCChReserve( bytesDecoded/(2*numChannels), samplingRate, numChannels );
}
// Output the decoded samples and accumulate the number of played samples to get the playtime
sceAudioSRCOutputBlocking( volume, buf );
}
}
}
if (channel>=0)
sceAudioSRCChRelease();
status = sceMp3ReleaseMp3Handle( handle );
status = sceMp3TermResource();
status = sceIoClose( fd );
return 0;
}
|
I delete some debug information. I call scekerneldelaythread () in the music playing thread . and i change the music thread prioty to 45.
Now the program turns out to blink several times (which i think the delay of the music playing causes) and then freeze.
And could anybody help me for that problem.And is there any examples to explain how two threads run in the PSP.Thank you very much. |
|
| Back to top |
|
 |
jesil
Joined: 17 Feb 2009 Posts: 10
|
Posted: Tue Jun 02, 2009 3:47 pm Post subject: |
|
|
Ok it's me .Finally I figure it out .
We should call sceKernelDelayThread() to delay the current thread and let the thread which you want to start run. And in my Music playing thread . I should add delay time to a certain amount , and thus the thread can run perfectly. Maybe different threads demand different delay time ,depending on initialization of the functions .
So it is my experience .Wish it helps somebody . |
|
| Back to top |
|
 |
jesil
Joined: 17 Feb 2009 Posts: 10
|
Posted: Tue Jun 02, 2009 3:56 pm Post subject: |
|
|
| And in this mp3 playing thread ,it needs about 100000us delay |
|
| Back to top |
|
 |
Torch

Joined: 28 May 2008 Posts: 842
|
Posted: Tue Jun 02, 2009 4:08 pm Post subject: |
|
|
| jesil wrote: | | And in this mp3 playing thread ,it needs about 100000us delay |
That depends on how much audio is buffered. |
|
| Back to top |
|
 |
Devun_06
Joined: 17 Jun 2006 Posts: 15
|
Posted: Sun Jan 24, 2010 4:43 am Post subject: |
|
|
It is quite old, but this thread was my better option to gathering whether or not I may have had a thread issue, instead of opening an entire new one, since this may actually already have a solution to my problem.
| Code: |
PSP_MODULE_INFO("LevolAVG", 0, 1, 6);
PSP_MAIN_THREAD_ATTR(0);
PSP_HEAP_SIZE_KB(18*1024);
/* Exit callback */
int exit_callback(int arg1, int arg2, void *common)
{
sceKernelExitGame();
return 0;
}
int CallbackThread(SceSize args, void *argp)
{
int cbid;
cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
sceKernelRegisterExitCallback(cbid);
sceKernelSleepThreadCB();
return 0;
}
/* Sets up the callback thread and returns its thread id */
int SetupCallbacks(void)
{
int thid = 0;
thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0x3F40, 0, 0);
if(thid >= 0)
{
sceKernelStartThread(thid, 0, 0);
}
return thid;
}
//Functions Definition and Variables Delaration
void show_menu(void);
void show_menu(void)
{
printf("Press circle to load a imge\n");
}
int main()
{
int errorInteger=0;
pspDebugScreenInit();
SetupCallbacks();
sceDisplaySetMode(0, SCREEN_WIDTH, SCREEN_HEIGHT);
EnableGU();
errorInteger=FreeTypeInitial();
if ( errorInteger == 0 )
{
ERRORMSG("Error Error in FreeTypeInitial\n");
}
errorInteger = MovieInitial();
if (errorInteger == 0)
{
ERRORMSG("Error in Movie Initial\n");
}
ScriptFlow("my.txt");
sceKernelSleepThread();
return 0;
}
|
I added a phony identifier to jesil's ScriptFlow function below. Only for easing the comprehension strain.
| Code: |
void * ScriptFlow(char *)
{
myAvgThread->MusicPlayThread=sceKernelCreateThread("playmusic",PlayMusicThread,0x8,0x10000,0,0);
if(myAvgThread->MusicPlayThread < 0)
{
ERRORMSG("ERROR: creat startPlay thread failed returned 0x%08X\n", myAvgThread->MusicPlayThread);
}
sceKernelStartThread(myAvgThread->MusicPlayThread,4,&myAvgThread);
sceKerneSleepThread();
} |
| jesil wrote: | Ok it's me .Finally I figure it out .
We should call sceKernelDelayThread() to delay the current thread and let the thread which you want to start run. And in my Music playing thread . I should add delay time to a certain amount , and thus the thread can run perfectly. Maybe different threads demand different delay time ,depending on initialization of the functions .
So it is my experience .Wish it helps somebody . |
1.) Okay, so you effectively start the script flow, and then, immediately after it, you put the main thread into sleep mode.
2.) Next, you start another thread, the music thread, and launch it at a decently high priority to avoid anything near real-time. Then, you sleep the main thread again.
3.) As you continue, you then place a delay at a 10th less than a second, at every instance the separate music thread is NOT paused in the dead lock.
I also noticed your ScriptFlow() captures the error, and handles it. But, from how it seems, it quickly forgets the thread wasn't able to be started, and follows up on attempting to call a thread that wasn't created successfully.
So, are you saying that this is the proper threading technique?
| Code: |
int function thread();
void make thread();
void make thread()
{
create thread( function thread);
launch thread( function thread);
sleep main thread();
}
int function thread()
{
don't sleep function thread();
while(1)
{
delaythread(10000);
}
}
int main()
{
make thread();
sleep main thread again();
while(1)
{
delaythread(100000);
}
end program();
} |
I noticed you said delay to let the new thread run, so does that mean the main threads delay should come immediately after the launch thread(); where the main thread's sleep call is?
Now, I'm confused, why sleep the thread twice? By trial and error, you can adjust the delay to threads, but when you said you have to delay the primary thread, why is that if it's already placed in a subtle state such as sleep, or anything similar? If sleep isn't sufficient for that, what is the use of it? When would you wake the sleep thread? I think this is valuable information that may actually help me quite a bit, since your error seems a lot like my own at the moment.http://forums.ps2dev.org/viewtopic.php?p=87015#87015 |
|
| Back to top |
|
 |
Jim

Joined: 02 Jul 2005 Posts: 487 Location: Sydney
|
Posted: Sun Jan 24, 2010 8:40 am Post subject: |
|
|
Look up Cooperative Multitasking.
When a thread is running, nothing else[1] can run
When a thread sleeps, it's put on a queue for its priority level with a restart time of now+sleep time, and the next queued highest priority thread that is ready to run is restarted.
Every thread must play this game of running for a short time then sleeping for it to work.
So there is no 'sleep a thread twice in a row'. It just means it skips being scheduled and the next thread runs.
Jim
[1] there are exceptions, like interrupt handlers. _________________ http://www.dbfinteractive.com |
|
| Back to top |
|
 |
Devun_06
Joined: 17 Jun 2006 Posts: 15
|
Posted: Sun Jan 24, 2010 1:12 pm Post subject: |
|
|
| Jim wrote: | Look up Cooperative Multitasking.
When a thread is running, nothing else[1] can run
When a thread sleeps, it's put on a queue for its priority level with a restart time of now+sleep time, and the next queued highest priority thread that is ready to run is restarted.
Every thread must play this game of running for a short time then sleeping for it to work.
So there is no 'sleep a thread twice in a row'. It just means it skips being scheduled and the next thread runs.
Jim
[1] there are exceptions, like interrupt handlers. |
Thanks Jim, I took your advice, I reviewed plenty of documents, but of them all, the most useful I could find were these:
| Code: |
http://www.netrino.com/Embedded-Systems/How-To/RTOS-Preemption-Multitasking
http://en.wikipedia.org/wiki/Computer_multitasking
http://www.softvelocity.com/Clarion/pdf/Cooperative%20threading%20versus%20Preemptive%20threading.pdf
http://en.wikipedia.org/wiki/Thread_%28computer_science%29
http://c2.com/cgi/wiki$?CooperativeThreading
|
And the best, was :
http://wiki.tcl.tk/20153 It sucked on explaining the code itself, and doesn't look like C or or any language I've come across. But, at the least, it kindof gave a simple frame work to the design.
| Code: | load ./tcor.so
set cmd {
while 1 {
puts HELLO
tcor-yield
}
}
tcor-spawn $::cmd
while 1 {
puts MAIN
tcor-yield
after 1000
} |
Still though, none of them fully explained sleep, suspend, or any of the other terminology used int the pspthreadman.h library. Which, essentially, is getting me no where, all of the material I found basically reworded "FlatMush" at http://www.psp-programming.com/forums/index.php/topic,3820.0.html, but in poorer methods using way more words. Except http://www.netrino.com/Embedded-Systems/How-To/RTOS-Preemption-Multitasking gave a very good visual illustration, to explain another threading method including Interrupts.
It's proving quite hard to find, could someone point me to the best material they've found for this topic. I'd definitely love to read it, and follow up on my work.
Thanks a lot though Jim, I appreciate your assistance. I completely understand how the concept works, my only problem now though, is how do I implement it. Doing so, still is difficult to do since I haven't completely wrapped my brain around how you explained sleep. What do you mean by NOW TIME when you said NOW + SLEEP time, and by sleep time, do you mean the delay time? I don't recall sleep having a time-stamp, I'm assuming by your explanation that it only yields the CPU over to the next thread, right? Does sleep record, or set a time or anything?
EDIT:
I found a FANTASTIC source to follow, even better than a framework. I wouldn't have assumed the pspthreadman.h would be built to resemble Java like code. Thanks Jim, that was very helpful. I couldn't have found it without you telling me what the name of it was!
So, basically, the concept still flows completely, there is no actual sleep, just a delay(0), and now that the CPU has moved on, it won't go back till it's completed it's job with other threads next in line, threads with higher priority, or other threads yield with a delay or sleep themselves.
I'm going to assume that Sleep, and Delay(0) are the same.
Go Here: http://www.geom.uiuc.edu/~daeron/docs/javaguide/java/threads/states.html |
|
| Back to top |
|
 |
jesil
Joined: 17 Feb 2009 Posts: 10
|
Posted: Mon Jan 25, 2010 4:06 pm Post subject: |
|
|
Ok, i've read your problem,But i can just explain the few things you mentioned above.
Althougn psp support multithread working ,it doesn't mean that it can run two thread at the same time.When a thread is runing ,other threads can not make any function.The Other threads wait until the running thread delay. So you should always add "scekerneldelay(xxx)" in your thread to make other thread run. In my opinion,i call it suspend. SleepThread is not reqaired in my Project. |
|
| 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
|