| /* do not edit automatically generated by mc from SysStorage. */ |
| /* SysStorage.mod provides dynamic allocation for the system components. |
| |
| Copyright (C) 2001-2025 Free Software Foundation, Inc. |
| Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>. |
| |
| 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/>. */ |
| |
| #include "config.h" |
| #include "system.h" |
| #include <stdbool.h> |
| # if !defined (PROC_D) |
| # define PROC_D |
| typedef void (*PROC_t) (void); |
| typedef struct { PROC_t proc; } PROC; |
| # endif |
| |
| # if !defined (TRUE) |
| # define TRUE (1==1) |
| # endif |
| |
| # if !defined (FALSE) |
| # define FALSE (1==0) |
| # endif |
| |
| #if defined(__cplusplus) |
| # undef NULL |
| # define NULL 0 |
| #endif |
| #define _SysStorage_C |
| |
| #include "GSysStorage.h" |
| # include "Glibc.h" |
| # include "GDebug.h" |
| # include "GSYSTEM.h" |
| |
| # define enableDeallocation true |
| # define enableZero true |
| # define enableTrace false |
| static unsigned int callno; |
| static bool zero; |
| static bool trace; |
| extern "C" void SysStorage_ALLOCATE (void * *a, unsigned int size); |
| extern "C" void SysStorage_DEALLOCATE (void * *a, unsigned int size); |
| |
| /* |
| 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. |
| */ |
| |
| extern "C" void SysStorage_REALLOCATE (void * *a, unsigned int size); |
| |
| /* |
| 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. |
| */ |
| |
| extern "C" bool SysStorage_Available (unsigned int size); |
| |
| /* |
| 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. |
| */ |
| |
| extern "C" void SysStorage_Init (void); |
| |
| extern "C" void SysStorage_ALLOCATE (void * *a, unsigned int size) |
| { |
| (*a) = libc_malloc (static_cast<size_t> (size)); |
| if ((*a) == NULL) |
| { |
| Debug_Halt ((const char *) "out of memory error", 19, (const char *) "../../gcc/m2/gm2-libs/SysStorage.mod", 36, (const char *) "ALLOCATE", 8, 51); |
| } |
| if (enableTrace && trace) |
| { |
| libc_printf ((const char *) "<DEBUG-CALL> %d SysStorage.ALLOCATE (0x%x, %d bytes)\\n", 54, callno, (*a), size); |
| libc_printf ((const char *) "<MEM-ALLOC> %ld %d\\n", 20, (*a), size); |
| callno += 1; |
| } |
| } |
| |
| extern "C" void SysStorage_DEALLOCATE (void * *a, unsigned int size) |
| { |
| if (enableTrace && trace) |
| { |
| libc_printf ((const char *) "<DEBUG-CALL> %d SysStorage.DEALLOCATE (0x%x, %d bytes)\\n", 56, callno, (*a), size); |
| callno += 1; |
| } |
| if (enableZero && zero) |
| { |
| if (enableTrace && trace) |
| { |
| libc_printf ((const char *) " memset (0x%x, 0, %d bytes)\\n", 30, (*a), size); |
| } |
| if ((libc_memset ((*a), 0, static_cast<size_t> (size))) != (*a)) |
| { |
| Debug_Halt ((const char *) "memset should have returned the first parameter", 47, (const char *) "../../gcc/m2/gm2-libs/SysStorage.mod", 36, (const char *) "DEALLOCATE", 10, 78); |
| } |
| } |
| if (enableDeallocation) |
| { |
| if (enableTrace && trace) |
| { |
| libc_printf ((const char *) " free (0x%x) %d bytes\\n", 26, (*a), size); |
| libc_printf ((const char *) "<MEM-FREE> %ld %d\\n", 19, (*a), size); |
| } |
| libc_free ((*a)); |
| } |
| (*a) = NULL; |
| } |
| |
| |
| /* |
| 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. |
| */ |
| |
| extern "C" void SysStorage_REALLOCATE (void * *a, unsigned int size) |
| { |
| if ((*a) == NULL) |
| { |
| SysStorage_ALLOCATE (a, size); |
| } |
| else |
| { |
| if (enableTrace && trace) |
| { |
| libc_printf ((const char *) "<DEBUG-CALL> %d SysStorage.REALLOCATE (0x%x, %d bytes)\\n", 56, callno, (*a), size); |
| callno += 1; |
| } |
| if (enableTrace && trace) |
| { |
| libc_printf ((const char *) " realloc (0x%x, %d bytes) -> ", 32, (*a), size); |
| libc_printf ((const char *) "<MEM-FREE> %ld %d\\n", 19, (*a), size); |
| } |
| (*a) = libc_realloc ((*a), static_cast<size_t> (size)); |
| if ((*a) == NULL) |
| { |
| Debug_Halt ((const char *) "out of memory error", 19, (const char *) "../../gcc/m2/gm2-libs/SysStorage.mod", 36, (const char *) "REALLOCATE", 10, 122); |
| } |
| if (enableTrace && trace) |
| { |
| libc_printf ((const char *) "<MEM-ALLOC> %ld %d\\n", 20, (*a), size); |
| libc_printf ((const char *) " 0x%x %d bytes\\n", 18, (*a), size); |
| } |
| } |
| } |
| |
| |
| /* |
| 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. |
| */ |
| |
| extern "C" bool SysStorage_Available (unsigned int size) |
| { |
| void * a; |
| |
| if (enableTrace && trace) |
| { |
| libc_printf ((const char *) "<DEBUG-CALL> %d SysStorage.Available (%d bytes)\\n", 49, callno, size); |
| callno += 1; |
| } |
| a = libc_malloc (static_cast<size_t> (size)); |
| if (a == NULL) |
| { |
| if (enableTrace && trace) |
| { |
| libc_printf ((const char *) " no\\n", 7, size); |
| } |
| return false; |
| } |
| else |
| { |
| if (enableTrace && trace) |
| { |
| libc_printf ((const char *) " yes\\n", 8, size); |
| } |
| libc_free (a); |
| return true; |
| } |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| 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. |
| */ |
| |
| extern "C" void SysStorage_Init (void) |
| { |
| } |
| |
| extern "C" void _M2_SysStorage_init (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[]) |
| { |
| callno = 0; |
| if (enableTrace) |
| { |
| trace = (libc_getenv (const_cast<void*> (static_cast<const void*>("M2DEBUG_SYSSTORAGE_trace")))) != NULL; |
| } |
| else |
| { |
| trace = false; |
| } |
| if (enableZero) |
| { |
| zero = (libc_getenv (const_cast<void*> (static_cast<const void*>("M2DEBUG_SYSSTORAGE_zero")))) != NULL; |
| } |
| else |
| { |
| zero = false; |
| } |
| } |
| |
| extern "C" void _M2_SysStorage_fini (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[]) |
| { |
| } |