| (* LongSysStorage.mod provides dynamic allocation for the system components. | |
| Copyright (C) 2026 Free Software Foundation, Inc. | |
| Contributed by Gaius Mulley <gaiusmod2@gmail.com>. | |
| This file is part of GNU Modula-2. | |
| GNU Modula-2 is free software; you can redistribute it and/or modify | |
| it under the terms of the GNU General Public License as published by | |
| the Free Software Foundation; either version 3, or (at your option) | |
| any later version. | |
| GNU Modula-2 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. See the GNU | |
| General Public License for more details. | |
| Under Section 7 of GPL version 3, you are granted additional | |
| permissions described in the GCC Runtime Library Exception, version | |
| 3.1, as published by the Free Software Foundation. | |
| You should have received a copy of the GNU General Public License and | |
| a copy of the GCC Runtime Library Exception along with this program; | |
| see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
| <http://www.gnu.org/licenses/>. *) | |
| IMPLEMENTATION MODULE LongSysStorage ; | |
| FROM libc IMPORT malloc, free, realloc, memset, getenv, printf ; | |
| FROM Debug IMPORT Halt ; | |
| FROM SYSTEM IMPORT ADR ; | |
| IMPORT M2Diagnostic ; | |
| CONST | |
| enableDeallocation = TRUE ; | |
| enableZero = TRUE ; | |
| enableTrace = FALSE ; | |
| VAR | |
| callno: CARDINAL ; | |
| zero, | |
| trace : BOOLEAN ; | |
| PROCEDURE ALLOCATE (VAR a: ADDRESS ; size: LONGCARD) ; | |
| BEGIN | |
| a := malloc (size) ; | |
| IF a = NIL | |
| THEN | |
| Halt ('out of memory error', | |
| __FILE__, __FUNCTION__, __LINE__) | |
| END ; | |
| IF enableTrace AND trace | |
| THEN | |
| printf ("<DEBUG-CALL> %d LongSysStorage.ALLOCATE (0x%x, %ld bytes)\n", callno, a, size) ; | |
| printf ("<MEM-ALLOC> %ld %ld\n", a, size); | |
| INC (callno) | |
| END ; | |
| M2Diagnostic.TotalHeapIncrLong (size) | |
| END ALLOCATE ; | |
| PROCEDURE DEALLOCATE (VAR a: ADDRESS; size: LONGCARD); | |
| BEGIN | |
| IF enableTrace AND trace | |
| THEN | |
| printf ("<DEBUG-CALL> %d LongSysStorage.DEALLOCATE (0x%x, %ld bytes)\n", callno, a, size) ; | |
| INC (callno) | |
| END ; | |
| IF enableZero AND zero | |
| THEN | |
| IF enableTrace AND trace | |
| THEN | |
| printf (" memset (0x%x, 0, %ld bytes)\n", a, size) | |
| END ; | |
| IF memset (a, 0, size) # a | |
| THEN | |
| Halt ('memset should have returned the first parameter', | |
| __FILE__, __FUNCTION__, __LINE__) | |
| END | |
| END ; | |
| IF enableDeallocation | |
| THEN | |
| IF enableTrace AND trace | |
| THEN | |
| printf (" free (0x%x) %ld bytes\n", a, size) ; | |
| printf ("<MEM-FREE> %ld %d\n", a, size); | |
| END ; | |
| free (a) | |
| END ; | |
| M2Diagnostic.TotalHeapDecrLong (size) ; | |
| a := NIL | |
| END DEALLOCATE ; | |
| (* | |
| REALLOCATE - attempts to reallocate storage. The address, | |
| a, should either be NIL in which case ALLOCATE | |
| is called, or alternatively it should have already | |
| been initialized by ALLOCATE. The allocated storage | |
| is resized accordingly. | |
| Note that this procedure does not adjust the | |
| M2Diagnostic.TotalHeap it is expected that the caller | |
| must track the reallocation differences and call | |
| M2Diagnostic.TotalHeapIncr or M2Diagnostic.TotalHeapDecr | |
| as appropriate. | |
| *) | |
| PROCEDURE REALLOCATE (VAR a: ADDRESS; size: LONGCARD) ; | |
| BEGIN | |
| IF a = NIL | |
| THEN | |
| ALLOCATE (a, size) | |
| ELSE | |
| IF enableTrace AND trace | |
| THEN | |
| printf ("<DEBUG-CALL> %d LongSysStorage.REALLOCATE (0x%x, %ld bytes)\n", | |
| callno, a, size) ; | |
| INC (callno) | |
| END ; | |
| IF enableTrace AND trace | |
| THEN | |
| printf (" realloc (0x%x, %ld bytes) -> ", a, size) ; | |
| printf ("<MEM-FREE> %ld %ld\n", a, size) | |
| END ; | |
| a := realloc (a, size) ; | |
| IF a = NIL | |
| THEN | |
| Halt ('out of memory error', | |
| __FILE__, __FUNCTION__, __LINE__) | |
| END ; | |
| IF enableTrace AND trace | |
| THEN | |
| printf ("<MEM-ALLOC> %ld %d\n", a, size) ; | |
| printf (" 0x%x %ld bytes\n", a, size) | |
| END | |
| END | |
| END REALLOCATE ; | |
| PROCEDURE Available (size: LONGCARD) : BOOLEAN; | |
| VAR | |
| a: ADDRESS ; | |
| BEGIN | |
| IF enableTrace AND trace | |
| THEN | |
| printf ("<DEBUG-CALL> %d LongSysStorage.Available (%ld bytes)\n", | |
| callno, size) ; | |
| INC (callno) | |
| END ; | |
| a := malloc (size) ; | |
| IF a = NIL | |
| THEN | |
| IF enableTrace AND trace | |
| THEN | |
| printf (" no\n") | |
| END ; | |
| RETURN FALSE | |
| ELSE | |
| IF enableTrace AND trace | |
| THEN | |
| printf (" yes\n") | |
| END ; | |
| free (a) ; | |
| RETURN TRUE | |
| END | |
| END Available ; | |
| (* | |
| Init - initializes the heap. This does nothing on a GNU/Linux system. | |
| But it remains here since it might be used in an embedded system. | |
| *) | |
| PROCEDURE Init ; | |
| END Init ; | |
| BEGIN | |
| callno := 0 ; | |
| IF enableTrace | |
| THEN | |
| trace := getenv (ADR ("M2DEBUG_SYSSTORAGE_trace")) # NIL | |
| ELSE | |
| trace := FALSE | |
| END ; | |
| IF enableZero | |
| THEN | |
| zero := getenv (ADR ("M2DEBUG_SYSSTORAGE_zero")) # NIL | |
| ELSE | |
| zero := FALSE | |
| END | |
| END LongSysStorage. |