diff --git a/fpPS4.lpi b/fpPS4.lpi
index dc5f1657..88687a9b 100644
--- a/fpPS4.lpi
+++ b/fpPS4.lpi
@@ -1558,6 +1558,10 @@
+
+
+
+
diff --git a/sys/md/md_map.pas b/sys/md/md_map.pas
index 5b6b04c9..29b1ec8c 100644
--- a/sys/md/md_map.pas
+++ b/sys/md/md_map.pas
@@ -14,7 +14,7 @@ const
MD_PAGE_SHIFT = 12;
MD_PAGE_SIZE = 4*1024;
MD_PAGE_MASK = MD_PAGE_SIZE-1;
- MD_ALLOC_GRANULARITY=64*1024;
+ MD_ALLOC_GRANULARITY= 64*1024;
const
VM_RW =VM_PROT_READ or VM_PROT_WRITE;
diff --git a/sys/md/vm_pmap.pas b/sys/md/vm_pmap.pas
index 09986bb4..61a099ea 100644
--- a/sys/md/vm_pmap.pas
+++ b/sys/md/vm_pmap.pas
@@ -98,22 +98,10 @@ procedure pmap_protect(pmap :pmap_t;
__end :vm_offset_t;
prot :vm_prot_t);
-{
-procedure _pmap_prot_fix(pmap :pmap_t;
- start:vm_offset_t;
- __end:vm_offset_t;
- mode :Integer);
-
-procedure _pmap_prot_int(pmap :pmap_t;
- start:vm_offset_t;
- __end:vm_offset_t;
- prot :vm_prot_t);
-}
-
procedure pmap_prot_track(pmap :pmap_t;
start:vm_offset_t;
__end:vm_offset_t;
- prots:Byte);
+ prot :Byte);
procedure pmap_prot_restore(pmap :pmap_t;
start:vm_offset_t;
@@ -1009,15 +997,10 @@ begin
begin
_default:
- vm_nt_map_prot_fix(@pmap^.nt_map,
- start,
- __end,
- TRACK_PROT or REMAP_PROT);
-
- //vm_nt_map_protect(@pmap^.nt_map,
- // start,
- // __end,
- // (prot and VM_RW));
+ vm_nt_map_protect(@pmap^.nt_map,
+ start,
+ __end,
+ (prot and VM_RW));
end;
OBJT_DEVICE:
@@ -1054,58 +1037,34 @@ begin
pmap_unlock(pmap,lock);
end;
-procedure _pmap_prot_fix(pmap :pmap_t;
- start:vm_offset_t;
- __end:vm_offset_t;
- mode :Integer);
-begin
- start:=start and (not PMAPP_MASK);
- __end:=(__end+PMAPP_MASK) and (not PMAPP_MASK);
-
- vm_nt_map_prot_fix(@pmap^.nt_map,
- start,
- __end,
- mode);
-end;
-
-procedure _pmap_prot_int(pmap :pmap_t;
- start:vm_offset_t;
- __end:vm_offset_t;
- prot :vm_prot_t);
-begin
- start:=start and (not PMAPP_MASK);
- __end:=(__end+PMAPP_MASK) and (not PMAPP_MASK);
-
- vm_nt_map_protect(@pmap^.nt_map,
- start,
- __end,
- (prot and VM_RW));
-end;
-
procedure pmap_prot_track(pmap :pmap_t;
start:vm_offset_t;
__end:vm_offset_t;
- prots:Byte); public;
+ prot :Byte); public;
begin
if (p_print_pmap) then
begin
- Writeln('pmap_prot_track:',HexStr(start,11),':',HexStr(__end,11),':',HexStr(prots,2));
+ Writeln('pmap_prot_track:',HexStr(start,11),':',HexStr(__end,11),':',HexStr(prot,2));
end;
start:=start and (not PMAPP_MASK);
__end:=(__end+PMAPP_MASK) and (not PMAPP_MASK);
- ppmap_track(start,__end,prots);
+ //Don't do range lock here!
- vm_nt_map_prot_fix(@pmap^.nt_map,
+ ppmap_track(start,__end,prot);
+
+ vm_nt_map_tracking(@pmap^.nt_map,
start,
__end,
- TRACK_PROT or REMAP_PROT);
+ prot);
end;
procedure pmap_prot_restore(pmap :pmap_t;
start:vm_offset_t;
__end:vm_offset_t);
+var
+ lock:Pointer;
begin
if (p_print_pmap) then
begin
@@ -1115,10 +1074,14 @@ begin
start:=start and (not PMAPP_MASK);
__end:=(__end+PMAPP_MASK) and (not PMAPP_MASK);
+ lock:=pmap_wlock(pmap,start,__end);
+
vm_nt_map_prot_fix(@pmap^.nt_map,
start,
__end,
REMAP_PROT);
+
+ pmap_unlock(pmap,lock);
end;
procedure pmap_madvise(pmap :pmap_t;
diff --git a/sys/vm/vm_nt_map.pas b/sys/vm/vm_nt_map.pas
index 562d2f95..9837c873 100644
--- a/sys/vm/vm_nt_map.pas
+++ b/sys/vm/vm_nt_map.pas
@@ -9,7 +9,8 @@ uses
sysutils,
vm,
kern_mtx,
- vm_pmap_prot;
+ vm_pmap_prot,
+ vm_nt_sub_map;
const
NT_FILE_FREE=1;
@@ -44,30 +45,31 @@ type
maxp :Byte;
end;
+ ///
+
pp_vm_nt_entry=^p_vm_nt_entry;
p_vm_nt_entry=^vm_nt_entry;
- vm_nt_entry=packed record
- prev :p_vm_nt_entry; // previous entry
- next :p_vm_nt_entry; // next entry
- left :p_vm_nt_entry; // left child in binary search tree
- right :p_vm_nt_entry; // right child in binary search tree
- start :vm_offset_t; // start address
- __end :vm_offset_t; // end address
- size :vm_offset_t; // unaligned size
- obj :p_vm_nt_file_obj; // object I point to
- offset :vm_ooffset_t; // offset into object
+ vm_nt_entry=packed object
+ prev :p_vm_nt_entry; // previous entry
+ next :p_vm_nt_entry; // next entry
+ left :p_vm_nt_entry; // left child in binary search tree
+ right :p_vm_nt_entry; // right child in binary search tree
+ usize :vm_offset_t; // unaligned size
+ offset:vm_ooffset_t; // offset into object
+ obj :p_vm_nt_file_obj; // object I point to
+ sub :t_vm_nt_sub_map;
+ property start:vm_offset_t read sub.header.start write sub.header.start; // start address
+ property __end:vm_offset_t read sub.header.__end write sub.header.__end; // end address
end;
p_vm_nt_map=^t_vm_nt_map;
t_vm_nt_map=object
header :vm_nt_entry; // List of entries
- size :vm_size_t; // virtual size
- nentries :Integer; // Number of entries
+ lock :mtx; // Lock for map data
root :p_vm_nt_entry; // Root of a binary search tree
danger_zone:t_danger_zone;
- lock :mtx;
- property min_offset:vm_offset_t read header.start write header.start;
- property max_offset:vm_offset_t read header.__end write header.__end;
+ property min_offset:vm_offset_t read header.sub.header.start write header.sub.header.start;
+ property max_offset:vm_offset_t read header.sub.header.__end write header.sub.header.__end;
end;
function vm_nt_file_obj_allocate (hfile:THandle;maxp:Byte):p_vm_nt_file_obj;
@@ -86,27 +88,36 @@ function vm_nt_map_insert(
offset:vm_ooffset_t;
start :vm_offset_t;
__end :vm_offset_t;
- size :vm_offset_t;
+ usize :vm_offset_t;
prot :Integer):Integer;
function vm_nt_map_delete(map:p_vm_nt_map;start:vm_offset_t;__end:vm_offset_t):Integer;
-procedure vm_nt_map_protect(map:p_vm_nt_map;
+//Change protection taking into account tracking
+procedure vm_nt_map_protect(map :p_vm_nt_map;
start:vm_offset_t;
__end:vm_offset_t;
- prot :Integer);
+ prot :Integer);
-procedure vm_nt_map_prot_fix(map:p_vm_nt_map;
+//Change protection tracking
+procedure vm_nt_map_tracking(map :p_vm_nt_map;
+ start:vm_offset_t;
+ __end:vm_offset_t;
+ prot :Integer);
+
+//Update page protection by mode
+procedure vm_nt_map_prot_fix(map :p_vm_nt_map;
start:vm_offset_t;
__end:vm_offset_t;
mode :Integer);
-procedure vm_nt_map_madvise(map:p_vm_nt_map;
- start:vm_offset_t;
- __end:vm_offset_t;
+procedure vm_nt_map_madvise(map :p_vm_nt_map;
+ start :vm_offset_t;
+ __end :vm_offset_t;
advise:Integer);
-function vm_nt_map_mirror(map:p_vm_nt_map;
+//Create a memory mirror of the current state of the pages
+function vm_nt_map_mirror(map :p_vm_nt_map;
start:vm_offset_t;
__end:vm_offset_t):Pointer;
@@ -191,60 +202,6 @@ end;
//
-procedure vm_prot_fixup(map:p_vm_nt_map;
- start:vm_offset_t;
- __end:vm_offset_t;
- max :Integer;
- mode :Integer);
-var
- next:vm_offset_t;
- base,size:vm_size_t;
- prot:Integer;
- mask:Integer;
- r:Integer;
-begin
- if (PAGE_PROT=nil) then Exit;
- if (start=__end) then Exit;
-
- while (start<__end) do
- begin
- if ((mode and TRACK_PROT)=0) then
- begin
- next:=ppmap_scan_rwx(start,__end);
-
- prot:=ppmap_get_prot(start);
-
- prot:=(prot and VM_RW);
- end else
- begin
- next:=ppmap_scan(start,__end);
-
- prot:=ppmap_get_prot(start);
-
- mask:=not (prot shr PAGE_TRACK_SHIFT);
-
- prot:=(prot and VM_RW) and mask;
- end;
-
- base:=start;
- size:=next-start;
-
- if ((mode and REMAP_PROT)<>0) or (prot<>(max and VM_RW)) then
- begin
- r:=md_protect(Pointer(base),size,prot);
- if (r<>0) then
- begin
- Writeln('failed md_protect(',HexStr(base,11),',',HexStr(base+size,11),'):0x',HexStr(r,8));
- Assert(false,'vm_prot_fixup');
- end;
- end;
-
- start:=next;
- end;
-end;
-
-//
-
procedure vm_init_stat(var stat:t_range_stat;entry:p_vm_nt_entry); inline;
begin
stat:=Default(t_range_stat);
@@ -313,7 +270,7 @@ begin
r:=md_file_mmap_ex(entry^.obj^.hfile,
Pointer(entry^.start),
entry^.offset,
- entry^.size, //unaligned size
+ entry^.usize, //unaligned size
(max and VM_RW));
if (r<>0) then
begin
@@ -562,7 +519,7 @@ begin
r:=md_file_mmap_ex(stat.obj^.hfile,
Pointer(ets[i]^.start),
ets[i]^.offset,
- ets[i]^.size, //unaligned size
+ ets[i]^.usize, //unaligned size
(max and VM_RW));
if (r<>0) then
begin
@@ -584,12 +541,11 @@ begin
if (ets[i]^.obj<>nil) then
if (stat.obj^.hfile<>0) then
begin
- vm_prot_fixup(map,
- ets[i]^.start,
- ets[i]^.__end,
- max,
- TRACK_PROT or REMAP_PROT //untrack trigger or restore track?
- );
+ vm_nt_sub_map_prot_fixup(@ets[i]^.sub,
+ ets[i]^.start,
+ ets[i]^.__end,
+ TRACK_PROT or REMAP_PROT //untrack trigger or restore track?
+ );
end;
end;
end;
@@ -690,6 +646,13 @@ begin
FreeMem(entry);
end;
+procedure vm_nt_entry_deallocate(map:p_vm_nt_map;entry:p_vm_nt_entry); inline;
+begin
+ vm_nt_sub_map_free (@entry^.sub);
+ vm_nt_file_obj_deallocate(entry^.obj);
+ vm_nt_entry_dispose (map,entry);
+end;
+
function vm_nt_entry_create(map:p_vm_nt_map):p_vm_nt_entry;
var
new_entry:p_vm_nt_entry;
@@ -779,7 +742,6 @@ procedure vm_nt_entry_link(
after_where:p_vm_nt_entry;
entry :p_vm_nt_entry);
begin
- Inc(map^.nentries);
entry^.prev:=after_where;
entry^.next:=after_where^.next;
entry^.next^.prev:=entry;
@@ -826,7 +788,6 @@ begin
next:=entry^.next;
next^.prev:=prev;
prev^.next:=next;
- Dec(map^.nentries);
end;
function vm_nt_map_lookup_entry(
@@ -874,7 +835,7 @@ function _vm_nt_map_insert(
offset:vm_ooffset_t;
start :vm_offset_t;
__end :vm_offset_t;
- size :vm_offset_t; //unaligned size
+ usize :vm_offset_t; //unaligned size
prot :Integer):Integer;
var
new_entry :p_vm_nt_entry;
@@ -903,12 +864,16 @@ begin
new_entry:=vm_nt_entry_create(map);
new_entry^.start :=start;
new_entry^.__end :=__end;
- new_entry^.size :=size; //unaligned size
+ new_entry^.usize :=usize; //unaligned size
new_entry^.obj :=obj;
new_entry^.offset:=offset;
+ vm_nt_sub_map_init (@new_entry^.sub,start,__end);
+
+ //fill full map
+ vm_nt_sub_map_insert(@new_entry^.sub,start,__end,prot);
+
vm_nt_entry_link(map, prev_entry, new_entry);
- map^.size:=map^.size+(new_entry^.__end - new_entry^.start);
vm_map(map,new_entry,prot);
@@ -925,7 +890,7 @@ function vm_nt_map_insert(
offset:vm_ooffset_t;
start :vm_offset_t;
__end :vm_offset_t;
- size :vm_offset_t; //unaligned size
+ usize :vm_offset_t; //unaligned size
prot :Integer):Integer;
begin
if (start=__end) then
@@ -941,7 +906,7 @@ begin
offset,
start ,
__end ,
- size ,
+ usize ,
prot );
vm_nt_map_unlock(map);
@@ -985,10 +950,15 @@ begin
entry^.start :=prev^.start;
entry^.offset:=prev^.offset;
- entry^.size :=entry^.size+prev^.size; //unaligned size
+ entry^.usize :=entry^.usize+prev^.usize; //unaligned size
- vm_nt_file_obj_deallocate(prev^.obj);
- vm_nt_entry_dispose(map, prev);
+ //update (implicitly)
+ //entry^.sub.min_offset:=entry^.start;
+
+ //move
+ vm_nt_sub_map_move(@entry^.sub,@prev^.sub);
+
+ vm_nt_entry_deallocate(map,prev);
end;
end;
@@ -1002,18 +972,21 @@ begin
((stat.obj=nil) or (entry^.offset + esize=next^.offset))
then
begin
- begin
- vm_nt_entry_unlink(map, next);
+ vm_nt_entry_unlink(map, next);
- stat.rnext.start:=next^.start;
- stat.rnext.__end:=next^.__end;
+ stat.rnext.start:=next^.start;
+ stat.rnext.__end:=next^.__end;
- entry^.__end:=next^.__end;
- entry^.size :=entry^.size+next^.size; //unaligned size
+ entry^.__end:=next^.__end;
+ entry^.usize:=entry^.usize+next^.usize; //unaligned size
- vm_nt_file_obj_deallocate(next^.obj);
- vm_nt_entry_dispose(map, next);
- end;
+ //update (implicitly)
+ //entry^.sub.max_offset:=entry^.__end;
+
+ //move
+ vm_nt_sub_map_move(@entry^.sub,@next^.sub);
+
+ vm_nt_entry_deallocate(map,next);
end;
end;
@@ -1047,11 +1020,21 @@ begin
prev^:=entry^;
prev^.__end:=start;
- prev^.size :=(prev^.__end-prev^.start); //unaligned size
+ prev^.usize:=(prev^.__end-prev^.start); //unaligned size
entry^.offset:=entry^.offset + (start - entry^.start);
entry^.start :=start;
- entry^.size :=entry^.size-prev^.size; //unaligned size
+ entry^.usize :=entry^.usize-prev^.usize; //unaligned size
+
+ //update (implicitly)
+ //prev ^.sub.max_offset:=start;
+ //entry^.sub.min_offset:=start;
+
+ //new map
+ vm_nt_sub_map_init(@prev^.sub,prev^.start,prev^.__end);
+
+ //move
+ vm_nt_sub_map_move(@prev^.sub,@entry^.sub);
vm_nt_entry_link(map, entry^.prev, prev);
vm_nt_file_obj_reference(prev^.obj);
@@ -1065,10 +1048,20 @@ begin
next^.start :=__end;
entry^.__end:=__end;
- entry^.size :=(entry^.__end-entry^.start); //unaligned size
+ entry^.usize:=(entry^.__end-entry^.start); //unaligned size
next^.offset:=next^.offset + (__end - entry^.start);
- next^.size :=next^.size-entry^.size; //unaligned size
+ next^.usize :=next^.usize-entry^.usize; //unaligned size
+
+ //update (implicitly)
+ //next ^.sub.min_offset:=__end;
+ //entry^.sub.max_offset:=__end;
+
+ //new map
+ vm_nt_sub_map_init(@next^.sub,next^.start,next^.__end);
+
+ //move
+ vm_nt_sub_map_move(@next^.sub,@entry^.sub);
vm_nt_entry_link(map, entry, next);
vm_nt_file_obj_reference(next^.obj);
@@ -1106,10 +1099,20 @@ begin
next^.start :=__end;
entry^.__end:=__end;
- entry^.size :=(entry^.__end-entry^.size); //unaligned size
+ entry^.usize:=(entry^.__end-entry^.usize); //unaligned size
next^.offset:=next^.offset + (__end - entry^.start);
- next^.size :=next^.size-entry^.size; //unaligned size
+ next^.usize :=next^.usize-entry^.usize; //unaligned size
+
+ //update (implicitly)
+ //next ^.sub.min_offset:=__end;
+ //entry^.sub.max_offset:=__end;
+
+ //new map
+ vm_nt_sub_map_init(@next^.sub,next^.start,next^.__end);
+
+ //move
+ vm_nt_sub_map_move(@next^.sub,@entry^.sub);
vm_nt_entry_link(map, entry, next);
vm_nt_file_obj_reference(next^.obj);
@@ -1128,22 +1131,10 @@ begin
end;
-procedure vm_nt_entry_deallocate(entry:p_vm_nt_entry);
+procedure vm_nt_entry_delete(map:p_vm_nt_map;entry:p_vm_nt_entry); inline;
begin
- vm_nt_file_obj_deallocate(entry^.obj);
- Freemem(entry);
-end;
-
-procedure vm_nt_entry_delete(map:p_vm_nt_map;entry:p_vm_nt_entry);
-var
- size:vm_ooffset_t;
-begin
- vm_nt_entry_unlink(map, entry);
-
- size:=entry^.__end - entry^.start;
- map^.size:=map^.size-size;
-
- vm_nt_entry_deallocate(entry);
+ vm_nt_entry_unlink (map, entry);
+ vm_nt_entry_deallocate(map, entry);
end;
function vm_nt_map_delete(map:p_vm_nt_map;start:vm_offset_t;__end:vm_offset_t):Integer;
@@ -1189,16 +1180,15 @@ begin
Result:=(KERN_SUCCESS);
end;
-procedure vm_nt_map_protect(map:p_vm_nt_map;
+procedure vm_nt_map_protect(map :p_vm_nt_map;
start:vm_offset_t;
__end:vm_offset_t;
- prot :Integer);
+ prot :Integer);
var
entry:p_vm_nt_entry;
e_start:vm_offset_t;
e___end:vm_offset_t;
max:Integer;
- r:Integer;
begin
if (start=__end) then Exit;
@@ -1209,7 +1199,7 @@ begin
entry:=entry^.next;
end else
begin
- entry:=entry;
+ //
end;
while (entry<>@map^.header) and (entry^.start<__end) do
@@ -1238,13 +1228,7 @@ begin
max:=0;
end;
- r:=md_protect(Pointer(e_start),e___end-e_start,(prot and max and VM_RW));
- if (r<>0) then
- begin
- Writeln('failed md_protect(',HexStr(e_start,11),',',HexStr(e___end,11),'):0x',HexStr(r,8));
- Assert(false,'vm_nt_map_protect');
- end;
-
+ vm_nt_sub_map_protect(@entry^.sub,e_start,e___end,(prot and max and VM_RW));
end;
entry:=entry^.next;
@@ -1253,7 +1237,57 @@ begin
vm_nt_map_unlock(map);
end;
-procedure vm_nt_map_prot_fix(map:p_vm_nt_map;
+procedure vm_nt_map_tracking(map :p_vm_nt_map;
+ start:vm_offset_t;
+ __end:vm_offset_t;
+ prot :Integer);
+var
+ entry:p_vm_nt_entry;
+ e_start:vm_offset_t;
+ e___end:vm_offset_t;
+begin
+ if (start=__end) then Exit;
+
+ vm_nt_map_lock(map);
+
+ if (not vm_nt_map_lookup_entry(map, start, @entry)) then
+ begin
+ entry:=entry^.next;
+ end else
+ begin
+ //
+ end;
+
+ while (entry<>@map^.header) and (entry^.start<__end) do
+ begin
+ e_start:=entry^.start;
+ e___end:=entry^.__end;
+
+ if (e_start__end) then
+ begin
+ e___end:=__end;
+ end;
+
+ if (e___end>e_start) then
+ begin
+ vm_nt_sub_map_tracking(@entry^.sub,e_start,e___end,prot);
+ end;
+
+ entry:=entry^.next;
+ end;
+
+ vm_nt_map_unlock(map);
+end;
+
+
+
+
+procedure vm_nt_map_prot_fix(map :p_vm_nt_map;
start:vm_offset_t;
__end:vm_offset_t;
mode :Integer);
@@ -1294,7 +1328,7 @@ begin
if (e___end>e_start) then
begin
- vm_prot_fixup(map,e_start,e___end,entry^.obj^.maxp,mode);
+ vm_nt_sub_map_prot_fixup(@entry^.sub,e_start,e___end,mode);
end;
end;
@@ -1327,9 +1361,9 @@ asm
_exit:
end;
-procedure vm_nt_map_madvise(map:p_vm_nt_map;
- start:vm_offset_t;
- __end:vm_offset_t;
+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;
@@ -1379,7 +1413,7 @@ begin
mirror:=vm_nt_map_mirror(map,base,base+size);
if (mirror<>nil) then
begin
- ZeroPages(mirror,size);
+ ZeroPages (mirror,size);
md_unmap_ex(mirror,size);
end;
@@ -1396,7 +1430,7 @@ begin
end;
-function vm_nt_map_mirror(map:p_vm_nt_map;
+function vm_nt_map_mirror(map :p_vm_nt_map;
start:vm_offset_t;
__end:vm_offset_t):Pointer;
var
diff --git a/sys/vm/vm_nt_sub_map.pas b/sys/vm/vm_nt_sub_map.pas
new file mode 100644
index 00000000..4eb11df3
--- /dev/null
+++ b/sys/vm/vm_nt_sub_map.pas
@@ -0,0 +1,653 @@
+unit vm_nt_sub_map;
+
+{$mode ObjFPC}{$H+}
+{$CALLING SysV_ABI_CDecl}
+
+interface
+
+uses
+ sysutils,
+ vm,
+ vm_pmap_prot;
+
+type
+ pp_vm_nt_sub_entry=^p_vm_nt_sub_entry;
+ p_vm_nt_sub_entry=^vm_nt_sub_entry;
+ vm_nt_sub_entry=packed record
+ prev :p_vm_nt_sub_entry; // previous entry
+ next :p_vm_nt_sub_entry; // next entry
+ left :p_vm_nt_sub_entry; // left child in binary search tree
+ right:p_vm_nt_sub_entry; // right child in binary search tree
+ start:vm_offset_t; // start address
+ __end:vm_offset_t; // end address
+ //
+ decl_prot:Byte; // declared protection (with tracking bits)
+ real_prot:Byte; // real page protection
+ align :Word;
+ end;
+
+ p_vm_nt_sub_map=^t_vm_nt_sub_map;
+ t_vm_nt_sub_map=object
+ header:vm_nt_sub_entry; // List of entries
+ root :p_vm_nt_sub_entry; // Root of a binary search tree
+ property min_offset:vm_offset_t read header.start write header.start;
+ property max_offset:vm_offset_t read header.__end write header.__end;
+ end;
+
+procedure vm_nt_sub_map_init(map:p_vm_nt_sub_map;min,max:vm_offset_t);
+
+function vm_nt_sub_map_insert(
+ map :p_vm_nt_sub_map;
+ start:vm_offset_t;
+ __end:vm_offset_t;
+ prot :Byte):Integer;
+
+// Move nodes from one submap to another
+procedure vm_nt_sub_map_move(dst,src:p_vm_nt_sub_map);
+
+procedure vm_nt_sub_map_free(map:p_vm_nt_sub_map);
+
+//Change protection taking into account tracking
+function vm_nt_sub_map_protect(map :p_vm_nt_sub_map;
+ start:vm_offset_t;
+ __end:vm_offset_t;
+ prot :Byte):Integer;
+
+//Change protection tracking
+function vm_nt_sub_map_tracking(map :p_vm_nt_sub_map;
+ start:vm_offset_t;
+ __end:vm_offset_t;
+ prot :Byte):Integer;
+
+//Update page protection by mode
+procedure vm_nt_sub_map_prot_fixup(map :p_vm_nt_sub_map;
+ start:vm_offset_t;
+ __end:vm_offset_t;
+ mode :Integer);
+
+implementation
+
+uses
+ md_map;
+
+procedure vm_nt_sub_map_init(map:p_vm_nt_sub_map;min,max:vm_offset_t); inline;
+begin
+ map^:=Default(t_vm_nt_sub_map);
+ map^.header.next:=@map^.header;
+ map^.header.prev:=@map^.header;
+ map^.min_offset :=min;
+ map^.max_offset :=max;
+end;
+
+function vm_nt_sub_entry_create(map:p_vm_nt_sub_map):p_vm_nt_sub_entry;
+var
+ new_entry:p_vm_nt_sub_entry;
+begin
+ new_entry:=AllocMem(SizeOf(vm_nt_sub_entry));
+ Assert((new_entry<>nil),'vm_nt_sub_entry_create: kernel resources exhausted');
+ Result:=new_entry;
+end;
+
+procedure vm_nt_sub_entry_dispose(map:p_vm_nt_sub_map;entry:p_vm_nt_sub_entry); inline;
+begin
+ FreeMem(entry);
+end;
+
+function vm_nt_sub_entry_splay(addr:vm_offset_t;root:p_vm_nt_sub_entry):p_vm_nt_sub_entry;
+var
+ llist,rlist:p_vm_nt_sub_entry;
+ ltree,rtree:p_vm_nt_sub_entry;
+ y :p_vm_nt_sub_entry;
+begin
+ if (root=nil) then Exit(root);
+
+ llist:=nil;
+ rlist:=nil;
+ repeat
+ { root is never nil in here. }
+ if (addrnil) then
+ begin
+ { Rotate right and put y on rlist. }
+ root^.left:=y^.right;
+ y^.right:=root;
+ root:=y^.left;
+ y^.left:=rlist;
+ rlist:=y;
+ end else
+ begin
+ { Put root on rlist. }
+ root^.left:=rlist;
+ rlist:=root;
+ root:=y;
+ end;
+ end else
+ if (addr>=root^.__end) then
+ begin
+ y:=root^.right;
+ if (y=nil) then break;
+ if (addr>=y^.__end) and (y^.right<>nil) then
+ begin
+ { Rotate left and put y on llist. }
+ root^.right:=y^.left;
+ y^.left:=root;
+ root:=y^.right;
+ y^.right:=llist;
+ llist:=y;
+ end else
+ begin
+ { Put root on llist. }
+ root^.right:=llist;
+ llist:=root;
+ root:=y;
+ end;
+ end else
+ begin
+ break;
+ end;
+ until false;
+
+ ltree:=root^.left;
+ while (llist<>nil) do
+ begin
+ y:=llist^.right;
+ llist^.right:=ltree;
+ ltree:=llist;
+ llist:=y;
+ end;
+ rtree:=root^.right;
+ while (rlist<>nil) do
+ begin
+ y:=rlist^.left;
+ rlist^.left:=rtree;
+ rtree:=rlist;
+ rlist:=y;
+ end;
+
+ root^.left :=ltree;
+ root^.right:=rtree;
+
+ Result:=(root);
+end;
+
+procedure vm_nt_sub_entry_link(
+ map :p_vm_nt_sub_map;
+ after_where:p_vm_nt_sub_entry;
+ entry :p_vm_nt_sub_entry);
+begin
+ entry^.prev:=after_where;
+ entry^.next:=after_where^.next;
+ entry^.next^.prev:=entry;
+ after_where^.next:=entry;
+
+ if (after_where<>@map^.header) then
+ begin
+ if (after_where<>map^.root) then
+ begin
+ vm_nt_sub_entry_splay(after_where^.start, map^.root);
+ end;
+ entry^.right:=after_where^.right;
+ entry^.left :=after_where;
+ after_where^.right:=nil;
+ end else
+ begin
+ entry^.right:=map^.root;
+ entry^.left :=nil;
+ end;
+ map^.root:=entry;
+end;
+
+procedure vm_nt_sub_entry_unlink(
+ map :p_vm_nt_sub_map;
+ entry:p_vm_nt_sub_entry);
+var
+ next,prev,root:p_vm_nt_sub_entry;
+begin
+ if (entry<>map^.root) then
+ begin
+ vm_nt_sub_entry_splay(entry^.start, map^.root);
+ end;
+ if (entry^.left=nil) then
+ begin
+ root:=entry^.right;
+ end else
+ begin
+ root:=vm_nt_sub_entry_splay(entry^.start, entry^.left);
+ root^.right:=entry^.right;
+ end;
+ map^.root:=root;
+
+ prev:=entry^.prev;
+ next:=entry^.next;
+ next^.prev:=prev;
+ prev^.next:=next;
+end;
+
+function vm_nt_sub_map_lookup_entry(
+ map :p_vm_nt_sub_map;
+ address:vm_offset_t;
+ entry :pp_vm_nt_sub_entry):Boolean;
+var
+ cur:p_vm_nt_sub_entry;
+begin
+ cur:=map^.root;
+ if (cur=nil) then
+ begin
+ entry^:=@map^.header;
+ end else
+ if (address>=cur^.start) and (cur^.__end>address) then
+ begin
+ entry^:=cur;
+ Exit(TRUE);
+ end else
+ begin
+ cur:=vm_nt_sub_entry_splay(address,cur);
+ map^.root:=cur;
+
+ if (address>=cur^.start) then
+ begin
+ entry^:=cur;
+ if (cur^.__end>address) then
+ begin
+ Exit(TRUE);
+ end;
+ end else
+ begin
+ entry^:=cur^.prev;
+ end;
+ end;
+ Result:=(FALSE);
+end;
+
+procedure vm_nt_sub_simplify_entry(map:p_vm_nt_sub_map;entry:p_vm_nt_sub_entry); forward;
+
+function vm_nt_sub_map_insert(
+ map :p_vm_nt_sub_map;
+ start:vm_offset_t;
+ __end:vm_offset_t;
+ prot :Byte):Integer;
+var
+ new_entry :p_vm_nt_sub_entry;
+ prev_entry :p_vm_nt_sub_entry;
+ temp_entry :p_vm_nt_sub_entry;
+
+begin
+ if (start