void VFS_CloseAllUserHandles(struct sProcess *Process) { const int max_handles = *Threads_GetMaxFD(Process); ENTER("pProcess", Process); if( max_handles >= PAGE_SIZE / sizeof(tVFS_Handle) ) TODO("More than a page of handles"); tVFS_Handle *handles = MM_MapTempFromProc(Process, gaUserHandles); LOG("handles=%p", handles); // Check if this process has any handles if( !handles ) { LEAVE('-'); return ; } for( int i = 0; i < max_handles; i ++ ) { tVFS_Handle *h = &handles[i]; LOG("handles[%i].Node = %p", i, h->Node); if( !h->Node ) continue ; _CloseNode(h->Node); h->Node = NULL; } MM_FreeTemp(handles); LEAVE('-'); }
/** * \brief Clone a page from an entry * \param Ent Pointer to the entry in the PML4/PDP/PD/PT * \param NextLevel Pointer to contents of the entry * \param Addr Dest address * \note Used in COW */ void MM_int_ClonePageEnt( Uint64 *Ent, void *NextLevel, tVAddr Addr, int bTable ) { tPAddr curpage = *Ent & PADDR_MASK; int bCopied = 0; if( MM_GetRefCount( curpage ) <= 0 ) { Log_KernelPanic("MMVirt", "Page %P still marked COW, but unreferenced", curpage); } if( MM_GetRefCount( curpage ) == 1 ) { *Ent &= ~PF_COW; *Ent |= PF_PRESENT|PF_WRITE; #if TRACE_COW Log_Debug("MMVirt", "COW ent at %p (%p) only %P", Ent, NextLevel, curpage); #endif } else { void *tmp; tPAddr paddr; if( !(paddr = MM_AllocPhys()) ) { Threads_SegFault(Addr); return ; } ASSERT(paddr != curpage); tmp = MM_MapTemp(paddr); memcpy( tmp, NextLevel, 0x1000 ); MM_FreeTemp( tmp ); #if TRACE_COW Log_Debug("MMVirt", "COW ent at %p (%p) from %P to %P", Ent, NextLevel, curpage, paddr); #endif MM_DerefPhys( curpage ); *Ent &= PF_USER; *Ent |= paddr|PF_PRESENT|PF_WRITE; bCopied = 1; } INVLPG( (tVAddr)NextLevel ); // Mark COW on contents if it's a PDPT, Dir or Table if(bTable) { Uint64 *dp = NextLevel; int i; for( i = 0; i < 512; i ++ ) { if( !(dp[i] & PF_PRESENT) ) continue; if( bCopied ) MM_RefPhys( dp[i] & PADDR_MASK ); if( dp[i] & PF_WRITE ) { dp[i] &= ~PF_WRITE; dp[i] |= PF_COW; } } } }