Просмотр исходного кода

* Darwin now uses Mach VM calls for memory allocation instead of mmap/munmap
+ added sysrealloc support for Darwin (Darwin does not have mremap)

git-svn-id: trunk@42729 -

Jonas Maebe 6 лет назад
Родитель
Сommit
693e72ade3
5 измененных файлов с 180 добавлено и 1 удалено
  1. 1 0
      .gitattributes
  2. 3 0
      rtl/bsd/sysos.inc
  3. 3 0
      rtl/bsd/system.pp
  4. 166 0
      rtl/darwin/sysmach.inc
  5. 7 1
      rtl/unix/sysheap.inc

+ 1 - 0
.gitattributes

@@ -10181,6 +10181,7 @@ rtl/darwin/rtldefs.inc svneol=native#text/plain
 rtl/darwin/signal.inc svneol=native#text/plain
 rtl/darwin/sysctlh.inc svneol=native#text/plain
 rtl/darwin/sysinit.pas svneol=native#text/pascal
+rtl/darwin/sysmach.inc svneol=native#text/plain
 rtl/darwin/termio.pp svneol=native#text/plain
 rtl/darwin/termios.inc svneol=native#text/plain
 rtl/darwin/termiosproc.inc svneol=native#text/plain

+ 3 - 0
rtl/bsd/sysos.inc

@@ -85,6 +85,9 @@ end;
   {$Linklib c}
   {$i oscdeclh.inc}
   {$i oscdecl.inc}
+  {$ifdef darwin}
+    {$i sysmach.inc}
+  {$endif}
 {$else}
   {$I syscallh.inc}
   {$I syscall.inc}

+ 3 - 0
rtl/bsd/system.pp

@@ -361,6 +361,9 @@ begin
 end;
 
 Begin
+{$ifdef darwin}
+  darwin_init_page_size;
+{$endif darwin}
   IsConsole := TRUE;
   StackLength := CheckInitialStkLen(InitialStkLen);
   StackBottom := Sptr - StackLength;

+ 166 - 0
rtl/darwin/sysmach.inc

@@ -0,0 +1,166 @@
+type
+  __darwin_natural_t = cardinal;
+  __darwin_mach_port_name_t = __darwin_natural_t;
+  __darwin_mach_port_t = __darwin_mach_port_name_t;
+{$ifdef cpu64}
+  boolean_t = cardinal;
+  vm_offset_t = ptruint;
+  vm_size_t = ptruint;
+{$else}
+  boolean_t = longint;
+  vm_offset_t = __darwin_natural_t;
+  vm_size_t = __darwin_natural_t;
+{$endif}
+  mach_port_t = __darwin_mach_port_t;
+  vm_map_t = mach_port_t;
+  vm_address_t = vm_offset_t;
+  pvm_address_t = ^vm_address_t;
+  vm_prot_t = longint;
+  pvm_prot_t = ^vm_prot_t;
+  vm_inherit_t = cardinal;
+  kern_return_t = longint;
+
+const
+  KERN_SUCCESS                       = 0;
+
+  VM_FLAGS_FIXED                     = $0000;
+  VM_FLAGS_ANYWHERE                  = $0001;
+  VM_FLAGS_PURGABLE                  = $0002;
+(*
+  flags that are different between 10.4 and 10.12; fortunately, we don't need them
+
+  VM_FLAGS_RANDOM_ADDR               = $0008;
+  VM_FLAGS_NO_CACHE                  = $0010;
+  VM_FLAGS_RESILIENT_CODESIGN        = $0020;
+  VM_FLAGS_RESILIENT_MEDIA           = $0040;
+  VM_FLAGS_OVERWRITE                 = $4000;   { delete any existing mappings first }
+  {*
+   * VM_FLAGS_SUPERPAGE_MASK
+   *      3 bits that specify whether large pages should be used instead of
+   *      base pages (!=0), as well as the requested page size.
+   *}
+  VM_FLAGS_SUPERPAGE_MASK            = $70000;  {* bits 0x10000, 0x20000, 0x40000 *}
+  VM_FLAGS_RETURN_DATA_ADDR          = $100000; {* Return address of target data, rather than base of page *}
+  VM_FLAGS_RETURN_4K_DATA_ADDR       = $800000; {* Return 4K aligned address of target data *}
+*)
+
+  VM_INHERIT_SHARE                   = vm_inherit_t(0); {* share with child *}
+  VM_INHERIT_COPY                    = vm_inherit_t(1); {* copy into child *}
+  VM_INHERIT_NONE                    = vm_inherit_t(2); {* absent from child *}
+  VM_INHERIT_DONATE_COPY             = vm_inherit_t(3); {* copy and delete *}
+
+  VM_INHERIT_DEFAULT                 = VM_INHERIT_COPY;
+  VM_INHERIT_LAST_VALID              = VM_INHERIT_NONE;
+
+  VM_MEMORY_MALLOC                   = 1;
+  VM_MEMORY_MALLOC_SMALL             = 2;
+  VM_MEMORY_MALLOC_LARGE             = 3;
+  VM_MEMORY_MALLOC_HUGE              = 4;
+  VM_MEMORY_SBRK                     = 5; // uninteresting -- no one should call
+  VM_MEMORY_REALLOC                  = 6;
+  VM_MEMORY_MALLOC_TINY              = 7;
+
+
+var
+  mach_task_self_: mach_port_t; cvar; external;
+
+  vm_page_size: vm_size_t; cvar; external;
+
+  vm_kernel_page_size: vm_size_t; cvar; weakexternal; //__OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0)
+
+  darwin_page_size: vm_size_t;
+
+  procedure darwin_init_page_size;
+    begin
+      if (@vm_kernel_page_size<>nil) and (vm_kernel_page_size>vm_page_size) then
+        darwin_page_size:=vm_kernel_page_size
+      else
+        darwin_page_size:=vm_page_size;
+    end;
+
+
+  function mach_task_self: mach_port_t; inline;
+    begin
+      result:=mach_task_self_;
+    end;
+
+
+  function vm_allocate(target: vm_map_t;
+                       address: pvm_address_t;
+                       size: vm_size_t;
+                       flags: longint): kern_return_t; cdecl; external;
+
+  function vm_deallocate(target: vm_map_t;
+                         address: vm_address_t;
+                         size: vm_size_t) : kern_return_t; cdecl; external;
+
+  function vm_remap(target_task: vm_map_t;
+                         target_address: pvm_address_t;
+                         size: vm_size_t;
+                         mask: vm_offset_t;
+                         flags: longint;
+                         src_task: vm_map_t;
+                         src_address: vm_address_t;
+                         copy: boolean_t;
+                         cur_protection, max_protection: pvm_prot_t;
+                         inheritance: vm_inherit_t): kern_return_t; cdecl; external;
+
+  function DARWIN_VM_MAKE_TAG(tag: longint): longint; inline;
+    begin
+      result:=longint(cardinal(tag) shl 24);
+    end;
+
+  function darwin_round_page(size: vm_size_t): vm_size_t; inline;
+    var
+      local_page_size: vm_size_t;
+    begin
+      local_page_size:=darwin_page_size;
+      result:=(size+local_page_size-1) and not(local_page_size-1);
+    end;
+
+  {$define HAS_SYSOSALLOC}
+  function SysOSAlloc(size: ptruint): pointer;
+  var
+    addr: vm_address_t;
+    tag: longint;
+  begin
+    addr:=0;
+    if size<=growheapsizesmall then
+      tag:=DARWIN_VM_MAKE_TAG(VM_MEMORY_MALLOC_TINY) or VM_FLAGS_ANYWHERE
+    else if size<=growheapsize2 then
+      tag:=DARWIN_VM_MAKE_TAG(VM_MEMORY_MALLOC) or VM_FLAGS_ANYWHERE
+    else
+      tag:=DARWIN_VM_MAKE_TAG(VM_MEMORY_MALLOC_LARGE) or VM_FLAGS_ANYWHERE;
+
+    if vm_allocate(mach_task_self(), @addr, darwin_round_page(size), tag)=KERN_SUCCESS then
+      result:=pointer(addr)
+    else
+      result:=nil;
+  end;
+
+
+  {$define HAS_SYSOSFREE}
+  procedure SysOSFree(p: pointer; size: ptruint);
+  begin
+    if vm_deallocate(mach_task_self(), vm_address_t(p), darwin_round_page(size))<>KERN_SUCCESS then
+      HandleError(204);
+  end;
+
+
+{$define FPC_SYSTEM_HAS_SYSOSREALLOC}
+function SysOSRealloc(p: pointer;oldsize,newsize: ptruint): pointer;
+  var
+    addr: vm_address_t;
+    oldsize_rounded: vm_address_t;
+  begin
+    oldsize_rounded:=darwin_round_page(oldsize);
+    addr:=vm_address_t(p)+oldsize_rounded;
+    { fits in the previously allocated block -> return directly}
+    if (vm_address_t(p+newsize)<=addr) or
+    { otherwise try to map extra space at the end }
+       (vm_allocate(mach_task_self(), @addr, darwin_round_page(newsize-oldsize_rounded), DARWIN_VM_MAKE_TAG(VM_MEMORY_REALLOC))=KERN_SUCCESS) then
+      result:=p
+    else
+      result:=nil;
+  end;
+

+ 7 - 1
rtl/unix/sysheap.inc

@@ -15,6 +15,9 @@
 
  **********************************************************************}
 
+{$ifndef HAS_SYSOSALLOC}
+{$define HAS_SYSOSALLOC}
+
 function SysOSAlloc(size: ptruint): pointer;
 begin
   result:=Fpmmap(nil,Size,3,MAP_PRIVATE+MAP_ANONYMOUS,-1,0);
@@ -23,14 +26,17 @@ begin
   else
     seterrno(0);
 end;
+{$endif HAS_SYSOSALLOC}
+
 
+{$ifndef HAS_SYSOSFREE}
 {$define HAS_SYSOSFREE}
 
 procedure SysOSFree(p: pointer; size: ptruint);
 begin
   fpmunmap(p, size);
 end;
-
+{$endif HAS_SYSOSFREE}
 
 {$ifdef FPC_SYSTEM_HAS_MREMAP}
 const