forums.ps2dev.org Forum Index forums.ps2dev.org
Homebrew PS2, PSP & PS3 Development Discussions
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Busy waits?

 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PS2 Development
View previous topic :: View next topic  
Author Message
mharris



Joined: 25 Jan 2004
Posts: 155
Location: Annapolis, MD, USA

PostPosted: Thu Jan 27, 2005 2:34 pm    Post subject: Busy waits? Reply with quote

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
View user's profile Send private message AIM Address
mrbrown



Joined: 17 Jan 2004
Posts: 1536

PostPosted: Thu Jan 27, 2005 4:02 pm    Post subject: Reply with quote

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
View user's profile Send private message
mharris



Joined: 25 Jan 2004
Posts: 155
Location: Annapolis, MD, USA

PostPosted: Fri Jan 28, 2005 5:53 am    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
mrbrown



Joined: 17 Jan 2004
Posts: 1536

PostPosted: Fri Jan 28, 2005 11:16 am    Post subject: Reply with quote

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
View user's profile Send private message
mrbrown



Joined: 17 Jan 2004
Posts: 1536

PostPosted: Fri Jan 28, 2005 11:18 am    Post subject: Reply with quote

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
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PS2 Development All times are GMT + 10 Hours
Page 1 of 1

 
Jump to:  
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