Page 1 of 1

Non-preemptive Multitasking and Signals

Posted: Thu Jun 19, 2008 11:42 pm
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;
}

Posted: Fri Jun 20, 2008 12:44 am
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.

Posted: Fri Jun 20, 2008 2:22 am
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...

Posted: Fri Jun 20, 2008 5:52 pm
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...

Posted: Sat Jun 21, 2008 4:03 am
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;
}

Posted: Sun Jun 22, 2008 5:42 am
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...