diff options
author | sotech117 <michael_foiani@brown.edu> | 2024-05-15 02:13:46 +0000 |
---|---|---|
committer | sotech117 <michael_foiani@brown.edu> | 2024-05-15 02:13:46 +0000 |
commit | a27bbe631191814fe02990afccd9fe0565f6bdc5 (patch) | |
tree | 97162303f95f979dbfbfca47ba21aff8514c2cfb | |
parent | f077699e3c77321235c007ec7e47e066ed55ca68 (diff) |
it works!
-rw-r--r-- | kernel/vm/shadow.c | 62 |
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; + } } |