aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsotech117 <michael_foiani@brown.edu>2024-05-15 02:13:46 +0000
committersotech117 <michael_foiani@brown.edu>2024-05-15 02:13:46 +0000
commita27bbe631191814fe02990afccd9fe0565f6bdc5 (patch)
tree97162303f95f979dbfbfca47ba21aff8514c2cfb
parentf077699e3c77321235c007ec7e47e066ed55ca68 (diff)
it works!
-rw-r--r--kernel/vm/shadow.c62
1 files changed, 61 insertions, 1 deletions
diff --git a/kernel/vm/shadow.c b/kernel/vm/shadow.c
index bf04bc9..4166597 100644
--- a/kernel/vm/shadow.c
+++ b/kernel/vm/shadow.c
@@ -116,7 +116,67 @@ 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");
+
+ mobj_shadow_t *so = MOBJ_TO_SO(o);
+ mobj_t *shadowed = so->shadowed;
+
+ if (shadowed->mo_type != MOBJ_SHADOW)
+ {
+ return;
+ }
+
+ dbg(DBG_PRINT, "shadow_collapse: refcount bottom: %d\n", so->bottom_mobj->mo_refcount);
+
+ while (shadowed->mo_type == MOBJ_SHADOW)
+ {
+ mobj_shadow_t *so_shadowed = MOBJ_TO_SO(shadowed);
+ mobj_t *shadowed_shadowed = so_shadowed->shadowed;
+
+ // if the refcount is not 1, then we can't collapse
+ if (shadowed_shadowed->mo_refcount != 1)
+ {
+ // continue down the shadow chain
+ shadowed = shadowed_shadowed;
+ continue;
+ }
+
+ mobj_lock(shadowed_shadowed);
+ list_iterate(&shadowed_shadowed->mo_pframes, pf, pframe_t, pf_link)
+ {
+ pframe_t *pf_shadow = NULL;
+ mobj_find_pframe(shadowed_shadowed, pf->pf_pagenum, &pf_shadow);
+ if (!pf_shadow)
+ {
+ list_remove(&pf->pf_link);
+ // append to the list of pframes
+ list_insert_tail(&shadowed_shadowed->mo_pframes, &pf->pf_link);
+ }
+ else
+ {
+ pframe_release(&pf_shadow);
+ }
+ }
+ mobj_unlock(shadowed_shadowed);
+
+ if (shadowed_shadowed->mo_type != MOBJ_SHADOW)
+ {
+ // put the shadowed object
+ mobj_put(&shadowed);
+ break;
+ }
+
+ // get the pointer to the shadowed object
+ mobj_shadow_t *so_shadowed_shadowed = MOBJ_TO_SO(shadowed_shadowed);
+ so->shadowed = shadowed_shadowed;
+ mobj_ref(so->shadowed);
+
+ // put the shadowed object
+ mobj_put(&shadowed);
+
+ // continue down the shadow chain
+ shadowed = shadowed_shadowed;
+ }
}