Skip to content

Instantly share code, notes, and snippets.

@PiotrJander
Last active February 3, 2019 05:07
Show Gist options
  • Save PiotrJander/449b77a8cc6a15c8629a5c167ae48522 to your computer and use it in GitHub Desktop.
Save PiotrJander/449b77a8cc6a15c8629a5c167ae48522 to your computer and use it in GitHub Desktop.
Scheduler process cleanup

Scheduler process cleanup

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.

  1. Is there just one global cleanup_context or is there one for each process?
  2. Where are cleanup_contexts 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.

Understanding ucontext

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);

Conclusion

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment