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
longjmp from signal handler vs Screen mode CRASH
Re: longjmp from signal handler vs Screen mode CRASH
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.
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.
Re: longjmp from signal handler vs Screen mode CRASH
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 :
FB :
This works perfectly with standard DOS screen mode.
With another FreeBasic screen resolution, during TICK signal, it's crashs in the switch_() function
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,
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);
}
Code: Select all
init()
add_timer()
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);
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,
Re: longjmp from signal handler vs Screen mode CRASH
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
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
Re: longjmp from signal handler vs Screen mode CRASH
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
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
Re: longjmp from signal handler vs Screen mode CRASH
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 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
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;
My question is... Why fb_dos.locked = TRUE when i use longjmp ??
Thank you,
Sébastien FAVIER
Re: longjmp from signal handler vs Screen mode CRASH
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).
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).
Re: longjmp from signal handler vs Screen mode CRASH
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 !!
I'll let you know if have found an alternative..
Thank a lot coderJeff !!