 |
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
| View previous topic :: View next topic |
| Author |
Message |
scanty
Joined: 30 Nov 2007 Posts: 3
|
Posted: Fri Nov 30, 2007 3:03 pm Post subject: threads & semaphores... |
|
|
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. |
|
| Back to top |
|
 |
Jim

Joined: 02 Jul 2005 Posts: 487 Location: Sydney
|
Posted: Fri Nov 30, 2007 4:23 pm Post subject: |
|
|
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 _________________ http://www.dbfinteractive.com |
|
| Back to top |
|
 |
jimparis
Joined: 10 Jun 2005 Posts: 1179 Location: Boston
|
Posted: Fri Nov 30, 2007 4:31 pm Post subject: |
|
|
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 like
| Code: | void *asdf = this;
sKST(id, sizeof(asdf), &asdf); | then | Code: | | run(info) { thisptr = (thread *)*info; } |
(double check me on that, the details are hazy) |
|
| Back to top |
|
 |
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Fri Nov 30, 2007 4:59 pm Post subject: |
|
|
Not to mention this:
| Code: | #
#elif defined(PSP)
//sceKernelWaitSema(mSemaphore, 1, NULL); // infinite, I hope!
sceKernelPollSema(mSemaphore, 1);
|
Poll returns an error if the semaphore is not the value passed in arg2, and returns instantly. Hopefully, that's what you want there. |
|
| Back to top |
|
 |
scanty
Joined: 30 Nov 2007 Posts: 3
|
Posted: Sat Dec 01, 2007 8:28 am Post subject: |
|
|
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. |
|
| Back to top |
|
 |
Jim

Joined: 02 Jul 2005 Posts: 487 Location: Sydney
|
Posted: Sat Dec 01, 2007 12:18 pm Post subject: |
|
|
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).
| Code: |
#define usleep(usecs) sceKernelDelayThread(usecs)
|
Jim _________________ http://www.dbfinteractive.com |
|
| 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
|