I want to know how erlang's VM preempts the running code and contexts the stack. How it can be done in a language such as c?
2 Answers
The trick is that the Erlang runtime has control over the VM, so it can - entirely in userspace - keep track of how many VM instructions it's already executed (or, better yet, an estimate or representation of the actual physical computation required for those instructions - a.k.a. "reductions" in Erlang VM parlance) and - if that number exceeds some threshold - immediately swap around process pointers/structs/whatever and resume the execution loop.
Think of it something like this (in kind of a pseudo-C that may or may not actually be C, but I wouldn't know because I ain't a C programmer, but you asked how you'd go about it in C so I'll try my darndest):
void proc_execute(Proc* proc)
{
/* I don't recall if Erlang's VM supports different
reduction limits for different processes, but if it
did, it'd be a rather intuitive way to define process
priorities, i.e. making sure higher-priority processes
get more reductions to spend */
int rds = proc->max_reductions;
for (; rds > 0; rds--) {
/* Different virtual instructions might execute different numbers of
physical instructions, so vm_execute_next_instruction will return
however many reductions are left after executing that virtual
instruction. */
rds = vm_execute_next_instruction(proc, rds);
if (proc->exited) break;
}
}
void vm_loop(Scheduler* sched)
{
Proc *proc;
for (;;) {
proc = sched_next_in_queue(sched);
/* we'll assume that the proc will be null if the
scheduler doesn't have any processes left in its
list */
if (!proc) break;
proc_execute(proc);
}
}
Proc* sched_next_in_queue(Scheduler* sched)
{
if (!sched->current_proc->exited) {
/* If the process hasn't exited yet, readd it to the
end of the queue so we can resume running it
later */
shift(sched->queue, sched->current_proc);
}
sched->current_proc = pop(sched->queue);
return sched->current_proc;
}
This is obviously quite simplified (notably excluding/eliding a lot of important stuff like how VM instructions are implemented and how messages get passed), but hopefully it illustrates how (if I'm understanding right, at least) Erlang's preemptive scheduler and process model works on a basic level.

- 901
- 8
- 13
All code of Erlang will compile to operation code of Erlang's VM. Erlang's VM execute Erlang's operation code by OS's threads which are created at startup of Erlang's VM.
Erlang's code run on Virtual CPUs which are controlled by Erlang's VM. And Erlang's VM consider IO as interrupt of Virtual CPUs. So Erlang's VM implements a machine and a scheduler like an OS. Because of operation code and non-blocking IO, we can implements preempts in Erlang's VM using C languange.

- 71
- 1
- 5
-
@BunnyDhaliwal Erlang's VM will use one or more OS threads. On the machine with only one CPU core, Erlang's VM will use one thread. If the machine with more then one CPU core, Erlang's VM will use more then one thread default. Erlang's VM achieve preempts with Interpreter of operation code and non-blocking IO. – Tianpo Gao Mar 03 '18 at 12:03