Embedded Systems Programming A simple embedded system The ...
Embedded Systems Programming A simple embedded system The ...
Embedded Systems Programming A simple embedded system The ...
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
<strong>Embedded</strong> <strong>Systems</strong> <strong>Programming</strong><br />
Lecture 3<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
A <strong>simple</strong> <strong>embedded</strong> <strong>system</strong><br />
Follow (track) an object using sonar echoes. Control parameters<br />
are sent over wireless. <strong>The</strong> servo controls wheels.<br />
Verónica Gaspes<br />
www2.hh.se/staff/vero<br />
Object<br />
Sonar<br />
Distance<br />
data<br />
Input<br />
Servo<br />
Controller<br />
signals<br />
Output<br />
Control<br />
Params<br />
Center for Research on <strong>Embedded</strong> <strong>Systems</strong><br />
School of Information Science, Computer and Electrical Engineering<br />
Decoder<br />
Radio<br />
packets<br />
Input<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
<strong>The</strong> view from the processor<br />
Concurrent waiting<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Sensor input port<br />
Servo output port<br />
radio<br />
packets<br />
read<br />
write<br />
Program<br />
sonar<br />
echoes<br />
read<br />
Radio input port<br />
We ended up with the cyclic executive: one big loop busy waiting<br />
on all input sources!
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Concurrent execution<br />
About laboration 1<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
radio<br />
packets<br />
sonar<br />
echoes<br />
Imagine . . .<br />
. . . that we could interrupt execution of packet decoding when a<br />
sonar echo arrives so that the control algorithm can be ran. <strong>The</strong>n<br />
decoding could resume! <strong>The</strong> two tasks fragments are interleaved.<br />
In lab 1 you will program 3 functions<br />
Writing prime numbers to the LCD<br />
Blinking with a symbol in the LCD<br />
Turing on and off a symbol in the LCD using the joystick<br />
In lab 1 you will then write a big program to do all things at once.<br />
You will then test the cyclic executive and interleaving by hand (to<br />
experience the difficulties with it!)<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Automatic interleaving<br />
Two CPUs<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Sensor input port<br />
Servo output port<br />
<strong>The</strong>re are 2 tasks, driven by independent input sources.<br />
read<br />
CPU1<br />
Controller<br />
write<br />
Handle sonar echoes running the<br />
control algorithm and updating<br />
the servo.<br />
Handle radio packets by running<br />
the decoder.<br />
RAM<br />
parameters<br />
Had we had access to 2 CPUs we could place one task in each. We<br />
can imagine some contruct that allows us to express this in our<br />
program.<br />
CPU2<br />
Controller<br />
read<br />
Radio input port
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Two CPU’s program<br />
struct Params params;<br />
void controller_main(){<br />
int dist, signal;<br />
while(1){<br />
dist = sonar_read();<br />
control(dist,<br />
&signal,<br />
¶ms);<br />
servo_write(signal);<br />
}<br />
}<br />
We need some way of making one program of this!<br />
void decoder_main(){<br />
struct Packet packet;<br />
while(1){<br />
radio_read(&packet);<br />
decode(&packet,¶ms);<br />
}<br />
}<br />
Our first multithreaded program<br />
void controller_main(){<br />
int dist, signal;<br />
while(1){<br />
dist = sonar_read();<br />
control(dist,<br />
&signal,<br />
¶ms);<br />
servo_write(signal);<br />
}<br />
}<br />
struct Params params;<br />
void decoder_main(){<br />
struct Packet packet;<br />
while(1){<br />
radio_read(&packet);<br />
decode(&packet,¶ms);<br />
}<br />
}<br />
main(){<br />
spawn(decoder_main);<br />
controller_main();<br />
}<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
<strong>The</strong> critical section problem<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Critical sections in real life<br />
What will happen if the params struct is read (by the controller)<br />
at the same time it is written (by the decoder)<br />
I.e., what if the scheduler happens to insert some decoder<br />
instructions while some, but not all, of the controller’s reads have<br />
been done<br />
This problem is central to concurrent programming where there is<br />
any ammount of sharing!<br />
Car dealer<br />
Displays used car<br />
Puts up price tag<br />
Displays luxury car<br />
Updates price tag<br />
Car buyer<br />
Becomes interested,sells her old<br />
car<br />
Gets angry!
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Critical sections in real life<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Critical sections in programs<br />
Car dealer<br />
Displays used car<br />
Puts up price tag<br />
Displays luxury car<br />
Updates price tag<br />
Car buyer<br />
Chooses to keep her old car<br />
All good!<br />
Imagine uppdating the same bank account from two places at<br />
approximately the same time (e.g. your employer deposits your<br />
salary at more or less the same time as you are making a small<br />
deposit).<br />
int account = 0;<br />
account = account + 500; account = account + 10000;<br />
When this is compiled there might be several instructions for each<br />
update!<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Critical sections in programs<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Critical sections in programs<br />
load account,r1<br />
add 500,r1<br />
store r1, account<br />
load account, r2<br />
add 10000, r2<br />
store r2, account<br />
load account,r1<br />
add 500,r1<br />
store r1, account<br />
load account, r2<br />
add 10000, r2<br />
store r2, account<br />
Final balance is 10500<br />
Final balance is 10500
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Critical sections in programs<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Critical sections in programs<br />
load account,r1<br />
add 500,r1<br />
store r1, account<br />
Final balance is 500<br />
load account, r2<br />
add 10000, r2<br />
store r2, account<br />
Testing and setting<br />
int shopper;<br />
if(shopper == NONE)<br />
shopper = HUSBAND<br />
Possible interleaving<br />
if(shopper == NONE)<br />
if(shopper==NONE)<br />
shopper = WIFE<br />
if(shopper==NONE)<br />
shopper = HUSBAND<br />
shopper = WIFE<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Our <strong>embedded</strong> <strong>system</strong><br />
Exchanging parameters<br />
struct Params p;<br />
while(1){<br />
while(1){<br />
... local_minD = p.minDistance;<br />
p.minDistance = e1; local_maxS = p.maxSpeed;<br />
p.maxSpeed = e2; ...<br />
} }<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
<strong>The</strong> classical solution<br />
Apply an access protocol to the critical sections that ensures<br />
mutual exclusion<br />
Require that all parties follow the protocol<br />
Possible interleaving<br />
p.minDistance = 1;<br />
p.maxSpeed = 1;<br />
p.minDistance = 200;<br />
p.maxSpeed = 150;<br />
local_minD = 1;<br />
local_maxS = 150<br />
Access protocols are realized by means of a shared datastructure<br />
known as amutex or a lock.
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Mutual exclusion<br />
Exchanging parameters<br />
struct Params p;<br />
mutex m;<br />
while(1){<br />
while(1){<br />
... lock (&m)<br />
lock (&m);<br />
local_minD = p.minDistance;<br />
p.minDistance = e1; local_maxS = p.maxSpeed;<br />
p.maxSpeed = e2;<br />
unlock (&m)<br />
unlock (&m); ...<br />
}<br />
}<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Execution of a C program<br />
<strong>The</strong> following slides will help us understand what we will need to<br />
do to implement threads and automatic interleaving.<br />
SP<br />
Stack<br />
Locals of a()<br />
x =<br />
Globals<br />
v = 0<br />
w v = 0<br />
u = 0<br />
PC<br />
Code<br />
a(){<br />
int x;<br />
}<br />
...<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Execution of a C program<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Execution of a C program<br />
Stack<br />
Code<br />
Stack<br />
Code<br />
SP<br />
Locals of a()<br />
x =<br />
a(){<br />
int x;<br />
SP<br />
Locals of a()<br />
x = 9<br />
a(){<br />
int x;<br />
PC<br />
...<br />
PC<br />
x = 9;<br />
w = 6;<br />
...<br />
}<br />
}<br />
Globals<br />
Globals<br />
v = 0<br />
w v = 0<br />
u = 0<br />
v = 0<br />
w = 6<br />
u = 0
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Execution of a C program<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Execution of a C program<br />
Stack<br />
Code<br />
Stack<br />
Code<br />
SP<br />
Locals of a()<br />
x = 9<br />
a(){<br />
int x;<br />
Locals of a()<br />
x = 9<br />
a(){<br />
int x;<br />
b(int y){<br />
PC<br />
x = 9;<br />
w = 6;<br />
b(55);<br />
SP<br />
Locals of b()<br />
y = 55<br />
x = 9;<br />
w = 6;<br />
b(55);<br />
PC<br />
...<br />
}<br />
}<br />
}<br />
Globals<br />
Globals<br />
v = 0<br />
w = 6<br />
u = 0<br />
v = 0<br />
w = 6<br />
u = 0<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Execution of a C program<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Execution of a C program<br />
Stack<br />
Code<br />
Stack<br />
Code<br />
SP<br />
Locals of a()<br />
x = 9<br />
Locals of b()<br />
y = 55<br />
a(){<br />
int x;<br />
x = 9;<br />
w = 6;<br />
b(55);<br />
}<br />
PC<br />
b(int y){<br />
...<br />
y = c();<br />
}<br />
SP<br />
Locals of a()<br />
x = 9<br />
Locals of b()<br />
y = 55<br />
Locals of c()<br />
z = 23<br />
a(){<br />
int x;<br />
x = 9;<br />
w = 6;<br />
b(55);<br />
}<br />
b(int y){<br />
...<br />
y = c();<br />
}<br />
PC<br />
c(){<br />
int z = 23;<br />
...<br />
}<br />
Globals<br />
Globals<br />
v = 0<br />
w = 6<br />
u = 0<br />
v = 0<br />
w = 6<br />
u = 0
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Execution of a C program<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Execution of a C program<br />
Stack<br />
Code<br />
Stack<br />
Code<br />
SP<br />
Locals of a()<br />
x = 9<br />
Locals of b()<br />
y = 55<br />
Locals of c()<br />
z = 23<br />
a(){<br />
int x;<br />
x = 9;<br />
w = 6;<br />
b(55);<br />
}<br />
b(int y){<br />
...<br />
y = c();<br />
}<br />
PC<br />
c(){<br />
int z = 23;<br />
w = 77;<br />
...<br />
}<br />
SP<br />
Locals of a()<br />
x = 9<br />
Locals of b()<br />
y = 55<br />
Locals of c()<br />
z = 23<br />
a(){<br />
int x;<br />
x = 9;<br />
w = 6;<br />
b(55);<br />
}<br />
b(int y){<br />
...<br />
y = c();<br />
}<br />
PC<br />
c(){<br />
int z = 23;<br />
w = 77;<br />
return z;<br />
}<br />
Globals<br />
Globals<br />
v = 0<br />
w = 77<br />
u = 0<br />
v = 0<br />
w = 77<br />
u = 0<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Execution of a C program<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Execution of a C program<br />
Stack<br />
Code<br />
Stack<br />
Code<br />
SP<br />
Locals of a()<br />
x = 9<br />
Locals of b()<br />
y = 23<br />
a(){<br />
int x;<br />
x = 9;<br />
w = 6;<br />
b(55);<br />
PC<br />
b(int y){<br />
...<br />
y = c();<br />
}<br />
c(){<br />
int z = 23;<br />
w = 77;<br />
return z;<br />
}<br />
SP<br />
Locals of a()<br />
x = 9<br />
PC<br />
a(){<br />
int x;<br />
b(int y){<br />
c(){<br />
int z = 23;<br />
x = 9;<br />
w = 6;<br />
...<br />
w = 77;<br />
b(55);<br />
y = c();<br />
... return z;<br />
}<br />
}<br />
}<br />
}<br />
Globals<br />
Globals<br />
v = 0<br />
w = 77<br />
u = 0<br />
v = 0<br />
w = 77<br />
u = 0
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
2 CPUs<br />
What is it about<br />
struct Params params;<br />
Imagine we had 2 CPUs, then we could run two programs at the<br />
same time!<br />
One way of programming this in only 1 CPU is to keep track of 2<br />
stack pointers and 2 program counters! How to do this is the<br />
content of lecture 4.<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
What might a program look like<br />
void controller_main() {<br />
int dist, signal;<br />
while(1){<br />
dist = sonar_read();<br />
control(dist,<br />
&signal,<br />
¶ms);<br />
servo_write(signal);<br />
}<br />
}<br />
void decoder_main() {<br />
struct Packet packet;<br />
while(1){<br />
radio_read(&packet);<br />
decode(&packet,¶ms);<br />
}<br />
}<br />
We want to provide means for these two mains to execute<br />
concurrently! As if we had 2 CPUs!<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Introducing setjmp/longjmp (non-local goto)<br />
Notice that the function spawn<br />
takes a function as an argument!<br />
<strong>The</strong> role of spawn is to provide<br />
one extra Program Counter and<br />
Stack Pointer<br />
main(){<br />
spawn(decoder_main);<br />
controller_main();<br />
}<br />
We should also provide a way of<br />
interleaving fragments of the<br />
threads.<br />
First we will introduce a way of<br />
yielding execution so that another<br />
thread can take over. Later we<br />
will also see how this function<br />
might be called.<br />
#include<br />
#include<br />
jmp_buf bf;<br />
main(int argc, char*argv[]){<br />
int x = atoi(argv[1]);<br />
while(1){<br />
if( setjmp(bf) ) break;<br />
f(argv[2],x);<br />
}<br />
printf("... Got here!\n\n");<br />
}<br />
void f(char * s, int n){<br />
int y = n-1;<br />
printf(s);<br />
if(y==0) longjmp(bf,1) ;<br />
else f(s, y);<br />
}
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
setjmp/longjmp<br />
Using setjmp/longjmp<br />
1 <strong>The</strong> type jmp buf is declared in the library . It is<br />
known to be an array.<br />
2 <strong>The</strong> operation setjmp(bf) saves the program counter and<br />
the stack pointer to the jmp buf bf.<br />
It returns 0.<br />
3 <strong>The</strong> operation longjmp(bf,n) loads the content of bf to the<br />
program counter and the stack pointer.<br />
It returns n.<br />
longjmp(bf,n) returns after the registers have been restored so it<br />
looks as if it is setjmp(bf) that returns n!<br />
jmp_buf buf;<br />
Locals of a<br />
x = 9<br />
v =<br />
a () {<br />
int x, v;<br />
...<br />
}<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Using setjmp/longjmp<br />
Using setjmp/longjmp<br />
jmp_buf buf;<br />
jmp_buf buf;<br />
Locals of a<br />
a () {<br />
Locals of a<br />
a () {<br />
x = 9<br />
v = 0<br />
int x, v;<br />
x = 9<br />
v = 0<br />
int x, v;<br />
...<br />
...<br />
v = setjmp(buf);<br />
v = setjmp(buf);<br />
...<br />
b();<br />
}<br />
}
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Using setjmp/longjmp<br />
Using setjmp/longjmp<br />
jmp_buf buf;<br />
jmp_buf buf;<br />
Locals of a<br />
a () {<br />
Locals of a<br />
a () {<br />
x = 9<br />
v = 0<br />
int x, v;<br />
x = 9<br />
v = 0<br />
int x, v;<br />
Locals of b<br />
y = 2<br />
...<br />
v = setjmp(buf);<br />
...<br />
b () {<br />
int y;<br />
Locals of b<br />
y = 2<br />
...<br />
v = setjmp(buf);<br />
...<br />
b () {<br />
int y;<br />
b();<br />
...<br />
b();<br />
...<br />
c();<br />
}<br />
}<br />
}<br />
}<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Using setjmp/longjmp<br />
Using setjmp/longjmp<br />
jmp_buf buf;<br />
jmp_buf buf;<br />
Locals of a<br />
a () {<br />
Locals of a<br />
a () {<br />
x = 9<br />
v = 0<br />
int x, v;<br />
x = 9<br />
v = 0<br />
int x, v;<br />
Locals of b<br />
y = 2<br />
Locals of c<br />
...<br />
v = setjmp(buf);<br />
...<br />
b();<br />
b () {<br />
int y;<br />
...<br />
c();<br />
c () {<br />
int z;<br />
...<br />
Locals of b<br />
y = 2<br />
Locals of c<br />
...<br />
v = setjmp(buf);<br />
...<br />
b();<br />
b () {<br />
int y;<br />
...<br />
c();<br />
c () {<br />
int z;<br />
...<br />
longjmp(buf,7);<br />
z = 23<br />
}<br />
}<br />
}<br />
z = 23<br />
}<br />
}<br />
}
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Using setjmp/longjmp<br />
Using setjmp/longjmp<br />
jmp_buf buf;<br />
jmp_buf buf;<br />
Locals of a<br />
a () {<br />
Locals of a<br />
a () {<br />
x = 9<br />
v = 0<br />
int x, v;<br />
x = 9<br />
v = 7<br />
int x, v;<br />
Locals of b<br />
y = 2<br />
Locals of c<br />
...<br />
v = setjmp(buf);<br />
...<br />
b();<br />
b () {<br />
int y;<br />
...<br />
c();<br />
c () {<br />
int z;<br />
...<br />
longjmp(buf,7);<br />
...<br />
v = setjmp(buf);<br />
...<br />
b();<br />
b () {<br />
int y;<br />
...<br />
c();<br />
c () {<br />
int z;<br />
...<br />
longjmp(buf,7);<br />
z = 23<br />
}<br />
}<br />
...<br />
}<br />
}<br />
}<br />
...<br />
}<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Using setjmp/longjmp for our purposes<br />
<strong>The</strong> trick<br />
setjmp(buf);<br />
STACKPTR(buf) = malloc(...);<br />
<strong>The</strong> macro STACKPTR will select the stack pointer part of the<br />
buffer.<br />
We assign to it the address of a new chunk of memory.<br />
<strong>The</strong> size of this chunk of memory is the size of a function-call<br />
stack frame.<br />
This is very much platform dependent!<br />
spawn will do the trick<br />
setjmp(buf);<br />
STACKPTR(buf) = malloc(...);<br />
before calling the function to be executed. <strong>The</strong> function will then<br />
run with its own stack!<br />
After this, the context-switching between threads is just<br />
setjmp(A);longjmp(B);<br />
setjmp(B);longjmp(C);<br />
setjmp(C);longjmp(A);
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Completing the trick<br />
We will have to keep track of the threads, so we introduce a data<br />
structure describing a thread.<br />
struct Thread_Block{<br />
void (*fun)(int) // function to run<br />
int arg; // argument to the above<br />
jmp_buf context, // pc and sp<br />
... // ...<br />
};<br />
typedef struct Thread_Block Thread<br />
We will keep track of threads using global variables for<br />
1 a queue of Threads: the ready queue<br />
2 and the current thread.<br />
Defining spawn<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
void spawn(void (*fun)(int), int arg){<br />
Thread t = malloc(...);<br />
t->fun = fun;<br />
t->arg = arg;<br />
if(setjmp(t->context)!=0){<br />
// this will be done when a longjmp leads here:<br />
current->fun(current->arg);<br />
// What has to be done when the thread<br />
// we spawn for fun terminates<br />
}<br />
// DO the stack pointer trick:<br />
STACKPTR(t->context) = malloc(...);<br />
// enqueue t in the ready queue!<br />
}<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
<strong>The</strong> ready queue, the current thread and yield<br />
Dispatch<br />
<strong>The</strong> need for threads Mutual exclusion <strong>The</strong> C execution model Context Switch<br />
Yielding control<br />
By keeping the runnable threads<br />
in a queue, we can define a<br />
function yield() to switch<br />
execution to another thread.<br />
yield() must<br />
enqueue the current thread in the ready queue<br />
pick a new thread from the ready queue and make it the<br />
current thread<br />
perform the setjmp(A);longjmp(B); trick (also called<br />
dispatch)<br />
void dispatch(Thread next){<br />
if(setjmp(current->context)==0){<br />
current = next;<br />
longjmp(next->context,1);<br />
}<br />
}<br />
<strong>The</strong> function returns directly when control later enters via the fake<br />
return from setjmp.