add lab4 spoc exercises
This commit is contained in:
parent
91d8793b24
commit
28605e36e7
3
related_info/lab4/some-exercises/build-2.sh
Executable file
3
related_info/lab4/some-exercises/build-2.sh
Executable file
@ -0,0 +1,3 @@
|
||||
as -gstabs --32 -o callee.o callee.s
|
||||
gcc -m32 -g -c -fno-stack-protector caller.c
|
||||
gcc -m32 -g -o caller caller.o callee.o
|
2
related_info/lab4/some-exercises/build.sh
Executable file
2
related_info/lab4/some-exercises/build.sh
Executable file
@ -0,0 +1,2 @@
|
||||
as -arch i386 -o prog.o prog.s
|
||||
ld -arch i386 -o prog prog.o
|
5
related_info/lab4/some-exercises/call.c
Normal file
5
related_info/lab4/some-exercises/call.c
Normal file
@ -0,0 +1,5 @@
|
||||
int addtwo(int a)
|
||||
{
|
||||
int x = 2;
|
||||
return a + x;
|
||||
}
|
11
related_info/lab4/some-exercises/call2.c
Normal file
11
related_info/lab4/some-exercises/call2.c
Normal file
@ -0,0 +1,11 @@
|
||||
void func2(int a, int b)
|
||||
{
|
||||
a++;
|
||||
b+=2;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
func2( 1111, 2222);
|
||||
return 0;
|
||||
}
|
218
related_info/lab4/some-exercises/call2.s
Normal file
218
related_info/lab4/some-exercises/call2.s
Normal file
@ -0,0 +1,218 @@
|
||||
|
||||
call2: file format elf32-i386
|
||||
|
||||
|
||||
Disassembly of section .init:
|
||||
|
||||
08048294 <_init>:
|
||||
8048294: 53 push %ebx
|
||||
8048295: 83 ec 08 sub $0x8,%esp
|
||||
8048298: e8 83 00 00 00 call 8048320 <__x86.get_pc_thunk.bx>
|
||||
804829d: 81 c3 63 1d 00 00 add $0x1d63,%ebx
|
||||
80482a3: 8b 83 fc ff ff ff mov -0x4(%ebx),%eax
|
||||
80482a9: 85 c0 test %eax,%eax
|
||||
80482ab: 74 05 je 80482b2 <_init+0x1e>
|
||||
80482ad: e8 1e 00 00 00 call 80482d0 <__gmon_start__@plt>
|
||||
80482b2: 83 c4 08 add $0x8,%esp
|
||||
80482b5: 5b pop %ebx
|
||||
80482b6: c3 ret
|
||||
|
||||
Disassembly of section .plt:
|
||||
|
||||
080482c0 <__gmon_start__@plt-0x10>:
|
||||
80482c0: ff 35 04 a0 04 08 pushl 0x804a004
|
||||
80482c6: ff 25 08 a0 04 08 jmp *0x804a008
|
||||
80482cc: 00 00 add %al,(%eax)
|
||||
...
|
||||
|
||||
080482d0 <__gmon_start__@plt>:
|
||||
80482d0: ff 25 0c a0 04 08 jmp *0x804a00c
|
||||
80482d6: 68 00 00 00 00 push $0x0
|
||||
80482db: e9 e0 ff ff ff jmp 80482c0 <_init+0x2c>
|
||||
|
||||
080482e0 <__libc_start_main@plt>:
|
||||
80482e0: ff 25 10 a0 04 08 jmp *0x804a010
|
||||
80482e6: 68 08 00 00 00 push $0x8
|
||||
80482eb: e9 d0 ff ff ff jmp 80482c0 <_init+0x2c>
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
080482f0 <main>:
|
||||
|
||||
int main()
|
||||
{
|
||||
func2( 1111, 2222);
|
||||
return 0;
|
||||
}
|
||||
80482f0: 31 c0 xor %eax,%eax
|
||||
80482f2: c3 ret
|
||||
|
||||
080482f3 <_start>:
|
||||
80482f3: 31 ed xor %ebp,%ebp
|
||||
80482f5: 5e pop %esi
|
||||
80482f6: 89 e1 mov %esp,%ecx
|
||||
80482f8: 83 e4 f0 and $0xfffffff0,%esp
|
||||
80482fb: 50 push %eax
|
||||
80482fc: 54 push %esp
|
||||
80482fd: 52 push %edx
|
||||
80482fe: 68 60 84 04 08 push $0x8048460
|
||||
8048303: 68 00 84 04 08 push $0x8048400
|
||||
8048308: 51 push %ecx
|
||||
8048309: 56 push %esi
|
||||
804830a: 68 f0 82 04 08 push $0x80482f0
|
||||
804830f: e8 cc ff ff ff call 80482e0 <__libc_start_main@plt>
|
||||
8048314: f4 hlt
|
||||
8048315: 66 90 xchg %ax,%ax
|
||||
8048317: 66 90 xchg %ax,%ax
|
||||
8048319: 66 90 xchg %ax,%ax
|
||||
804831b: 66 90 xchg %ax,%ax
|
||||
804831d: 66 90 xchg %ax,%ax
|
||||
804831f: 90 nop
|
||||
|
||||
08048320 <__x86.get_pc_thunk.bx>:
|
||||
8048320: 8b 1c 24 mov (%esp),%ebx
|
||||
8048323: c3 ret
|
||||
8048324: 66 90 xchg %ax,%ax
|
||||
8048326: 66 90 xchg %ax,%ax
|
||||
8048328: 66 90 xchg %ax,%ax
|
||||
804832a: 66 90 xchg %ax,%ax
|
||||
804832c: 66 90 xchg %ax,%ax
|
||||
804832e: 66 90 xchg %ax,%ax
|
||||
|
||||
08048330 <deregister_tm_clones>:
|
||||
8048330: b8 1f a0 04 08 mov $0x804a01f,%eax
|
||||
8048335: 2d 1c a0 04 08 sub $0x804a01c,%eax
|
||||
804833a: 83 f8 06 cmp $0x6,%eax
|
||||
804833d: 76 1a jbe 8048359 <deregister_tm_clones+0x29>
|
||||
804833f: b8 00 00 00 00 mov $0x0,%eax
|
||||
8048344: 85 c0 test %eax,%eax
|
||||
8048346: 74 11 je 8048359 <deregister_tm_clones+0x29>
|
||||
8048348: 55 push %ebp
|
||||
8048349: 89 e5 mov %esp,%ebp
|
||||
804834b: 83 ec 14 sub $0x14,%esp
|
||||
804834e: 68 1c a0 04 08 push $0x804a01c
|
||||
8048353: ff d0 call *%eax
|
||||
8048355: 83 c4 10 add $0x10,%esp
|
||||
8048358: c9 leave
|
||||
8048359: f3 c3 repz ret
|
||||
804835b: 90 nop
|
||||
804835c: 8d 74 26 00 lea 0x0(%esi,%eiz,1),%esi
|
||||
|
||||
08048360 <register_tm_clones>:
|
||||
8048360: b8 1c a0 04 08 mov $0x804a01c,%eax
|
||||
8048365: 2d 1c a0 04 08 sub $0x804a01c,%eax
|
||||
804836a: c1 f8 02 sar $0x2,%eax
|
||||
804836d: 89 c2 mov %eax,%edx
|
||||
804836f: c1 ea 1f shr $0x1f,%edx
|
||||
8048372: 01 d0 add %edx,%eax
|
||||
8048374: d1 f8 sar %eax
|
||||
8048376: 74 1b je 8048393 <register_tm_clones+0x33>
|
||||
8048378: ba 00 00 00 00 mov $0x0,%edx
|
||||
804837d: 85 d2 test %edx,%edx
|
||||
804837f: 74 12 je 8048393 <register_tm_clones+0x33>
|
||||
8048381: 55 push %ebp
|
||||
8048382: 89 e5 mov %esp,%ebp
|
||||
8048384: 83 ec 10 sub $0x10,%esp
|
||||
8048387: 50 push %eax
|
||||
8048388: 68 1c a0 04 08 push $0x804a01c
|
||||
804838d: ff d2 call *%edx
|
||||
804838f: 83 c4 10 add $0x10,%esp
|
||||
8048392: c9 leave
|
||||
8048393: f3 c3 repz ret
|
||||
8048395: 8d 74 26 00 lea 0x0(%esi,%eiz,1),%esi
|
||||
8048399: 8d bc 27 00 00 00 00 lea 0x0(%edi,%eiz,1),%edi
|
||||
|
||||
080483a0 <__do_global_dtors_aux>:
|
||||
80483a0: 80 3d 1c a0 04 08 00 cmpb $0x0,0x804a01c
|
||||
80483a7: 75 13 jne 80483bc <__do_global_dtors_aux+0x1c>
|
||||
80483a9: 55 push %ebp
|
||||
80483aa: 89 e5 mov %esp,%ebp
|
||||
80483ac: 83 ec 08 sub $0x8,%esp
|
||||
80483af: e8 7c ff ff ff call 8048330 <deregister_tm_clones>
|
||||
80483b4: c6 05 1c a0 04 08 01 movb $0x1,0x804a01c
|
||||
80483bb: c9 leave
|
||||
80483bc: f3 c3 repz ret
|
||||
80483be: 66 90 xchg %ax,%ax
|
||||
|
||||
080483c0 <frame_dummy>:
|
||||
80483c0: b8 10 9f 04 08 mov $0x8049f10,%eax
|
||||
80483c5: 8b 10 mov (%eax),%edx
|
||||
80483c7: 85 d2 test %edx,%edx
|
||||
80483c9: 75 05 jne 80483d0 <frame_dummy+0x10>
|
||||
80483cb: eb 93 jmp 8048360 <register_tm_clones>
|
||||
80483cd: 8d 76 00 lea 0x0(%esi),%esi
|
||||
80483d0: ba 00 00 00 00 mov $0x0,%edx
|
||||
80483d5: 85 d2 test %edx,%edx
|
||||
80483d7: 74 f2 je 80483cb <frame_dummy+0xb>
|
||||
80483d9: 55 push %ebp
|
||||
80483da: 89 e5 mov %esp,%ebp
|
||||
80483dc: 83 ec 14 sub $0x14,%esp
|
||||
80483df: 50 push %eax
|
||||
80483e0: ff d2 call *%edx
|
||||
80483e2: 83 c4 10 add $0x10,%esp
|
||||
80483e5: c9 leave
|
||||
80483e6: e9 75 ff ff ff jmp 8048360 <register_tm_clones>
|
||||
80483eb: 66 90 xchg %ax,%ax
|
||||
80483ed: 66 90 xchg %ax,%ax
|
||||
80483ef: 90 nop
|
||||
|
||||
080483f0 <func2>:
|
||||
void func2(int a, int b)
|
||||
{
|
||||
80483f0: f3 c3 repz ret
|
||||
80483f2: 66 90 xchg %ax,%ax
|
||||
80483f4: 66 90 xchg %ax,%ax
|
||||
80483f6: 66 90 xchg %ax,%ax
|
||||
80483f8: 66 90 xchg %ax,%ax
|
||||
80483fa: 66 90 xchg %ax,%ax
|
||||
80483fc: 66 90 xchg %ax,%ax
|
||||
80483fe: 66 90 xchg %ax,%ax
|
||||
|
||||
08048400 <__libc_csu_init>:
|
||||
8048400: 55 push %ebp
|
||||
8048401: 57 push %edi
|
||||
8048402: 31 ff xor %edi,%edi
|
||||
8048404: 56 push %esi
|
||||
8048405: 53 push %ebx
|
||||
8048406: e8 15 ff ff ff call 8048320 <__x86.get_pc_thunk.bx>
|
||||
804840b: 81 c3 f5 1b 00 00 add $0x1bf5,%ebx
|
||||
8048411: 83 ec 0c sub $0xc,%esp
|
||||
8048414: 8b 6c 24 20 mov 0x20(%esp),%ebp
|
||||
8048418: 8d b3 0c ff ff ff lea -0xf4(%ebx),%esi
|
||||
804841e: e8 71 fe ff ff call 8048294 <_init>
|
||||
8048423: 8d 83 08 ff ff ff lea -0xf8(%ebx),%eax
|
||||
8048429: 29 c6 sub %eax,%esi
|
||||
804842b: c1 fe 02 sar $0x2,%esi
|
||||
804842e: 85 f6 test %esi,%esi
|
||||
8048430: 74 23 je 8048455 <__libc_csu_init+0x55>
|
||||
8048432: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
|
||||
8048438: 83 ec 04 sub $0x4,%esp
|
||||
804843b: ff 74 24 2c pushl 0x2c(%esp)
|
||||
804843f: ff 74 24 2c pushl 0x2c(%esp)
|
||||
8048443: 55 push %ebp
|
||||
8048444: ff 94 bb 08 ff ff ff call *-0xf8(%ebx,%edi,4)
|
||||
804844b: 83 c7 01 add $0x1,%edi
|
||||
804844e: 83 c4 10 add $0x10,%esp
|
||||
8048451: 39 f7 cmp %esi,%edi
|
||||
8048453: 75 e3 jne 8048438 <__libc_csu_init+0x38>
|
||||
8048455: 83 c4 0c add $0xc,%esp
|
||||
8048458: 5b pop %ebx
|
||||
8048459: 5e pop %esi
|
||||
804845a: 5f pop %edi
|
||||
804845b: 5d pop %ebp
|
||||
804845c: c3 ret
|
||||
804845d: 8d 76 00 lea 0x0(%esi),%esi
|
||||
|
||||
08048460 <__libc_csu_fini>:
|
||||
8048460: f3 c3 repz ret
|
||||
|
||||
Disassembly of section .fini:
|
||||
|
||||
08048464 <_fini>:
|
||||
8048464: 53 push %ebx
|
||||
8048465: 83 ec 08 sub $0x8,%esp
|
||||
8048468: e8 b3 fe ff ff call 8048320 <__x86.get_pc_thunk.bx>
|
||||
804846d: 81 c3 93 1b 00 00 add $0x1b93,%ebx
|
||||
8048473: 83 c4 08 add $0x8,%esp
|
||||
8048476: 5b pop %ebx
|
||||
8048477: c3 ret
|
17
related_info/lab4/some-exercises/callee.s
Normal file
17
related_info/lab4/some-exercises/callee.s
Normal file
@ -0,0 +1,17 @@
|
||||
.code32
|
||||
SYSWRITE = 4 # sys_write()系统调用号
|
||||
.global mywrite
|
||||
.text
|
||||
mywrite:
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
pushl %ebx
|
||||
movl 8(%ebp),%ebx # ebx :文件描述符
|
||||
movl 12(%ebp),%ecx # ecx :缓冲区指针
|
||||
movl 16(%ebp),%edx # edx :显示字符数
|
||||
movl $SYSWRITE,%eax # eax :系统调用号
|
||||
int $0x80
|
||||
popl %ebx
|
||||
mov %ebp, %esp
|
||||
popl %ebp
|
||||
ret
|
7
related_info/lab4/some-exercises/caller.c
Normal file
7
related_info/lab4/some-exercises/caller.c
Normal file
@ -0,0 +1,7 @@
|
||||
#include <string.h>
|
||||
int main()
|
||||
{
|
||||
char* mystr = "Welcome to baby OS!\n";
|
||||
mywrite(1, mystr, strlen(mystr));
|
||||
return 0;
|
||||
}
|
411
related_info/lab4/some-exercises/proc.c
Normal file
411
related_info/lab4/some-exercises/proc.c
Normal file
@ -0,0 +1,411 @@
|
||||
#include <proc.h>
|
||||
#include <kmalloc.h>
|
||||
#include <string.h>
|
||||
#include <sync.h>
|
||||
#include <pmm.h>
|
||||
#include <error.h>
|
||||
#include <sched.h>
|
||||
#include <elf.h>
|
||||
#include <vmm.h>
|
||||
#include <trap.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* ------------- process/thread mechanism design&implementation -------------
|
||||
(an simplified Linux process/thread mechanism )
|
||||
introduction:
|
||||
ucore implements a simple process/thread mechanism. process contains the independent memory sapce, at least one threads
|
||||
for execution, the kernel data(for management), processor state (for context switch), files(in lab6), etc. ucore needs to
|
||||
manage all these details efficiently. In ucore, a thread is just a special kind of process(share process's memory).
|
||||
------------------------------
|
||||
process state : meaning -- reason
|
||||
PROC_UNINIT : uninitialized -- alloc_proc
|
||||
PROC_SLEEPING : sleeping -- try_free_pages, do_wait, do_sleep
|
||||
PROC_RUNNABLE : runnable(maybe running) -- proc_init, wakeup_proc,
|
||||
PROC_ZOMBIE : almost dead -- do_exit
|
||||
|
||||
-----------------------------
|
||||
process state changing:
|
||||
|
||||
alloc_proc RUNNING
|
||||
+ +--<----<--+
|
||||
+ + proc_run +
|
||||
V +-->---->--+
|
||||
PROC_UNINIT -- proc_init/wakeup_proc --> PROC_RUNNABLE -- try_free_pages/do_wait/do_sleep --> PROC_SLEEPING --
|
||||
A + +
|
||||
| +--- do_exit --> PROC_ZOMBIE +
|
||||
+ +
|
||||
-----------------------wakeup_proc----------------------------------
|
||||
-----------------------------
|
||||
process relations
|
||||
parent: proc->parent (proc is children)
|
||||
children: proc->cptr (proc is parent)
|
||||
older sibling: proc->optr (proc is younger sibling)
|
||||
younger sibling: proc->yptr (proc is older sibling)
|
||||
-----------------------------
|
||||
related syscall for process:
|
||||
SYS_exit : process exit, -->do_exit
|
||||
SYS_fork : create child process, dup mm -->do_fork-->wakeup_proc
|
||||
SYS_wait : wait process -->do_wait
|
||||
SYS_exec : after fork, process execute a program -->load a program and refresh the mm
|
||||
SYS_clone : create child thread -->do_fork-->wakeup_proc
|
||||
SYS_yield : process flag itself need resecheduling, -- proc->need_sched=1, then scheduler will rescheule this process
|
||||
SYS_sleep : process sleep -->do_sleep
|
||||
SYS_kill : kill process -->do_kill-->proc->flags |= PF_EXITING
|
||||
-->wakeup_proc-->do_wait-->do_exit
|
||||
SYS_getpid : get the process's pid
|
||||
|
||||
*/
|
||||
|
||||
// the process set's list
|
||||
list_entry_t proc_list;
|
||||
|
||||
#define HASH_SHIFT 10
|
||||
#define HASH_LIST_SIZE (1 << HASH_SHIFT)
|
||||
#define pid_hashfn(x) (hash32(x, HASH_SHIFT))
|
||||
|
||||
// has list for process set based on pid
|
||||
static list_entry_t hash_list[HASH_LIST_SIZE];
|
||||
|
||||
// idle proc
|
||||
struct proc_struct *idleproc = NULL;
|
||||
// init proc
|
||||
struct proc_struct *initproc = NULL;
|
||||
// current proc
|
||||
struct proc_struct *current = NULL;
|
||||
|
||||
static int nr_process = 0;
|
||||
|
||||
void kernel_thread_entry(void);
|
||||
void forkrets(struct trapframe *tf);
|
||||
void switch_to(struct context *from, struct context *to);
|
||||
|
||||
// alloc_proc - alloc a proc_struct and init all fields of proc_struct
|
||||
static struct proc_struct *
|
||||
alloc_proc(void) {
|
||||
struct proc_struct *proc = kmalloc(sizeof(struct proc_struct));
|
||||
if (proc != NULL) {
|
||||
//LAB4:EXERCISE1 YOUR CODE
|
||||
/*
|
||||
* below fields in proc_struct need to be initialized
|
||||
* enum proc_state state; // Process state
|
||||
* int pid; // Process ID
|
||||
* int runs; // the running times of Proces
|
||||
* uintptr_t kstack; // Process kernel stack
|
||||
* volatile bool need_resched; // bool value: need to be rescheduled to release CPU?
|
||||
* struct proc_struct *parent; // the parent process
|
||||
* struct mm_struct *mm; // Process's memory management field
|
||||
* struct context context; // Switch here to run process
|
||||
* struct trapframe *tf; // Trap frame for current interrupt
|
||||
* uintptr_t cr3; // CR3 register: the base addr of Page Directroy Table(PDT)
|
||||
* uint32_t flags; // Process flag
|
||||
* char name[PROC_NAME_LEN + 1]; // Process name
|
||||
*/
|
||||
proc->state = PROC_UNINIT;
|
||||
proc->pid = -1;
|
||||
proc->runs = 0;
|
||||
proc->kstack = 0;
|
||||
proc->need_resched = 0;
|
||||
proc->parent = NULL;
|
||||
proc->mm = NULL;
|
||||
memset(&(proc->context), 0, sizeof(struct context));
|
||||
proc->tf = NULL;
|
||||
proc->cr3 = boot_cr3;
|
||||
proc->flags = 0;
|
||||
memset(proc->name, 0, PROC_NAME_LEN);
|
||||
}
|
||||
return proc;
|
||||
}
|
||||
|
||||
// set_proc_name - set the name of proc
|
||||
char *
|
||||
set_proc_name(struct proc_struct *proc, const char *name) {
|
||||
memset(proc->name, 0, sizeof(proc->name));
|
||||
return memcpy(proc->name, name, PROC_NAME_LEN);
|
||||
}
|
||||
|
||||
// get_proc_name - get the name of proc
|
||||
char *
|
||||
get_proc_name(struct proc_struct *proc) {
|
||||
static char name[PROC_NAME_LEN + 1];
|
||||
memset(name, 0, sizeof(name));
|
||||
return memcpy(name, proc->name, PROC_NAME_LEN);
|
||||
}
|
||||
|
||||
// get_pid - alloc a unique pid for process
|
||||
static int
|
||||
get_pid(void) {
|
||||
static_assert(MAX_PID > MAX_PROCESS);
|
||||
struct proc_struct *proc;
|
||||
list_entry_t *list = &proc_list, *le;
|
||||
static int next_safe = MAX_PID, last_pid = MAX_PID;
|
||||
if (++ last_pid >= MAX_PID) {
|
||||
last_pid = 1;
|
||||
goto inside;
|
||||
}
|
||||
if (last_pid >= next_safe) {
|
||||
inside:
|
||||
next_safe = MAX_PID;
|
||||
repeat:
|
||||
le = list;
|
||||
while ((le = list_next(le)) != list) {
|
||||
proc = le2proc(le, list_link);
|
||||
if (proc->pid == last_pid) {
|
||||
if (++ last_pid >= next_safe) {
|
||||
if (last_pid >= MAX_PID) {
|
||||
last_pid = 1;
|
||||
}
|
||||
next_safe = MAX_PID;
|
||||
goto repeat;
|
||||
}
|
||||
}
|
||||
else if (proc->pid > last_pid && next_safe > proc->pid) {
|
||||
next_safe = proc->pid;
|
||||
}
|
||||
}
|
||||
}
|
||||
return last_pid;
|
||||
}
|
||||
|
||||
// proc_run - make process "proc" running on cpu
|
||||
// NOTE: before call switch_to, should load base addr of "proc"'s new PDT
|
||||
void
|
||||
proc_run(struct proc_struct *proc) {
|
||||
if (proc != current) {
|
||||
bool intr_flag;
|
||||
struct proc_struct *prev = current, *next = proc;
|
||||
local_intr_save(intr_flag);
|
||||
{
|
||||
current = proc;
|
||||
load_esp0(next->kstack + KSTACKSIZE);
|
||||
lcr3(next->cr3);
|
||||
switch_to(&(prev->context), &(next->context));
|
||||
}
|
||||
local_intr_restore(intr_flag);
|
||||
}
|
||||
}
|
||||
|
||||
// forkret -- the first kernel entry point of a new thread/process
|
||||
// NOTE: the addr of forkret is setted in copy_thread function
|
||||
// after switch_to, the current proc will execute here.
|
||||
static void
|
||||
forkret(void) {
|
||||
forkrets(current->tf);
|
||||
}
|
||||
|
||||
// hash_proc - add proc into proc hash_list
|
||||
static void
|
||||
hash_proc(struct proc_struct *proc) {
|
||||
list_add(hash_list + pid_hashfn(proc->pid), &(proc->hash_link));
|
||||
}
|
||||
|
||||
// find_proc - find proc frome proc hash_list according to pid
|
||||
struct proc_struct *
|
||||
find_proc(int pid) {
|
||||
if (0 < pid && pid < MAX_PID) {
|
||||
list_entry_t *list = hash_list + pid_hashfn(pid), *le = list;
|
||||
while ((le = list_next(le)) != list) {
|
||||
struct proc_struct *proc = le2proc(le, hash_link);
|
||||
if (proc->pid == pid) {
|
||||
return proc;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// kernel_thread - create a kernel thread using "fn" function
|
||||
// NOTE: the contents of temp trapframe tf will be copied to
|
||||
// proc->tf in do_fork-->copy_thread function
|
||||
int
|
||||
kernel_thread(int (*fn)(void *), void *arg, uint32_t clone_flags) {
|
||||
struct trapframe tf;
|
||||
memset(&tf, 0, sizeof(struct trapframe));
|
||||
tf.tf_cs = KERNEL_CS;
|
||||
tf.tf_ds = tf.tf_es = tf.tf_ss = KERNEL_DS;
|
||||
tf.tf_regs.reg_ebx = (uint32_t)fn;
|
||||
tf.tf_regs.reg_edx = (uint32_t)arg;
|
||||
tf.tf_eip = (uint32_t)kernel_thread_entry;
|
||||
return do_fork(clone_flags | CLONE_VM, 0, &tf);
|
||||
}
|
||||
|
||||
// setup_kstack - alloc pages with size KSTACKPAGE as process kernel stack
|
||||
static int
|
||||
setup_kstack(struct proc_struct *proc) {
|
||||
struct Page *page = alloc_pages(KSTACKPAGE);
|
||||
if (page != NULL) {
|
||||
proc->kstack = (uintptr_t)page2kva(page);
|
||||
return 0;
|
||||
}
|
||||
return -E_NO_MEM;
|
||||
}
|
||||
|
||||
// put_kstack - free the memory space of process kernel stack
|
||||
static void
|
||||
put_kstack(struct proc_struct *proc) {
|
||||
free_pages(kva2page((void *)(proc->kstack)), KSTACKPAGE);
|
||||
}
|
||||
|
||||
// copy_mm - process "proc" duplicate OR share process "current"'s mm according clone_flags
|
||||
// - if clone_flags & CLONE_VM, then "share" ; else "duplicate"
|
||||
static int
|
||||
copy_mm(uint32_t clone_flags, struct proc_struct *proc) {
|
||||
assert(current->mm == NULL);
|
||||
/* do nothing in this project */
|
||||
return 0;
|
||||
}
|
||||
|
||||
// copy_thread - setup the trapframe on the process's kernel stack top and
|
||||
// - setup the kernel entry point and stack of process
|
||||
static void
|
||||
copy_thread(struct proc_struct *proc, uintptr_t esp, struct trapframe *tf) {
|
||||
proc->tf = (struct trapframe *)(proc->kstack + KSTACKSIZE) - 1;
|
||||
*(proc->tf) = *tf;
|
||||
proc->tf->tf_regs.reg_eax = 0;
|
||||
proc->tf->tf_esp = esp;
|
||||
proc->tf->tf_eflags |= FL_IF;
|
||||
|
||||
proc->context.eip = (uintptr_t)forkret;
|
||||
proc->context.esp = (uintptr_t)(proc->tf);
|
||||
}
|
||||
|
||||
/* do_fork - parent process for a new child process
|
||||
* @clone_flags: used to guide how to clone the child process
|
||||
* @stack: the parent's user stack pointer. if stack==0, It means to fork a kernel thread.
|
||||
* @tf: the trapframe info, which will be copied to child process's proc->tf
|
||||
*/
|
||||
int
|
||||
do_fork(uint32_t clone_flags, uintptr_t stack, struct trapframe *tf) {
|
||||
int ret = -E_NO_FREE_PROC;
|
||||
struct proc_struct *proc;
|
||||
if (nr_process >= MAX_PROCESS) {
|
||||
goto fork_out;
|
||||
}
|
||||
ret = -E_NO_MEM;
|
||||
//LAB4:EXERCISE2 YOUR CODE
|
||||
/*
|
||||
* Some Useful MACROs, Functions and DEFINEs, you can use them in below implementation.
|
||||
* MACROs or Functions:
|
||||
* alloc_proc: create a proc struct and init fields (lab4:exercise1)
|
||||
* setup_kstack: alloc pages with size KSTACKPAGE as process kernel stack
|
||||
* copy_mm: process "proc" duplicate OR share process "current"'s mm according clone_flags
|
||||
* if clone_flags & CLONE_VM, then "share" ; else "duplicate"
|
||||
* copy_thread: setup the trapframe on the process's kernel stack top and
|
||||
* setup the kernel entry point and stack of process
|
||||
* hash_proc: add proc into proc hash_list
|
||||
* get_pid: alloc a unique pid for process
|
||||
* wakeup_proc: set proc->state = PROC_RUNNABLE
|
||||
* VARIABLES:
|
||||
* proc_list: the process set's list
|
||||
* nr_process: the number of process set
|
||||
*/
|
||||
|
||||
// 1. call alloc_proc to allocate a proc_struct
|
||||
// 2. call setup_kstack to allocate a kernel stack for child process
|
||||
// 3. call copy_mm to dup OR share mm according clone_flag
|
||||
// 4. call copy_thread to setup tf & context in proc_struct
|
||||
// 5. insert proc_struct into hash_list && proc_list
|
||||
// 6. call wakeup_proc to make the new child process RUNNABLE
|
||||
// 7. set ret vaule using child proc's pid
|
||||
if ((proc = alloc_proc()) == NULL) {
|
||||
goto fork_out;
|
||||
}
|
||||
|
||||
proc->parent = current;
|
||||
|
||||
if (setup_kstack(proc) != 0) {
|
||||
goto bad_fork_cleanup_proc;
|
||||
}
|
||||
if (copy_mm(clone_flags, proc) != 0) {
|
||||
goto bad_fork_cleanup_kstack;
|
||||
}
|
||||
copy_thread(proc, stack, tf);
|
||||
|
||||
bool intr_flag;
|
||||
local_intr_save(intr_flag);
|
||||
{
|
||||
proc->pid = get_pid();
|
||||
hash_proc(proc);
|
||||
list_add(&proc_list, &(proc->list_link));
|
||||
nr_process ++;
|
||||
}
|
||||
local_intr_restore(intr_flag);
|
||||
|
||||
wakeup_proc(proc);
|
||||
|
||||
ret = proc->pid;
|
||||
fork_out:
|
||||
return ret;
|
||||
|
||||
bad_fork_cleanup_kstack:
|
||||
put_kstack(proc);
|
||||
bad_fork_cleanup_proc:
|
||||
kfree(proc);
|
||||
goto fork_out;
|
||||
}
|
||||
|
||||
// do_exit - called by sys_exit
|
||||
// 1. call exit_mmap & put_pgdir & mm_destroy to free the almost all memory space of process
|
||||
// 2. set process' state as PROC_ZOMBIE, then call wakeup_proc(parent) to ask parent reclaim itself.
|
||||
// 3. call scheduler to switch to other process
|
||||
int
|
||||
do_exit(int error_code) {
|
||||
panic("process exit!!.\n");
|
||||
}
|
||||
|
||||
// init_main - the second kernel thread used to create user_main kernel threads
|
||||
static int
|
||||
init_main(void *arg) {
|
||||
cprintf("this initproc, pid = %d, name = \"%s\"\n", current->pid, get_proc_name(current));
|
||||
cprintf("To U: \"%s\".\n", (const char *)arg);
|
||||
cprintf("To U: \"en.., Bye, Bye. :)\"\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// proc_init - set up the first kernel thread idleproc "idle" by itself and
|
||||
// - create the second kernel thread init_main
|
||||
void
|
||||
proc_init(void) {
|
||||
int i;
|
||||
|
||||
list_init(&proc_list);
|
||||
for (i = 0; i < HASH_LIST_SIZE; i ++) {
|
||||
list_init(hash_list + i);
|
||||
}
|
||||
|
||||
if ((idleproc = alloc_proc()) == NULL) {
|
||||
panic("cannot alloc idleproc.\n");
|
||||
}
|
||||
|
||||
idleproc->pid = 0;
|
||||
idleproc->state = PROC_RUNNABLE;
|
||||
idleproc->kstack = (uintptr_t)bootstack;
|
||||
idleproc->need_resched = 1;
|
||||
set_proc_name(idleproc, "idle");
|
||||
nr_process ++;
|
||||
|
||||
current = idleproc;
|
||||
|
||||
int pid = kernel_thread(init_main, "Hello world!!", 0);
|
||||
if (pid <= 0) {
|
||||
panic("create init_main failed.\n");
|
||||
}
|
||||
|
||||
initproc = find_proc(pid);
|
||||
set_proc_name(initproc, "init");
|
||||
|
||||
assert(idleproc != NULL && idleproc->pid == 0);
|
||||
assert(initproc != NULL && initproc->pid == 1);
|
||||
}
|
||||
|
||||
// cpu_idle - at the end of kern_init, the first kernel thread idleproc will do below works
|
||||
void
|
||||
cpu_idle(void) {
|
||||
while (1) {
|
||||
if (current->need_resched) {
|
||||
schedule();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
8
related_info/lab4/some-exercises/prog.s
Normal file
8
related_info/lab4/some-exercises/prog.s
Normal file
@ -0,0 +1,8 @@
|
||||
.section __TEXT,__text
|
||||
.globl start
|
||||
start:
|
||||
mov $0x1, %eax
|
||||
push $0x0
|
||||
call _syscall
|
||||
_syscall:
|
||||
int $0x80
|
30
related_info/lab4/some-exercises/switch.S
Normal file
30
related_info/lab4/some-exercises/switch.S
Normal file
@ -0,0 +1,30 @@
|
||||
.text
|
||||
.globl switch_to
|
||||
switch_to: # switch_to(from, to)
|
||||
|
||||
# save from's registers
|
||||
movl 4(%esp), %eax # eax points to from
|
||||
popl 0(%eax) # save eip !popl
|
||||
movl %esp, 4(%eax)
|
||||
movl %ebx, 8(%eax)
|
||||
movl %ecx, 12(%eax)
|
||||
movl %edx, 16(%eax)
|
||||
movl %esi, 20(%eax)
|
||||
movl %edi, 24(%eax)
|
||||
movl %ebp, 28(%eax)
|
||||
|
||||
# restore to's registers
|
||||
movl 4(%esp), %eax # not 8(%esp): popped return address already
|
||||
# eax now points to to
|
||||
movl 28(%eax), %ebp
|
||||
movl 24(%eax), %edi
|
||||
movl 20(%eax), %esi
|
||||
movl 16(%eax), %edx
|
||||
movl 12(%eax), %ecx
|
||||
movl 8(%eax), %ebx
|
||||
movl 4(%eax), %esp
|
||||
|
||||
pushl 0(%eax) # push eip
|
||||
|
||||
ret
|
||||
|
Loading…
Reference in New Issue
Block a user