This commit is contained in:
Pavel 2024-01-29 00:05:09 +03:00
parent b817a72d01
commit cbb844782b
13 changed files with 523 additions and 91 deletions

View File

@ -31,6 +31,7 @@ uses
//internal libs
ps4_libSceSystemService,
ps4_libSceUserService,
ps4_libSceIpmi,
ps4_libSceDialogs,
ps4_libSceAvSetting

View File

@ -73,6 +73,8 @@ const
ThreadSetTlsArrayAddress = 15;
ThreadIsIoPending = 16;
ThreadHideFromDebugger = 17;
ThreadNameInformation = 38;
ThreadSystemThreadInformation = 40;
//ProcessInformationClass
ProcessBasicInformation=0;
@ -155,6 +157,8 @@ const
MEM_COALESCE_PLACEHOLDERS=$01;
MEM_PRESERVE_PLACEHOLDER =$02;
MEM_RESET_UNDO=$1000000;
OBJ_INHERIT =$00000002;
OBJ_PERMANENT =$00000010;
OBJ_EXCLUSIVE =$00000020;

View File

@ -20,7 +20,8 @@ uses
vm_pmap,
sys_vm_object,
vm_pager,
subr_backtrace;
subr_backtrace,
bittype;
var
gc_page:Pointer;
@ -43,6 +44,49 @@ type
param3:DWORD;
end;
p_Submit=^t_Submit;
t_Submit=packed record
arg0 :DWORD;
count:DWORD;
cmds :PQWORD;
end;
function PM4_TYPE(token:DWORD):Byte; inline;
begin
Result:=(token shr 30) and 3;
end;
function PM4_LENGTH_DW(token:DWORD):WORD; inline;
begin
Result:=((token shr 16) and $3FFF) + 2;
end;
type
PPM4_TYPE_3_HEADER=^PM4_TYPE_3_HEADER;
PM4_TYPE_3_HEADER=bitpacked record
predicate:bit1; //1
shaderType:bit1; //1
reserved:bit6; //6
opcode:Byte; //8
count:bit14; //14
_type:bit2; //2
end;
PPM4CMDINDIRECTBUFFER=^PM4CMDINDIRECTBUFFER;
PM4CMDINDIRECTBUFFER=bitpacked record
ibBaseLo :DWORD; ///< Indirect buffer base address, must be 4 byte aligned
ibBaseHi32 :DWORD; ///< Indirect buffer base address
//
ibSize :bit20; ///< Indirect buffer size
chain :bit1; ///< set to chain to IB allocations
offLoadPolling:bit1;
volatile__CI :bit1;
valid :bit1;
vmid :bit4; ///< Virtual memory domain ID for command buffer
cachePolicy :bit2;
reserved1 :bit2;
end;
Function gc_ioctl(dev:p_cdev;cmd:QWORD;data:Pointer;fflag:Integer):Integer;
begin
Result:=0;
@ -79,6 +123,7 @@ begin
end;
$C008811B: //sceGnmAreSubmitsAllowed
begin
//ret1 = mmap_addr(0xfe0100000,0x4000,1,(ulong *)&paddr,&local_50);
PPointer(data)^:=@gc_AreSubmitsAllowed;
end;
@ -98,7 +143,32 @@ begin
$C0048114: //sceGnmFlushGarlic
begin
Writeln('sceGnmFlushGarlic');
end
end;
$C0108102: //submit
begin
Writeln(p_Submit(data)^.arg0);
Writeln(p_Submit(data)^.count);
Writeln(HexStr(p_Submit(data)^.cmds));
//IT_INDIRECT_BUFFER_CNST = $00000033; ccb
//IT_COND_INDIRECT_BUFFER = $0000003f; dcb
//opcode 0x33 0x3F
//if ((op != L'\xc0023300') && (op != L'\xc0023f00')) {
// printf("## %s: invalid opcode = 0x%08x\n","gc_insert_indirect_buffer");
// ret1 = 0x804c0010;
// goto LAB_ffffffff826bd78b;
//}
//if ((_buffer[1] & 0xfffff00000000) == 0) {
// printf("## %s: invalid ib_size = 0x%05x\n","gc_insert_indirect_buffer",0);
// ret1 = 0x804c0011;
// goto LAB_ffffffff826bd78b;
//}
Assert(False);
end;
else

View File

@ -1422,21 +1422,7 @@ begin
Move(p_proc.p_comm, td^.td_name, sizeof(td^.td_name));
KernSetThreadDebugName(td,'ps4:');
{
* mark as execed, wakeup the process that vforked (if any) and tell
* it that it now has its own resources back
}
p_proc.p_flag:=p_proc.p_flag or P_EXEC;
{
* Notify others that we exec'd, and clear the P_INEXEC flag
* as we're now a bona fide freshly-execed process.
}
KNOTE_LOCKED(@p_proc.p_klist, NOTE_EXEC);
p_proc.p_flag:=p_proc.p_flag and (not P_INEXEC);
{ clear 'fork but no exec' flag, as we _are_ execing }
//p^.p_acflag:= and ~AFORK;
PROC_UNLOCK();
{
* Free any previous argument cache and replace it with
@ -1446,8 +1432,6 @@ begin
p_proc.p_args:=newargs;
newargs:=nil;
PROC_UNLOCK();
dynlib_proc_initialize_step3(imgp);
if (dynlibs_info.libkernel=nil) then
@ -1456,6 +1440,26 @@ begin
goto exec_fail_dealloc;
end;
PROC_LOCK();
{
* mark as execed, wakeup the process that vforked (if any) and tell
* it that it now has its own resources back
}
p_proc.p_flag:=p_proc.p_flag or P_EXEC;
{
* Notify others that we exec'd, and clear the P_INEXEC flag
* as we're now a bona fide freshly-execed process.
}
KNOTE_LOCKED(@p_proc.p_klist, NOTE_EXEC);
p_proc.p_flag:=p_proc.p_flag and (not P_INEXEC);
{ clear 'fork but no exec' flag, as we _are_ execing }
//p^.p_acflag:= and ~AFORK;
PROC_UNLOCK();
vms:=p_proc.p_vmspace;
{ Set values passed into the program in registers. }
@ -1556,6 +1560,13 @@ done2:
VFS_UNLOCK_GIANT(vfslocked);
exec_free_args(args);
if (error<>0) then
begin
// sorry, no more process anymore. exit gracefully
//exit1(td, W_EXITCODE(0, SIGABRT));
// NOT REACHED
end;
Exit(error);
end;

View File

@ -325,13 +325,17 @@ end;
procedure KernSetThreadDebugName(newtd:p_kthread;prefix:PChar);
var
td:p_kthread;
backup:array[0..1] of QWORD;
//td:p_kthread;
//backup:array[0..1] of QWORD;
name:shortstring;
begin
name:=shortstring(prefix)+shortstring(newtd^.td_name);
cpu_thread_set_name(newtd,name);
{
td:=curkthread;
if (td<>nil) then
begin
//prevent bullshit in ntdll:__chkstk
@ -349,6 +353,7 @@ begin
PQWORD(td^.td_kstack.stack)[-1]:=backup[0];
PQWORD(td^.td_kstack.stack)[-2]:=backup[1];
end;
}
end;
procedure before_start(td:p_kthread);

View File

@ -327,7 +327,7 @@ begin
Writeln(stderr,_get_msg(Msg),' (',FName,', line ',LineNo,').');
print_backtrace(stderr,Get_pc_addr,get_frame,2);
sleep(-1);
//sleep(-1);
if IsDebuggerPresent then
Raise EAssertionFailed.
@ -340,6 +340,8 @@ begin
// int3
//end;
sleep(-1);
md_halt(217);
end;

View File

@ -47,7 +47,9 @@ function md_memfd_open (var hMem:THandle;hFile:THandle):Integer;
function md_memfd_close (hMem:THandle):Integer;
function md_protect(base:Pointer;size:QWORD;prot:Integer):Integer;
function md_reset (base:Pointer;size:QWORD;prot:Integer):Integer;
function md_dontneed(base:Pointer;size:QWORD):Integer;
function md_activate(base:Pointer;size:QWORD):Integer;
function md_mmap (var base:Pointer;size:QWORD;prot:Integer):Integer;
function md_unmap (base:Pointer;size:QWORD):Integer;
@ -212,7 +214,7 @@ begin
);
end;
function md_reset(base:Pointer;size:QWORD;prot:Integer):Integer;
function md_dontneed(base:Pointer;size:QWORD):Integer;
begin
Result:=NtAllocateVirtualMemory(
NtCurrentProcess,
@ -220,7 +222,19 @@ begin
0,
@size,
MEM_RESET,
prot
PAGE_NOACCESS
);
end;
function md_activate(base:Pointer;size:QWORD):Integer;
begin
Result:=NtAllocateVirtualMemory(
NtCurrentProcess,
@base,
0,
@size,
MEM_RESET_UNDO,
PAGE_NOACCESS
);
end;

View File

@ -8,7 +8,8 @@ interface
uses
ntapi,
windows,
kern_thr;
kern_thr,
sysutils;
Const
SYS_STACK_RSRV=64*1024;
@ -32,6 +33,8 @@ function cpu_thread_finished(td:p_kthread):Boolean;
function cpuset_setaffinity(td:p_kthread;new:Ptruint):Integer;
function cpu_set_priority(td:p_kthread;prio:Integer):Integer;
function cpu_thread_set_name(td:p_kthread;const name:shortstring):Integer;
procedure seh_wrapper_before(td:p_kthread;var func:Pointer);
procedure seh_wrapper_after (td:p_kthread;func:Pointer);
@ -320,6 +323,27 @@ begin
Result:=NtSetInformationThread(td^.td_handle,ThreadBasePriority,@prio,SizeOf(Integer));
end;
function cpu_thread_set_name(td:p_kthread;const name:shortstring):Integer;
var
W:array[0..255] of WideChar;
UNAME:UNICODE_STRING;
L:DWORD;
begin
Result:=0;
if (td=nil) then Exit;
if (td^.td_handle=0) or (td^.td_handle=THandle(-1)) then Exit;
L:=Utf8ToUnicode(@W,length(W),@name[1],length(name));
W:=UTF8Decode(name);
UNAME.Length :=L*SizeOf(WideChar);
UNAME.MaximumLength:=UNAME.Length;
UNAME.Buffer :=@W;
Result:=NtSetInformationThread(td^.td_handle,ThreadNameInformation,@UNAME,SizeOf(UNAME));
end;
procedure main_wrapper; assembler; nostackframe;
asm
subq $40, %rsp

View File

@ -92,24 +92,20 @@ procedure pmap_enter_object(pmap :pmap_t;
procedure pmap_protect(pmap :pmap_t;
obj :vm_object_t;
offset:vm_ooffset_t;
start :vm_offset_t;
__end :vm_offset_t;
prot :vm_prot_t);
procedure pmap_madv_free(pmap :pmap_t;
obj :vm_object_t;
offset:vm_ooffset_t;
start :vm_offset_t;
__end :vm_offset_t;
prot :vm_prot_t);
procedure pmap_madvise(pmap :pmap_t;
obj :vm_object_t;
start :vm_offset_t;
__end :vm_offset_t;
advise:Integer);
procedure pmap_remove(pmap :pmap_t;
obj :vm_object_t;
offset:vm_ooffset_t;
start :vm_offset_t;
__end :vm_offset_t;
prot :vm_prot_t);
__end :vm_offset_t);
implementation
@ -760,14 +756,11 @@ end;
procedure pmap_protect(pmap :pmap_t;
obj :vm_object_t;
offset:vm_ooffset_t;
start :vm_offset_t;
__end :vm_offset_t;
prot :vm_prot_t);
label
_default;
var
size:QWORD;
begin
Writeln('pmap_protect:',HexStr(start,11),':',HexStr(__end,11),':prot:',HexStr(prot,2));
@ -816,19 +809,18 @@ begin
pmap_mark(start,__end,prot and VM_RWX);
end;
procedure pmap_madv_free(pmap :pmap_t;
obj :vm_object_t;
offset:vm_ooffset_t;
start :vm_offset_t;
__end :vm_offset_t;
prot :vm_prot_t);
procedure pmap_madvise(pmap :pmap_t;
obj :vm_object_t;
start :vm_offset_t;
__end :vm_offset_t;
advise:Integer);
label
_default;
var
size:QWORD;
r:Integer;
begin
Writeln('pmap_madv_free:',HexStr(start,11),':',HexStr(__end,11),':',HexStr(prot,2));
Writeln('pmap_madv_free:',HexStr(start,11),':',HexStr(__end,11),':',HexStr(advise,2));
r:=0;
case vm_object_type(obj) of
@ -840,7 +832,7 @@ begin
size:=(__end-start);
r:=md_reset(Pointer(start),size,wprots[prot and VM_RWX]);
r:=md_dontneed(Pointer(start),size);
end;
OBJT_DEVICE:
begin
@ -875,16 +867,14 @@ end;
procedure pmap_remove(pmap :pmap_t;
obj :vm_object_t;
offset:vm_ooffset_t;
start :vm_offset_t;
__end :vm_offset_t;
prot :vm_prot_t);
__end :vm_offset_t);
label
_default;
var
r:Integer;
begin
Writeln('pmap_remove:',HexStr(start,11),':',HexStr(__end,11),':',HexStr(prot,2));
Writeln('pmap_remove:',HexStr(start,11),':',HexStr(__end,11));
pmap_unmark(start,__end);
@ -910,10 +900,10 @@ begin
if ((obj^.flags and OBJ_DMEM_EXT)<>0) then
begin
Writeln('pmap_remove_gpuobj:',HexStr(start,11),':',HexStr(__end,11),':',HexStr(prot,2));
Writeln('pmap_remove_gpuobj:',HexStr(start,11),':',HexStr(__end,11));
end else
begin
Writeln('pmap_remove_devobj:',HexStr(start,11),':',HexStr(__end,11),':',HexStr(prot,2));
Writeln('pmap_remove_devobj:',HexStr(start,11),':',HexStr(__end,11));
end;
goto _default;

View File

@ -0,0 +1,166 @@
unit ps4_libSceUserService;
{$mode objfpc}{$H+}
{$CALLING SysV_ABI_CDecl}
interface
uses
subr_dynlib,
atomic,
Classes,
SysUtils;
const
SCE_USER_SERVICE_MAX_LOGIN_USERS=4;
SCE_USER_SERVICE_USER_ID_INVALID=Integer($FFFFFFFF);
type
PUserServiceInitializeParams=^TUserServiceInitializeParams;
TUserServiceInitializeParams=packed record
priority:DWORD;
end;
PUserServiceLoginUserIdList=^TUserServiceLoginUserIdList;
TUserServiceLoginUserIdList=packed record
userId:array[0..SCE_USER_SERVICE_MAX_LOGIN_USERS-1] of Integer;
end;
const
//SceUserServiceEventType
SCE_USER_SERVICE_EVENT_TYPE_LOGIN =0;
SCE_USER_SERVICE_EVENT_TYPE_LOGOUT =1;
type
pSceUserServiceEvent=^SceUserServiceEvent;
SceUserServiceEvent=packed record
eventType:Integer; //SceUserServiceEventType
userId:Integer; //SceUserServiceUserId
end;
TUserServiceEventCallback=procedure(event:pSceUserServiceEvent;arg:Pointer);
implementation
const
SCE_USER_SERVICE_ERROR_NOT_INITIALIZED =-2137653246; //0x80960002
SCE_USER_SERVICE_ERROR_INVALID_ARGUMENT=-2137653243; //0x80960005
SCE_USER_SERVICE_ERROR_NO_EVENT =-2137653241; //0x80960007
SCE_USER_SERVICE_ERROR_BUFFER_TOO_SHORT=-2137653238; //0x8096000A
function ps4_sceUserServiceInitialize(params:PUserServiceInitializeParams):Integer;
begin
Result:=0;
end;
function ps4_sceUserServiceInitialize2(threadPriority:Integer;cpuAffinityMask:qword):Integer;
begin
Result:=0;
end;
function ps4_sceUserServiceTerminate:Integer;
begin
Result:=0;
end;
function ps4_sceUserServiceGetLoginUserIdList(List:PUserServiceLoginUserIdList):Integer;
var
i:Integer;
begin
Result:=-1;
if (List=nil) then Exit;
List^.userId[0]:=1;
For i:=1 to SCE_USER_SERVICE_MAX_LOGIN_USERS-1 do
List^.userId[i]:=SCE_USER_SERVICE_USER_ID_INVALID;
Result:=0;
end;
function ps4_sceUserServiceGetInitialUser(pUserId:PInteger):Integer;
begin
if (pUserId=nil) then Exit(SCE_USER_SERVICE_ERROR_INVALID_ARGUMENT);
pUserId^:=1;
Result:=0;
end;
function ps4_sceUserServiceGetUserName(userId:Integer;userName:PChar;size:size_t):Integer;
Const
cuser:PChar='user'#0;
begin
if (userName=nil) then Exit(SCE_USER_SERVICE_ERROR_INVALID_ARGUMENT);
if (size<Length(cuser)) then Exit(SCE_USER_SERVICE_ERROR_BUFFER_TOO_SHORT);
Move(cuser^,userName^,Length(cuser));
Result:=0;
end;
function ps4_sceUserServiceRegisterEventCallback(func:TUserServiceEventCallback;arg:Pointer):Integer;
begin
Writeln('sceUserServiceRegisterEventCallback:',HexStr(func));
Result:=0;
end;
var
login_event:Integer=0;
function ps4_sceUserServiceGetEvent(event:pSceUserServiceEvent):Integer;
begin
if (event=nil) then Exit(SCE_USER_SERVICE_ERROR_INVALID_ARGUMENT);
if not CAS(login_event,0,1) then
begin
Result:=SCE_USER_SERVICE_ERROR_NO_EVENT;
end else
begin
event^:=Default(SceUserServiceEvent);
event^.eventType:=SCE_USER_SERVICE_EVENT_TYPE_LOGIN;
event^.userId :=1;
Result:=0;
end;
end;
const
//SceUserServiceUserColor
SCE_USER_SERVICE_USER_COLOR_BLUE =0;
SCE_USER_SERVICE_USER_COLOR_RED =1;
SCE_USER_SERVICE_USER_COLOR_GREEN=2;
SCE_USER_SERVICE_USER_COLOR_PINK =3;
function ps4_sceUserServiceGetUserColor(userId:Integer;
color:pInteger //SceUserServiceUserColor
):Integer;
begin
if (color=nil) then Exit(SCE_USER_SERVICE_ERROR_INVALID_ARGUMENT);
color^:=SCE_USER_SERVICE_USER_COLOR_BLUE;
Result:=0;
end;
function Load_libSceUserService(name:pchar):p_lib_info;
var
lib:TLIBRARY;
begin
Result:=obj_new_int('libSceUserService');
lib:=Result^.add_lib('libSceUserService');
lib.set_proc($8F760CBB531534DA,@ps4_sceUserServiceInitialize);
lib.set_proc($6B3FF447A7AF899D,@ps4_sceUserServiceInitialize2);
lib.set_proc($6F01634BE6D7F660,@ps4_sceUserServiceTerminate);
lib.set_proc($7CF87298A36F2BF0,@ps4_sceUserServiceGetLoginUserIdList);
lib.set_proc($09D5A9D281D61ABD,@ps4_sceUserServiceGetInitialUser);
lib.set_proc($D71C5C3221AED9FA,@ps4_sceUserServiceGetUserName);
lib.set_proc($C87D7B43A356B558,@ps4_sceUserServiceGetEvent);
lib.set_proc($954A2AC1342EE06A,@ps4_sceUserServiceGetUserColor);
lib:=Result^.add_lib('libSceUserServiceForNpToolkit');
lib.set_proc($C2E23B73B50D9340,@ps4_sceUserServiceRegisterEventCallback);
end;
var
stub:t_int_file;
initialization
reg_int_file(stub,'libSceUserService.prx',@Load_libSceUserService);
end.

View File

@ -1785,7 +1785,6 @@ begin
begin
pmap_protect(map^.pmap,
current^.vm_obj,
current^.offset,
current^.start,
current^.__end,
current^.protection and MASK(current));
@ -1921,6 +1920,7 @@ begin
end;
else;
end;
vm_map_simplify_entry(map, current);
current:=current^.next;
@ -1967,30 +1967,15 @@ begin
continue;
end;
//vm_object_madvise(current^.vm_obj, pstart, p__end, behav);
vm_object_madvise(map^.pmap,
current^.vm_obj,
useStart,
useStart+ptoa(pend-pstart),
behav);
if (current^.vm_obj=nil) then
if (behav=MADV_WILLNEED) then
begin
Case behav of
MADV_WILLNEED:
begin
pmap_enter_object(map^.pmap,
current^.vm_obj,
ptoa(pstart),
useStart,
useStart+ptoa(pend-pstart),
current^.protection);
end;
MADV_FREE:
begin
pmap_madv_free(map^.pmap,
current^.vm_obj,
ptoa(pstart),
useStart,
useStart+ptoa(pend-pstart),
current^.protection);
end;
end;
//re enter?
end;
current:=current^.next;
@ -2399,10 +2384,8 @@ begin
begin
pmap_remove(map^.pmap,
entry^.vm_obj,
entry^.offset,
entry^.start,
entry^.__end,
entry^.protection);
entry^.__end);
end;

View File

@ -81,6 +81,11 @@ procedure vm_nt_map_protect(map:p_vm_nt_map;
__end:vm_offset_t;
prot :Integer);
procedure vm_nt_map_madvise(map:p_vm_nt_map;
start:vm_offset_t;
__end:vm_offset_t;
advise:Integer);
procedure vm_nt_entry_deallocate(entry:p_vm_nt_entry);
implementation
@ -124,6 +129,7 @@ var
r:Integer;
begin
if ((obj^.flags and NT_FILE_FREE)<>0) then
if (obj^.hfile<>0) then
begin
r:=md_memfd_close(obj^.hfile);
if (r<>0) then
@ -281,15 +287,18 @@ begin
end;
end;
r:=md_file_mmap_ex(entry^.obj^.hfile,
Pointer(entry^.start),
entry^.offset,
entry^.size, //unaligned size
MD_PROT_RW);
if (r<>0) then
if (entry^.obj^.hfile<>0) then
begin
Writeln('failed md_file_mmap_ex(',HexStr(entry^.start,11),',',HexStr(entry^.start+size,11),'):0x',HexStr(r,8));
Assert(false,'vm_map');
r:=md_file_mmap_ex(entry^.obj^.hfile,
Pointer(entry^.start),
entry^.offset,
entry^.size, //unaligned size
MD_PROT_RW);
if (r<>0) then
begin
Writeln('failed md_file_mmap_ex(',HexStr(entry^.start,11),',',HexStr(entry^.start+size,11),'):0x',HexStr(r,8));
Assert(false,'vm_map');
end;
end;
if (prot<>MD_PROT_RW) then
@ -384,11 +393,15 @@ begin
if (p^.start<>0) and
(p^.start<>p^.__end) then
begin
r:=md_file_unmap_ex(Pointer(p^.start));
if (r<>0) then
//
if (stat.obj^.hfile<>0) then
begin
Writeln('failed md_file_unmap_ex(',HexStr(p^.start,11),',',HexStr(p^.__end,11),'):0x',HexStr(r,8));
Assert(false,'vm_remap');
r:=md_file_unmap_ex(Pointer(p^.start));
if (r<>0) then
begin
Writeln('failed md_file_unmap_ex(',HexStr(p^.start,11),',',HexStr(p^.__end,11),'):0x',HexStr(r,8));
Assert(false,'vm_remap');
end;
end;
//
//Writeln('md_file_unmap_ex(',HexStr(p^.start,11),',',HexStr(p^.__end,11),'):0x',HexStr(r,8));
@ -440,6 +453,7 @@ begin
begin
//map new
if (ets[i]^.obj<>nil) then
if (stat.obj^.hfile<>0) then
begin
r:=md_file_mmap_ex(stat.obj^.hfile,
Pointer(ets[i]^.start),
@ -482,6 +496,7 @@ var
r:Integer;
begin
if (entry^.obj<>nil) then
if (entry^.obj^.hfile<>0) then
begin
r:=md_file_unmap_ex(Pointer(entry^.start));
if (r<>0) then
@ -1066,6 +1081,55 @@ begin
end;
end;
procedure vm_nt_map_madvise(map:p_vm_nt_map;
start:vm_offset_t;
__end:vm_offset_t;
advise:Integer);
var
entry:p_vm_nt_entry;
base,size:vm_size_t;
r:Integer;
begin
if (start=__end) then Exit;
if (not vm_nt_map_lookup_entry(map, start, @entry)) then
begin
entry:=entry^.next;
end else
begin
entry:=entry;
end;
while (entry<>@map^.header) and (entry^.start<__end) do
begin
base:=entry^.start;
size:=entry^.__end;
if (base<start) then
begin
base:=start;
end;
if (size>__end) then
begin
size:=__end;
end;
size:=size-base;
case advise of
MADV_WILLNEED:r:=md_dontneed(Pointer(base),size);
MADV_DONTNEED,
MADV_FREE :r:=md_activate(Pointer(base),size);
else;
end;
//ignore errors
entry:=entry^.next;
end;
end;
end.

View File

@ -33,10 +33,17 @@ function vm_object_coalesce(prev_object:vm_object_t;
next_size :vm_ooffset_t;
reserved :Boolean):Boolean;
procedure vm_object_madvise(pmap :Pointer;
obj :vm_object_t;
start :vm_offset_t;
__end :vm_offset_t;
advise:Integer);
implementation
uses
vmparam,
vm_pmap,
vnode,
vnode_if,
vmount,
@ -409,5 +416,96 @@ begin
Result:=(TRUE);
end;
{
vm_object_madvise:
Implements the madvise function at the object/page level.
MADV_WILLNEED (any object)
Activate the specified pages if they are resident.
MADV_DONTNEED (any object)
Deactivate the specified pages if they are resident.
MADV_FREE (OBJT_DEFAULT/OBJT_SWAP objects,
OBJ_ONEMAPPING only)
Deactivate and clean the specified pages if they are
resident. This permits the process to reuse the pages
without faulting or the kernel to reclaim the pages
without I/O.
}
procedure vm_object_madvise(pmap :Pointer;
obj :vm_object_t;
start :vm_offset_t;
__end :vm_offset_t;
advise:Integer);
label
unlock_tobject;
begin
if (obj=nil) then
begin
case advise of
MADV_WILLNEED,
MADV_DONTNEED,
MADV_FREE :
begin
pmap_madvise(pmap,
obj,
start,
__end,
advise);
end
else;
end;
Exit;
end;
VM_OBJECT_LOCK(obj);
{
* MADV_FREE only operates on OBJT_DEFAULT or OBJT_SWAP pages
* and those pages must be OBJ_ONEMAPPING.
}
if (advise=MADV_FREE) then
begin
if ((obj^.otype<>OBJT_DEFAULT) and
(obj^.otype<>OBJT_SELF) and //
(obj^.otype<>OBJT_SWAP)) or
((obj^.flags and OBJ_ONEMAPPING)=0) then
begin
goto unlock_tobject;
end;
end else
if (obj^.otype=OBJT_PHYS) then
begin
goto unlock_tobject;
end;
case advise of
MADV_WILLNEED,
MADV_DONTNEED,
MADV_FREE :
begin
pmap_madvise(pmap,
obj,
start,
__end,
advise);
end
else;
end;
unlock_tobject:
VM_OBJECT_UNLOCK(obj);
end;
end.