From 406d5b7b3de5f13439f4b0d3a0816ceee1b673a8 Mon Sep 17 00:00:00 2001
From: nickysn <nickysn@gmail.com>
Date: Sun, 27 Sep 2015 13:00:27 +0000
Subject: [PATCH] + implemented a win16 heap manager for the far data memory
 models, using the   global heap; TODO: allocate heap in blocks and perform
 suballocation for small   memory blocks, because the number of global heap
 blocks is limited

git-svn-id: trunk@31846 -
---
 .gitattributes         |   2 +
 rtl/win16/glbheap.inc  | 136 +++++++++++++++++++++++++++++++++++++++++
 rtl/win16/glbheaph.inc |  22 +++++++
 rtl/win16/system.pp    |   8 +--
 4 files changed, 163 insertions(+), 5 deletions(-)
 create mode 100644 rtl/win16/glbheap.inc
 create mode 100644 rtl/win16/glbheaph.inc

diff --git a/.gitattributes b/.gitattributes
index 03a8e3b093..367e4b4b3d 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -9700,6 +9700,8 @@ rtl/win/wininc/unifun.inc svneol=native#text/plain
 rtl/win/winres.inc svneol=native#text/plain
 rtl/win16/Makefile svneol=native#text/plain
 rtl/win16/Makefile.fpc svneol=native#text/plain
+rtl/win16/glbheap.inc svneol=native#text/plain
+rtl/win16/glbheaph.inc svneol=native#text/plain
 rtl/win16/locheap.inc svneol=native#text/plain
 rtl/win16/locheaph.inc svneol=native#text/plain
 rtl/win16/prt0c.asm svneol=native#text/plain
diff --git a/rtl/win16/glbheap.inc b/rtl/win16/glbheap.inc
new file mode 100644
index 0000000000..a0e27251a8
--- /dev/null
+++ b/rtl/win16/glbheap.inc
@@ -0,0 +1,136 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2015 by the Free Pascal development team
+
+    This file implements heap management for 16-bit Windows
+    using the Windows global heap.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+    function SysGlobalGetMem(Size: ptruint): pointer;
+      var
+        hglob: HGLOBAL;
+      begin
+        hglob:=GlobalAlloc(HeapAllocFlags, Size);
+        if hglob=0 then
+          if ReturnNilIfGrowHeapFails then
+            begin
+              result:=nil;
+              exit;
+            end
+          else
+            HandleError(203);
+        result:=GlobalLock(hglob);
+        if result=nil then
+          HandleError(204);
+      end;
+
+    function SysGlobalFreeMem(Addr: Pointer): ptruint;
+      var
+        hglob: HGLOBAL;
+      begin
+        if Addr<>nil then
+          begin
+            hglob:=HGLOBAL(GlobalHandle(Seg(Addr^)));
+            if hglob=0 then
+              HandleError(204);
+            result:=GlobalSize(hglob);
+            if GlobalUnlock(hglob) then
+              HandleError(204);
+            if GlobalFree(hglob)<>0 then
+              HandleError(204);
+          end
+        else
+          result:=0;
+      end;
+
+    function SysGlobalFreeMemSize(Addr: Pointer; Size: Ptruint): ptruint;
+      begin
+        result:=SysGlobalFreeMem(addr);
+      end;
+
+    function SysGlobalAllocMem(size: ptruint): pointer;
+      var
+        hglob: HGLOBAL;
+      begin
+        hglob:=GlobalAlloc(HeapAllocFlags or GMEM_ZEROINIT, Size);
+        if hglob=0 then
+          if ReturnNilIfGrowHeapFails then
+            begin
+              result:=nil;
+              exit;
+            end
+          else
+            HandleError(203);
+        result:=GlobalLock(hglob);
+        if result=nil then
+          HandleError(204);
+      end;
+
+    function SysGlobalReAllocMem(var p: pointer; size: ptruint):pointer;
+      var
+        hglob: HGLOBAL;
+      begin
+        if size=0 then
+          begin
+            SysGlobalFreeMem(p);
+            result := nil;
+          end
+        else if p=nil then
+          result := SysGlobalAllocMem(size)
+        else
+          begin
+            hglob:=HGLOBAL(GlobalHandle(Seg(p^)));
+            if hglob=0 then
+              HandleError(204);
+            if GlobalUnlock(hglob) then
+              HandleError(204);
+            hglob:=GlobalReAlloc(hglob,size,HeapAllocFlags or GMEM_ZEROINIT);
+            if hglob=0 then
+              if ReturnNilIfGrowHeapFails then
+                begin
+                  result:=nil;
+                  p:=nil;
+                  exit;
+                end
+              else
+                HandleError(203);
+            result:=GlobalLock(hglob);
+            if result=nil then
+              HandleError(204);
+          end;
+        p := result;
+      end;
+
+    function SysGlobalMemSize(p: pointer): ptruint;
+      var
+        hglob: HGLOBAL;
+      begin
+        hglob:=HGLOBAL(GlobalHandle(Seg(p^)));
+        if hglob=0 then
+          HandleError(204);
+        result:=GlobalSize(hglob);
+      end;
+
+    const
+      GlobalHeapMemoryManager: TMemoryManager = (
+        NeedLock: false;  // Obsolete
+        GetMem: @SysGlobalGetMem;
+        FreeMem: @SysGlobalFreeMem;
+        FreeMemSize: @SysGlobalFreeMemSize;
+        AllocMem: @SysGlobalAllocMem;
+        ReAllocMem: @SysGlobalReAllocMem;
+        MemSize: @SysGlobalMemSize;
+        InitThread: nil;
+        DoneThread: nil;
+        RelocateHeap: nil;
+        GetHeapStatus: nil;
+        GetFPCHeapStatus: nil;
+      );
diff --git a/rtl/win16/glbheaph.inc b/rtl/win16/glbheaph.inc
new file mode 100644
index 0000000000..0f0f90cc8e
--- /dev/null
+++ b/rtl/win16/glbheaph.inc
@@ -0,0 +1,22 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2015 by the Free Pascal development team
+
+    This file contains the interface section of the heap
+    management implementation for 16-bit Windows that uses
+    the Windows global heap.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+    var
+      { BP7 compatible vars }
+      HeapLimit: Word=1024;
+      HeapBlock: Word=8192;
+      HeapAllocFlags: Word=2;  { 2=GMEM_MOVEABLE }
diff --git a/rtl/win16/system.pp b/rtl/win16/system.pp
index 354ef2d3c5..281afa003b 100644
--- a/rtl/win16/system.pp
+++ b/rtl/win16/system.pp
@@ -19,8 +19,7 @@ interface
 {$IFDEF FPC_X86_DATA_NEAR}
 {$I locheaph.inc}
 {$ELSE FPC_X86_DATA_NEAR}
-{ todo: implement a working win16 heap manager for the far data models }
-{$I tnyheaph.inc}
+{$I glbheaph.inc}
 {$ENDIF FPC_X86_DATA_NEAR}
 
 const
@@ -152,8 +151,7 @@ procedure MsDos_Carry(var Regs: Registers); external name 'FPC_MSDOS_CARRY';
 {$IFDEF FPC_X86_DATA_NEAR}
 {$I locheap.inc}
 {$ELSE FPC_X86_DATA_NEAR}
-{ todo: implement a working win16 heap manager for the far data models }
-{$I tinyheap.inc}
+{$I glbheap.inc}
 {$ENDIF FPC_X86_DATA_NEAR}
 
 
@@ -373,7 +371,7 @@ begin
 {$ifdef FPC_X86_DATA_NEAR}
   SetMemoryManager(LocalHeapMemoryManager);
 {$else FPC_X86_DATA_NEAR}
-{ todo: implement a working win16 heap manager for the far data models }
+  SetMemoryManager(GlobalHeapMemoryManager);
 {$endif FPC_X86_DATA_NEAR}
 end;