Re: Problem with ucontext_t struct in signal handler
Glynn Clements <[email protected]>
| Newsgroups | org.kernel.vger.linux-c-programming |
|---|---|
| Message-ID | <[email protected]> |
XComp wrote:
> I want to switch between user contexts using a signal handler
> (something like a preemptive scheduler for userlevel threads). I've
> found several sources, which say that it's not a good idea to use
> setcontext or swapcontext in a signal handler. Nevertheless there also
> exists at least one sample code of such an preemptive scheduler, which
> seems to work well, at least on my machine (Ubuntu 8.04 with linux
> kernel 2.6.24-22): www.seas.upenn.edu/~cse381/context_demo.c
>
> // [...]
> static ucontext_t thread_context;
> static ucontext_t scheduler_context;
>
> int thread_finished;
> int i;
>
> static void simple_function(void) {
> // do nothing but counting
> for (i = 0; i < 1000000000; ++i) { }
>
> if (i == 1000000000) {
> printf("\n[Thread Function]\t1st counting worked fine...");
> } else {
> printf("\n[Thread Function]\tError: Counting didn't finished (%d)...", i);
> }
>
> thread_finished = 1;
> }
>
> static void other_function() {
> // thread_finished is a global variable, which is set to 1, if the thread function is finished
> while(thread_finished != 1) { swapcontext(&scheduler_context, &thread_context); }
> }
>
> static void signal_handler_function(int sig_nr, siginfo_t* info, void *old_context) {
> if (sig_nr == SIGPROF) {
> // saves the thread context
> thread_context = *((ucontext_t*) context);
>
> // swaps back to scheduler context
> setcontext(&scheduler_context);
> }
> }
> // [...]
>
> I ran into the following problem which belongs to the code above. I
> interrupted simple_function several times by using a ITimer. But the
> for-loop doesn't finish successfully everytime. Often the if condition
> is false.
It seems likely that either the registers or the stack (wherever "i"
is stored) is getting trashed. What is "i" in the cases where the test
fails?
> But it does not cancel after the first signal is raised.
> I've found out that using the third parameter old_context for storing
> the old context is the reason. But I don't know why.
Note that the old_context parameter to the signal handler won't be
pointing to any of your context "slots". When a signal occurs, the
current context will be saved in a ucontext_t on the current context's
stack, and the old_context argument will point to that.
It needs to be borne in mind that a ucontext_t isn't "the context"
itself. It's merely a structure for storing information about a
context, either for receiving information (e.g. getcontext) or
providing it (e.g. setcontext).
> So I thought there might be a problem in the kernel. Am I right?
I don't think so.
> I was afraid to post the whole code, so I hope that this code
> snippet is enough.
It would help if it was accurate (e.g. the signal handler refers to
"context" which isn't declared anywhere; is this supposed to be the
old_context parameter?) and more complete.
> I would appreciate if someone can give me a comment whether this
> strange behaviour is because of a wrong thinking of mine or because of
> a error in the kernel which needs to be fixed.
I suspect the former.
--
Glynn Clements <[email protected]>