-
Notifications
You must be signed in to change notification settings - Fork 0
/
fork.bak
197 lines (177 loc) · 5.71 KB
/
fork.bak
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
// implement fork from user space
#include "lib.h"
#include <mmu.h>
#include <env.h>
/* ----------------- help functions ---------------- */
/* Overview:
* Copy `len` bytes from `src` to `dst`.
*
* Pre-Condition:
* `src` and `dst` can't be NULL. Also, the `src` area
* shouldn't overlap the `dest`, otherwise the behavior of this
* function is undefined.
*/
void user_bcopy(const void *src, void *dst, size_t len)
{
void *max;
// writef("~~~~~~~~~~~~~~~~ src:%x dst:%x len:%x\n",(int)src,(int)dst,len);
max = dst + len;
// copy machine words while possible
if (((int)src % 4 == 0) && ((int)dst % 4 == 0)) {
while (dst + 3 < max) {
*(int *)dst = *(int *)src;
dst += 4;
src += 4;
}
}
// finish remaining 0-3 bytes
while (dst < max) {
*(char *)dst = *(char *)src;
dst += 1;
src += 1;
}
//for(;;);
}
/* Overview:
* Sets the first n bytes of the block of memory
* pointed by `v` to zero.
*
* Pre-Condition:
* `v` must be valid.
*
* Post-Condition:
* the content of the space(from `v` to `v`+ n)
* will be set to zero.
*/
void user_bzero(void *v, u_int n)
{
char *p;
int m;
p = v;
m = n;
while (--m >= 0) {
*p++ = 0;
}
}
/*--------------------------------------------------------------*/
/* Overview:
* Custom page fault handler - if faulting page is copy-on-write,
* map in our own private writable copy.
*
* Pre-Condition:
* `va` is the address which leads to a TLBS exception.
*
* Post-Condition:
* Launch a user_panic if `va` is not a copy-on-write page.
* Otherwise, this handler should map a private writable copy of
* the faulting page at correct address.
*/
static void
pgfault(u_int va)
{
u_int *tmp;
// writef("fork.c:pgfault():\t va:%x\n",va);
tmp=UXSTACKTOP-2*BY2PG;
va=ROUNDDOWN(va,BY2PG);
if(!((*vpt)[VPN(va)]&PTE_COW))
{
user_panic("not COW");
}
if(syscall_mem_alloc(0,tmp,PTE_V|PTE_R))
{
user_panic("syscall mem alloc error");
}
user_bcopy((void*)va,tmp,BY2PG);
if(syscall_mem_map(0,tmp,0,va,PTE_V|PTE_R))
{
user_panic("syscall mem map error");
}
if(syscall_mem_unmap(0,tmp))
{
user_panic("syscall mem unmap error");
}
//map the new page at a temporary place
//copy the content
//map the page on the appropriate place
//unmap the temporary place
}
/* Overview:
* Map our virtual page `pn` (address pn*BY2PG) into the target `envid`
* at the same virtual address.
*
* Post-Condition:
* if the page is writable or copy-on-write, the new mapping must be
* created copy on write and then our mapping must be marked
* copy on write as well. In another word, both of the new mapping and
* our mapping should be copy-on-write if the page is writable or
* copy-on-write.
*
* Hint:
* PTE_LIBRARY indicates that the page is shared between processes.
* A page with PTE_LIBRARY may have PTE_R at the same time. You
* should process it correctly.
*/
static void
duppage(u_int envid, u_int pn)
{
/* Note:
* I am afraid I have some bad news for you. There is a ridiculous,
* annoying and awful bug here. I could find another more adjectives
* to qualify it, but you have to reproduce it to understand
* how disturbing it is.
* To reproduce this bug, you should follow the steps bellow:
* 1. uncomment the statement "writef("");" bellow.
* 2. make clean && make
* 3. lauch Gxemul and check the result.
* 4. you can add serveral `writef("");` and repeat step2~3.
* Then, you will find that additional `writef("");` may lead to
* a kernel panic. Interestingly, some students, who faced a strange
* kernel panic problem, found that adding a `writef("");` could solve
* the problem.
* Unfortunately, we cannot find the code which leads to this bug,
* although we have debugged it for serveral weeks. If you face this
* bug, we would like to say "Good luck. God bless."
*/
// writef("");
u_int addr;
u_int perm;
// user_panic("duppage not implemented");
}
/* Overview:
* User-level fork. Create a child and then copy our address space
* and page fault handler setup to the child.
*
* Hint: use vpd, vpt, and duppage.
* Hint: remember to fix "env" in the child process!
* Note: `set_pgfault_handler`(user/pgfault.c) is different from
* `syscall_set_pgfault_handler`.
*/
extern void __asm_pgfault_handler(void);
int
fork(void)
{
// Your code here.
u_int newenvid;
extern struct Env *envs;
extern struct Env *env;
u_int i;
set_pgfault_handler(pgfault);
newenvid=syscall_env_alloc();
if(newenvid==0) {
env=&(envs[ENVX(syscall_getenvid())]);
} else {
syscall_mem_alloc(newenvid, UXSTACKTOP - BY2PG, PTE_V|PTE_R);
syscall_set_pgfault_handler(newenvid, __asm_pgfault_handler, UXSTACKTOP);
syscall_set_env_status(newenvid,ENV_RUNNABLE);
//The parent installs pgfault using set_pgfault_handler
//alloc a new alloc
return newenvid;
}
}
// Challenge!
int
sfork(void)
{
user_panic("sfork not implemented");
return -E_INVAL;
}