 |
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
| View previous topic :: View next topic |
| Author |
Message |
mharris
Joined: 25 Jan 2004 Posts: 155 Location: Annapolis, MD, USA
|
Posted: Thu Jan 27, 2005 2:34 pm Post subject: Busy waits? |
|
|
A lot of the code I've seen has a vblank routine that looks something like this:
| Code: | while(!((*CSR) & GS_VSINT))
/* do nothing */ ;
|
This is obviously going to eat up all of the CPU cycles that it can while it's waiting for the GS to set the VSync flag. Not a big deal if this is the only thread, but I'd like to have a render thread and one or more "worker" threads, and not have the workers starve while the render thread's doing nothing.
Is there a more elegant way of doing this? Most of the "delay" routines I've seen have been NOP loops as well.
Here's what I'm thinking: I suppose there's a way to hook an interrupt handler on the VSync signal from the GS; the render thread could call SleepThread() when it's done working. The interrupt handler would then call iWakeupThread() on the render thread when it gets its interrupt, and the render thread would pick up where it left off. Meanwhile, the worker threads could be chugging along, doing their own things.
Is this the correct way of doing it? How hard is it to add an interrupt handler?
A somewhat-related question regarding threads on the PS2 -- does the kernel automatically handle the context switches? Or does each thread need to call a suspend() routine (i.e., non-preemptive multitasking).
thx |
|
| Back to top |
|
 |
mrbrown
Joined: 17 Jan 2004 Posts: 1536
|
Posted: Thu Jan 27, 2005 4:02 pm Post subject: |
|
|
We use something similiar to what you describe - a thread woken up by a vblank interrupt handler.. You can use AddIntcHandler() to add a vblank handler. IIRC there are some ps2dev examples that show how to do this.
Every thread must yield unless an interrupt or syscall causes a context switch, i.e. if your render thread had a higher priority than your main thread, and you put it to sleep, the main thread will lose control once you wake the render thread. _________________ "He was warned..." |
|
| Back to top |
|
 |
mharris
Joined: 25 Jan 2004 Posts: 155 Location: Annapolis, MD, USA
|
Posted: Fri Jan 28, 2005 5:53 am Post subject: |
|
|
| mrbrown wrote: | | We use something similiar to what you describe - a thread woken up by a vblank interrupt handler.. You can use AddIntcHandler() to add a vblank handler. IIRC there are some ps2dev examples that show how to do this. |
Cool, thanks. Also, I see this in kernel.h:
| Code: | void SetVInterruptHandler(s32 handler_num, void* handler_func);
|
I haven't tried it yet, but from its name. it looks like it's a VSync-specific interrupt handler. Has anyone experimented with this one? If so, what's the first argument used for, and what's the signature for the callback?
| mrbrown wrote: | | Every thread must yield unless an interrupt or syscall causes a context switch, i.e. if your render thread had a higher priority than your main thread, and you put it to sleep, the main thread will lose control once you wake the render thread. |
That's also useful information that I haven't seen elsewhere. Thanks.
I'm guessing that waiting on a semaphore will also suspend the thread -- it should context-switch (because WaitSema() is a syscall), but I assume the kernel doesn't schedule the waiting thread(s) until the semaphore has been signaled. Right? |
|
| Back to top |
|
 |
mrbrown
Joined: 17 Jan 2004 Posts: 1536
|
Posted: Fri Jan 28, 2005 11:16 am Post subject: |
|
|
| mharris wrote: | Cool, thanks. Also, I see this in kernel.h:
| Code: | void SetVInterruptHandler(s32 handler_num, void* handler_func);
|
I haven't tried it yet, but from its name. it looks like it's a VSync-specific interrupt handler. Has anyone experimented with this one? If so, what's the first argument used for, and what's the signature for the callback?
|
SetVInterruptHandler() is used to set MIPS hardware interrupt handlers, i.e. INT0 and INT1. I don't remember how all of that works, but you can only attach a vblank handler by using AddIntcHandler(), as AIH() builds on top of SetVInterruptHandler(). To make a long story short, you would only ever use SetVInterruptHandler() if you were writing kernel-level code.
| mharris wrote: |
I'm guessing that waiting on a semaphore will also suspend the thread -- it should context-switch (because WaitSema() is a syscall), but I assume the kernel doesn't schedule the waiting thread(s) until the semaphore has been signaled. Right? |
WaitSema() will suspend the calling thread if the semaphore can't be acquired. So if you create a semaphore with it's initial count at 0 and max count at 1, then the first time you call WaitSema() on that semaphore your thread will yield. And you're right, the kernel maintains a list of threads waiting on that semaphore, and their priorities are checked once the semaphore becomes available. The thread with the highest priority is woken up.
Just remember that the kernel always schedules the thread with the highest priority, and that threads with a lower priority can only be scheduled if the higher priority threads are suspended (via SleepThread, WaitSema, or whatever). Typically you give your main thread a low priority (like 100) and your render, rpc, or file I/O threads a higher priority than the main thread. _________________ "He was warned..." |
|
| Back to top |
|
 |
mrbrown
Joined: 17 Jan 2004 Posts: 1536
|
Posted: Fri Jan 28, 2005 11:18 am Post subject: |
|
|
Oh, another thing, I've seen games like Xenosaga implement a ghetto round-robin scheme using the RotateThreadReadyQueue() syscall. IIRC, they started all threads (and changed the main thread's priority) at a single priority, and when one thread was done with it's work called a function that did RotateThreadReadyQueue(). I don't know how well that worked out for them. _________________ "He was warned..." |
|
| 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
|