Files
codezero/tasks/mm0/src/exit.c
Bahadir Balban 46937eab88 Added preliminary support for execve(). Updates to clone, fork, exit, task handling.
It turned out we used one version of kmalloc for malloc() and another for kfree()!
Now fixed.
Added parent-child relationship to tasks. Need to polish handling CLONE_PARENT and THREAD.
2008-11-19 12:59:52 +02:00

117 lines
2.6 KiB
C

/*
* exit()
*
* Copyright (C) 2008 Bahadir Balban
*/
#include <task.h>
#include <file.h>
#include <utcb.h>
#include <exit.h>
#include <test.h>
#include <vm_area.h>
#include <syscalls.h>
#include <l4lib/arch/syslib.h>
#include <l4lib/arch/syscalls.h>
#include <l4lib/exregs.h>
#include <l4lib/ipcdefs.h>
#include <lib/malloc.h>
#include <l4/api/space.h>
/*
* Sends vfs task information about forked child, and its utcb
*/
int vfs_notify_exit(struct tcb *task, int status)
{
int err = 0;
// printf("%s/%s\n", __TASKNAME__, __FUNCTION__);
l4_save_ipcregs();
/* Write parent and child information */
write_mr(L4SYS_ARG0, task->tid);
write_mr(L4SYS_ARG1, status);
if ((err = l4_sendrecv(VFS_TID, VFS_TID,
L4_IPC_TAG_NOTIFY_EXIT)) < 0) {
printf("%s: L4 IPC Error: %d.\n", __FUNCTION__, err);
goto out;
}
/* Check if syscall was successful */
if ((err = l4_get_retval()) < 0) {
printf("%s: VFS returned ipc error: %d.\n",
__FUNCTION__, err);
goto out;
}
out:
l4_restore_ipcregs();
return err;
}
/* Closes all file descriptors of a task */
int task_close_files(struct tcb *task)
{
int err = 0;
/* Flush all file descriptors */
for (int fd = 0; fd < TASK_FILES_MAX; fd++)
if (task->files->fd[fd].vmfile)
if ((err = sys_close(task, fd)) < 0) {
printf("File close error. Tid: %d,"
" fd: %d, error: %d\n",
task->tid, fd, err);
break;
}
return err;
}
void do_exit(struct tcb *task, unsigned int flags, int status)
{
struct task_ids ids = {
.tid = task->tid,
.spid = task->spid,
.tgid = task->tgid,
};
/* Flush all IO on task's files and close fds */
task_close_files(task);
/* Tell vfs that task is exiting */
vfs_notify_exit(task, status);
/* Remove utcb shm areas from vfs */
// printf("Unmapping 0x%p from vfs as utcb of %d\n", task->utcb, task->tid);
utcb_unmap_from_task(task, find_task(VFS_TID));
/* Free task's local tcb */
tcb_destroy(task);
/* Ask the kernel to reset this thread's page tables */
if (flags & EXIT_UNMAP_ALL_SPACE)
l4_unmap((void *)UNMAP_ALL_SPACE,
UNMAP_ALL_SPACE, task->tid);
/* Ask the kernel to delete the thread from its records */
if (flags & EXIT_THREAD_DESTROY)
l4_thread_control(THREAD_DESTROY, &ids);
/* TODO: Wake up any waiters about task's destruction */
#if 0
struct tcb *parent = find_task(task->parentid);
if (parent->waiting) {
exregs_set_mr_return(status);
l4_exchange_registers(parent->tid);
l4_thread_control(THREAD_RUN, parent->tid);
}
#endif
}
void sys_exit(struct tcb *task, int status)
{
do_exit(task, EXIT_THREAD_DESTROY, status);
}