mirror of
https://github.com/drasko/codezero.git
synced 2026-04-13 07:29:02 +02:00
Address space creation/deletion implemented
- Proper releasing of user pmd and pgds when a space is not used. - Proper releasing of task, space ids. - At occasions a starting thread gets bogus SPSR, this needs investigating. - At a very rare occasion arch_setup_new_thread() had a kernel data abort during register copying from one task to another. Needs investigating.
This commit is contained in:
@@ -6,12 +6,14 @@
|
||||
#include INC_GLUE(memory.h)
|
||||
#include INC_GLUE(memlayout.h)
|
||||
#include INC_ARCH(exception.h)
|
||||
#include INC_SUBARCH(mm.h)
|
||||
#include <l4/generic/space.h>
|
||||
#include <l4/generic/tcb.h>
|
||||
#include <l4/generic/kmalloc.h>
|
||||
#include <l4/api/space.h>
|
||||
#include <l4/api/errno.h>
|
||||
#include <l4/api/kip.h>
|
||||
#include <l4/lib/idpool.h>
|
||||
|
||||
struct address_space_list {
|
||||
struct list_head list;
|
||||
@@ -69,7 +71,9 @@ struct address_space *address_space_find(l4id_t spid)
|
||||
void address_space_add(struct address_space *space)
|
||||
{
|
||||
spin_lock(&address_space_list.list_lock);
|
||||
BUG_ON(!list_empty(&space->list));
|
||||
list_add(&space->list, &address_space_list.list);
|
||||
BUG_ON(!++address_space_list.count);
|
||||
spin_unlock(&address_space_list.list_lock);
|
||||
}
|
||||
|
||||
@@ -77,23 +81,24 @@ void address_space_remove(struct address_space *space)
|
||||
{
|
||||
spin_lock(&address_space_list.list_lock);
|
||||
BUG_ON(list_empty(&space->list));
|
||||
BUG_ON(--address_space_list.count < 0);
|
||||
list_del_init(&space->list);
|
||||
spin_unlock(&address_space_list.list_lock);
|
||||
}
|
||||
|
||||
/* Assumes address space reflock is already held */
|
||||
void address_space_delete(struct address_space *space)
|
||||
{
|
||||
/* Address space refcount lock must be held */
|
||||
|
||||
/* Sanity checks ??? */
|
||||
BUG_ON(space->ktcb_refs);
|
||||
|
||||
/* Traverse the page tables and delete private pmds */
|
||||
delete_page_tables(space);
|
||||
|
||||
/* Delete the top-level pgd */
|
||||
|
||||
/* Return the space id ??? */
|
||||
/* Return the space id */
|
||||
id_del(space_id_pool, space->spid);
|
||||
|
||||
/* Deallocate the space structure */
|
||||
kfree(space);
|
||||
}
|
||||
|
||||
struct address_space *address_space_create(struct address_space *orig)
|
||||
@@ -120,6 +125,13 @@ struct address_space *address_space_create(struct address_space *orig)
|
||||
/* Copy all kernel entries */
|
||||
copy_pgd_kern_all(pgd);
|
||||
|
||||
/*
|
||||
* Set up space id: Always allocate a new one. Specifying a space id
|
||||
* is not allowed since spid field is used to indicate the space to
|
||||
* copy from.
|
||||
*/
|
||||
space->spid = id_new(space_id_pool);
|
||||
|
||||
/* If an original space is supplied */
|
||||
if (orig) {
|
||||
/* Copy its user entries/tables */
|
||||
|
||||
@@ -75,6 +75,7 @@ void tcb_delete(struct ktcb *tcb)
|
||||
BUG_ON(tcb->wqh_recv.sleepers > 0);
|
||||
BUG_ON(!list_empty(&tcb->task_list));
|
||||
BUG_ON(!list_empty(&tcb->rq_list));
|
||||
BUG_ON(tcb->rq);
|
||||
BUG_ON(tcb->nlocks);
|
||||
BUG_ON(tcb->waiting_on);
|
||||
BUG_ON(tcb->wq);
|
||||
@@ -87,15 +88,35 @@ void tcb_delete(struct ktcb *tcb)
|
||||
BUG_ON(--tcb->space->ktcb_refs < 0);
|
||||
|
||||
/* No refs left for the space, delete it */
|
||||
if (tcb->space->ktcb_refs == 0)
|
||||
if (tcb->space->ktcb_refs == 0) {
|
||||
address_space_remove(tcb->space);
|
||||
address_space_delete(tcb->space);
|
||||
}
|
||||
|
||||
address_space_reference_unlock();
|
||||
|
||||
/* Deallocate tcb ids */
|
||||
id_del(thread_id_pool, tcb->tid);
|
||||
|
||||
/* Free the tcb */
|
||||
free_page(tcb);
|
||||
}
|
||||
|
||||
struct ktcb *tcb_find_by_space(l4id_t spid)
|
||||
{
|
||||
struct ktcb *task;
|
||||
|
||||
spin_lock(&ktcb_list.list_lock);
|
||||
list_for_each_entry(task, &ktcb_list.list, task_list) {
|
||||
if (task->space->spid == spid) {
|
||||
spin_unlock(&ktcb_list.list_lock);
|
||||
return task;
|
||||
}
|
||||
}
|
||||
spin_unlock(&ktcb_list.list_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ktcb *tcb_find(l4id_t tid)
|
||||
{
|
||||
struct ktcb *task;
|
||||
@@ -115,6 +136,7 @@ void tcb_add(struct ktcb *new)
|
||||
{
|
||||
spin_lock(&ktcb_list.list_lock);
|
||||
BUG_ON(!list_empty(&new->task_list));
|
||||
BUG_ON(!++ktcb_list.count);
|
||||
list_add(&new->task_list, &ktcb_list.list);
|
||||
spin_unlock(&ktcb_list.list_lock);
|
||||
}
|
||||
@@ -123,6 +145,7 @@ void tcb_remove(struct ktcb *new)
|
||||
{
|
||||
spin_lock(&ktcb_list.list_lock);
|
||||
BUG_ON(list_empty(&new->task_list));
|
||||
BUG_ON(--ktcb_list.count < 0);
|
||||
list_del_init(&new->task_list);
|
||||
spin_unlock(&ktcb_list.list_lock);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user