-
Notifications
You must be signed in to change notification settings - Fork 1
/
tennis.c
85 lines (67 loc) · 1.85 KB
/
tennis.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/*
A program to demostrate the use of getcontext, swapcontext, makecontext, etc.
Federer returns control to Nadal, who returns control back to Federer....
*/
#include <ucontext.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
static ucontext_t uctx_federer, uctx_nadal;
static void federer(void* p){
double v = *(double*)p;
puts("Federer serves!"); fflush(stdout);
swapcontext(&uctx_federer, &uctx_nadal);
while(rand() / (RAND_MAX+1.0) < v){
puts("Federer returns!");
swapcontext(&uctx_federer, &uctx_nadal);
}
puts("Nadal wins the point!");
}
static void nadal(void *p){
double v = *(double*)p;
while(rand() / (RAND_MAX+1.0) < v){
puts("Nadal returns!");
swapcontext(&uctx_nadal, &uctx_federer);
}
puts("Federer wins the point!");
}
int main(int argc, char *argv[]) {
ucontext_t uctx_main;
double p = 0.9;
/*
getcontext must be called on a uncontext object
before makecontext can.
*/
if (getcontext(&uctx_federer) == -1 ||
getcontext(&uctx_nadal) == -1){
perror("getcontext");
exit(EXIT_FAILURE);
}
/*
Allocating a new stacks
*/
uctx_federer.uc_stack.ss_sp = (char*) malloc(SIGSTKSZ);
uctx_federer.uc_stack.ss_size = SIGSTKSZ;
uctx_nadal.uc_stack.ss_sp = (char*) malloc(SIGSTKSZ);
uctx_nadal.uc_stack.ss_size = SIGSTKSZ;
/*
Setting the successor context
*/
uctx_federer.uc_link = &uctx_main;
uctx_nadal.uc_link = &uctx_main;
/*
makecontext sets the starting routine for the context
*/
makecontext(&uctx_federer, federer, 1, &p);
makecontext(&uctx_nadal, nadal, 1, &p);
/*
federer serves. When we switch back to uctx_main,
control will resume here.
*/
if (swapcontext(&uctx_main, &uctx_federer) == -1){
perror("swapcontext");
exit(EXIT_FAILURE);
}
printf("main: exiting\n");
exit(EXIT_SUCCESS);
}