aboutsummaryrefslogtreecommitdiff
path: root/kernel/vm/shadow.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/vm/shadow.c')
-rw-r--r--kernel/vm/shadow.c188
1 files changed, 177 insertions, 11 deletions
diff --git a/kernel/vm/shadow.c b/kernel/vm/shadow.c
index 312b32e..91b1fce 100644
--- a/kernel/vm/shadow.c
+++ b/kernel/vm/shadow.c
@@ -41,7 +41,8 @@ static mobj_ops_t shadow_mobj_ops = {.get_pframe = shadow_get_pframe,
*/
void shadow_init()
{
- NOT_YET_IMPLEMENTED("VM: shadow_init");
+ // NOT_YET_IMPLEMENTED("VM: shadow_init");
+ shadow_allocator = slab_allocator_create("shadow", sizeof(mobj_shadow_t));
}
/*
@@ -60,8 +61,37 @@ void shadow_init()
*/
mobj_t *shadow_create(mobj_t *shadowed)
{
- NOT_YET_IMPLEMENTED("VM: shadow_create");
- return NULL;
+ // NOT_YET_IMPLEMENTED("VM: shadow_create");
+
+ // create a new shadow object
+ mobj_shadow_t *so = (mobj_shadow_t *)slab_obj_alloc(shadow_allocator);
+ if (!so)
+ {
+ return NULL;
+ }
+
+ // initialize the mobj_shadow_t
+
+ // set the bottom_mobj based on the two cases
+ if (shadowed->mo_type == MOBJ_SHADOW)
+ {
+ so->bottom_mobj = MOBJ_TO_SO(so->shadowed)->bottom_mobj;
+ }
+ else
+ {
+ so->bottom_mobj = shadowed;
+ }
+ // init the other fields
+ so->shadowed = shadowed;
+ mobj_init(&so->mobj, MOBJ_SHADOW, &shadow_mobj_ops);
+ mobj_ref(so->shadowed);
+ mobj_ref(so->bottom_mobj);
+
+ // lock the shadow object
+ mobj_lock(&so->mobj);
+
+ // return the shadow object
+ return &so->mobj;
}
/*
@@ -80,7 +110,52 @@ mobj_t *shadow_create(mobj_t *shadowed)
*/
void shadow_collapse(mobj_t *o)
{
- NOT_YET_IMPLEMENTED("VM: shadow_collapse");
+ // NOT_YET_IMPLEMENTED("VM: shadow_collapse");
+
+ // get the mobj_shadow_t and it's mobj
+ mobj_shadow_t *so = MOBJ_TO_SO(o);
+ mobj_t *iter = so->shadowed;
+ // iterate through the shadow chain
+ while (iter && so->shadowed->mo_type == MOBJ_SHADOW)
+ {
+ // check to see if the refcount is not 1. if so, continue to next shadowed object
+ if (so->shadowed->mo_refcount != 1)
+ {
+ iter = so->shadowed;
+ continue;
+ }
+ // else, go over the shadowed object's pframes
+
+ // iterate through the pframes
+ mobj_lock(&so->shadowed);
+ list_iterate(&so->shadowed->mo_pframes, pframe, pframe_t, pf_link)
+ {
+ // get the pframe from the shadow object
+ pframe_t *spf = NULL;
+
+ mobj_lock(iter); // lock before getting the pframe
+ mobj_find_pframe(o, pframe->pf_pagenum, &spf);
+ mobj_unlock(iter);
+
+ // check if the pframe is not in the shadow object when migrating
+ if (spf == NULL)
+ {
+ // if not, remove the pframe from the shadowed object
+ // and insert it into out iterated shadow object
+ list_remove(&pframe->pf_link);
+ list_insert_tail(&iter->mo_pframes, &pframe->pf_link);
+ }
+ else
+ {
+ // if it is, release the pframe we found
+ pframe_release(&spf);
+ }
+ }
+
+ // put locked the shadowed object after iterating through it
+ mobj_put_locked(&so->shadowed);
+ // FIXME: this is probably wrong
+ }
}
/*
@@ -111,8 +186,47 @@ void shadow_collapse(mobj_t *o)
static long shadow_get_pframe(mobj_t *o, size_t pagenum, long forwrite,
pframe_t **pfp)
{
- NOT_YET_IMPLEMENTED("VM: shadow_get_pframe");
- return 0;
+ // NOT_YET_IMPLEMENTED("VM: shadow_get_pframe");
+
+ // if forwrite is set, use mobj_default_get_pframe
+ if (forwrite)
+ {
+ return mobj_default_get_pframe(o, pagenum, forwrite, pfp);
+ }
+
+ // else, check if the object already contains the desired frame
+ pframe_t *pf = NULL;
+ mobj_find_pframe(o, pagenum, &pf);
+ if (pf)
+ {
+ // if it does, return the pframe
+ *pfp = pf;
+ return 0;
+ }
+
+ // iterate through the shadow chain to find the nearest shadow mobj that has the frame
+ mobj_shadow_t *so = MOBJ_TO_SO(o);
+ mobj_t *iter = so->shadowed;
+ while (iter && iter->mo_type == MOBJ_SHADOW)
+ {
+ mobj_lock(iter);
+ mobj_find_pframe(o, pagenum, &pf);
+ mobj_unlock(iter);
+ if (pf)
+ {
+ *pfp = pf;
+ return 0;
+ }
+ // update the iterator
+ iter = MOBJ_TO_SO(iter)->shadowed;
+ }
+
+ // if no shadow objects have the page, call mobj_get_pframe() to get the page from the bottom object
+ // at this point, iter is the bottom object
+ mobj_lock(iter);
+ long ret = mobj_get_pframe(iter, pagenum, forwrite, pfp);
+ mobj_unlock(iter);
+ return ret;
}
/*
@@ -138,8 +252,47 @@ static long shadow_get_pframe(mobj_t *o, size_t pagenum, long forwrite,
*/
static long shadow_fill_pframe(mobj_t *o, pframe_t *pf)
{
- NOT_YET_IMPLEMENTED("VM: shadow_fill_pframe");
- return -1;
+ // NOT_YET_IMPLEMENTED("VM: shadow_fill_pframe");
+
+ // get the mobj_shadow_t
+ mobj_shadow_t *so = MOBJ_TO_SO(o);
+ // iterate over the shadow chain
+ mobj_t *iter = so->shadowed;
+ while (iter && iter->mo_type == MOBJ_SHADOW)
+ {
+ // get the pframe from the shadow object
+ pframe_t *spf = NULL;
+ mobj_lock(iter);
+ mobj_find_pframe(o, pf->pf_pagenum, &spf);
+ mobj_unlock(iter);
+
+ // if the pframe is found, copy the contents into pf
+ // then release the pframe
+ if (spf)
+ {
+ memcpy(pf->pf_addr, spf->pf_addr, PAGE_SIZE);
+ pframe_release(&spf);
+ return 0;
+ }
+
+ // update the iterator
+ iter = MOBJ_TO_SO(iter)->shadowed;
+ }
+
+ // if none of the shadow objects have a copy of the frame, use mobj_get_pframe on the bottom object
+ pframe_t *spf = NULL;
+ mobj_lock(iter);
+ long ret = mobj_get_pframe(iter, pf->pf_pagenum, 0, &spf);
+ mobj_unlock(iter);
+ // check if the operation was sucessful, memcpy the contents into pf
+ // and release the pframe
+ if (ret == 0)
+ {
+ memcpy(pf->pf_addr, pf->pf_addr, PAGE_SIZE);
+ pframe_release(&spf);
+ }
+
+ return ret;
}
/*
@@ -153,8 +306,8 @@ static long shadow_fill_pframe(mobj_t *o, pframe_t *pf)
*/
static long shadow_flush_pframe(mobj_t *o, pframe_t *pf)
{
- NOT_YET_IMPLEMENTED("VM: shadow_flush_pframe");
- return -1;
+ // NOT_YET_IMPLEMENTED("VM: shadow_flush_pframe");
+ return 0;
}
/*
@@ -169,5 +322,18 @@ static long shadow_flush_pframe(mobj_t *o, pframe_t *pf)
*/
static void shadow_destructor(mobj_t *o)
{
- NOT_YET_IMPLEMENTED("VM: shadow_destructor");
+ // NOT_YET_IMPLEMENTED("VM: shadow_destructor");
+
+ // get the mobj_shadow_t
+ mobj_shadow_t *so = MOBJ_TO_SO(o);
+
+ // call the default destructor
+ mobj_default_destructor(o);
+
+ // put the shadow and bottom_mobj
+ mobj_put(&so->shadowed);
+ mobj_put(&so->bottom_mobj);
+
+ // free the slab
+ slab_obj_free(shadow_allocator, so);
}