Steven
One thing I dont understand is why if I use setcontext instead of swapcontext in the
following program, I crash? Look at where I commented out my swapcontext
Thanks
Lee
#include <ucontext.h>
#include <stdio.h>
#include <setjmp.h>
ucontext_t mainucp;
ucontext_t fooucp;
char stack[SIGSTKSZ];
int flag = 0;
int foo()
{
printf("(2) foo setting context\n");
if (!flag)
{
flag = 1;
swapcontext(&fooucp, &mainucp);
}
printf("(3) foo done\n");
return 0;
}
void eleven()
{
printf("(1) calling foo\n");
foo();
printf("(4) foo now finished\n");
}
void ten()
{
eleven();
}
void nine()
{
ten();
}
void eight()
{
nine();
}
void seven()
{
eight();
}
void six()
{
seven();
}
void five()
{
six();
}
void four()
{
five();
}
void three()
{
four();
}
void two()
{
three();
}
void one()
{
two();
}
int main()
{
getcontext(&fooucp);
fooucp.uc_link = &mainucp;
fooucp.uc_stack.ss_sp = stack;
fooucp.uc_stack.ss_size = sizeof(stack);
makecontext(&fooucp, one, 0);
getcontext(&mainucp);
printf("(1, 2.2) main checking flag flag\n");
if (!flag)
{
setcontext(&fooucp);
}
else
{
printf("(2.5) main again\n");
// HERE IS WHERE I COMMENTED OUT
// swapcontext(&mainucp, &fooucp);
setcontext(&fooucp);
}
}
~
~
----- Original Message -----
From: Steven Smith <[EMAIL PROTECTED]>
Date: Mon, 20 Jan 2003 14:32:40 +0000
To: Lee Chin <[EMAIL PROTECTED]>
Subject: Re: why does this program crash while using setcontext?
> I think this problem is largely my fault; I should have been more
> clear last time I posted. Feel free to insult me.
>
> I think the program below is trying to:
>
> 1) have main() record its context immediately. Call this the
> main context.
> 2) Call foo() indirectly through one().
> 3) Record foo()'s context. Call this the foo context.
> 4) Switch back to the main context.
> 5) Switch back to the foo context.
> 6) Return back from foo() to main() and then exit.
>
> Now, the problem is that the various contexts are all running on the
> same stack. This means that the bit of main() which runs between
> steps 4 and 5 is mangling the foo context, and so step 6 doesn't work.
>
> The way to avoid this is to have the two contexts operating on
> different stacks. The main context can happily run on the process
> stack, but one will need to be allocated for the foo context.
> An array of chars is perfectly good for this; the usual size
> is SIGSTKSZ, defined in signal.h. In addition, we need to tell
> the ucontext functions to use this stack. Unfortunately, there's
> no (easy) way to copy the current stack onto the context stack,
> and so we need to use makecontext() rather than getcontext().
>
> This means the design of the program looks more like this:
>
> 1) Have main() record its context. Call this the main context.
> 2) Have main() construct a context which will invoke foo() on a
> different stack. Call this the foo context.
> 3) Have main() invoke the foo context.
> 4) Switch back to the main context.
> 5) Switch back to the foo context.
> 6) Let the foo context return. This will cause the context library
> to automatically switch back to the main context, which
> can then return and exit the program.
>
> I've shown these changes below.
>
> > ucontext_t mainucp;
> > ucontext_t fooucp;
> > int flag = 0;
> char stack[SIGSTKSZ];
>
> > int foo()
> > {
> > printf("(2) foo setting context\n");
>
> > getcontext(&fooucp);
> Kill this line - the foo context has already been constructed.
>
> > if (!flag)
> > {
> > flag = 1;
>
> > setcontext(&mainucp);
> Replace this line with:
> swapcontext(&fooucp, &mainucp);
> We need swapcontext() rather than setcontext() so as the foo
> context resumes from here, rather than the entry to one(),
> which would cause an infinite loop.
>
> > }
> > printf("(3) foo done\n");
> > return 0;
> > }
>
> <snip deeply nested call to foo() from one()>
>
> > int main()
> > {
> Insert
> getcontext(&fooucp);
> fooucp.uc_link = &mainucp;
> fooucp.uc_stack.ss_sp = stack;
> fooucp.uc_stack.ss_size = sizeof(stack);
> makecontext(&fooucp, one, 0);
> The uc_link line says to return the main context if the foo context
> ever returns. The uc_stack lines are just setting up the stack,
> and the makecontext() modified the foo context so that it calls
> one() with 0 arguments.
>
> For various reasons, primarily historical, contexts which are passed
> to makecontext() must first be initialised with getcontext(), even
> though makecontext() overwrites or makes redundant 95% of the work
> which getcontext() did.
>
> > getcontext(&mainucp);
> > if (!flag)
> > {
>
> > one();
> Replace this line with
> setcontext(&fooucp);
> Note that this is setcontext() and not swapcontext(); if we used
> swapcontext(), then the main context would resume from here
> rather than the call to getcontext(), above, and so the else
> branch of the if would never run.
>
> > }
> > else
> > {
> > printf("(2.5) main again\n");
>
> > setcontext(&fooucp);
> Replace this line with
> swapcontext(&mainucp, &fooucp);
> We need swapcontext() here, rather than setcontext(), because we
> want the main context to resume here rather than at the getcontext(),
> to avoid an infinite loop.
>
> > }
> Insert:
> return 0;
> :)
> > }
>
> Hopefully, that's a little clearer.
>
> In general, it's a good idea to use swapcontext() rather than
> setcontext() if at all possible, because then functions return to the
> same place as they were called from, which is a lot easier to think
> about.
>
> Steven.
--
__________________________________________________________
Sign-up for your own FREE Personalized E-mail at Mail.com
http://www.mail.com/?sr=signup
Meet Singles
http://corp.mail.com/lavalife
-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs