exit() almost there.

- Implemented reasonable way to suspend task.
  - A task that has a pending suspend would be interrupted
    from its sleep via the suspender task.
  - If suspend was raised and right after, task became about to sleep,
    then scheduler wakes it up.
  - If suspend was raised when task was in user mode, then an irq suspends it.
  - Also suspends are checked at the end of a syscall so that if suspend was
    raised because of a syscall from the task, the task is suspended before it
    goes back to user mode.

  - This mechanism is very similar to signals, and it may lead as a base for
    implementing signal handling.

- Implemented common vma dropping for shadow vm object dropping and task exiting.
This commit is contained in:
Bahadir Balban
2008-10-20 12:56:30 +03:00
parent 0db0f7e334
commit aa2be891cd
15 changed files with 150 additions and 138 deletions

View File

@@ -5,20 +5,22 @@
#include <unistd.h>
#include <l4/macros.h>
static inline void l4_exit(int status)
static inline void __attribute__ ((noreturn)) l4_exit(int status)
{
int err;
int ret;
write_mr(L4SYS_ARG0, status);
/* Call pager with exit() request. */
err = l4_send(PAGER_TID, L4_IPC_TAG_EXIT);
printf("%s: L4 IPC Error: %d.\n", __FUNCTION__, err);
/* Call pager with exit() request and block on its receive phase */
ret = l4_sendrecv(PAGER_TID, PAGER_TID, L4_IPC_TAG_EXIT);
/* This call should not fail or return */
printf("%s: L4 IPC returned: %d.\n", __FUNCTION__, ret);
BUG();
}
void exit(int status)
void __attribute__ ((noreturn)) _exit(int status)
{
l4_exit(status);
}

View File

@@ -123,6 +123,11 @@ void handle_requests(void)
ret = sys_fork(sender);
break;
}
case L4_IPC_TAG_EXIT: {
/* An exiting task has no receive phase */
sys_exit(sender, (int)mr[0]);
return;
}
case L4_IPC_TAG_BRK: {
// ret = sys_brk(sender, (void *)mr[0]);
// break;

View File

@@ -365,7 +365,20 @@ int vma_drop_merge_delete(struct vm_area *vma, struct vm_obj_link *link)
/* This version is used when exiting. */
int vma_drop_merge_delete_all(struct vm_area *vma)
{
struct vm_obj_link *vmo_link;
struct vm_obj_link *vmo_link, *n;
/* Vma cannot be empty */
BUG_ON(list_empty(&vma->vm_obj_list));
/* Traverse and get rid of all links */
list_for_each_entry_safe(vmo_link, n, &vma->vm_obj_list, list)
vma_drop_merge_delete(vma, vmo_link);
return 0;
}
int vma_drop_merge_delete_all_old(struct vm_area *vma)
{
struct vm_obj_link *vmo_link, *n;
/* Get the first link on the vma */
BUG_ON(list_empty(&vma->vm_obj_list));
@@ -373,6 +386,9 @@ int vma_drop_merge_delete_all(struct vm_area *vma)
struct vm_obj_link, list);
/* Traverse and get rid of all links */
list_for_each_entry_safe(vmo_link, n, &vma->vm_obj_list, list) {
vma_drop_merge_delete(vma, vmo_link);
}
do {
vma_drop_merge_delete(vma, vmo_link);
@@ -382,6 +398,7 @@ int vma_drop_merge_delete_all(struct vm_area *vma)
return 0;
}
/* TODO:
* - Why not allocate a swap descriptor in vma_create_shadow() rather than
* a bare vm_object? It will be needed.

View File

@@ -106,19 +106,6 @@ static void *do_shmat(struct vm_file *shm_file, void *shm_addr, int shmflg,
return shm->shm_addr;
}
/* TODO: Do we need this?
* MM0 never needs a task's utcb page. vfs needs it.
* UTCBs get special treatment here. If the task
* is attaching to its utcb, mm0 prefaults it so
* that it can access it later on whether or not
* the task makes a syscall to mm0 without first
* faulting the utcb.
*/
/*
if ((unsigned long)shmaddr == task->utcb_address)
utcb_prefault(task, VM_READ | VM_WRITE);
*/
void *sys_shmat(struct tcb *task, l4id_t shmid, void *shmaddr, int shmflg)
{
struct vm_file *shm_file, *n;

View File

@@ -1,9 +1,8 @@
/*
* Utcb address allocation for user tasks.
* utcb address allocation for user tasks.
*
* Copyright (C) 2008 Bahadir Balban
*/
#include <stdio.h>
#include <utcb.h>
#include <lib/addr.h>
@@ -71,44 +70,3 @@ void *task_send_utcb_address(struct tcb *sender, l4id_t taskid)
return 0;
}
#if 0
To be ditched
/*
* Triggered during a sys_shmat() by a client task when mapping its utcb.
* This prefaults the utcb and maps it in to mm0 so that it can freely
* access it anytime later.
*/
int utcb_prefault(struct tcb *task, unsigned int vmflags)
{
int err;
struct page *pg;
/* First map in the page to task with given flags, e.g. read/write */
if ((err = prefault_page(task, task->utcb_address, vmflags)) < 0) {
printf("%s: Failed: %d\n", __FUNCTION__, err);
return err;
}
/*
* Get the topmost page. Since we did both a VM_READ and VM_WRITE
* prefault, this gets a writeable instead of a read-only page.
*/
pg = task_virt_to_page(task, task->utcb_address);
if (!pg || IS_ERR(pg)) {
printf("%s: Cannot retrieve task %d's utcb page.\n",
__FUNCTION__, task->tid);
BUG();
}
/* Map it in to self */
l4_map((void *)page_to_phys(pg), (void *)task->utcb_address, 1,
MAP_USR_RW_FLAGS, self_tid());
/* Flag that says this task's utcb is mapped to mm0 as r/w */
task->utcb_mapped = 1;
return 0;
}
#endif

View File

@@ -32,7 +32,7 @@ int forktest(void)
printf("PID: %d, my global: %d\n", myid, global);
printf("-- PASSED --\n");
out:
while(1)
;
printf("PID: %d exiting...\n", myid);
_exit(0);
}