Hi Guys,
I am new to PSP development, and this is my first post here! Not to worry, I'm not a total newbie, as I've been programming C/C++ for several years already, along with x86 and 6502 assembly.
I am currently working on porting my own NES emulator to the PSP, and am running into some issues regarding threads and semaphores. Hopefully, whoever is reading this is familiar with the "Dining Philosophers" CS problem, as that is what I am using as a testbench to test my thread and semaphore implementations.
As it is, the emulator is highly portable and targetable to several systems, including Win32 (native), BeOS (native), Linux and Solaris (Qt for UI, SDL for sound and video), MacOS, and of course PSP in the works. I have used the "Dining Philosophers" problem to test the thread and semaphore implementations on all these systems (bar MacOS, haven't gotten around to it yet), and it works fine on all systems, except for PSP.
Essentially, on PSP, the program will run for a while, freeze, and then my PSP shuts off. I'm not quite sure what the problem is, but I've put some code up on pastebin for anyone to look at and perhaps give me a few suggestions on how to fix the issue. Just keep an eye out for the
#if defined(PSP) parts for the PSP specific code....
thread implementation: http://psp.pastebin.com/m219dda3
semaphore implementation: http://psp.pastebin.com/m3d1dfec6
note, there's a commented out bit of code in there in Semaphore::P(), neither bit works
dining philosophers implementation: http://psp.pastebin.com/m604cd288
The program should run infinitely, as it does on the other platforms I have tested it on -- I'm not quite sure what's going on here, and hoping someone can point me in the right direction. Any and all help is kindly appreciated. Thanks.
threads & semaphores...
It's likely it's because the PSP has cooperative multitasking, while the other platforms have pre-emptive multitasking. That means that each of your threads must sleep or block on some other action regularly to let the next thread run. If one thread never yields, then all the other threads hang. I guess that includes the watchdog - if that doesn't get strobed often enough the PSP will reboot.
Jim
Jim
As Jim says, cooperative multitasking is the biggest difference and you'll have to make sure you deal with that case correctly.
Looking at the code briefly, one thing that jumps out at me is that your arglen/argp usage in sceKernelStartThread looks wrong. The kernel copies arglen bytes from address argp and the new thread gets a pointer to this copied data. You want something likethen
(double check me on that, the details are hazy)
Looking at the code briefly, one thing that jumps out at me is that your arglen/argp usage in sceKernelStartThread looks wrong. The kernel copies arglen bytes from address argp and the new thread gets a pointer to this copied data. You want something like
Code: Select all
void *asdf = this;
sKST(id, sizeof(asdf), &asdf);
Code: Select all
run(info) { thisptr = (thread *)*info; }
Not to mention this:
Poll returns an error if the semaphore is not the value passed in arg2, and returns instantly. Hopefully, that's what you want there.
Code: Select all
#
#elif defined(PSP)
//sceKernelWaitSema(mSemaphore, 1, NULL); // infinite, I hope!
sceKernelPollSema(mSemaphore, 1);
Hi Guys,
Thanks all for the tips. I didn't realise the bit about cooperative vs. preemptive multitasking. In any case, though, I believe the problem is now solved. I changed to using sceKernelWaitSema() instead of sceKernelPollSema(). I think the interesting bit here, though, is I had a macro for usleep() doing the following:
#define usleep(usecs) sceKernelDelayThread(1000000 / (usecs))
and my code was sleeping in between eating and thinking phases like this:
usleep(rand() % 3000)
We all know funny things happen when you try dividing by zero, so I changed the code to do this instead:
usleep((rand() % 3000) + 1)
and now all the philosophers are eating and thinking happily, and of course my PSP isn't crashing anymore.
Thanks all for the tips. I didn't realise the bit about cooperative vs. preemptive multitasking. In any case, though, I believe the problem is now solved. I changed to using sceKernelWaitSema() instead of sceKernelPollSema(). I think the interesting bit here, though, is I had a macro for usleep() doing the following:
#define usleep(usecs) sceKernelDelayThread(1000000 / (usecs))
and my code was sleeping in between eating and thinking phases like this:
usleep(rand() % 3000)
We all know funny things happen when you try dividing by zero, so I changed the code to do this instead:
usleep((rand() % 3000) + 1)
and now all the philosophers are eating and thinking happily, and of course my PSP isn't crashing anymore.
The parameter for sceKernelDelayThread is in microseconds anyway, so there's no need to divide (and you'd be dividing usecs by a constant not the other way round to fix it).
Jim
Code: Select all
#define usleep(usecs) sceKernelDelayThread(usecs)