mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
A better locking scheme for address spaces.
Same shall be done for the tcb list.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user