mirror of https://github.com/red-prig/fpPS4.git
This commit is contained in:
parent
d1fdd8221f
commit
e3fc81c59c
|
@ -205,7 +205,8 @@ uses
|
|||
kern_proc,
|
||||
kern_descrip,
|
||||
kern_mtxpool,
|
||||
subr_uio;
|
||||
subr_uio,
|
||||
vnode_pager;
|
||||
|
||||
function VFSTODEVFS(mp:p_mount):p_devfs_mount; inline;
|
||||
begin
|
||||
|
@ -1641,7 +1642,7 @@ begin
|
|||
end;
|
||||
mtx_unlock(devfs_de_interlock);
|
||||
|
||||
//vnode_destroy_vobject(vp);
|
||||
vnode_destroy_vobject(vp);
|
||||
|
||||
VI_LOCK(vp);
|
||||
dev_lock();
|
||||
|
|
|
@ -101,7 +101,8 @@ uses
|
|||
kern_thr,
|
||||
kern_proc,
|
||||
vfs_subr,
|
||||
subr_uio;
|
||||
subr_uio,
|
||||
vnode_pager;
|
||||
|
||||
const
|
||||
UFS_DEL_VNLOCKED =$01;
|
||||
|
@ -1026,7 +1027,7 @@ begin
|
|||
|
||||
ufs_relv(vp);
|
||||
|
||||
//vnode_destroy_vobject(vp);
|
||||
vnode_destroy_vobject(vp);
|
||||
|
||||
Exit(0);
|
||||
end;
|
||||
|
|
|
@ -20,18 +20,18 @@ type
|
|||
|
||||
//budget resid
|
||||
const
|
||||
SCE_KERNEL_BUDGET_MEMORY_INVALID=0;
|
||||
SCE_KERNEL_BUDGET_MEMORY_DMEM =1;
|
||||
SCE_KERNEL_BUDGET_MEMORY_VMEM =2;
|
||||
SCE_KERNEL_BUDGET_MEMORY_MLOCK =3;
|
||||
SCE_KERNEL_BUDGET_CPU_SET =4;
|
||||
SCE_KERNEL_BUDGET_FD_FILE =5;
|
||||
SCE_KERNEL_BUDGET_FD_SOCKET =6;
|
||||
SCE_KERNEL_BUDGET_FD_EQUEUE =7;
|
||||
SCE_KERNEL_BUDGET_FD_PIPE =8;
|
||||
SCE_KERNEL_BUDGET_FD_DEVICE =9;
|
||||
SCE_KERNEL_BUDGET_THREADS =10;
|
||||
SCE_KERNEL_BUDGET_FD_IPCSOCKET =11;
|
||||
SCE_KERNEL_BUDGET_INVALID =0;
|
||||
SCE_KERNEL_BUDGET_MEMORY_DMEM =1;
|
||||
SCE_KERNEL_BUDGET_MEMORY_VMEM =2;
|
||||
SCE_KERNEL_BUDGET_MEMORY_MLOCK=3;
|
||||
SCE_KERNEL_BUDGET_CPU_SET =4;
|
||||
SCE_KERNEL_BUDGET_FD_FILE =5;
|
||||
SCE_KERNEL_BUDGET_FD_SOCKET =6;
|
||||
SCE_KERNEL_BUDGET_FD_EQUEUE =7;
|
||||
SCE_KERNEL_BUDGET_FD_PIPE =8;
|
||||
SCE_KERNEL_BUDGET_FD_DEVICE =9;
|
||||
SCE_KERNEL_BUDGET_THREADS =10;
|
||||
SCE_KERNEL_BUDGET_FD_IPCSOCKET=11;
|
||||
|
||||
//budget proc_type
|
||||
PTYPE_BIG_APP = 0;
|
||||
|
|
|
@ -463,7 +463,7 @@ begin
|
|||
if (imgp=nil) then Exit;
|
||||
|
||||
imgp^.authinfo:=Default(t_authinfo);
|
||||
imgp^.authinfo.app_caps [0]:=QWORD($2000000000000000); //IsGameProcess1
|
||||
imgp^.authinfo.app_caps [0]:=QWORD($2000000000000000); //IsGame
|
||||
imgp^.authinfo.app_attrs[0]:=$400000 or $800000; //allow dmem map
|
||||
|
||||
if (imgp^.image_header=nil) or
|
||||
|
|
|
@ -123,7 +123,8 @@ uses
|
|||
vstat,
|
||||
vfs_subr,
|
||||
subr_uio,
|
||||
kern_thr;
|
||||
kern_thr,
|
||||
vnode_pager;
|
||||
|
||||
const
|
||||
UFS_SET_READONLY=(not &0222);
|
||||
|
@ -1094,7 +1095,7 @@ begin
|
|||
md_delete_cache(de);
|
||||
end;
|
||||
|
||||
//vnode_destroy_vobject(vp);
|
||||
vnode_destroy_vobject(vp);
|
||||
|
||||
Exit(0);
|
||||
end;
|
||||
|
@ -1944,7 +1945,7 @@ begin
|
|||
VLNK:Exit(0);
|
||||
VDIR:Exit(0);
|
||||
else
|
||||
Exit(EPERM);
|
||||
Exit(EOPNOTSUPP);
|
||||
end;
|
||||
|
||||
de:=vp^.v_data;
|
||||
|
@ -1997,6 +1998,8 @@ begin
|
|||
|
||||
vp^.v_un:=Pointer(FD);
|
||||
|
||||
vnode_create_vobject(vp, de^.ufs_size);
|
||||
|
||||
if ((de^.ufs_flags and UFS_CREATE)<>0) then
|
||||
begin
|
||||
if ((flags and O_EXCL)<>0) then
|
||||
|
@ -2028,6 +2031,8 @@ begin
|
|||
NtClose(FD);
|
||||
end;
|
||||
|
||||
vnode_destroy_vobject(vp);
|
||||
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
|
@ -2259,6 +2264,8 @@ begin
|
|||
if (Result<>0) then goto _err;
|
||||
|
||||
de^.ufs_size:=SIZE;
|
||||
|
||||
vnode_pager_setsize(vp, SIZE);
|
||||
end;
|
||||
|
||||
_err:
|
||||
|
@ -2396,6 +2403,19 @@ begin
|
|||
Dec(uio^.uio_iovcnt);
|
||||
end;
|
||||
|
||||
if (Result=0) and (uio^.uio_rw=UIO_WRITE) then
|
||||
begin
|
||||
if not locked then
|
||||
begin
|
||||
sx_xlock(@de^.ufs_md_lock);
|
||||
end;
|
||||
|
||||
md_update_dirent(F,de,nil);
|
||||
|
||||
vnode_pager_setsize(vp, de^.ufs_size);
|
||||
|
||||
sx_xunlock(@de^.ufs_md_lock);
|
||||
end else
|
||||
if locked then
|
||||
begin
|
||||
sx_xunlock(@de^.ufs_md_lock);
|
||||
|
|
|
@ -799,6 +799,10 @@
|
|||
<Filename Value="..\sys_crt.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="..\vm\vnode_pager.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
|
|
|
@ -2164,8 +2164,8 @@ var
|
|||
mp:p_mount;
|
||||
begin
|
||||
Inc(vp^.v_holdcnt);
|
||||
if (not VSHOULDBUSY(vp)) then
|
||||
Exit;
|
||||
if (not VSHOULDBUSY(vp)) then Exit;
|
||||
|
||||
ASSERT_VI_LOCKED(vp,'vholdl');
|
||||
Assert((vp^.v_iflag and VI_FREE)<>0,'vnode not free');
|
||||
Assert(vp^.v_op<>nil,'vholdl: vnode already reclaimed.');
|
||||
|
@ -2659,7 +2659,7 @@ begin
|
|||
begin
|
||||
obj:=vp^.v_object;
|
||||
if (obj<>nil) and
|
||||
{((obj^.flags and OBJ_MIGHTBEDIRTY)<>0)} False and
|
||||
((obj^.flags and OBJ_MIGHTBEDIRTY)<>0) and
|
||||
((flags=MNT_WAIT) or (VOP_ISLOCKED(vp)=0)) then
|
||||
begin
|
||||
if (vget(vp, LK_EXCLUSIVE or LK_RETRY or LK_INTERLOCK)=0) then
|
||||
|
@ -2960,17 +2960,21 @@ begin
|
|||
error:=0;
|
||||
dev_lock();
|
||||
if (vp^.v_type<>VCHR) then
|
||||
begin
|
||||
error:=ENOTBLK
|
||||
else
|
||||
end else
|
||||
if (vp^.v_rdev=nil) then
|
||||
begin
|
||||
error:=ENXIO
|
||||
else
|
||||
end else
|
||||
if (p_cdev(vp^.v_rdev)^.si_devsw=nil) then
|
||||
begin
|
||||
error:=ENXIO
|
||||
end{ else
|
||||
if ((p_cdev(vp^.v_rdev)^.si_devsw^.d_flags and D_DISK)=0) then
|
||||
error:=ENOTBLK};
|
||||
end else
|
||||
if ((p_cdevsw(p_cdev(vp^.v_rdev)^.si_devsw)^.d_flags and D_DISK)=0) then
|
||||
begin
|
||||
error:=ENOTBLK;
|
||||
end;
|
||||
dev_unlock();
|
||||
error:=ENOTBLK;
|
||||
if (errp<>nil) then
|
||||
|
|
|
@ -311,6 +311,8 @@ procedure vn_rangelock_unlock_range(vp:p_vnode;cookie:Pointer;start,__end:Int64)
|
|||
function vn_rangelock_rlock(vp:p_vnode;start,__end:Int64):Pointer;
|
||||
function vn_rangelock_wlock(vp:p_vnode;start,__end:Int64):Pointer;
|
||||
|
||||
function vn_canvmio(vp:p_vnode):Boolean;
|
||||
|
||||
var
|
||||
rootvnode:p_vnode=nil;
|
||||
|
||||
|
@ -463,5 +465,22 @@ begin
|
|||
//Result:=rangelock_wlock(@vp^.v_rl, start, __end, VI_MTX(vp))
|
||||
end;
|
||||
|
||||
const
|
||||
vmiodirenable=False;
|
||||
|
||||
function vn_canvmio(vp:p_vnode):Boolean;
|
||||
begin
|
||||
if (vp<>nil) then
|
||||
begin
|
||||
if (vp^.v_type=VREG) or
|
||||
(vmiodirenable and (vp^.v_type=VDIR)) then
|
||||
begin
|
||||
Exit(True);
|
||||
end;
|
||||
end;
|
||||
Result:=False;
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
||||
|
|
|
@ -32,9 +32,7 @@ type
|
|||
vm_object_t=^t_vm_object;
|
||||
t_vm_object=packed record
|
||||
mtx :mtx;
|
||||
memq :TAILQ_HEAD; // list of resident pages
|
||||
patchq :TAILQ_HEAD; // list of patches
|
||||
root :Pointer; // root of the resident page splay tree
|
||||
size :vm_pindex_t; // Object size
|
||||
generation :Integer; // generation ID
|
||||
ref_count :Integer; // How many refs??
|
||||
|
@ -118,6 +116,15 @@ function vm_object_page_clean(obj:vm_object_t;
|
|||
|
||||
implementation
|
||||
|
||||
uses
|
||||
vnode;
|
||||
|
||||
//
|
||||
|
||||
procedure vref(vp:p_vnode); external;
|
||||
|
||||
//
|
||||
|
||||
function VM_OBJECT_MTX(obj:vm_object_t):p_mtx;
|
||||
begin
|
||||
Result:=@obj^.mtx;
|
||||
|
@ -166,7 +173,6 @@ begin
|
|||
|
||||
mtx_init(Result^.mtx,'vm_object');
|
||||
|
||||
TAILQ_INIT(@Result^.memq);
|
||||
TAILQ_INIT(@Result^.patchq);
|
||||
|
||||
Result^.otype :=t;
|
||||
|
@ -190,7 +196,19 @@ procedure vm_object_reference(obj:vm_object_t);
|
|||
begin
|
||||
if (obj=nil) then Exit;
|
||||
|
||||
System.InterlockedIncrement(obj^.ref_count);
|
||||
VM_OBJECT_LOCK(obj);
|
||||
|
||||
Inc(obj^.ref_count);
|
||||
|
||||
if (obj^.otype=OBJT_VNODE) then
|
||||
begin
|
||||
if (obj^.otype=OBJT_VNODE) then
|
||||
begin
|
||||
vref(obj^.handle);
|
||||
end;
|
||||
end;
|
||||
|
||||
VM_OBJECT_UNLOCK(obj);
|
||||
end;
|
||||
|
||||
procedure vm_object_pip_add(obj:vm_object_t;i:word);
|
||||
|
|
|
@ -181,7 +181,7 @@ begin
|
|||
end;
|
||||
foff:=foffp^;
|
||||
flags:=flagsp^;
|
||||
obj:=nil;
|
||||
|
||||
obj:=vp^.v_object;
|
||||
|
||||
case vp^.v_type of
|
||||
|
@ -258,12 +258,14 @@ begin
|
|||
begin
|
||||
flags:=flags or MAP_NOSYNC;
|
||||
end;
|
||||
|
||||
obj:=vm_pager_allocate(OBJT_VNODE, vp, objsize, prot, foff);
|
||||
if (obj=nil) then
|
||||
begin
|
||||
error:=ENOMEM;
|
||||
goto done;
|
||||
end;
|
||||
|
||||
objp^:=obj;
|
||||
flagsp^:=flags;
|
||||
|
||||
|
@ -276,7 +278,9 @@ done:
|
|||
writecounted^:=FALSE;
|
||||
//vnode_pager_update_writecount(obj, objsize, 0);
|
||||
end;
|
||||
|
||||
vput(vp);
|
||||
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
Result:=(error);
|
||||
end;
|
||||
|
|
|
@ -38,7 +38,11 @@ implementation
|
|||
uses
|
||||
vmparam,
|
||||
vnode,
|
||||
vfs_subr;
|
||||
vnode_if,
|
||||
vmount,
|
||||
vfs_subr,
|
||||
vfs_vnops,
|
||||
kern_mtx;
|
||||
|
||||
//
|
||||
|
||||
|
@ -71,7 +75,7 @@ end;
|
|||
The object must be locked.
|
||||
This routine may block.
|
||||
}
|
||||
procedure vm_object_terminate(obj:vm_object_t);
|
||||
procedure vm_object_terminate(obj:vm_object_t); public;
|
||||
var
|
||||
vp:p_vnode;
|
||||
begin
|
||||
|
@ -118,26 +122,112 @@ begin
|
|||
vm_object_destroy(obj);
|
||||
end;
|
||||
|
||||
procedure vm_object_deallocate(obj:vm_object_t); public;
|
||||
{
|
||||
Handle deallocating an object of type OBJT_VNODE.
|
||||
}
|
||||
procedure vm_object_vndeallocate(obj:vm_object_t);
|
||||
var
|
||||
ref:Integer;
|
||||
vp:p_vnode;
|
||||
begin
|
||||
vp:=obj^.handle;
|
||||
|
||||
VFS_ASSERT_GIANT(vp^.v_mount);
|
||||
VM_OBJECT_LOCK_ASSERT(obj);
|
||||
|
||||
Assert(obj^.otype=OBJT_VNODE,'vm_object_vndeallocate: not a vnode obj');
|
||||
Assert(vp<>nil, 'vm_object_vndeallocate: missing vp');
|
||||
|
||||
if (obj^.ref_count > 1) then
|
||||
begin
|
||||
VM_OBJECT_UNLOCK(obj);
|
||||
// vrele may need the vnode lock.
|
||||
vrele(vp);
|
||||
end else
|
||||
begin
|
||||
vhold(vp);
|
||||
VM_OBJECT_UNLOCK(obj);
|
||||
|
||||
vn_lock(vp, LK_EXCLUSIVE or LK_RETRY);
|
||||
vdrop(vp);
|
||||
|
||||
VM_OBJECT_LOCK(obj);
|
||||
|
||||
Dec(obj^.ref_count);
|
||||
|
||||
if (obj^.otype=OBJT_DEAD) then
|
||||
begin
|
||||
VM_OBJECT_UNLOCK(obj);
|
||||
VOP_UNLOCK(vp, 0);
|
||||
end else
|
||||
begin
|
||||
if (obj^.ref_count=0) then
|
||||
begin
|
||||
//VOP_UNSET_TEXT(vp);
|
||||
end;
|
||||
VM_OBJECT_UNLOCK(obj);
|
||||
vput(vp);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{
|
||||
vm_object_deallocate:
|
||||
|
||||
Release a reference to the specified object,
|
||||
gained either through a vm_object_allocate
|
||||
or a vm_object_reference call. When all references
|
||||
are gone, storage associated with this object
|
||||
may be relinquished.
|
||||
|
||||
No object may be locked.
|
||||
}
|
||||
procedure vm_object_deallocate(obj:vm_object_t); public;
|
||||
label
|
||||
restart;
|
||||
var
|
||||
vfslocked:Integer;
|
||||
vp:p_vnode;
|
||||
begin
|
||||
if (obj=nil) then Exit;
|
||||
|
||||
ref:=System.InterlockedDecrement(obj^.ref_count);
|
||||
VM_OBJECT_LOCK(obj);
|
||||
|
||||
if (ref=1) then
|
||||
begin
|
||||
VM_OBJECT_LOCK(obj);
|
||||
vm_object_set_flag(obj, OBJ_ONEMAPPING);
|
||||
VM_OBJECT_UNLOCK(obj);
|
||||
end else
|
||||
if (ref=0) then
|
||||
if ((obj^.flags and OBJ_DEAD)=0) then
|
||||
begin
|
||||
VM_OBJECT_LOCK(obj);
|
||||
vm_object_terminate(obj);
|
||||
end;
|
||||
if (obj^.otype=OBJT_VNODE) then
|
||||
begin
|
||||
restart:
|
||||
|
||||
vp:=obj^.handle;
|
||||
|
||||
vfslocked:=0;
|
||||
if VFS_NEEDSGIANT(vp^.v_mount) then
|
||||
begin
|
||||
vfslocked:=1;
|
||||
if not mtx_trylock(VFS_Giant) then
|
||||
begin
|
||||
VM_OBJECT_UNLOCK(obj);
|
||||
mtx_lock(VFS_Giant);
|
||||
goto restart;
|
||||
end;
|
||||
end;
|
||||
|
||||
vm_object_vndeallocate(obj);
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
Dec(obj^.ref_count);
|
||||
|
||||
if (obj^.ref_count=1) then
|
||||
begin
|
||||
vm_object_set_flag(obj, OBJ_ONEMAPPING);
|
||||
end else
|
||||
if (obj^.ref_count=0) then
|
||||
if ((obj^.flags and OBJ_DEAD)=0) then
|
||||
begin
|
||||
vm_object_terminate(obj);
|
||||
end;
|
||||
|
||||
VM_OBJECT_UNLOCK(obj);
|
||||
end;
|
||||
|
||||
procedure vm_object_pip_wakeup(obj:vm_object_t);
|
||||
|
@ -166,7 +256,7 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
procedure vm_object_pip_wait(obj:vm_object_t;waitid:pchar);
|
||||
procedure vm_object_pip_wait(obj:vm_object_t;waitid:pchar); public;
|
||||
begin
|
||||
if (obj=nil) then Exit;
|
||||
|
||||
|
|
|
@ -21,7 +21,8 @@ implementation
|
|||
|
||||
uses
|
||||
vmparam,
|
||||
device_pager;
|
||||
device_pager,
|
||||
vnode_pager;
|
||||
|
||||
function OFF_TO_IDX(x:QWORD):DWORD; inline;
|
||||
begin
|
||||
|
@ -37,7 +38,7 @@ begin
|
|||
case otype of
|
||||
OBJT_DEFAULT :Result:=vm_object_allocate(otype,OFF_TO_IDX(size));
|
||||
//OBJT_SWAP :;
|
||||
//OBJT_VNODE :;
|
||||
OBJT_VNODE :Result:=vnode_pager_alloc(handle,size,prot,off);
|
||||
OBJT_DEVICE :Result:=dev_pager_alloc(handle,size,prot,off);
|
||||
//OBJT_PHYS :;
|
||||
//OBJT_DEAD :;
|
||||
|
@ -65,7 +66,7 @@ begin
|
|||
case obj^.otype of
|
||||
OBJT_DEFAULT :default_dealloc(obj);
|
||||
OBJT_SWAP :;
|
||||
OBJT_VNODE :;
|
||||
OBJT_VNODE :vnode_pager_dealloc(obj);
|
||||
OBJT_DEVICE :dev_pager_dealloc(obj);
|
||||
OBJT_PHYS :;
|
||||
OBJT_DEAD :;
|
||||
|
|
|
@ -0,0 +1,325 @@
|
|||
unit vnode_pager;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
{$CALLING SysV_ABI_CDecl}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
vnode,
|
||||
vm,
|
||||
vmparam,
|
||||
sys_vm_object;
|
||||
|
||||
function vnode_pager_alloc(handle:Pointer;
|
||||
size:vm_ooffset_t;
|
||||
prot:vm_prot_t;
|
||||
offset:vm_ooffset_t):vm_object_t;
|
||||
|
||||
function vnode_create_vobject(vp:p_vnode;isize:vm_ooffset_t):Integer;
|
||||
|
||||
procedure vnode_destroy_vobject(vp:p_vnode);
|
||||
|
||||
procedure vnode_pager_dealloc(obj:vm_object_t);
|
||||
|
||||
procedure vnode_pager_setsize(vp:p_vnode;nsize:vm_ooffset_t);
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
vnode_if,
|
||||
vfs_subr,
|
||||
vfs_vnops,
|
||||
kern_synch,
|
||||
kern_param,
|
||||
kern_mtx;
|
||||
|
||||
//
|
||||
|
||||
procedure vm_object_terminate(obj:vm_object_t); external;
|
||||
procedure vm_pager_deallocate(obj:vm_object_t); external;
|
||||
procedure vm_object_pip_wait(obj:vm_object_t;waitid:pchar); external;
|
||||
|
||||
//
|
||||
|
||||
function IDX_TO_OFF(x:DWORD):QWORD; inline;
|
||||
begin
|
||||
Result:=QWORD(x) shl PAGE_SHIFT;
|
||||
end;
|
||||
|
||||
function OFF_TO_IDX(x:QWORD):DWORD; inline;
|
||||
begin
|
||||
Result:=QWORD(x) shr PAGE_SHIFT;
|
||||
end;
|
||||
|
||||
{
|
||||
* Allocate (or lookup) pager for a vnode.
|
||||
* Handle is a vnode pointer.
|
||||
*
|
||||
* MPSAFE
|
||||
}
|
||||
|
||||
function vnode_pager_alloc(handle:Pointer;
|
||||
size:vm_ooffset_t;
|
||||
prot:vm_prot_t;
|
||||
offset:vm_ooffset_t):vm_object_t;
|
||||
label
|
||||
retry;
|
||||
var
|
||||
obj:vm_object_t;
|
||||
vp:p_vnode;
|
||||
begin
|
||||
{
|
||||
* Pageout to vnode, no can do yet.
|
||||
}
|
||||
if (handle=nil) then Exit(nil);
|
||||
|
||||
vp:=handle;
|
||||
|
||||
{
|
||||
* If the obj is being terminated, wait for it to
|
||||
* go away.
|
||||
}
|
||||
retry:
|
||||
obj:=vp^.v_object;
|
||||
while (obj<>nil) do
|
||||
begin
|
||||
VM_OBJECT_LOCK(obj);
|
||||
if ((obj^.flags and OBJ_DEAD)=0) then
|
||||
begin
|
||||
break;
|
||||
end;
|
||||
vm_object_set_flag(obj, OBJ_DISCONNECTWNT);
|
||||
msleep(obj, VM_OBJECT_MTX(obj), PDROP or PVM, 'vadead', 0);
|
||||
obj:=vp^.v_object;
|
||||
end;
|
||||
|
||||
Assert(vp^.v_usecount<>0, 'vnode_pager_alloc: no vnode reference');
|
||||
|
||||
if (obj=nil) then
|
||||
begin
|
||||
{
|
||||
* Add an obj of the appropriate size
|
||||
}
|
||||
obj:=vm_object_allocate(OBJT_VNODE, OFF_TO_IDX(round_page(size)));
|
||||
|
||||
obj^.un_pager.vnp.vnp_size:=size;
|
||||
obj^.un_pager.vnp.writemappings:=0;
|
||||
|
||||
obj^.handle:=handle;
|
||||
|
||||
VI_LOCK(vp);
|
||||
if (vp^.v_object<>nil) then
|
||||
begin
|
||||
// Obj has been created while we were sleeping
|
||||
VI_UNLOCK(vp);
|
||||
VM_OBJECT_LOCK(obj);
|
||||
Assert(obj^.ref_count=1, 'leaked ref %p %d');
|
||||
|
||||
obj^.otype:=OBJT_DEAD;
|
||||
obj^.ref_count:=0;
|
||||
VM_OBJECT_UNLOCK(obj);
|
||||
vm_object_destroy(obj);
|
||||
goto retry;
|
||||
end;
|
||||
|
||||
vp^.v_object:=obj;
|
||||
VI_UNLOCK(vp);
|
||||
end else
|
||||
begin
|
||||
Inc(obj^.ref_count);
|
||||
VM_OBJECT_UNLOCK(obj);
|
||||
end;
|
||||
|
||||
vref(vp);
|
||||
Exit(obj);
|
||||
end;
|
||||
|
||||
{ Create the VM system backing object for this vnode }
|
||||
function vnode_create_vobject(vp:p_vnode;isize:vm_ooffset_t):Integer;
|
||||
var
|
||||
obj:vm_object_t;
|
||||
size:QWORD;
|
||||
va:t_vattr;
|
||||
begin
|
||||
size:=isize;
|
||||
|
||||
if (not vn_isdisk(vp, nil)) and (vn_canvmio(vp)=FALSE) then
|
||||
begin
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
obj:=vp^.v_object;
|
||||
while (obj<>nil) do
|
||||
begin
|
||||
VM_OBJECT_LOCK(obj);
|
||||
if ((obj^.flags and OBJ_DEAD)=0) then
|
||||
begin
|
||||
VM_OBJECT_UNLOCK(obj);
|
||||
Exit(0);
|
||||
end;
|
||||
VOP_UNLOCK(vp, 0);
|
||||
vm_object_set_flag(obj, OBJ_DISCONNECTWNT);
|
||||
msleep(obj, VM_OBJECT_MTX(obj), PDROP or PVM, 'vodead', 0);
|
||||
vn_lock(vp, LK_EXCLUSIVE or LK_RETRY);
|
||||
//
|
||||
obj:=vp^.v_object;
|
||||
end;
|
||||
|
||||
if (size=0) then
|
||||
begin
|
||||
if (vn_isdisk(vp, nil)) then
|
||||
begin
|
||||
size:=IDX_TO_OFF(High(Integer));
|
||||
end else
|
||||
begin
|
||||
if (VOP_GETATTR(vp, @va)<>0) then
|
||||
begin
|
||||
Exit(0);
|
||||
end;
|
||||
size:=va.va_size;
|
||||
end;
|
||||
end;
|
||||
|
||||
obj:=vnode_pager_alloc(vp, size, 0, 0);
|
||||
|
||||
{
|
||||
* Dereference the reference we just created. This assumes
|
||||
* that the obj is associated with the vp.
|
||||
}
|
||||
//VM_OBJECT_LOCK(obj);
|
||||
// Dec(obj^.ref_count);
|
||||
//VM_OBJECT_UNLOCK(obj);
|
||||
|
||||
//vrele(vp);
|
||||
|
||||
Assert(vp^.v_object<>nil, 'vnode_create_vobject: nil obj');
|
||||
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
procedure vnode_destroy_vobject(vp:p_vnode);
|
||||
var
|
||||
obj:vm_object_t;
|
||||
begin
|
||||
obj:=vp^.v_object;
|
||||
if (obj=nil) then Exit;
|
||||
|
||||
ASSERT_VOP_ELOCKED(vp, 'vnode_destroy_vobject');
|
||||
|
||||
VM_OBJECT_LOCK(obj);
|
||||
if (obj^.ref_count=0) then
|
||||
begin
|
||||
{
|
||||
* vclean() may be called twice. The first time
|
||||
* removes the primary reference to the object,
|
||||
* the second time goes one further and is a
|
||||
* special-case to terminate the object.
|
||||
*
|
||||
* don't double-terminate the object
|
||||
}
|
||||
if ((obj^.flags and OBJ_DEAD)=0) then
|
||||
vm_object_terminate(obj)
|
||||
else
|
||||
VM_OBJECT_UNLOCK(obj);
|
||||
|
||||
end else
|
||||
begin
|
||||
{
|
||||
* Woe to the process that tries to page now :-).
|
||||
}
|
||||
vm_pager_deallocate(obj);
|
||||
VM_OBJECT_UNLOCK(obj);
|
||||
end;
|
||||
vp^.v_object:=nil;
|
||||
end;
|
||||
|
||||
|
||||
{
|
||||
* The object must be locked.
|
||||
}
|
||||
procedure vnode_pager_dealloc(obj:vm_object_t);
|
||||
var
|
||||
vp:p_vnode;
|
||||
refs:Integer;
|
||||
begin
|
||||
vp:=obj^.handle;
|
||||
|
||||
if (vp=nil) then
|
||||
begin
|
||||
Writeln(StdErr,'vnode_pager_dealloc: pager already dealloced');
|
||||
Exit;
|
||||
end;
|
||||
|
||||
VM_OBJECT_LOCK_ASSERT(obj);
|
||||
vm_object_pip_wait(obj, 'vnpdea');
|
||||
refs:=obj^.ref_count;
|
||||
|
||||
obj^.handle:=nil;
|
||||
obj^.otype:=OBJT_DEAD;
|
||||
|
||||
if ((obj^.flags and OBJ_DISCONNECTWNT)<>0) then
|
||||
begin
|
||||
vm_object_clear_flag(obj, OBJ_DISCONNECTWNT);
|
||||
wakeup(obj);
|
||||
end;
|
||||
|
||||
ASSERT_VOP_ELOCKED(vp, 'vnode_pager_dealloc');
|
||||
|
||||
if (obj^.un_pager.vnp.writemappings > 0) then
|
||||
begin
|
||||
obj^.un_pager.vnp.writemappings:=0;
|
||||
VOP_ADD_WRITECOUNT(vp, -1);
|
||||
end;
|
||||
vp^.v_object:=nil;
|
||||
//VOP_UNSET_TEXT(vp);
|
||||
VM_OBJECT_UNLOCK(obj);
|
||||
|
||||
while (refs>0) do
|
||||
begin
|
||||
vunref(vp);
|
||||
Dec(refs);
|
||||
end;
|
||||
|
||||
VM_OBJECT_LOCK(obj);
|
||||
end;
|
||||
|
||||
{
|
||||
Lets the VM system know about a change in size for a file.
|
||||
We adjust our own internal size and flush any cached pages in
|
||||
the associated object that are affected by the size change.
|
||||
|
||||
Note: this routine may be invoked as a result of a pager put
|
||||
operation (possibly at object termination time), so we must be careful.
|
||||
}
|
||||
procedure vnode_pager_setsize(vp:p_vnode;nsize:vm_ooffset_t);
|
||||
var
|
||||
obj:vm_object_t;
|
||||
nobjsize:DWORD;
|
||||
begin
|
||||
obj:=vp^.v_object;
|
||||
if (obj=nil) then Exit;
|
||||
|
||||
nobjsize:=OFF_TO_IDX(nsize + PAGE_MASK);
|
||||
|
||||
VM_OBJECT_LOCK(obj);
|
||||
|
||||
if (obj^.otype=OBJT_DEAD) then
|
||||
begin
|
||||
VM_OBJECT_UNLOCK(obj);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
Assert(obj^.otype=OBJT_VNODE,'not vnode-backed obj %p');
|
||||
|
||||
obj^.un_pager.vnp.vnp_size:=nsize;
|
||||
obj^.size:=nobjsize;
|
||||
|
||||
VM_OBJECT_UNLOCK(obj);
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue