Mon 14 Oct 23:06:38 CEST 2024
This commit is contained in:
		
							parent
							
								
									d25540ebf0
								
							
						
					
					
						commit
						33ccfd0c2f
					
				
							
								
								
									
										561
									
								
								kernel/process.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										561
									
								
								kernel/process.c
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,561 @@ | ||||||
|  | /*
 | ||||||
|  | Copyright (C) 2015-2019 The University of Notre Dame | ||||||
|  | This software is distributed under the GNU General Public License. | ||||||
|  | See the file LICENSE for details. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #include "process.h" | ||||||
|  | #include "kobject.h" | ||||||
|  | #include "page.h" | ||||||
|  | #include "string.h" | ||||||
|  | #include "list.h" | ||||||
|  | #include "x86.h" | ||||||
|  | #include "interrupt.h" | ||||||
|  | #include "memorylayout.h" | ||||||
|  | #include "kmalloc.h" | ||||||
|  | #include "kernel/types.h" | ||||||
|  | #include "kernelcore.h" | ||||||
|  | #include "main.h" | ||||||
|  | #include "keyboard.h" | ||||||
|  | #include "clock.h" | ||||||
|  | 
 | ||||||
|  | struct process *current = 0; | ||||||
|  | struct list ready_list = { 0, 0 }; | ||||||
|  | struct list grave_list = { 0, 0 }; | ||||||
|  | struct list grave_watcher_list = { 0, 0 };	// parent processes are put here to wait for their children
 | ||||||
|  | struct process *process_table[PROCESS_MAX_PID] = { 0 }; | ||||||
|  | 
 | ||||||
|  | void process_init() | ||||||
|  | { | ||||||
|  | 	current = process_create(); | ||||||
|  | 
 | ||||||
|  | 	pagetable_load(current->pagetable); | ||||||
|  | 	pagetable_enable(); | ||||||
|  | 
 | ||||||
|  | 	current->state = PROCESS_STATE_READY; | ||||||
|  | 
 | ||||||
|  | 	current->waiting_for_child_pid = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void process_kstack_reset(struct process *p, unsigned entry_point) | ||||||
|  | { | ||||||
|  | 	struct x86_stack *s; | ||||||
|  | 
 | ||||||
|  | 	p->state = PROCESS_STATE_CRADLE; | ||||||
|  | 
 | ||||||
|  | 	s = (struct x86_stack *) p->kstack_ptr; | ||||||
|  | 
 | ||||||
|  | 	s->regs2.ebp = (uint32_t) (p->kstack_ptr + 28); | ||||||
|  | 	s->old_ebp = (uint32_t) (p->kstack_ptr + 32); | ||||||
|  | 	s->old_eip = (unsigned) intr_return; | ||||||
|  | 	s->fs = 0; | ||||||
|  | 	s->gs = 0; | ||||||
|  | 	s->es = X86_SEGMENT_USER_DATA; | ||||||
|  | 	s->ds = X86_SEGMENT_USER_DATA; | ||||||
|  | 	s->cs = X86_SEGMENT_USER_CODE; | ||||||
|  | 	s->eip = entry_point; | ||||||
|  | 	s->eflags.interrupt = 1; | ||||||
|  | 	s->eflags.iopl = 3; | ||||||
|  | 	s->esp = PROCESS_STACK_INIT; | ||||||
|  | 	s->ss = X86_SEGMENT_USER_DATA; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void process_kstack_copy(struct process *parent, struct process *child) | ||||||
|  | { | ||||||
|  | 	child->kstack_top = child->kstack + PAGE_SIZE - 8; | ||||||
|  | 	child->kstack_ptr = child->kstack_top - sizeof(struct x86_stack); | ||||||
|  | 
 | ||||||
|  | 	struct x86_stack *child_regs = (struct x86_stack *) child->kstack_ptr; | ||||||
|  | 	struct x86_stack *parent_regs = (struct x86_stack *) (parent->kstack_top - sizeof(struct x86_stack)); | ||||||
|  | 
 | ||||||
|  | 	*child_regs = *parent_regs; | ||||||
|  | 
 | ||||||
|  | 	child_regs->regs2.ebp = (uint32_t) (child->kstack_ptr + 28); | ||||||
|  | 	child_regs->old_ebp = (uint32_t) (child->kstack_ptr + 32); | ||||||
|  | 	child_regs->old_eip = (unsigned) intr_return; | ||||||
|  | 	child_regs->regs1.eax = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  | Valid pids start at 1 and go to PROCESS_MAX_PID. | ||||||
|  | To avoid confusion, keep picking increasing | ||||||
|  | pids until it is necessary to wrap around. | ||||||
|  | "last" is the most recently selected pid. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | static int process_allocate_pid() | ||||||
|  | { | ||||||
|  | 	static int last = 0; | ||||||
|  | 
 | ||||||
|  | 	int i; | ||||||
|  | 
 | ||||||
|  | 	for(i = last + 1; i < PROCESS_MAX_PID; i++) { | ||||||
|  | 		if(!process_table[i]) { | ||||||
|  | 			last = i; | ||||||
|  | 			return i; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for(i = 1; i < last; i++) { | ||||||
|  | 		if(!process_table[i]) { | ||||||
|  | 			last = i; | ||||||
|  | 			return i; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void process_selective_inherit(struct process *parent, struct process *child, int * fds, int length) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 
 | ||||||
|  | 	for (i=0;i<length;i++) { | ||||||
|  | 		if(fds[i]>-1) { | ||||||
|  | 			child->ktable[i] = kobject_copy(parent->ktable[fds[i]]); | ||||||
|  | 		} else { | ||||||
|  | 			child->ktable[i] = 0; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	child->ppid = parent->pid; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void process_inherit(struct process *parent, struct process *child) | ||||||
|  | { | ||||||
|  | 	/* Child inherits everything parent inherits */ | ||||||
|  | 	int i; | ||||||
|  | 	int * fds = kmalloc(sizeof(int)*PROCESS_MAX_OBJECTS); | ||||||
|  | 	for (i = 0; i < PROCESS_MAX_OBJECTS; i++) | ||||||
|  | 	{ | ||||||
|  | 		if (parent->ktable[i]) { | ||||||
|  | 			fds[i] = i; | ||||||
|  | 		} else { | ||||||
|  | 			fds[i] = -1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	process_selective_inherit(parent, child, fds, PROCESS_MAX_OBJECTS); | ||||||
|  | 	kfree(fds); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int process_data_size_set(struct process *p, unsigned size) | ||||||
|  | { | ||||||
|  | 	// XXX check valid ranges
 | ||||||
|  | 	// XXX round up to page size
 | ||||||
|  | 
 | ||||||
|  | 	if(size % PAGE_SIZE) { | ||||||
|  | 		size += (PAGE_SIZE - size % PAGE_SIZE); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(size > p->vm_data_size) { | ||||||
|  | 		uint32_t start = PROCESS_ENTRY_POINT + p->vm_data_size; | ||||||
|  | 		pagetable_alloc(p->pagetable, start, size, PAGE_FLAG_USER | PAGE_FLAG_READWRITE | PAGE_FLAG_CLEAR); | ||||||
|  | 	} else if(size < p->vm_data_size) { | ||||||
|  | 		uint32_t start = PROCESS_ENTRY_POINT + size; | ||||||
|  | 		pagetable_free(p->pagetable, start, p->vm_data_size); | ||||||
|  | 	} else { | ||||||
|  | 		// requested size is equal to current.
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	p->vm_data_size = size; | ||||||
|  | 	pagetable_refresh(); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int process_stack_size_set(struct process *p, unsigned size) | ||||||
|  | { | ||||||
|  | 	// XXX check valid ranges
 | ||||||
|  | 	// XXX round up to page size
 | ||||||
|  | 
 | ||||||
|  | 	if(size > p->vm_stack_size) { | ||||||
|  | 		uint32_t start = -size; | ||||||
|  | 		pagetable_alloc(p->pagetable, start, size - p->vm_stack_size, PAGE_FLAG_USER | PAGE_FLAG_READWRITE | PAGE_FLAG_CLEAR); | ||||||
|  | 	} else { | ||||||
|  | 		uint32_t start = -p->vm_stack_size; | ||||||
|  | 		pagetable_free(p->pagetable, start, p->vm_stack_size - size); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	p->vm_stack_size = size; | ||||||
|  | 	pagetable_refresh(); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void process_stack_reset(struct process *p, unsigned size) | ||||||
|  | { | ||||||
|  | 	process_stack_size_set(p, size); | ||||||
|  | 	memset((void *) -size, size, 0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct process *process_create() | ||||||
|  | { | ||||||
|  | 	struct process *p; | ||||||
|  | 
 | ||||||
|  | 	p = page_alloc(1); | ||||||
|  | 
 | ||||||
|  | 	p->pid = process_allocate_pid(); | ||||||
|  | 	process_table[p->pid] = p; | ||||||
|  | 
 | ||||||
|  | 	p->pagetable = pagetable_create(); | ||||||
|  | 	pagetable_init(p->pagetable); | ||||||
|  | 
 | ||||||
|  | 	p->vm_data_size = 0; | ||||||
|  | 	p->vm_stack_size = 0; | ||||||
|  | 
 | ||||||
|  | 	process_data_size_set(p, 2 * PAGE_SIZE); | ||||||
|  | 	process_stack_size_set(p, 2 * PAGE_SIZE); | ||||||
|  | 
 | ||||||
|  | 	p->kstack = page_alloc(1); | ||||||
|  | 	p->kstack_top = p->kstack + PAGE_SIZE - 8; | ||||||
|  | 	p->kstack_ptr = p->kstack_top - sizeof(struct x86_stack); | ||||||
|  | 
 | ||||||
|  | 	process_kstack_reset(p, PROCESS_ENTRY_POINT); | ||||||
|  | 
 | ||||||
|  | 	// XXX table should be allocated
 | ||||||
|  | 	int i; | ||||||
|  | 	for(i = 0; i < PROCESS_MAX_OBJECTS; i++) { | ||||||
|  | 		p->ktable[i] = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	p->state = PROCESS_STATE_READY; | ||||||
|  | 
 | ||||||
|  | 	return p; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void process_delete(struct process *p) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	for(i = 0; i < PROCESS_MAX_OBJECTS; i++) { | ||||||
|  | 		if(p->ktable[i]) { | ||||||
|  | 			kobject_close(p->ktable[i]); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	pagetable_delete(p->pagetable); | ||||||
|  | 	page_free(p->kstack); | ||||||
|  | 	page_free(p); | ||||||
|  | 	process_table[p->pid] = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void process_launch(struct process *p) | ||||||
|  | { | ||||||
|  | 	list_push_tail(&ready_list, &p->node); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void process_switch(int newstate) | ||||||
|  | { | ||||||
|  | 	interrupt_block(); | ||||||
|  | 
 | ||||||
|  | 	if(current) { | ||||||
|  | 		if(current->state != PROCESS_STATE_CRADLE) { | ||||||
|  | 			asm("pushl %ebp"); | ||||||
|  | 			asm("pushl %edi"); | ||||||
|  | 			asm("pushl %esi"); | ||||||
|  | 			asm("pushl %edx"); | ||||||
|  | 			asm("pushl %ecx"); | ||||||
|  | 			asm("pushl %ebx"); | ||||||
|  | 			asm("pushl %eax"); | ||||||
|  | 		      asm("movl %%esp, %0":"=r"(current->kstack_ptr)); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		interrupt_stack_pointer = (void *) INTERRUPT_STACK_TOP; | ||||||
|  | 		current->state = newstate; | ||||||
|  | 
 | ||||||
|  | 		if(newstate == PROCESS_STATE_READY) { | ||||||
|  | 			list_push_tail(&ready_list, ¤t->node); | ||||||
|  | 		} | ||||||
|  | 		if(newstate == PROCESS_STATE_GRAVE) { | ||||||
|  | 			list_push_tail(&grave_list, ¤t->node); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	current = 0; | ||||||
|  | 
 | ||||||
|  | 	while(1) { | ||||||
|  | 		current = (struct process *) list_pop_head(&ready_list); | ||||||
|  | 		if(current) | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		interrupt_unblock(); | ||||||
|  | 		interrupt_wait(); | ||||||
|  | 		interrupt_block(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	current->state = PROCESS_STATE_RUNNING; | ||||||
|  | 	interrupt_stack_pointer = current->kstack_top; | ||||||
|  | 
 | ||||||
|  | 	asm("movl %0, %%cr3"::"r"(current->pagetable)); | ||||||
|  | 	asm("movl %0, %%esp"::"r"(current->kstack_ptr)); | ||||||
|  | 
 | ||||||
|  | 	asm("popl %eax"); | ||||||
|  | 	asm("popl %ebx"); | ||||||
|  | 	asm("popl %ecx"); | ||||||
|  | 	asm("popl %edx"); | ||||||
|  | 	asm("popl %esi"); | ||||||
|  | 	asm("popl %edi"); | ||||||
|  | 	asm("popl %ebp"); | ||||||
|  | 
 | ||||||
|  | 	interrupt_unblock(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int allow_preempt = 0; | ||||||
|  | 
 | ||||||
|  | void process_preempt() | ||||||
|  | { | ||||||
|  | 	if(allow_preempt && current && ready_list.head) { | ||||||
|  | 		process_switch(PROCESS_STATE_READY); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void process_yield() | ||||||
|  | { | ||||||
|  | 	/* no-op if process module not yet initialized. */ | ||||||
|  | 	if(!current) return; | ||||||
|  | 	process_switch(PROCESS_STATE_READY); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void process_exit(int code) | ||||||
|  | { | ||||||
|  | 	// printf("process %d exiting with status %d...\n", current->pid, code); --> transport to kshell run
 | ||||||
|  | 	current->exitcode = code; | ||||||
|  | 	current->exitreason = PROCESS_EXIT_NORMAL; | ||||||
|  | 	process_wakeup_parent(&grave_watcher_list);	// On exit, wake up parent if need be
 | ||||||
|  | 	process_switch(PROCESS_STATE_GRAVE); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void process_wait(struct list *q) | ||||||
|  | { | ||||||
|  | 	list_push_tail(q, ¤t->node); | ||||||
|  | 	process_switch(PROCESS_STATE_BLOCKED); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void process_wakeup(struct list *q) | ||||||
|  | { | ||||||
|  | 	struct process *p; | ||||||
|  | 	p = (struct process *) list_pop_head(q); | ||||||
|  | 	if(p) { | ||||||
|  | 		p->state = PROCESS_STATE_READY; | ||||||
|  | 		list_push_tail(&ready_list, &p->node); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void process_reap_all() | ||||||
|  | { | ||||||
|  | 	struct process *p; | ||||||
|  | 	while((p = (struct process *) list_pop_head(&grave_list))) { | ||||||
|  | 		process_delete(p); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Wakes up parent off of the corresponding list*/ | ||||||
|  | void process_wakeup_parent(struct list *q) | ||||||
|  | { | ||||||
|  | 	struct process *p = (struct process *) q->head; | ||||||
|  | 	// Loop through all the waiting parents to see if one needs to be woken up
 | ||||||
|  | 	while(p) { | ||||||
|  | 		if(p->pid == current->ppid && (p->waiting_for_child_pid == 0 || p->waiting_for_child_pid == current->pid)) { | ||||||
|  | 			p->state = PROCESS_STATE_READY; | ||||||
|  | 			p->waiting_for_child_pid = 0; | ||||||
|  | 			list_remove(&p->node); | ||||||
|  | 			list_push_tail(&ready_list, &p->node); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		p = (struct process *) (&p->node)->next; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void process_wakeup_all(struct list *q) | ||||||
|  | { | ||||||
|  | 	struct process *p; | ||||||
|  | 	while((p = (struct process *) list_pop_head(q))) { | ||||||
|  | 		p->state = PROCESS_STATE_READY; | ||||||
|  | 		list_push_tail(&ready_list, &p->node); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void process_dump(struct process *p) | ||||||
|  | { | ||||||
|  | 	struct x86_stack *s = (struct x86_stack *) (INTERRUPT_STACK_TOP - sizeof(*s)); | ||||||
|  | 	printf("kstack: %x\n", p->kstack); | ||||||
|  | 	printf("stackp: %x\n", p->kstack_ptr); | ||||||
|  | 	printf("eax: %x     cs: %x\n", s->regs1.eax, s->cs); | ||||||
|  | 	printf("ebx: %x     ds: %x\n", s->regs1.ebx, s->ds); | ||||||
|  | 	printf("ecx: %x     ss: %x\n", s->regs1.ecx, s->ss); | ||||||
|  | 	printf("edx: %x eflags: %x\n", s->regs1.edx, s->eflags); | ||||||
|  | 	printf("esi: %x\n", s->regs1.esi); | ||||||
|  | 	printf("edi: %x\n", s->regs1.edi); | ||||||
|  | 	printf("ebp: %x\n", s->regs1.ebp); | ||||||
|  | 	printf("esp: %x\n", s->esp); | ||||||
|  | 	printf("eip: %x\n", s->eip); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int process_available_fd(struct process *p) | ||||||
|  | { | ||||||
|  | 	struct kobject **fdtable = current->ktable; | ||||||
|  | 	int i; | ||||||
|  | 	for(i = 0; i < PROCESS_MAX_OBJECTS; i++) { | ||||||
|  | 		if(fdtable[i] == 0) | ||||||
|  | 			return i; | ||||||
|  | 	} | ||||||
|  | 	return -1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int process_object_max(struct process *p) | ||||||
|  | { | ||||||
|  | 	struct kobject **fdtable = current->ktable; | ||||||
|  | 	int i; | ||||||
|  | 	// Because of 0-indexing, PROCESS_MAX_OBJECTS is the size and
 | ||||||
|  | 	// therefor 1 offset, don't look for 0 there.
 | ||||||
|  | 	for(i = PROCESS_MAX_OBJECTS - 1; i > -1; i--) { | ||||||
|  | 		if(fdtable[i] != 0) | ||||||
|  | 			return i; | ||||||
|  | 	} | ||||||
|  | 	return -1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void process_make_dead(struct process *dead) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	for(i = 0; i < PROCESS_MAX_PID; i++) { | ||||||
|  | 		if(process_table[i] && process_table[i]->ppid == dead->pid) { | ||||||
|  | 			process_make_dead(process_table[i]); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	dead->exitcode = 0; | ||||||
|  | 	dead->exitreason = PROCESS_EXIT_KILLED; | ||||||
|  | 	if(dead == current) { | ||||||
|  | 		process_switch(PROCESS_STATE_GRAVE); | ||||||
|  | 	} else { | ||||||
|  | 		list_remove(&dead->node); | ||||||
|  | 		list_push_tail(&grave_list, &dead->node); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int process_kill(uint32_t pid) | ||||||
|  | { | ||||||
|  | 	if(pid > 0 && pid <= PROCESS_MAX_PID) { | ||||||
|  | 		struct process *dead = process_table[pid]; | ||||||
|  | 		if(dead) { | ||||||
|  | 			printf("process killed\n"); | ||||||
|  | 			process_make_dead(dead); | ||||||
|  | 			return 0; | ||||||
|  | 		} else { | ||||||
|  | 			return 1; | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int process_wait_child(uint32_t pid, struct process_info *info, int timeout) | ||||||
|  | { | ||||||
|  | 	clock_t start, elapsed; | ||||||
|  | 	uint32_t total; | ||||||
|  | 
 | ||||||
|  | 	if(!info) | ||||||
|  | 		return -1; | ||||||
|  | 
 | ||||||
|  | 	start = clock_read(); | ||||||
|  | 
 | ||||||
|  | 	do { | ||||||
|  | 		struct process *p = (struct process *) (grave_list.head); | ||||||
|  | 		while(p) { | ||||||
|  | 			struct process *next = (struct process *) p->node.next; | ||||||
|  | 			if((pid != 0 && p->pid == pid) || (p->ppid == current->pid)) { | ||||||
|  | 				info->exitcode = p->exitcode; | ||||||
|  | 				info->exitreason = p->exitreason; | ||||||
|  | 				info->pid = p->pid; | ||||||
|  | 				return p->pid; | ||||||
|  | 			} | ||||||
|  | 			p = next; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		current->waiting_for_child_pid = pid; | ||||||
|  | 		process_wait(&grave_watcher_list); | ||||||
|  | 
 | ||||||
|  | 		elapsed = clock_diff(start, clock_read()); | ||||||
|  | 		total = elapsed.millis + elapsed.seconds * 1000; | ||||||
|  | 	} while(total < timeout || timeout < 0); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int process_reap(uint32_t pid) | ||||||
|  | { | ||||||
|  | 	struct process *p = (struct process *) (grave_list.head); | ||||||
|  | 	while(p) { | ||||||
|  | 		struct process *next = (struct process *) p->node.next; | ||||||
|  | 		if(p->pid == pid) { | ||||||
|  | 			list_remove(&p->node); | ||||||
|  | 			process_delete(p); | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 		p = next; | ||||||
|  | 	} | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  | process_pass_arguments set up the current process stack | ||||||
|  | so that it contains a copy of p->args and p->args_length | ||||||
|  | at the very top, serving as the initial arguments to the entry function: | ||||||
|  | void entry( const char *args, int args_length ); | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #define PUSH_INTEGER( value ) esp -= sizeof(int); *((int*)esp)=(int)(value); | ||||||
|  | 
 | ||||||
|  | void process_pass_arguments(struct process *p, int argc, char **argv) | ||||||
|  | { | ||||||
|  | 	/* Get the default stack pointer position. */ | ||||||
|  | 	char *esp = (char *) PROCESS_STACK_INIT; | ||||||
|  | 
 | ||||||
|  | 	/* Make a local array to keep track of user addresses. */ | ||||||
|  | 	char **addr_of_argv = kmalloc(sizeof(char *) * argc); | ||||||
|  | 
 | ||||||
|  | 	/* For each argument, in reverse order: */ | ||||||
|  | 	int i; | ||||||
|  | 	for(i = (argc - 1); i >= 0; i--) { | ||||||
|  | 		/* Size is strlen plus null terminator, integer aligned. */ | ||||||
|  | 		int length = strlen(argv[i]) + 1; | ||||||
|  | 		if(length % 4) { | ||||||
|  | 			length += (4 - length % 4); | ||||||
|  | 		} | ||||||
|  | 		esp -= length; | ||||||
|  | 
 | ||||||
|  | 		/* Push length bytes onto the stack. */ | ||||||
|  | 		memcpy(esp, argv[i], length); | ||||||
|  | 
 | ||||||
|  | 		/* Remember that address for later */ | ||||||
|  | 		addr_of_argv[i] = esp; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Push each item of argc, in reverse order. */ | ||||||
|  | 	for(i = (argc - 1); i >= 0; i--) { | ||||||
|  | 		PUSH_INTEGER(addr_of_argv[i]); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Keep the address of the array start. */ | ||||||
|  | 	const char *addr_of_addr_of_argv = esp; | ||||||
|  | 
 | ||||||
|  | 	/* Push the arguments to main */ | ||||||
|  | 	PUSH_INTEGER(addr_of_addr_of_argv); | ||||||
|  | 	PUSH_INTEGER(argc); | ||||||
|  | 
 | ||||||
|  | 	/* Final stack pointer should be below the last item. */ | ||||||
|  | 	esp -= 4; | ||||||
|  | 
 | ||||||
|  | 	/* Set the starting stack pointer on the kstack to this new value */ | ||||||
|  | 	struct x86_stack *s = (struct x86_stack *) p->kstack_ptr; | ||||||
|  | 	s->esp = (int) (esp); | ||||||
|  | 
 | ||||||
|  | 	kfree(addr_of_argv); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int process_stats(int pid, struct process_stats *s) | ||||||
|  | { | ||||||
|  | 	if(pid > PROCESS_MAX_PID || !process_table[pid]) { | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  | 	*s = process_table[pid]->stats; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user