Problem: recall that each process in Penn OS is implemented by a ucontext
instance.
An instance of ucontext_t
has the uc_link
field. When the context's main function (the one set by makecontext
) finishes
and uc_link
is NULL
, then the whole Penn OS finishes and this is clearly not what we want.
Therefore, we want to have a cleanup_context
(either one global or one for each process) such that we have
uc_link = cleanup_context
. The cleanup_context
would perform cleanup (among other things set the state of the process
to ZOMBIE
) and then invoke the scheduler to schedule a new process.
Now there are a number of design decisions to make with regard to cleanup_context
.
- Is there just one global
cleanup_context
or is there one for each process? - Where are
cleanup_context
s allocated? In the data or heap segment? (I once run into an error which might have been to do with allocating a context's stack on the heap).
I went for the design with one global cleanup_context
and it seems to work fine when spawn three processes running busy loops.
But my implementation of p_wait
, which in principle should not affect the cleanup_context
, results in a cryptic error
Program received signal SIGFPE, Arithmetic exception.
setcontext () at ../sysdeps/unix/sysv/linux/i386/setcontext.S:52
52 ../sysdeps/unix/sysv/linux/i386/setcontext.S: No such file or directory.
when a process finishes and there is an attempt to switch to the cleanup_context
pointed to by uc_link
.
I have no clue how my p_wait
affects the uc_link
, and I have no knowledge of the internal workings of ucontext
to find out
the cause.
Suppose we create a context like this
void *stack = malloc(X);
getcontext(&uc);
...
uc.stack = stack;
makecontext(&uc, uc_main, 0);
My understanding of ucontext
is that the state of the context uc
is defined by the the contents of uc
's stack
as well as the program pointer $pc
. I also understand that makecontext
initializes the stack with some data.
// switch to `uc`
setcontext(&uc);
// `uc` now runs uc_main as specified by makecontext (*)
// switch out of `uc` by setcontext as opposed to swapcontext
// context state not saved; but what does that exactly mean in terms of the `$pc` and the context's stack?
setcontext(&othercontext);
// switch to `uc` again
setcontext(&uc);
// does `uc` run uc_main just like in (*)??
compare this with
setcontext(&uc);
// what happens when we call makecontext on `uc` while `uc` is running?
// and specify a different function
makecontext(&uc, other_uc_main, 0);
// vs same function
makecontext(&uc, uc_main, 0);
setcontext(&othercontext);
// what happens when we call makecontext on `uc` while *another context is running*?
// is makecontext(&uc, uc_main, 0) idempotent
makecontext(&uc, uc_main, 0);
setcontext(&uc);
I do not expect whoever is reading this to solve my problem without my code and a debugger. I wrote the above to show
that I actually made a big effort to design the cleanup_context
, and I arrived with a solution which works in simple cases
and inexplicably breaks when combined with p_wait
.
But I would greatly appreciate help with how to set up the cleanup_context
in a reliable way, and address the questions regarding internal workings of ucontext
.