From 9123eb49a817982dd2d3b20975242833b746776a Mon Sep 17 00:00:00 2001 From: Bahadir Balban Date: Tue, 2 Dec 2008 18:29:40 +0200 Subject: [PATCH] execve working from vfs executable file along with clone/fork/exit --- src/arch/arm/exception.c | 2 +- tasks/libposix/exit.c | 1 - tasks/mm0/include/exit.h | 2 +- tasks/mm0/src/execve.c | 15 +++------------ tasks/mm0/src/exit.c | 33 ++++++++++++++++++++++++++------- tasks/mm0/src/fault.c | 9 +++++++-- tasks/mm0/src/mmap.c | 15 ++++++++++++--- tasks/mm0/src/task.c | 6 ++++++ tasks/test0/main.c | 12 ++++++------ tasks/test0/src/forktest.c | 2 ++ 10 files changed, 64 insertions(+), 33 deletions(-) diff --git a/src/arch/arm/exception.c b/src/arch/arm/exception.c index 33a12af..77176d0 100644 --- a/src/arch/arm/exception.c +++ b/src/arch/arm/exception.c @@ -18,7 +18,7 @@ #include INC_SUBARCH(mm.h) /* Abort debugging conditions */ - #define DEBUG_ABORTS +// #define DEBUG_ABORTS #if defined (DEBUG_ABORTS) #define dbg_abort(...) dprintk(__VA_ARGS__) #else diff --git a/tasks/libposix/exit.c b/tasks/libposix/exit.c index d9cede9..79083ad 100644 --- a/tasks/libposix/exit.c +++ b/tasks/libposix/exit.c @@ -21,7 +21,6 @@ static inline void __attribute__ ((noreturn)) l4_exit(int status) void __attribute__ ((noreturn)) _exit(int status) { - printf("In %s.\n", __FUNCTION__); l4_exit(status); } diff --git a/tasks/mm0/include/exit.h b/tasks/mm0/include/exit.h index 1ddd871..9965a06 100644 --- a/tasks/mm0/include/exit.h +++ b/tasks/mm0/include/exit.h @@ -8,6 +8,6 @@ #define __EXIT_H__ void do_exit(struct tcb *task, int status); -int execve_recycle_task(struct tcb *task); +int execve_recycle_task(struct tcb *new, struct tcb *orig); #endif /* __EXIT_H__ */ diff --git a/tasks/mm0/src/execve.c b/tasks/mm0/src/execve.c index 52d3fe4..95e8b4c 100644 --- a/tasks/mm0/src/execve.c +++ b/tasks/mm0/src/execve.c @@ -123,10 +123,7 @@ int do_execve(struct tcb *sender, char *filename, struct args_struct *args, /* Find the thread group leader of sender */ BUG_ON(!(tgleader = find_task(sender->tgid))); - /* - * Destroy all children threads. - * TODO: Set up parents for children's children - */ + /* Destroy all children threads. */ list_for_each_entry(thread, &tgleader->children, child_ref) do_exit(thread, 0); } else { @@ -134,18 +131,12 @@ int do_execve(struct tcb *sender, char *filename, struct args_struct *args, tgleader = sender; } - /* Copy data to new task that is to be retained from exec'ing task */ - new_task->tid = tgleader->tid; - new_task->spid = tgleader->spid; - new_task->tgid = tgleader->tgid; - new_task->pagerid = tgleader->pagerid; - new_task->utcb = tgleader->utcb; - /* + * Copy data to be retained from exec'ing task to new one. * Release all task resources, do everything done in * exit() except destroying the actual thread. */ - if ((err = execve_recycle_task(tgleader)) < 0) { + if ((err = execve_recycle_task(new_task, tgleader)) < 0) { vm_file_put(vmfile); kfree(new_task); return err; diff --git a/tasks/mm0/src/exit.c b/tasks/mm0/src/exit.c index 2949308..87ec895 100644 --- a/tasks/mm0/src/exit.c +++ b/tasks/mm0/src/exit.c @@ -69,17 +69,36 @@ int task_close_files(struct tcb *task) } /* Prepare old task's environment for new task */ -int execve_recycle_task(struct tcb *task) +int execve_recycle_task(struct tcb *new, struct tcb *orig) { int err; struct task_ids ids = { - .tid = task->tid, - .spid = task->spid, - .tgid = task->tgid, + .tid = orig->tid, + .spid = orig->spid, + .tgid = orig->tgid, }; + /* + * Copy data to new task that is + * to be retained from original + */ + + /* Copy ids */ + new->tid = orig->tid; + new->spid = orig->spid; + new->tgid = orig->tgid; + new->pagerid = orig->pagerid; + + /* Copy utcb */ + new->utcb = orig->utcb; + + /* Copy parent relationship */ + BUG_ON(new->parent); + new->parent = orig->parent; + list_add(&new->child_ref, &orig->parent->children); + /* Flush all IO on task's files and close fds */ - task_close_files(task); + task_close_files(orig); /* Vfs still knows the thread */ @@ -88,12 +107,12 @@ int execve_recycle_task(struct tcb *task) /* Ask the kernel to recycle the thread */ if ((err = l4_thread_control(THREAD_RECYCLE, &ids)) < 0) { printf("%s: Suspending thread %d failed with %d.\n", - __FUNCTION__, task->tid, err); + __FUNCTION__, orig->tid, err); return err; } /* Destroy the locally known tcb */ - tcb_destroy(task); + tcb_destroy(orig); return 0; } diff --git a/tasks/mm0/src/fault.c b/tasks/mm0/src/fault.c index c139cd8..2c9c507 100644 --- a/tasks/mm0/src/fault.c +++ b/tasks/mm0/src/fault.c @@ -22,9 +22,14 @@ /* Given a page and the vma it is in, returns that page's virtual address */ -unsigned long vma_page_to_virtual(struct vm_area *vma, struct page *p) +unsigned long vma_page_to_virtual(struct vm_area *vma, struct page *page) { - return __pfn_to_addr(vma->pfn_start + p->offset); + unsigned long virtual_pfn = vma->pfn_start + page->offset - vma->file_offset; + + /* Page must be contained in vma's pages */ + BUG_ON(vma->file_offset > page->offset); + + return __pfn_to_addr(virtual_pfn); } unsigned long fault_to_file_offset(struct fault_data *fault) diff --git a/tasks/mm0/src/mmap.c b/tasks/mm0/src/mmap.c index 8fc315e..3a7df1e 100644 --- a/tasks/mm0/src/mmap.c +++ b/tasks/mm0/src/mmap.c @@ -97,14 +97,23 @@ int task_insert_vma(struct vm_area *this, struct list_head *vma_list) BUG(); } -/* Search an empty space in the task's mmapable address region. */ +/* + * Search an empty space in the task's mmapable address region. + * + * This does a less than O(n) algorithm by starting the estimated region + * and vma comparison from the beginning, once a vma is not intersected + * that means it is an available slot. However if vma's and estimated + * region does not go head-to-head for comparison, individual intersection + * checks would be meaningless since any other vma could be intersecting. + * Therefore head-to-head comparison is essential here. + */ unsigned long find_unmapped_area(unsigned long npages, struct tcb *task) { - unsigned long pfn_start = __pfn(task->map_start); + unsigned long pfn_start = __pfn(task->start); unsigned long pfn_end = pfn_start + npages; struct vm_area *vma; - if (npages > __pfn(task->map_end - task->map_start)) + if (npages > __pfn(task->end - task->start)) return 0; /* If no vmas, first map slot is available. */ diff --git a/tasks/mm0/src/task.c b/tasks/mm0/src/task.c index e37453e..daa04c8 100644 --- a/tasks/mm0/src/task.c +++ b/tasks/mm0/src/task.c @@ -497,6 +497,12 @@ int task_mmap_segments(struct tcb *task, struct vm_file *file, struct exec_file_ //struct vm_file *shm; int err; + /* Set up task's user boundary regions */ + task->start = USER_AREA_START; + task->end = USER_AREA_END; + task->map_start = task->start; + task->map_end = task->end; + /* mmap task's text to task's address space. */ if (IS_ERR(mapped = do_mmap(file, efd->text_offset, task, task->text_start, VM_READ | VM_WRITE | VM_EXEC | VMA_PRIVATE, diff --git a/tasks/test0/main.c b/tasks/test0/main.c index adbd32b..04847c2 100644 --- a/tasks/test0/main.c +++ b/tasks/test0/main.c @@ -46,21 +46,21 @@ void main(void) pid = getpid(); printf("Child: file IO test 1.\n"); if (fileio() == 0) - printf("-- PASSED --\n"); + printf("-- Fileio PASSED --\n"); else - printf("-- FAILED --\n"); + printf("-- Fileio FAILED --\n"); printf("Child: forktest.\n"); if (forktest() == 0) - printf("-- PASSED -- \n"); + printf("-- Fork PASSED -- \n"); else - printf("-- FAILED -- \n"); + printf("-- Fork FAILED -- \n"); } else { printf("Parent: file IO test 2. child pid %d:\n", pid); if (fileio2() == 0) - printf("-- PASSED --\n"); + printf("-- Fileio2 PASSED --\n"); else - printf("-- FAILED --\n"); + printf("-- Fileio2 FAILED --\n"); } printf("Testing clone syscall...\n"); diff --git a/tasks/test0/src/forktest.c b/tasks/test0/src/forktest.c index 410f2e4..a723a49 100644 --- a/tasks/test0/src/forktest.c +++ b/tasks/test0/src/forktest.c @@ -6,6 +6,7 @@ #include #include #include +#include int global = 0; extern pid_t pid; @@ -39,5 +40,6 @@ int forktest(void) out: printf("PID: %d exiting...\n", myid); _exit(0); + BUG(); }