diff --git a/include/l4/generic/space.h b/include/l4/generic/space.h index 8e4f3a5..1c6adeb 100644 --- a/include/l4/generic/space.h +++ b/include/l4/generic/space.h @@ -41,12 +41,7 @@ struct address_space { struct address_space_list { struct link list; - - /* Lock for list add/removal */ - struct spinlock list_lock; - - /* Used when delete/creating spaces */ - struct mutex ref_lock; + struct mutex lock; int count; }; @@ -56,8 +51,6 @@ void address_space_attach(struct ktcb *tcb, struct address_space *space); struct address_space *address_space_find(l4id_t spid); void address_space_add(struct address_space *space); void address_space_remove(struct address_space *space); -void address_space_reference_lock(); -void address_space_reference_unlock(); void init_address_space_list(struct address_space_list *space_list); int check_access(unsigned long vaddr, unsigned long size, unsigned int flags, int page_in); diff --git a/src/api/thread.c b/src/api/thread.c index c0b8dd4..11bf8a4 100644 --- a/src/api/thread.c +++ b/src/api/thread.c @@ -271,30 +271,38 @@ int thread_setup_space(struct ktcb *tcb, struct task_ids *ids, unsigned int flag struct address_space *space, *new; int ret = 0; - address_space_reference_lock(); - if (flags & TC_SHARE_SPACE) { + mutex_lock(&curcont->space_list.lock); if (!(space = address_space_find(ids->spid))) { + mutex_unlock(&curcont->space_list.lock); ret = -ESRCH; goto out; } + mutex_lock(&space->lock); + mutex_unlock(&curcont->space_list.lock); address_space_attach(tcb, space); + mutex_unlock(&space->lock); } - if (flags & TC_COPY_SPACE) { + else if (flags & TC_COPY_SPACE) { + mutex_lock(&curcont->space_list.lock); if (!(space = address_space_find(ids->spid))) { ret = -ESRCH; goto out; } + mutex_lock(&space->lock); if (IS_ERR(new = address_space_create(space))) { + mutex_unlock(&curcont->space_list.lock); + mutex_unlock(&space->lock); ret = (int)new; goto out; } - /* New space id to be returned back to caller */ - ids->spid = new->spid; + mutex_unlock(&space->lock); + ids->spid = new->spid; /* Return newid to caller */ address_space_attach(tcb, new); address_space_add(new); + mutex_unlock(&curcont->space_list.lock); } - if (flags & TC_NEW_SPACE) { + else if (flags & TC_NEW_SPACE) { if (IS_ERR(new = address_space_create(0))) { ret = (int)new; goto out; @@ -302,11 +310,12 @@ int thread_setup_space(struct ktcb *tcb, struct task_ids *ids, unsigned int flag /* New space id to be returned back to caller */ ids->spid = new->spid; address_space_attach(tcb, new); + mutex_lock(&curcont->space_list.lock); address_space_add(new); + mutex_unlock(&curcont->space_list.lock); } out: - address_space_reference_unlock(); return ret; } diff --git a/src/generic/space.c b/src/generic/space.c index db5d033..200f89f 100644 --- a/src/generic/space.c +++ b/src/generic/space.c @@ -20,19 +20,8 @@ void init_address_space_list(struct address_space_list *space_list) { memset(space_list, 0, sizeof(*space_list)); - mutex_init(&space_list->ref_lock); - spin_lock_init(&space_list->list_lock); link_init(&space_list->list); -} - -void address_space_reference_lock() -{ - mutex_lock(&curcont->space_list.ref_lock); -} - -void address_space_reference_unlock() -{ - mutex_unlock(&curcont->space_list.ref_lock); + mutex_init(&space_list->lock); } void address_space_attach(struct ktcb *tcb, struct address_space *space) @@ -45,38 +34,24 @@ struct address_space *address_space_find(l4id_t spid) { struct address_space *space; - spin_lock(&curcont->space_list.list_lock); - list_foreach_struct(space, &curcont->space_list.list, list) { - if (space->spid == spid) { - spin_unlock(&curcont->space_list.list_lock); + list_foreach_struct(space, &curcont->space_list.list, list) + if (space->spid == spid) return space; - } - } - spin_unlock(&curcont->space_list.list_lock); return 0; } void address_space_add(struct address_space *space) { - spin_lock(&curcont->space_list.list_lock); BUG_ON(!list_empty(&space->list)); list_insert(&space->list, &curcont->space_list.list); BUG_ON(!++curcont->space_list.count); - spin_unlock(&curcont->space_list.list_lock); } void address_space_remove(struct address_space *space) { - spin_lock(&curcont->space_list.list_lock); - - /* - * If current is quitting as the last task of this space, - * its tcb may already be removed, and this is fine - */ - BUG_ON(list_empty(&space->list) && space != current->space); + BUG_ON(list_empty(&space->list)); BUG_ON(--curcont->space_list.count < 0); list_remove_init(&space->list); - spin_unlock(&curcont->space_list.list_lock); } /* Assumes address space reflock is already held */ diff --git a/src/generic/tcb.c b/src/generic/tcb.c index 42c49d4..47dcab4 100644 --- a/src/generic/tcb.c +++ b/src/generic/tcb.c @@ -77,21 +77,21 @@ void tcb_delete(struct ktcb *tcb) BUG_ON(tcb->waiting_on); BUG_ON(tcb->wq); - /* - * Take this lock as we may delete - * the address space as well - */ - address_space_reference_lock(); + mutex_lock(&curcont->space_list.lock); + mutex_lock(&tcb->space->lock); BUG_ON(--tcb->space->ktcb_refs < 0); /* No refs left for the space, delete it */ if (tcb->space->ktcb_refs == 0) { address_space_remove(tcb->space); + mutex_unlock(&tcb->space->lock); address_space_delete(tcb->space); + mutex_unlock(&curcont->space_list.lock); + } else { + mutex_unlock(&tcb->space->lock); + mutex_unlock(&curcont->space_list.lock); } - address_space_reference_unlock(); - /* Deallocate tcb ids */ id_del(&kernel_resources.ktcb_ids, tcb->tid);