longjmp from signal handler vs Screen mode CRASH

DOS specific questions.
Post Reply
Cpcdos
Posts: 207
Joined: Mar 06, 2013 13:52
Location: France - LYON 69003
Contact:

longjmp from signal handler vs Screen mode CRASH

Post by Cpcdos »

Hi,

I want know, why when I use longjmp/siglongjmp during signal handler (From DJGPP C++ code) from standard screen DOS mode (or screen 0 FB command) this work perfectly.

But if i using this, with another screen mode or resolution (With Screen or SetScreen FB command) ... this crashes immediately !?

I've looking FB source code, i've not find interesting solutions

Thank you for your help.
BR


PS : By the way,
My functions "setitimer" from DJGPP seems to be "reset" or not works when i use another FreeBasic screen resolution
coderJeff
Site Admin
Posts: 4313
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: longjmp from signal handler vs Screen mode CRASH

Post by coderJeff »

Hard to know without example code:

1) fb's gfxlib2 hooks the timer interrupt. You have to play nice with it. i.e. chain to it rather than replace it. Lock memory/procs, etc.
2) fb's dos rtlib has a function fb_isr_set() that is supposed to manage the interrupt service routines. This is going back a ways, but when I wrote the dos serial driver, I had a lot of trouble working with it. Eventually, I just managed the hooks myself.
3) I have used setjmp()/longjmp() in FB to successfully for -gen gcc implementation of GOSUB. Do you mean sigsetjmp()/siglongjmp()? I haven't ever used the sig*() version.

What system are you using? I have to ask, because I find developing and testing in DOS a real pain. If you have suggestions that make it easy, I really want to know. Thanks.
Cpcdos
Posts: 207
Joined: Mar 06, 2013 13:52
Location: France - LYON 69003
Contact:

Re: longjmp from signal handler vs Screen mode CRASH

Post by Cpcdos »

Thank you for your reply,

I use FreeDos and NTVDM (from Windows XP), i developp from XP

I've extremely simplified my code, (and adapt for task_1,task_2 only)
DJGPP :

Code: Select all

struct list_jmp
{
	char 				Stack_jmp[4096];
	jmp_buf 			Buffer_jmp;
} list_jmp[123];

struct itimerval 	timer_instance;
struct sigaction 	sig_action_instance;


void task_1()
{
	while(1)
		printf(" ### Task1\n");
}


void task_2()
{
	while(1)
		printf(" ### Task2\n");
}


void init()
{
	sigsetjmp(list_jmp[1].Buffer_jmp,1);
	list_jmp[1].Buffer_jmp[0].__esp = list_jmp[1].Stack_jmp; 
	list_jmp[1].Buffer_jmp[0].__eip = task_1; 
	
	sigsetjmp(list_jmp[2].Buffer_jmp,1);
	list_jmp[2].Buffer_jmp[0].__esp =  list_jmp[2].Stack_jmp; 
	list_jmp[2].Buffer_jmp[0].__eip = task_2; 
}


void Interruption_Timer(int sig)
{		
	// __dpmi_yield();

	switch_();
	
}

void switch_()
{

	// switch beetween 1 and 2
	if(jmp_id == 1)
		jmp_id = 2
	else
		jmp_id = 1
	
	if (sigsetjmp(list_jmp[jmp_id].Buffer_jmp ,1) == 1)
		return;


	siglongjmp(list_jmp[jmp_id].Buffer_jmp, 1);
	
}

void add_timer()
{
	timer_instance.it_interval.tv_sec 	= 0;
	timer_instance.it_interval.tv_usec 	= 10000;
	timer_instance.it_value.tv_sec 		= 0;
	timer_instance.it_value.tv_usec 	= 10000;

	// signal(SIGALRM, (void (*)(int)) Interruption_Timer);
	setitimer(ITIMER_REAL, &timer_instance, NULL);
	
	sig_action_instance.sa_handler 	= (void (*)(int)) Interruption_Timer;
	sigemptyset(&sig_action_instance.sa_mask);
	
	sig_action_instance.sa_flags 	= 0;
	sigaction(SIGALRM, &sig_action_instance, NULL);
}
FB :

Code: Select all

init()
add_timer()
This works perfectly with standard DOS screen mode.
With another FreeBasic screen resolution, during TICK signal, it's crashs in the switch_() function

Code: Select all

siglongjmp(list_jmp[jmp_id].Buffer_jmp, 1);
3) sigsetjmp()/siglongjmp() by POSIX are used specialy for use from signal handler function "sig" : signal

1) and 2) Okay, so sigaction(), setitimer(), and signal() functions are overrided ? Crashs are caused by memory lock ?
If i rewrite my djgpp code to FB syntax, this will not change ?

Thank,
coderJeff
Site Admin
Posts: 4313
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: longjmp from signal handler vs Screen mode CRASH

Post by coderJeff »

Sorry, I haven't tried any of the sample code, only have been reading up on all the stuff I have forgotten since DOS days. And I've been trying to build a mingw to msdosdjpp gcc cross compiler, so I can develop on win7. Limited success.

Here's what I mean when your code has to cooperate (play nice) with fbgfx:
DOS fbgfx driver handles IRQ 0 directly, and programs PIT directly for timing.
DOS fbgfx driver is in control of timing. (Also IRQ 1 for keyboard).
DOS fbgfx is using timer and keyboard at the lowest level.
Other mechanisms that depend on BIOS/DOS (like signal handlers) may not cooperate.

I see sigsetjmp()/siglongjmp() works similar to setjmp()/longjmp(), that is, they allow you to return to an EARLIER point in the execution. I do not think the intent was for it to be used to switch contexts. For example, printf(), at some level makes system calls to output to screen. Is this really context switching safe? Same for any code that uses a shared resource, like memory, disk drives, etc.

I see what you are trying to do, and have tried the same once upon a time. I got a scheduler working with some success. Unfortunately, really need to control EVERYTHING, like an operating system would. And I found that it was impossible to just run any code I wanted. Only very simple examples would work.

If you have a goal in mind, maybe explore DOS threading more. I see you responded in last topic about it was viewtopic.php?t=21274
Cpcdos
Posts: 207
Joined: Mar 06, 2013 13:52
Location: France - LYON 69003
Contact:

Re: longjmp from signal handler vs Screen mode CRASH

Post by Cpcdos »

Thank you for your reply, i've take account yours comments. So, i've investigate in FreeBasic source code, and i've discovered interesting informations!

In fact, during switching with longjmp, application NOT CRASH, but screen mode is "freezed" for ever, code working again in background.
ISR and others runtime is every in execution.

In file fb_gfx : https://github.com/freebasic/fbc/blob/1 ... dos.c#L324
The fb_dos.update() function updates screen from selected driver, for me it's gfx driver vesa bank --> driver_update() https://github.com/freebasic/fbc/blob/2 ... bnk.c#L144


The problem is the same when original context is restaured, this driver_update() won't update my screen, which gave the impression that my program crashes. (Where does my first thread come from)

An explanation ? :(

Best regards
Cpcdos
Posts: 207
Joined: Mar 06, 2013 13:52
Location: France - LYON 69003
Contact:

Re: longjmp from signal handler vs Screen mode CRASH

Post by Cpcdos »

I've resolv my problem ..... It's in FreeBasic source code! I must add a line for resolve this..


In function fb_dos_timer_handler() at line : https://github.com/freebasic/fbc/blob/1 ... dos.c#L337


If i use longjmp, fb_dos.locked every equal to TRUE;

so.. I've just add

Code: Select all

fb_dos.locked = FALSE; 
before the if condition and my problem is resolved!

My question is... Why fb_dos.locked = TRUE when i use longjmp ??

Thank you,
Sébastien FAVIER
coderJeff
Site Admin
Posts: 4313
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: longjmp from signal handler vs Screen mode CRASH

Post by coderJeff »

Good investigation. Hopefully this will help answer your question, and help you understand why forcing the lock to release is probably a bad thing.

Your Program:
- You are using signal handlers to switch context...
- When you call graphics commands, the driver automatically locks the shared resources (memory)
- if you interrupt a graphics command (likely) with a signal handler, the driver will be locked when the signal handler is called.
- it's not specific to longjmp

Graphics Driver:
- There is a memory buffer that represents the screen. All of the drawing takes place in memory.
- LINE, CIRCLE, PSET, PRINT, etc, are procedures that update the memory buffer
- Timer ISR is called automatically at a rate of 1000Hz. The Timer ISR wants to copy the memory buffer to the display memory
- The memory buffer and other GFX global state variables could potentially be accessed at the same time, by the GFX methods called by your main program and the Timer ISR called automatically.
- The fb_dos.locked variable is used as a mutex, that is constantly acquired, held, released ... repeatedly, every time any part of the program wants to access any of the shared GFX data.
- This lock prevents the GFX data from getting corrupted, having two different parts of the program access the data at the "same time"
- The Timer ISR, to be safe, just quits and returns without doing anything if a GFX method is busy drawing (fb_dos.locked).
- SCREENSYNC, will lock the driver and just wait until the display can be updated
- SCREENLOCK/SCREENUNLOCK will allow you to explicitly lock/unlock the driver for your own code (but not override the driver's code).
Cpcdos
Posts: 207
Joined: Mar 06, 2013 13:52
Location: France - LYON 69003
Contact:

Re: longjmp from signal handler vs Screen mode CRASH

Post by Cpcdos »

Thank! And Thank you for yours descriptions about inner workings, it looks a lot like what I investigated, this reassures me :)


I'll let you know if have found an alternative..

Thank a lot coderJeff !!
Post Reply