From 28605e36e75641e7ae0040b303e63a1a4501eb59 Mon Sep 17 00:00:00 2001 From: chyyuu Date: Mon, 11 Apr 2016 00:58:26 +0800 Subject: [PATCH] add lab4 spoc exercises --- related_info/lab4/some-exercises/build-2.sh | 3 + related_info/lab4/some-exercises/build.sh | 2 + related_info/lab4/some-exercises/call.c | 5 + related_info/lab4/some-exercises/call2.c | 11 + related_info/lab4/some-exercises/call2.s | 218 +++++++++++++++ related_info/lab4/some-exercises/callee.s | 17 ++ related_info/lab4/some-exercises/caller.c | 7 + related_info/lab4/some-exercises/proc.c | 411 ++++++++++++++++++++++++++++ related_info/lab4/some-exercises/prog.s | 8 + related_info/lab4/some-exercises/switch.S | 30 ++ 10 files changed, 712 insertions(+) create mode 100755 related_info/lab4/some-exercises/build-2.sh create mode 100755 related_info/lab4/some-exercises/build.sh create mode 100644 related_info/lab4/some-exercises/call.c create mode 100644 related_info/lab4/some-exercises/call2.c create mode 100644 related_info/lab4/some-exercises/call2.s create mode 100644 related_info/lab4/some-exercises/callee.s create mode 100644 related_info/lab4/some-exercises/caller.c create mode 100644 related_info/lab4/some-exercises/proc.c create mode 100644 related_info/lab4/some-exercises/prog.s create mode 100644 related_info/lab4/some-exercises/switch.S diff --git a/related_info/lab4/some-exercises/build-2.sh b/related_info/lab4/some-exercises/build-2.sh new file mode 100755 index 0000000..c0eba11 --- /dev/null +++ b/related_info/lab4/some-exercises/build-2.sh @@ -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 diff --git a/related_info/lab4/some-exercises/build.sh b/related_info/lab4/some-exercises/build.sh new file mode 100755 index 0000000..1987caa --- /dev/null +++ b/related_info/lab4/some-exercises/build.sh @@ -0,0 +1,2 @@ +as -arch i386 -o prog.o prog.s +ld -arch i386 -o prog prog.o diff --git a/related_info/lab4/some-exercises/call.c b/related_info/lab4/some-exercises/call.c new file mode 100644 index 0000000..84f72c2 --- /dev/null +++ b/related_info/lab4/some-exercises/call.c @@ -0,0 +1,5 @@ +int addtwo(int a) +{ + int x = 2; + return a + x; +} diff --git a/related_info/lab4/some-exercises/call2.c b/related_info/lab4/some-exercises/call2.c new file mode 100644 index 0000000..efeac22 --- /dev/null +++ b/related_info/lab4/some-exercises/call2.c @@ -0,0 +1,11 @@ +void func2(int a, int b) +{ + a++; + b+=2; +} + +int main() +{ + func2( 1111, 2222); + return 0; +} diff --git a/related_info/lab4/some-exercises/call2.s b/related_info/lab4/some-exercises/call2.s new file mode 100644 index 0000000..69fe199 --- /dev/null +++ b/related_info/lab4/some-exercises/call2.s @@ -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
: + +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 : + 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 + 804833f: b8 00 00 00 00 mov $0x0,%eax + 8048344: 85 c0 test %eax,%eax + 8048346: 74 11 je 8048359 + 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 : + 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 + 8048378: ba 00 00 00 00 mov $0x0,%edx + 804837d: 85 d2 test %edx,%edx + 804837f: 74 12 je 8048393 + 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 + 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 : + 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 + 80483cb: eb 93 jmp 8048360 + 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 + 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 + 80483eb: 66 90 xchg %ax,%ax + 80483ed: 66 90 xchg %ax,%ax + 80483ef: 90 nop + +080483f0 : +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 diff --git a/related_info/lab4/some-exercises/callee.s b/related_info/lab4/some-exercises/callee.s new file mode 100644 index 0000000..01566f6 --- /dev/null +++ b/related_info/lab4/some-exercises/callee.s @@ -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 diff --git a/related_info/lab4/some-exercises/caller.c b/related_info/lab4/some-exercises/caller.c new file mode 100644 index 0000000..427426a --- /dev/null +++ b/related_info/lab4/some-exercises/caller.c @@ -0,0 +1,7 @@ +#include +int main() +{ + char* mystr = "Welcome to baby OS!\n"; + mywrite(1, mystr, strlen(mystr)); + return 0; +} diff --git a/related_info/lab4/some-exercises/proc.c b/related_info/lab4/some-exercises/proc.c new file mode 100644 index 0000000..f0a9e36 --- /dev/null +++ b/related_info/lab4/some-exercises/proc.c @@ -0,0 +1,411 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* ------------- 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(); + } + } +} + diff --git a/related_info/lab4/some-exercises/prog.s b/related_info/lab4/some-exercises/prog.s new file mode 100644 index 0000000..3a47b0f --- /dev/null +++ b/related_info/lab4/some-exercises/prog.s @@ -0,0 +1,8 @@ +.section __TEXT,__text +.globl start +start: +mov $0x1, %eax +push $0x0 +call _syscall +_syscall: +int $0x80 diff --git a/related_info/lab4/some-exercises/switch.S b/related_info/lab4/some-exercises/switch.S new file mode 100644 index 0000000..27b4c8c --- /dev/null +++ b/related_info/lab4/some-exercises/switch.S @@ -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 +