setjmp()/longjmp()

Strictly for discussing ZSNES development and for submitting code. You can also join us on IRC at irc.libera.chat in #zsnes.
Please, no requests here.

Moderator: ZSNES Mods

Post Reply
Nach
ZSNES Developer
ZSNES Developer
Posts: 3904
Joined: Tue Jul 27, 2004 10:54 pm
Location: Solar powered park bench
Contact:

setjmp()/longjmp()

Post by Nach »

Anyone have a good understand how these work?

I have a question regarding valid usage. I know normally longjmp() is valid if setjmp()'s surrounding function hasn't returned yet. But what if the function calling setjmp() was reentered in the same manner causing the stack to setjmp()'s function to be the same as it was before?

For example:

Code: Select all

jmp_buf jmpbuf;
bool jumped = false;
void Opcode()
{
  if (jumped) { jumped = false; longjmp(jmbbuf, 1); }

  ...

  if (!setjmp(jmpbuf)) { jumped = true; return; }

  ...

  if (!setjmp(jmpbuf)) { jumped = true; return; }

  ...
}
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
anomie
Lurker
Posts: 151
Joined: Tue Dec 07, 2004 1:40 am

Re: setjmp()/longjmp()

Post by anomie »

Nach wrote:I have a question regarding valid usage. I know normally longjmp() is valid if setjmp()'s surrounding function hasn't returned yet. But what if the function calling setjmp() was reentered in the same manner causing the stack to setjmp()'s function to be the same as it was before?
But how do you know the stack is the same as before, especially with optimizing compilers? Take for example this sequence of calls:

Code: Select all

foo(a);
bar(b);
baz(c);
You'd expect some pseudo-asm code like this, on a machine where the caller frees the stack:

Code: Select all

push a
call foo
stack++
push b
call bar
stack++
push c
call baz
stack++
But there's nothing preventing the compiler from doing this if it's more efficient:

Code: Select all

push a
call foo
push b
call bar
push c
call baz
stack+=3
Which would probably screw up the return position. Or consider this:

Code: Select all

foo();
bar(a);
foo();
And consider that it may clean up bar after the second call to foo.

Or even consider this: setjmp may well change the stack frame in some way as part of whatever it does to enable longjmp to happen.

Why are you wanting to do this?
Nach
ZSNES Developer
ZSNES Developer
Posts: 3904
Joined: Tue Jul 27, 2004 10:54 pm
Location: Solar powered park bench
Contact:

Re: setjmp()/longjmp()

Post by Nach »

anomie wrote: Why are you wanting to do this?
I was looking at the mess known as dsp4emu.c/dsp4emu.cpp

There's all these parts where the code sets a number, drops out for more data, then continues by gotoing a lable based on the number. I was thinking to clean up the code a bit it would be possible to just drop out and have the continue continue from the drop out point via long jump instead of these messy switch()es on a variable to decide goto points.

Of course there's probably a better way to clean up this monstrosity but that's what came to mind first.
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
anomie
Lurker
Posts: 151
Joined: Tue Dec 07, 2004 1:40 am

Re: setjmp()/longjmp()

Post by anomie »

I was looking at the mess known as dsp4emu.c/dsp4emu.cpp

There's all these parts where the code sets a number, drops out for more data, then continues by gotoing a lable based on the number. I was thinking to clean up the code a bit it would be possible to just drop out and have the continue continue from the drop out point via long jump instead of these messy switch()es on a variable to decide goto points.
Hmmm... So it looks like the DSP4 works like this: You tell the DSP you're executing command #01, then you feed it some data, and at some point the DSP decides it's gotten enough data and it does something. Then you feed it more data, and it processes that more data. And eventually, I suppose you send "end of command" and it goes back to looking for the next command. Is all that correct?

It sounds like you'd want to implement a finite state machine. The current code works, but if you want to get rid of the gotos you could change it to something like this:

Code: Select all

void DSP4_Op01(bool restart=false){
    static int state;
    if(restart) state = 0;
    switch(state){
      case 0: // Init
        // do init stuff
        state = 1; // Next state: Check Subcommand
        break;
      case 1: // Check Subcommand
        // see if it's "terminate"
        state = 2; // Next state: Process Subcommand
        break;
      case 2: // Process Subcommand
        // do whatever it is we do
        state = 1; // Next state: Check Subcommand
        break;
    }
}
Which is basically the same thing you have now but more "structured" and a little more self-contained.
whicker
Trooper
Posts: 479
Joined: Sat Nov 27, 2004 4:33 am

Post by whicker »

aah, yes. State machine structures are the best.
Nach
ZSNES Developer
ZSNES Developer
Posts: 3904
Joined: Tue Jul 27, 2004 10:54 pm
Location: Solar powered park bench
Contact:

Post by Nach »

Yes, I guess that's pretty much what we're doing.

One of the problems though is that some of the code is in a loop, and the goto jumps right into the middle of it :x
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
anomie
Lurker
Posts: 151
Joined: Tue Dec 07, 2004 1:40 am

Post by anomie »

Nach wrote:One of the problems though is that some of the code is in a loop, and the goto jumps right into the middle of it :x
Well, on the one hand you can probably set things up so the FSM handles the loop: 0 -> 1 -> 2 -> back to 1. Or you could stick a Duff's Device in there.
Post Reply