Non-preemptive Multitasking and Signals

Discuss the development of software, tools, libraries and anything else that helps make ps2dev happen.

Moderators: cheriff, Herben

Post Reply
User avatar
whatisdot
Posts: 43
Joined: Mon Apr 07, 2008 8:43 am
Location: Purdue University, USA

Non-preemptive Multitasking and Signals

Post by whatisdot »

Hello, again.

I am having some trouble understanding the semantics of signals with the EE processor. As I understand it, "ee_thread_t" (EE kernel threads) are non-preemptive, which means we need to yield control to other threads actively. (Is this a hardware limitation, or is this part of the current kernel design...?)
What I am having trouble understanding is how we can make signals work to our advantage in this case... If I have seen a number of interrupt handlers in the SDK so far, but I haven't been able to understand exactly how these work in a non-preemptive environment. For example:

The following example is obviously naive and doesn't work. I try to set the "SetAlarm" function within the context of the default thread. Am I correct in assuming that the alarm is set correctly, but the thread continues to execute and returns from the main function? If this is the case, even putting something like an endless loop in the main thread should cause enough time to pass where the function would be called, but this isn't the case either... What will cause the SetAlarm function to execute (if it can be executed at all in this context).

Code: Select all

void *alarming(s32 alarm_id, u16 time, void *arg2) {
	char *myStr = "This is quite alarming!\n";
	printf( myStr );
	scr_printf( myStr );
	return arg2;
}

int main( int argc, char **argv) {
	init_scr();

	// Call the "alarming" function every 50ms
	SetAlarm( 50, alarming, NULL);

	return 0;
}
--------------------------------------------------------------
"A witty saying proves nothing."
--------------------------------------------------------------
cheriff
Regular
Posts: 258
Joined: Wed Jun 23, 2004 5:35 pm
Location: Sydney.au

Post by cheriff »

Hi,
Its not a HW limitation, Linux does preemptive multithreading just fine. I guess it was decided that the majority of uses (ie games) will take over the entire system so not need the overhead of being preempted every 5ms. If guys want this then can (and at least 1 game does) setup their own timer interrupt and rotate the thread queu when that comes in.

I'm not too sure on the specifics of SetAlarm, but
* are you sure it's recurring and not a one-off? If you need repeating, it might be best/easier to register a handler for the timer tick and program the clock's behaviour as you wish.
* scr_printf might be safe, but from experience, it's best not to have these handler threads do too much work, as they usually are running in the IRQ context. Try just having the alarm func incrementing a global (volatile?) variable, that the main thread is polling on and see if/when the count gets bumped.
Damn, I need a decent signature!
User avatar
jbit
Site Admin
Posts: 293
Joined: Sat May 28, 2005 3:11 am
Location: København, Danmark
Contact:

Post by jbit »

IIRC most IOP related things aren't safe to call from an interupt context... so printf is probably not a good idea either...
EEUG
Posts: 136
Joined: Fri May 13, 2005 4:49 am
Location: The Netherlands

Post by EEUG »

...as I wrote in my last post regarding threads alarm handler is executed only once, so
Call the "alarming" function every 50ms
clause is not entirely correct. More correct way would be:

Code: Select all

void *alarming(s32 alarm_id, u16 time, void *arg2) { 
   char *myStr = "This is quite alarming!\n"; 
   printf( myStr ); 
   scr_printf( myStr );
   iSetAlarm ( alarming, 50, NULL );
   return arg2; 
} 
Moreover using 'printf' inside alarm handler will crash the system. Note that time period is expressed in H-Syncs, not milliseconds...
User avatar
whatisdot
Posts: 43
Joined: Mon Apr 07, 2008 8:43 am
Location: Purdue University, USA

Post by whatisdot »

Okay, so an ugly but correct usage example would be this?

Also, why HSYNCs? Why not use the timer?

Sorry if I have forgotten something mentioned in a previous thread. It's a lot to take in all at once.

Code: Select all

void alarming(s32 alarm_id, u16 time, void *arg2) {
	//...rotate threads, or some other non Input/Output related task...
	iSetAlarm( 10, alarming, NULL);
}

int main( int argc, char **argv) {
	init_scr();

	// Call the "alarming" function every 10 H-Syncs
	SetAlarm( 10, alarming, NULL);

	// Keep the main thread from terminating
	while( true ) ;;;;

	return 0;
}
--------------------------------------------------------------
"A witty saying proves nothing."
--------------------------------------------------------------
EEUG
Posts: 136
Joined: Fri May 13, 2005 4:49 am
Location: The Netherlands

Post by EEUG »

Why not use the timer
That's the way it (alarm stuff ) is implemented in the kernel. I think that the value of 10 is a bit low. You can set it to 625 (for PAL video mode it will be ~40ms) or to 525 (for NTSC it will be ~33ms)
Okay, so an ugly but correct usage example would be this?
...yes. I would also advice you to read my last post of that another thread...
Post Reply