execve working from vfs executable file along with clone/fork/exit

This commit is contained in:
Bahadir Balban
2008-12-02 18:29:40 +02:00
parent 32b3dfe91d
commit 9123eb49a8
10 changed files with 64 additions and 33 deletions

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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__ */

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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. */

View File

@@ -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,

View File

@@ -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");

View File

@@ -6,6 +6,7 @@
#include <unistd.h>
#include <sys/types.h>
#include <tests.h>
#include <l4/macros.h>
int global = 0;
extern pid_t pid;
@@ -39,5 +40,6 @@ int forktest(void)
out:
printf("PID: %d exiting...\n", myid);
_exit(0);
BUG();
}