diff --git a/fpPS4.lpi b/fpPS4.lpi
index 018ebf42..e769282e 100644
--- a/fpPS4.lpi
+++ b/fpPS4.lpi
@@ -614,6 +614,234 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gui/game_run.pas b/gui/game_run.pas
index dfaa3aad..5763c1fb 100644
--- a/gui/game_run.pas
+++ b/gui/game_run.pas
@@ -8,25 +8,45 @@ uses
windows,
Classes,
SysUtils,
+ kern_thr,
md_pipe,
host_ipc,
md_host_ipc,
game_info;
-var
- t_wr_handle:THandle;
+type
+ TGameRunConfig=record
+ hOutput:THandle;
+ hError :THandle;
+
+ fork_proc:Boolean;
+ end;
+
+ TGameProcess=class
+ g_ipc :THostIpcConnect;
+ g_fork:Boolean;
+ end;
+
+ TGameProcessSimple=class(TGameProcess)
+ Ftd:p_kthread;
+ end;
+
+ TGameProcessPipe=class(TGameProcess)
+ FProcess:THandle;
+ FChild:THandle;
+ end;
+
+var
- mgui_ipc:THostIpcConnect=nil;
kern_ipc:THostIpcConnect=nil;
-procedure run_item(Item:TGameItem);
+function run_item(const cfg:TGameRunConfig;Item:TGameItem):TGameProcess;
implementation
uses
sys_sysinit,
kern_param,
- kern_thr,
kern_thread,
kern_exec,
vfs_mountroot,
@@ -187,12 +207,8 @@ begin
sleep(-1);
end;
-const
- fork_proc:Boolean=True;
-
-procedure run_item(Item:TGameItem);
+function run_item(const cfg:TGameRunConfig;Item:TGameItem):TGameProcess;
var
- td:p_kthread;
r:Integer;
kern2mgui:array[0..1] of THandle;
@@ -204,21 +220,29 @@ var
mem:TMemoryStream;
begin
+ Result:=nil;
if Item.FLock then Exit;
if runing then Exit;
- SetStdHandle(STD_ERROR_HANDLE ,t_wr_handle);
- SetStdHandle(STD_OUTPUT_HANDLE,t_wr_handle);
+ SetStdHandle(STD_OUTPUT_HANDLE,cfg.hOutput);
+ SetStdHandle(STD_ERROR_HANDLE ,cfg.hError );
- if fork_proc then
+ if cfg.fork_proc then
begin
- md_pipe2(@kern2mgui,MD_PIPE_ASYNC0 or MD_PIPE_ASYNC1);
+ Result:=TGameProcessPipe.Create;
+ Result.g_fork:=cfg.fork_proc;
- p_mgui_ipc:=THostIpcPipeMGUI.Create;
- p_mgui_ipc.set_pipe(kern2mgui[0]);
+ with TGameProcessPipe(Result) do
+ begin
+ md_pipe2(@kern2mgui,MD_PIPE_ASYNC0 or MD_PIPE_ASYNC1);
- mgui_ipc:=p_mgui_ipc;
+ p_mgui_ipc:=THostIpcPipeMGUI.Create;
+ p_mgui_ipc.set_pipe(kern2mgui[0]);
+
+ g_ipc:=p_mgui_ipc;
+ FChild:=kern2mgui[1];
+ end;
//
@@ -228,23 +252,34 @@ begin
Item.Serialize(mem);
- md_fork_process(@fork_process,mem.Memory,mem.Size);
+ with TGameProcessPipe(Result) do
+ begin
+ FProcess:=md_fork_process(@fork_process,mem.Memory,mem.Size);
+ end;
mem.Free;
end else
begin
- s_kern_ipc:=THostIpcSimpleKERN.Create;
- s_mgui_ipc:=THostIpcSimpleMGUI.Create;
+ Result:=TGameProcessSimple.Create;
+ Result.g_fork:=cfg.fork_proc;
- s_kern_ipc.FDest:=s_mgui_ipc;
- s_mgui_ipc.FDest:=s_kern_ipc;
+ with TGameProcessSimple(Result) do
+ begin
- kern_ipc:=s_kern_ipc;
- mgui_ipc:=s_mgui_ipc;
+ s_kern_ipc:=THostIpcSimpleKERN.Create;
+ s_mgui_ipc:=THostIpcSimpleMGUI.Create;
+
+ s_kern_ipc.FDest:=s_mgui_ipc;
+ s_mgui_ipc.FDest:=s_kern_ipc;
+
+ g_ipc:=s_mgui_ipc;
+
+ kern_ipc:=s_kern_ipc;
+
+ Ftd:=nil;
+ r:=kthread_add(@prepare,Item,@Ftd,'[main]');
+ end;
- td:=nil;
- r:=kthread_add(@prepare,Item,@td,'[main]');
- Assert(r=0);
end;
runing:=True;
diff --git a/gui/main.pas b/gui/main.pas
index cb4a6a57..f2407cbe 100644
--- a/gui/main.pas
+++ b/gui/main.pas
@@ -9,6 +9,7 @@ uses
game_info,
game_edit,
+ game_run,
host_ipc;
@@ -41,6 +42,8 @@ type
private
public
+ GameProcess:TGameProcess;
+
procedure ReadIniFile;
procedure LoadItemIni(Item:TGameItem);
procedure SaveItemIni(Item:TGameItem);
@@ -76,9 +79,7 @@ uses
Rtti,
evbuffer,
- evpoll,
-
- game_run;
+ evpoll;
//
@@ -309,9 +310,10 @@ begin
FLogUpdateTime:=GetTickCount64;
end;
- if (mgui_ipc<>nil) then
+ if (GameProcess<>nil) then
+ if (GameProcess.g_ipc<>nil) then
begin
- mgui_ipc.Update(IpcHandler);
+ GameProcess.g_ipc.Update(IpcHandler);
end;
end;
@@ -386,6 +388,7 @@ procedure TfrmMain.MIRunClick(Sender: TObject);
var
Item:TGameItem;
aRow:Integer;
+ cfg:TGameRunConfig;
begin
aRow:=ListGrid.Row;
@@ -394,8 +397,6 @@ begin
Item:=GetItemRow(aRow);
- t_wr_handle:=FAddHandle;
-
FList.FSynLog.TopLine:=FList.FSynLog.Lines.Count;
//reset file
@@ -405,7 +406,12 @@ begin
Pages.ActivePage:=TabLog;
- run_item(Item);
+ cfg.hOutput:=FAddHandle;
+ cfg.hError :=FAddHandle;
+
+ cfg.fork_proc:=False;
+
+ GameProcess:=run_item(cfg,Item);
end;
procedure TfrmMain.MIDelClick(Sender: TObject);
diff --git a/sys/host_ipc.pas b/sys/host_ipc.pas
index 8dbb900a..83cc30fd 100644
--- a/sys/host_ipc.pas
+++ b/sys/host_ipc.pas
@@ -64,6 +64,7 @@ type
procedure TriggerNodeSync(tid:DWORD;value:Ptruint);
procedure Pack(mtype:t_mtype;mlen,mtid:DWORD;buf:Pointer);
function Recv:PQNode;
+ procedure Flush;
procedure RecvSync(node:PQNode);
public
//
@@ -112,6 +113,7 @@ end;
Destructor THostIpcConnect.Destroy;
begin
+ Flush;
mtx_destroy(FWLock);
inherited;
end;
@@ -135,6 +137,17 @@ begin
FQueue.Pop(Result);
end;
+procedure THostIpcConnect.Flush;
+var
+ node:PQNode;
+begin
+ node:=nil;
+ while FQueue.Pop(node) do
+ begin
+ FreeMem(node);
+ end;
+end;
+
procedure THostIpcConnect.RecvSync(node:PQNode);
var
value:Ptruint;
diff --git a/sys/kern/kern_rtprio.pas b/sys/kern/kern_rtprio.pas
index 078d49ec..c2ac9519 100644
--- a/sys/kern/kern_rtprio.pas
+++ b/sys/kern/kern_rtprio.pas
@@ -6,6 +6,7 @@ unit kern_rtprio;
interface
uses
+ mqueue,
rtprio,
kern_thr;
@@ -133,7 +134,6 @@ function sys_rtprio(func,pid:Integer;rtp:Pointer):Integer;
var
td,tdp:p_kthread;
rtp1,rtp2:t_rtprio;
- i:kthread_iterator;
begin
if (pid<>0) and (pid<>p_proc.p_pid) then Exit(ESRCH);
@@ -162,24 +162,25 @@ begin
rtp1._type:=RTP_PRIO_IDLE;
rtp1._prio:=RTP_PRIO_MAX;
- if FOREACH_THREAD_START(@i) then
- begin
- repeat
- tdp:=THREAD_GET(@i);
+ threads_lock;
- pri_to_rtp(tdp,@rtp2);
-
- if (rtp2._typenil) do
begin
- rtp1:=rtp2;
+
+ pri_to_rtp(tdp,@rtp2);
+
+ if (rtp2._typenil) do
+ begin
- Result:=rtp_to_pri(@rtp1,tdp);
- if (Result<>0) then Break;
+ Result:=rtp_to_pri(@rtp1,tdp);
+ if (Result<>0) then Break;
- until not THREAD_NEXT(@i);
- FOREACH_THREAD_FINISH();
- end;
+ tdp:=TAILQ_NEXT(tdp,@tdp^.td_plist)
+ end;
+ threads_unlock;
end;
PROC_UNLOCK;
diff --git a/sys/kern/kern_sig.pas b/sys/kern/kern_sig.pas
index 27ef9b26..457cff57 100644
--- a/sys/kern/kern_sig.pas
+++ b/sys/kern/kern_sig.pas
@@ -417,21 +417,22 @@ procedure sigqueue_delete_set_proc(_set:p_sigset_t);
var
td0:p_kthread;
worklist:sigqueue_t;
- i:kthread_iterator;
begin
sigqueue_init(@worklist);
sigqueue_move_set(@p_proc.p_sigqueue,@worklist,_set);
- if FOREACH_THREAD_START(@i) then
- begin
- repeat
- td0:=THREAD_GET(@i);
+ threads_lock;
+
+ td0:=TAILQ_FIRST(@p_threads);
+ while (td0<>nil) do
+ begin
sigqueue_move_set(@td0^.td_sigqueue,@worklist,_set);
- until not THREAD_NEXT(@i);
- FOREACH_THREAD_FINISH();
- end;
+ td0:=TAILQ_NEXT(td0,@td0^.td_plist)
+ end;
+
+ threads_unlock;
sigqueue_flush(@worklist);
end;
@@ -1341,7 +1342,6 @@ var
td:p_kthread;
first_td :p_kthread;
signal_td:p_kthread;
- i:kthread_iterator;
begin
td:=curkthread;
@@ -1354,25 +1354,27 @@ begin
first_td :=nil;
signal_td:=nil;
- if FOREACH_THREAD_START(@i) then
- begin
- repeat
- td:=THREAD_GET(@i);
+ threads_lock;
- if (first_td=nil) then
+ td:=TAILQ_FIRST(@p_threads);
+ while (td<>nil) do
begin
- first_td:=td;
+
+ if (first_td=nil) then
+ begin
+ first_td:=td;
+ end;
+
+ if (not SIGISMEMBER(@td^.td_sigmask,sig)) then
+ begin
+ signal_td:=td;
+ Break;
+ end;
+
+ td:=TAILQ_NEXT(td,@td^.td_plist)
end;
- if (not SIGISMEMBER(@td^.td_sigmask,sig)) then
- begin
- signal_td:=td;
- Break;
- end;
-
- until not THREAD_NEXT(@i);
- FOREACH_THREAD_FINISH();
- end;
+ threads_unlock;
if (signal_td=nil) then
begin
diff --git a/sys/kern/kern_thr.pas b/sys/kern/kern_thr.pas
index b34904c5..625c435b 100644
--- a/sys/kern/kern_thr.pas
+++ b/sys/kern/kern_thr.pas
@@ -177,6 +177,7 @@ type
pp_kthread=^p_kthread;
p_kthread=^kthread;
kthread=record
+ td_plist :TAILQ_ENTRY;
td_umtxq :Pointer; //p_umtx_q
td_handle :THandle; //nt thread
td_teb :p_teb;
@@ -198,11 +199,9 @@ type
td_user_pri :Word;
td_name :t_td_name;
//
- td_cpuset :Ptruint;
td_sigmask :sigset_t;
td_oldsigmask :sigset_t;
td_sigqueue :sigqueue_t;
- td_align :Pointer;
td_frame :trapframe;
td_fpstate :t_fpstate;
td_retval :array[0..1] of QWORD;
@@ -210,6 +209,7 @@ type
td_ustack :t_td_stack;
td_kstack :t_td_stack;
//
+ td_cpuset :Ptruint;
td_sleepqueue :Pointer;
td_slpq :TAILQ_ENTRY;
td_wchan :Pointer;
diff --git a/sys/kern/kern_thread.pas b/sys/kern/kern_thread.pas
index f7ad645f..aac5f3e3 100644
--- a/sys/kern/kern_thread.pas
+++ b/sys/kern/kern_thread.pas
@@ -17,10 +17,6 @@ uses
rtprio,
hamt;
-type
- p_kthread_iterator=^kthread_iterator;
- kthread_iterator=THAMT_Iterator32;
-
procedure thread_reap();
function thread_alloc:p_kthread;
@@ -48,10 +44,8 @@ procedure thread_lock (td:p_kthread);
procedure thread_unlock (td:p_kthread);
function tdfind(tid:DWORD):p_kthread;
-function FOREACH_THREAD_START (i:p_kthread_iterator):Boolean;
-procedure FOREACH_THREAD_FINISH();
-function THREAD_NEXT(i:p_kthread_iterator):Boolean;
-function THREAD_GET (i:p_kthread_iterator):p_kthread;
+procedure threads_lock;
+procedure threads_unlock;
procedure KernSetThreadDebugName(newtd:p_kthread;prefix:PChar);
@@ -65,6 +59,9 @@ procedure kthread_exit();
var
init_tty_cb:Tprocedure;
+ p_threads:TAILQ_HEAD=(tqh_first:nil;tqh_last:@p_threads.tqh_first);
+ p_numthreads:Integer=0;
+
implementation
uses
@@ -74,7 +71,6 @@ uses
md_sleep,
md_context,
machdep,
- md_proc,
md_thread,
kern_rwlock,
kern_sig,
@@ -108,8 +104,6 @@ var
zombie_threads:TAILQ_HEAD=(tqh_first:nil;tqh_last:@zombie_threads.tqh_first);
zombie_lock:Pointer=nil;
- p_numthreads:Integer=0;
-
const
max_threads_per_proc=1500;
@@ -126,9 +120,12 @@ begin
Result:=0;
end;
+var
+ _t_init:Integer=0;
+
procedure threadinit;
begin
- FillChar(tidhashtbl,SizeOf(tidhashtbl),0);
+ if (System.InterlockedExchange(_t_init,1)<>0) then Exit;
//init internals
BeginThread(@_thread_null);
end;
@@ -265,6 +262,8 @@ var
begin
rw_wlock(tidhash_lock);
+ TAILQ_INSERT_HEAD(@p_threads, td, @td^.td_plist);
+
data:=HAMT_insert32(@tidhashtbl,td^.td_tid,td);
if (data<>nil) then
@@ -285,6 +284,8 @@ begin
data:=nil;
rw_wlock(tidhash_lock);
+ TAILQ_REMOVE(@p_threads, td, @td^.td_plist);
+
HAMT_delete32(@tidhashtbl,td^.td_tid,@data);
rw_wunlock(tidhash_lock);
@@ -295,33 +296,16 @@ begin
end;
end;
-function FOREACH_THREAD_START(i:p_kthread_iterator):Boolean;
+procedure threads_lock;
begin
- rw_rlock(tidhash_lock);
-
- Result:=HAMT_first32(@tidhashtbl,i);
-
- if not Result then //space
- begin
- rw_runlock(tidhash_lock);
- end;
+ rw_wlock(tidhash_lock);
end;
-procedure FOREACH_THREAD_FINISH();
+procedure threads_unlock;
begin
- rw_runlock(tidhash_lock);
+ rw_wunlock(tidhash_lock);
end;
-function THREAD_NEXT(i:p_kthread_iterator):Boolean;
-begin
- Result:=HAMT_next32(i);
-end;
-
-function THREAD_GET(i:p_kthread_iterator):p_kthread;
-begin
- Result:=nil;
- HAMT_get_value32(i,@Result);
-end;
procedure KernSetThreadDebugName(newtd:p_kthread;prefix:PChar);
var
@@ -605,6 +589,8 @@ var
begin
Result:=0;
+ threadinit;
+
if (func=nil) or
(newtdp=nil) then
begin
@@ -833,7 +819,6 @@ function sys_thr_kill(id,sig:Integer):Integer;
var
td,ttd:p_kthread;
ksi:ksiginfo_t;
- i:kthread_iterator;
begin
td:=curkthread;
@@ -854,19 +839,24 @@ begin
Result:=ESRCH;
PROC_LOCK;
- if FOREACH_THREAD_START(@i) then
- begin
- repeat
- ttd:=THREAD_GET(@i);
- if (ttd<>td) then
+ threads_lock;
+
+ ttd:=TAILQ_FIRST(@p_threads);
+ while (ttd<>nil) do
begin
- Result:=0;
- if (sig=0) then Break;
- tdksignal(ttd,sig,@ksi);
+
+ if (ttd<>td) then
+ begin
+ Result:=0;
+ if (sig=0) then Break;
+ tdksignal(ttd,sig,@ksi);
+ end;
+
+
+ ttd:=TAILQ_NEXT(ttd,@ttd^.td_plist)
end;
- until not THREAD_NEXT(@i);
- FOREACH_THREAD_FINISH();
- end;
+
+ threads_unlock;
PROC_UNLOCK;
end;
diff --git a/sys/md/md_map.pas b/sys/md/md_map.pas
index 8cf6d777..f582f80c 100644
--- a/sys/md/md_map.pas
+++ b/sys/md/md_map.pas
@@ -37,6 +37,17 @@ const
MD_PROT_RW //XWR
);
+ wprots_e:array[0..7] of Byte=(
+ MD_PROT_NONE,//___
+ MD_PROT_R ,//__R
+ MD_PROT_W ,//_W_
+ MD_PROT_RW ,//_WR
+ MD_PROT_X ,//X__
+ MD_PROT_RX ,//X_R
+ MD_PROT_WX ,//XW_
+ MD_PROT_RWX //XWR
+ );
+
function md_reserve(hProcess:THandle;var base:Pointer;size:QWORD):Integer;
function md_reserve(var base:Pointer;size:QWORD):Integer;
@@ -44,7 +55,7 @@ function md_split (base:Pointer;size:QWORD):Integer;
function md_union (base:Pointer;size:QWORD):Integer;
function md_memfd_create(var hMem:THandle;size:QWORD):Integer;
-function md_memfd_open (var hMem:THandle;hFile:THandle):Integer;
+function md_memfd_open (var hMem:THandle;hFile:THandle;maxprot:Byte):Integer;
function md_memfd_close (hMem:THandle):Integer;
function md_protect(hProcess:THandle;base:Pointer;size:QWORD;prot:Integer):Integer;
@@ -187,19 +198,39 @@ begin
);
end;
-function md_memfd_open(var hMem:THandle;hFile:THandle):Integer;
+function md_memfd_open(var hMem:THandle;hFile:THandle;maxprot:Byte):Integer;
var
+ Access:DWORD;
+ prot:DWORD;
size:QWORD;
begin
+ Access:=SECTION_QUERY;
+
+ if ((maxprot and VM_PROT_READ)<>0) then
+ begin
+ Access:=Access or SECTION_MAP_READ;
+ end;
+
+ if ((maxprot and VM_PROT_WRITE)<>0) then
+ begin
+ Access:=Access or SECTION_MAP_WRITE;
+ end;
+
+ if ((maxprot and VM_PROT_EXECUTE)<>0) then
+ begin
+ Access:=Access or SECTION_MAP_EXECUTE;
+ end;
+
+ prot:=wprots_e[maxprot and VM_RWX];
+
size:=0;
hMem:=0;
Result:=NtCreateSection(
@hMem,
- SECTION_ALL_ACCESS,
- //SECTION_MAP_WRITE or SECTION_MAP_READ or SECTION_MAP_EXECUTE,
+ Access,
nil,
@size,
- PAGE_READWRITE,
+ prot,
SEC_COMMIT,
hFile
);
@@ -293,31 +324,15 @@ end;
function md_file_mmap(handle:THandle;var base:Pointer;offset,size:QWORD;prot:Integer):Integer;
var
- hSection:THandle;
CommitSize:ULONG_PTR;
SectionOffset:ULONG_PTR;
begin
- CommitSize:=0; //full size
-
- hSection:=0;
- Result:=NtCreateSection(
- @hSection,
- SECTION_MAP_WRITE or SECTION_MAP_READ or SECTION_MAP_EXECUTE,
- nil,
- @CommitSize,
- prot,
- SEC_COMMIT,
- handle
- );
-
- if (Result<>0) then Exit;
-
base:=md_alloc_page(base);
CommitSize:=size;
SectionOffset:=offset and (not (MD_ALLOC_GRANULARITY-1));
- Result:=NtMapViewOfSection(hSection,
+ Result:=NtMapViewOfSection(handle,
NtCurrentProcess,
@base,
0,
@@ -328,8 +343,6 @@ begin
0,
prot
);
-
- NtClose(hSection);
end;
function md_file_unmap(base:Pointer;size:QWORD):Integer;
diff --git a/sys/md/vm_pmap.pas b/sys/md/vm_pmap.pas
index a4532924..197c27d9 100644
--- a/sys/md/vm_pmap.pas
+++ b/sys/md/vm_pmap.pas
@@ -86,6 +86,9 @@ procedure pmap_remove(pmap :pmap_t;
implementation
+uses
+ ntapi;
+
function atop(x:QWORD):DWORD; inline;
begin
Result:=QWORD(x) shr PAGE_SHIFT;
@@ -119,6 +122,8 @@ begin
Assert(false,'dev_mem_init');
end;
+ DEV_INFO.DEV_FD.maxp:=VM_PROT_READ or VM_PROT_WRITE;
+
DEV_INFO.DEV_PTR:=nil;
r:=md_reserve(DEV_INFO.DEV_PTR,DEV_INFO.DEV_SIZE);
if (r<>0) then
@@ -260,7 +265,7 @@ begin
Assert(false,'get_private_fd');
end;
- info.obj:=vm_nt_file_obj_allocate(hfile);
+ info.obj:=vm_nt_file_obj_allocate(hfile,VM_PROT_READ or VM_PROT_WRITE);
with info.obj^ do
begin
@@ -283,6 +288,8 @@ begin
begin
R:=md_memfd_create(DMEM_FD[i].hfile,PMAPP_1GB_SIZE);
+ DMEM_FD[i].maxp:=VM_PROT_READ or VM_PROT_WRITE;
+
if (r<>0) then
begin
Writeln('failed md_memfd_create(',HexStr(PMAPP_1GB_SIZE,11),'):0x',HexStr(r,8));
@@ -391,6 +398,9 @@ procedure pmap_copy(pmap :pmap_t;
delta :vm_ooffset_t;
size :vm_ooffset_t);
var
+ start :vm_ooffset_t;
+ __end :vm_ooffset_t;
+ offset:vm_ooffset_t;
src,dst:Pointer;
r:Integer;
begin
@@ -399,8 +409,12 @@ begin
size:=delta;
end;
+ start :=src_ofs and (not (MD_ALLOC_GRANULARITY-1)); //dw
+ __end :=src_ofs+size; //up
+ offset:=src_ofs and (MD_ALLOC_GRANULARITY-1);
+
src:=nil;
- r:=md_file_mmap(src_obj^.hfile,src,src_ofs,size,MD_PROT_R);
+ r:=md_file_mmap(src_obj^.hfile,src,start,__end-start,MD_PROT_R);
if (r<>0) then
begin
@@ -417,7 +431,7 @@ begin
Assert(false,'pmap_copy');
end;
- Move(src^,dst^,size);
+ Move((src+offset)^,dst^,size);
md_cacheflush(dst,size,DCACHE);
@@ -469,6 +483,8 @@ var
info:t_fd_info;
cow :p_vm_nt_file_obj;
+ max:Integer;
+
r:Integer;
begin
Writeln('pmap_enter_object:',HexStr(start,11),':',HexStr(__end,11),':',HexStr(prot,2));
@@ -605,7 +621,14 @@ begin
end;
size:=size-offset;
- r:=md_memfd_open(md,fd);
+ max:=VM_PROT_READ or VM_PROT_WRITE;
+ r:=md_memfd_open(md,fd,max);
+
+ if (DWORD(r)=STATUS_ACCESS_DENIED) then
+ begin
+ max:=VM_PROT_READ;
+ r:=md_memfd_open(md,fd,max);
+ end;
end;
VM_OBJECT_UNLOCK(obj);
@@ -629,9 +652,7 @@ begin
begin
Writeln('pmap_enter_cowobj:',HexStr(start,11),':',HexStr(__end,11),':',HexStr(prot,2));
- Assert(false,'TODO COW');
-
- cow:=vm_nt_file_obj_allocate(md);
+ cow:=vm_nt_file_obj_allocate(md,VM_PROT_READ);
info.offset:=offset;
info.start :=start;
@@ -675,7 +696,7 @@ begin
end else
begin
- info.obj :=vm_nt_file_obj_allocate(md);
+ info.obj :=vm_nt_file_obj_allocate(md,max);
info.offset:=offset;
info.start :=start;
info.__end :=start+paddi;
@@ -697,16 +718,14 @@ begin
pmap_mark(info.start,info.__end,prot and VM_RWX);
- //aligned size
- size:=paddi;
+ //upper pages
+ delta:=(paddi and PAGE_MASK);
- //padding pages
- paddi:=PAGE_SIZE-((delta-size) and PAGE_MASK);
-
- if (paddi<>0) then
+ if (delta<>0) then
begin
offset:=0;
- start:=start+size;
+ start:=start+paddi;
+ prot:=prot and (not VM_PROT_COPY);
goto _default;
end;
diff --git a/sys/vm/vm_nt_map.pas b/sys/vm/vm_nt_map.pas
index 6a51e620..b9b2c466 100644
--- a/sys/vm/vm_nt_map.pas
+++ b/sys/vm/vm_nt_map.pas
@@ -24,6 +24,7 @@ type
hfile:THandle;
refs :QWORD;
flags:QWORD;
+ maxp :Byte;
end;
pp_vm_nt_entry=^p_vm_nt_entry;
@@ -50,7 +51,7 @@ type
property max_offset:vm_offset_t read header.__end write header.__end;
end;
-function vm_nt_file_obj_allocate (hfile:THandle):p_vm_nt_file_obj;
+function vm_nt_file_obj_allocate (hfile:THandle;maxp:Byte):p_vm_nt_file_obj;
procedure vm_nt_file_obj_destroy (obj:p_vm_nt_file_obj);
procedure vm_nt_file_obj_reference (obj:p_vm_nt_file_obj);
procedure vm_nt_file_obj_deallocate(obj:p_vm_nt_file_obj);
@@ -114,13 +115,16 @@ type
);
end;
-function vm_nt_file_obj_allocate(hfile:THandle):p_vm_nt_file_obj;
+function vm_nt_file_obj_allocate(hfile:THandle;maxp:Byte):p_vm_nt_file_obj;
begin
+ Assert(maxp<>0);
+
Result:=AllocMem(SizeOf(vm_nt_file_obj));
Result^.hfile:=hfile;
Result^.refs :=1;
Result^.flags:=NT_FILE_FREE or NT_MOBJ_FREE or NT_UNION_OBJ;
+ Result^.maxp :=maxp;
end;
procedure vm_nt_file_obj_destroy(obj:p_vm_nt_file_obj);
@@ -163,7 +167,10 @@ end;
//
-procedure vm_prot_fixup(map:p_vm_nt_map;start,__end:vm_offset_t);
+procedure vm_prot_fixup(map:p_vm_nt_map;
+ start:vm_offset_t;
+ __end:vm_offset_t;
+ max :Integer);
var
next:vm_offset_t;
base,size:vm_size_t;
@@ -184,7 +191,7 @@ begin
prot:=wprots[prot and VM_RWX];
- if (prot<>MD_PROT_RW) then
+ if (prot<>max) then
begin
r:=md_protect(Pointer(base),size,prot);
if (r<>0) then
@@ -240,6 +247,7 @@ var
start:vm_offset_t;
__end:vm_offset_t;
size:vm_size_t;
+ max:Integer;
r:Integer;
begin
if (entry^.obj<>nil) then
@@ -260,13 +268,15 @@ begin
end;
end;
+ max:=wprots[entry^.obj^.maxp and VM_RWX];
+
if (entry^.obj^.hfile<>0) then
begin
r:=md_file_mmap_ex(entry^.obj^.hfile,
Pointer(entry^.start),
entry^.offset,
entry^.size, //unaligned size
- MD_PROT_RW);
+ max);
if (r<>0) then
begin
Writeln('failed md_file_mmap_ex(',HexStr(entry^.start,11),',',HexStr(entry^.start+size,11),'):0x',HexStr(r,8));
@@ -274,7 +284,7 @@ begin
end;
end;
- if (prot<>MD_PROT_RW) then
+ if (prot<>max) then
begin
r:=md_protect(Pointer(entry^.start),size,prot);
if (r<>0) then
@@ -304,6 +314,8 @@ var
__end:vm_offset_t;
size:vm_size_t;
+ max:Integer;
+
p:p_range;
i,r:Integer;
begin
@@ -419,6 +431,8 @@ begin
end;
end;
+ max:=wprots[stat.obj^.maxp and VM_RWX];
+
//map new parts
For i:=Low(ets) to High(ets) do
begin
@@ -432,7 +446,7 @@ begin
Pointer(ets[i]^.start),
ets[i]^.offset,
ets[i]^.size, //unaligned size
- MD_PROT_RW);
+ max);
if (r<>0) then
begin
Writeln('failed md_file_mmap_ex(',HexStr(ets[i]^.start,11),',',HexStr(ets[i]^.__end,11),'):0x',HexStr(r,8));
@@ -451,8 +465,13 @@ begin
if (ets[i]<>nil) then
begin
if (ets[i]^.obj<>nil) then
+ if (stat.obj^.hfile<>0) then
begin
- vm_prot_fixup(map,ets[i]^.start,ets[i]^.__end);
+ vm_prot_fixup(map,
+ ets[i]^.start,
+ ets[i]^.__end,
+ max
+ );
end;
end;
end;