diff --git a/sys/fs/devfs/devfs_vnops.pas b/sys/fs/devfs/devfs_vnops.pas
index 2f63913d..39b774d1 100644
--- a/sys/fs/devfs/devfs_vnops.pas
+++ b/sys/fs/devfs/devfs_vnops.pas
@@ -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();
diff --git a/sys/fs/ufs/ufs_vnops.pas b/sys/fs/ufs/ufs_vnops.pas
index 3b1a00bb..54b3f370 100644
--- a/sys/fs/ufs/ufs_vnops.pas
+++ b/sys/fs/ufs/ufs_vnops.pas
@@ -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;
diff --git a/sys/kern/kern_budget.pas b/sys/kern/kern_budget.pas
index b6805cba..a1b5e266 100644
--- a/sys/kern/kern_budget.pas
+++ b/sys/kern/kern_budget.pas
@@ -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;
diff --git a/sys/kern/kern_rtld.pas b/sys/kern/kern_rtld.pas
index 6095193f..d718bcf3 100644
--- a/sys/kern/kern_rtld.pas
+++ b/sys/kern/kern_rtld.pas
@@ -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
diff --git a/sys/md/md_vnops.pas b/sys/md/md_vnops.pas
index 10729c90..9bee3b75 100644
--- a/sys/md/md_vnops.pas
+++ b/sys/md/md_vnops.pas
@@ -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);
diff --git a/sys/test/project1.lpi b/sys/test/project1.lpi
index cdc1de9d..0226130f 100644
--- a/sys/test/project1.lpi
+++ b/sys/test/project1.lpi
@@ -799,6 +799,10 @@
+
+
+
+
diff --git a/sys/vfs/vfs_subr.pas b/sys/vfs/vfs_subr.pas
index 017214b0..53ef239c 100644
--- a/sys/vfs/vfs_subr.pas
+++ b/sys/vfs/vfs_subr.pas
@@ -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
diff --git a/sys/vfs/vnode.pas b/sys/vfs/vnode.pas
index 1f623f53..8241aae4 100644
--- a/sys/vfs/vnode.pas
+++ b/sys/vfs/vnode.pas
@@ -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.
diff --git a/sys/vm/sys_vm_object.pas b/sys/vm/sys_vm_object.pas
index cb4c9a09..11eed5c1 100644
--- a/sys/vm/sys_vm_object.pas
+++ b/sys/vm/sys_vm_object.pas
@@ -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);
diff --git a/sys/vm/vm_mmap.pas b/sys/vm/vm_mmap.pas
index 86994033..24e043a7 100644
--- a/sys/vm/vm_mmap.pas
+++ b/sys/vm/vm_mmap.pas
@@ -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;
diff --git a/sys/vm/vm_object.pas b/sys/vm/vm_object.pas
index 090db639..0778146a 100644
--- a/sys/vm/vm_object.pas
+++ b/sys/vm/vm_object.pas
@@ -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;
diff --git a/sys/vm/vm_pager.pas b/sys/vm/vm_pager.pas
index 1719b8a4..9ee406ff 100644
--- a/sys/vm/vm_pager.pas
+++ b/sys/vm/vm_pager.pas
@@ -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 :;
diff --git a/sys/vm/vnode_pager.pas b/sys/vm/vnode_pager.pas
new file mode 100644
index 00000000..2070e21b
--- /dev/null
+++ b/sys/vm/vnode_pager.pas
@@ -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.
+
+
+