mirror of
https://github.com/termux-pacman/termux-packages.git
synced 2026-01-07 11:23:23 +00:00
bump(main/ghc): 9.12.2
Patched `rts` heap reservation logic on Android:
* Need for patch
- There seems to be a bug on Android. Sometimes simple commands like `ghc --help` usage 90% - 100% cpu and hangs.
- It doesn't happen every time, but ~25% of the times (at least in my
testing).
* Cause of the bug
- The function `osReserveHeapMemory` tries to allocate virtual space starting
from `0x4200000000`. The allocated space has to start at an address >= this address.
- If the kernel doesn't allocate inside this space, it keeps on repeating the
`mmap` call with increasing starting point.
- Now, on Android the kernel sometimes return an address above (as in counting)
this `hint` address. It repeatedly returns the same address for subsequent calls.
- Thus, an infinite loop occurs.
References:
- 383be28ffd/rts/posix/OSMem.c (L461)
- https://github.com/termux/termux-packages/pull/22991#issuecomment-2759137291
* Solution (proposed by Robert Kirkman):
- It introduces a new helper function `osTryReserveHeapMemoryRecursive`.
This transforms the heap reservation logic into a recursive one.
- `osTryReserveHeapMemory()` is run multiple times without unmapping the
undesired addresses. Thus, forcing the kernel to map subsequent calls of
`mmap` to a new, unique address until an address above the `0x4200000000`
mark is obtained.
- After which each recursive call unmaps its undesired address before returning
the desired address (in order from last mapped to first mapped).
References:
- https://gitlab.haskell.org/ghc/ghc/-/merge_requests/14164
- https://github.com/termux/termux-packages/pull/22991#issuecomment-2761325484
Co-authored-by: Robert Kirkman <rkirkman@termux.dev>
Signed-off-by: Aditya Alok <alok@termux.dev>
This commit is contained in:
11
packages/ghc/always-use-pic.patch
Normal file
11
packages/ghc/always-use-pic.patch
Normal file
@@ -0,0 +1,11 @@
|
||||
--- ghc-9.12.1/compiler/GHC/Driver/DynFlags.hs 2024-12-16 00:59:45.000000000 +0530
|
||||
+++ ghc-9.12.1.mod/compiler/GHC/Driver/DynFlags.hs 2025-01-04 19:52:30.600705081 +0530
|
||||
@@ -1311,6 +1311,8 @@
|
||||
(OSDarwin, ArchAArch64) -> [Opt_PIC]
|
||||
(OSLinux, ArchAArch64) -> [Opt_PIC, Opt_ExternalDynamicRefs]
|
||||
(OSLinux, ArchARM {}) -> [Opt_PIC, Opt_ExternalDynamicRefs]
|
||||
+ (OSLinux, ArchX86_64) -> [Opt_PIC, Opt_ExternalDynamicRefs]
|
||||
+ (OSLinux, ArchX86) -> [Opt_PIC, Opt_ExternalDynamicRefs]
|
||||
(OSLinux, ArchRISCV64 {}) -> [Opt_PIC, Opt_ExternalDynamicRefs]
|
||||
(OSOpenBSD, ArchX86_64) -> [Opt_PIC] -- Due to PIE support in
|
||||
-- OpenBSD since 5.3 release
|
||||
112
packages/ghc/build.sh
Normal file
112
packages/ghc/build.sh
Normal file
@@ -0,0 +1,112 @@
|
||||
TERMUX_PKG_HOMEPAGE=https://www.haskell.org/ghc/
|
||||
TERMUX_PKG_DESCRIPTION="The Glasgow Haskell Compiler"
|
||||
TERMUX_PKG_LICENSE="custom"
|
||||
TERMUX_PKG_MAINTAINER="Aditya Alok <alok@termux.dev>"
|
||||
TERMUX_PKG_VERSION=9.12.2
|
||||
TERMUX_PKG_SRCURL="https://downloads.haskell.org/~ghc/$TERMUX_PKG_VERSION/ghc-$TERMUX_PKG_VERSION-src.tar.xz"
|
||||
TERMUX_PKG_SHA256=0e49cd5dde43f348c5716e5de9a5d7a0f8d68d945dc41cf75dfdefe65084f933
|
||||
TERMUX_PKG_DEPENDS="libiconv, libffi, libgmp, libandroid-posix-semaphore, ncurses"
|
||||
TERMUX_PKG_BUILD_IN_SRC=true
|
||||
TERMUX_PKG_EXTRA_CONFIGURE_ARGS="
|
||||
--host=$TERMUX_BUILD_TUPLE
|
||||
--with-system-libffi
|
||||
--disable-ld-override"
|
||||
TERMUX_PKG_NO_STATICSPLIT=true
|
||||
TERMUX_PKG_LICENSE_FILE="LICENSE"
|
||||
TERMUX_PKG_REPLACES="ghc-libs-static, ghc-libs"
|
||||
TERMUX_PKG_PROVIDES="ghc-libs, ghc-libs-static"
|
||||
|
||||
__setup_bootstrap_compiler() {
|
||||
local version=9.10.1
|
||||
local temp_folder="$TERMUX_PKG_CACHEDIR/ghc-bootstrap-$version"
|
||||
local tarball="$temp_folder.tar.xz"
|
||||
local runtime_folder="$temp_folder-runtime"
|
||||
|
||||
export PATH="$runtime_folder/bin:$PATH"
|
||||
|
||||
[[ -d "$runtime_folder" ]] && return
|
||||
|
||||
termux_download "https://downloads.haskell.org/~ghc/$version/ghc-$version-x86_64-ubuntu20_04-linux.tar.xz" \
|
||||
"$tarball" \
|
||||
ae3be406fdb73bd2b0c22baada77a8ff2f8cde6220dd591dc24541cfe9d895eb
|
||||
|
||||
mkdir -p "$temp_folder" "$runtime_folder"
|
||||
tar xf "$tarball" --strip-components=1 -C "$temp_folder"
|
||||
(
|
||||
set -e
|
||||
unset CC CXX CFLAGS CXXFLAGS CPPFLAGS LDFLAGS AR AS CPP LD RANLIB READELF STRIP
|
||||
cd "$temp_folder"
|
||||
./configure --prefix="$runtime_folder"
|
||||
make install
|
||||
) &>/dev/null
|
||||
|
||||
rm -Rf "$temp_folder" "$tarball"
|
||||
}
|
||||
|
||||
termux_step_pre_configure() {
|
||||
__setup_bootstrap_compiler && termux_setup_cabal
|
||||
|
||||
export CONF_CC_OPTS_STAGE2="$CFLAGS $CPPFLAGS"
|
||||
export CONF_GCC_LINKER_OPTS_STAGE2="$LDFLAGS"
|
||||
export CONF_CXX_OPTS_STAGE2="$CXXFLAGS"
|
||||
|
||||
export target="$TERMUX_HOST_PLATFORM"
|
||||
export no_profiled_libs=""
|
||||
|
||||
if [[ "$TERMUX_ARCH" == "arm" ]]; then
|
||||
target="armv7a-linux-androideabi"
|
||||
# NOTE: We do not build profiled libs for arm. It exceeds the 6 hours usage
|
||||
# limit of github CI.
|
||||
no_profiled_libs="+no_profiled_libs"
|
||||
fi
|
||||
|
||||
TERMUX_PKG_EXTRA_CONFIGURE_ARGS="$TERMUX_PKG_EXTRA_CONFIGURE_ARGS --target=$target"
|
||||
./boot.source
|
||||
}
|
||||
|
||||
termux_step_make() {
|
||||
(
|
||||
unset CFLAGS LDFLAGS CPPFLAGS # For hadrian compilation
|
||||
|
||||
./hadrian/build binary-dist-dir \
|
||||
-j"$TERMUX_PKG_MAKE_PROCESSES" \
|
||||
--flavour="release$no_profiled_libs" --docs=none \
|
||||
"stage1.unix.ghc.link.opts += -optl-landroid-posix-semaphore"
|
||||
)
|
||||
}
|
||||
|
||||
termux_step_make_install() {
|
||||
cd _build/bindist/ghc-"$TERMUX_PKG_VERSION"-"$target" || exit 1
|
||||
|
||||
# Remove unnecessary flags. They would get written to settings file otherwise:
|
||||
unset CONF_CC_OPTS_STAGE2 CONF_GCC_LINKER_OPTS_STAGE2 CONF_CXX_OPTS_STAGE2
|
||||
|
||||
# We need to re-run configure:
|
||||
# See: https://gitlab.haskell.org/ghc/ghc/-/issues/22058
|
||||
./configure \
|
||||
--prefix="$TERMUX_PREFIX" \
|
||||
--host="$target"
|
||||
|
||||
HOST_GHC_PKG="$(realpath ../../stage0/bin/ghc-pkg)" make install
|
||||
}
|
||||
|
||||
termux_step_post_massage() {
|
||||
local ghclibs_dir="lib/ghc-$TERMUX_PKG_VERSION"
|
||||
|
||||
if ! [[ -d "$ghclibs_dir" ]]; then
|
||||
echo "ERROR: GHC lib directory is not at expected place. Please verify before continuing."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Remove version suffix from `llc` and `opt`:
|
||||
sed -i -E 's|("LLVM llc command",) "llc.*"|\1 "llc"|' "$ghclibs_dir"/lib/settings
|
||||
sed -i -E 's|("LLVM opt command",) "opt.*"|\1 "opt"|' "$ghclibs_dir"/lib/settings
|
||||
|
||||
# Remove cross-prefix from tools:
|
||||
sed -i "s|$CC|${CC/${target}-/}|g" "$ghclibs_dir"/lib/settings
|
||||
sed -i "s|$CXX|${CXX/${target}-/}|g" "$ghclibs_dir"/lib/settings
|
||||
|
||||
# Strip unneeded symbols:
|
||||
find . -type f \( -name "*.so" -o -name "*.a" \) -exec "$STRIP" --strip-unneeded {} \;
|
||||
find "$ghclibs_dir"/bin -type f -exec "$STRIP" {} \;
|
||||
}
|
||||
11
packages/ghc/cabal-set-default-prefix.patch
Normal file
11
packages/ghc/cabal-set-default-prefix.patch
Normal file
@@ -0,0 +1,11 @@
|
||||
--- ghc-9.12.1/libraries/Cabal/Cabal/src/Distribution/Simple/InstallDirs.hs 2024-12-16 01:00:10.000000000 +0530
|
||||
+++ ghc-9.12.1.mod/libraries/Cabal/Cabal/src/Distribution/Simple/InstallDirs.hs 2025-01-04 20:05:06.846734461 +0530
|
||||
@@ -205,7 +205,7 @@
|
||||
windowsProgramFilesDir <- getWindowsProgramFilesDir
|
||||
return (windowsProgramFilesDir </> "Haskell")
|
||||
Haiku -> return "/boot/system/non-packaged"
|
||||
- _ -> return "/usr/local"
|
||||
+ _ -> return "@TERMUX_PREFIX@"
|
||||
installLibDir <-
|
||||
case buildOS of
|
||||
Windows -> return "$prefix"
|
||||
18
packages/ghc/disable-no-pie.patch
Normal file
18
packages/ghc/disable-no-pie.patch
Normal file
@@ -0,0 +1,18 @@
|
||||
--- ghc-9.12.1/m4/fp_gcc_supports_no_pie.m4 2025-02-24 22:46:43.263794157 +0530
|
||||
+++ ghc-9.12.1.mod/m4/fp_gcc_supports_no_pie.m4 2025-03-25 14:39:14.331731419 +0530
|
||||
@@ -6,15 +6,6 @@
|
||||
[
|
||||
AC_REQUIRE([AC_PROG_CC])
|
||||
AC_MSG_CHECKING([whether CC supports -no-pie])
|
||||
- echo 'int main() { return 0; }' > conftest.c
|
||||
- "$CC" $CONF_GCC_CC_OPTS_STAGE2 -c conftest.c
|
||||
- # Some GCC versions only warn when passed an unrecognized flag.
|
||||
- if "$CC" $CONF_GCC_LINKER_OPTS_STAGE2 -no-pie -Werror conftest.o -o conftest > conftest.txt 2>&1 && ! grep -i unrecognized conftest.txt > /dev/null 2>&1; then
|
||||
- CONF_GCC_SUPPORTS_NO_PIE=YES
|
||||
- AC_MSG_RESULT([yes])
|
||||
- else
|
||||
CONF_GCC_SUPPORTS_NO_PIE=NO
|
||||
AC_MSG_RESULT([no])
|
||||
- fi
|
||||
- rm -f conftest.c conftest.o conftest
|
||||
])
|
||||
14
packages/ghc/elf-types.patch
Normal file
14
packages/ghc/elf-types.patch
Normal file
@@ -0,0 +1,14 @@
|
||||
--- ghc-9.12.1/rts/linker/ElfTypes.h 2024-12-16 00:59:46.000000000 +0530
|
||||
+++ ghc-9.12.1.mod/rts/linker/ElfTypes.h 2025-01-04 21:31:55.550538431 +0530
|
||||
@@ -8,6 +8,11 @@
|
||||
#include <elf.h>
|
||||
#include "linker/InitFini.h"
|
||||
|
||||
+#define ELF32_ST_VISIBILITY(o) ((o) & 0x03)
|
||||
+
|
||||
+/* For ELF64 the definitions are the same. */
|
||||
+#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY(o)
|
||||
+
|
||||
/*
|
||||
* Define a set of types which can be used for both ELF32 and ELF64
|
||||
*/
|
||||
11
packages/ghc/fix-arch-check.patch
Normal file
11
packages/ghc/fix-arch-check.patch
Normal file
@@ -0,0 +1,11 @@
|
||||
--- ghc-9.12.1/m4/fptools_set_haskell_platform_vars.m4 2024-12-16 00:59:46.000000000 +0530
|
||||
+++ ghc-9.12.1.mod/m4/fptools_set_haskell_platform_vars.m4 2025-01-24 18:18:00.513871875 +0530
|
||||
@@ -21,7 +21,7 @@
|
||||
s390x)
|
||||
test -z "[$]2" || eval "[$]2=ArchS390X"
|
||||
;;
|
||||
- arm)
|
||||
+ arm*)
|
||||
GET_ARM_ISA()
|
||||
test -z "[$]2" || eval "[$]2=\"ArchARM \$ARM_ISA \$ARM_ISA_EXT \$ARM_ABI\""
|
||||
;;
|
||||
13
packages/ghc/hadrian-bindist-config.patch
Normal file
13
packages/ghc/hadrian-bindist-config.patch
Normal file
@@ -0,0 +1,13 @@
|
||||
--- ghc-9.12.1/hadrian/bindist/config.mk.in 2025-02-24 22:46:43.665077469 +0530
|
||||
+++ ghc-9.12.1.mod/hadrian/bindist/config.mk.in 2025-02-26 02:09:44.451291933 +0530
|
||||
@@ -130,8 +130,8 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Build configuration
|
||||
|
||||
-CrossCompiling = @CrossCompiling@
|
||||
-CrossCompilePrefix = @CrossCompilePrefix@
|
||||
+CrossCompiling = NO
|
||||
+CrossCompilePrefix =
|
||||
GhcUnregisterised = @Unregisterised@
|
||||
EnableDistroToolchain = @SettingsUseDistroMINGW@
|
||||
|
||||
22
packages/ghc/hadrian-bindist-use-host-ghc-pkg.patch
Normal file
22
packages/ghc/hadrian-bindist-use-host-ghc-pkg.patch
Normal file
@@ -0,0 +1,22 @@
|
||||
--- ghc-9.12.1/hadrian/src/Rules/BinaryDist.hs 2025-02-24 22:46:43.666788988 +0530
|
||||
+++ ghc-9.12.1.mod/hadrian/src/Rules/BinaryDist.hs 2025-02-25 16:56:59.718827035 +0530
|
||||
@@ -231,6 +231,6 @@
|
||||
--
|
||||
-- N.B. the ghc-pkg executable may be prefixed with a target triple
|
||||
-- (c.f. #20267).
|
||||
- ghcPkgName <- programName (vanillaContext Stage1 ghcPkg)
|
||||
- cmd_ (bindistFilesDir -/- "bin" -/- ghcPkgName) ["recache"]
|
||||
+ stage0ghcPkgPath <- programPath =<< programContext (Stage0 InTreeLibs) ghcPkg
|
||||
+ cmd_ stage0ghcPkgPath ["recache"]
|
||||
|
||||
--- ghc-9.12.1/hadrian/bindist/Makefile 2025-02-24 22:46:43.665077469 +0530
|
||||
+++ ghc-9.12.1.mod/hadrian/bindist/Makefile 2025-02-24 22:46:44.140454443 +0530
|
||||
@@ -253,7 +253,7 @@
|
||||
@echo "Updating the package DB"
|
||||
$(foreach p, $(PKG_CONFS),\
|
||||
$(call patchpackageconf,$(shell echo $(notdir $p) | sed 's/-[0-9.]*-[0-9a-zA-Z]*\.conf//g'),$(shell echo "$p" | sed 's:\0xxx\0: :g'),$(docdir),$(shell mk/relpath.sh "$(ActualLibsDir)" "$(docdir)"),$(shell echo $(notdir $p) | sed 's/.conf//g')))
|
||||
- '$(DESTDIR)$(ActualBinsDir)/$(CrossCompilePrefix)ghc-pkg' --global-package-db "$(DESTDIR)$(ActualLibsDir)/package.conf.d" recache
|
||||
+ '$(HOST_GHC_PKG)' --global-package-db "$(DESTDIR)$(ActualLibsDir)/package.conf.d" recache
|
||||
|
||||
.PHONY: install_mingw
|
||||
install_mingw:
|
||||
13
packages/ghc/hadrian-disable-speed-hack.patch
Normal file
13
packages/ghc/hadrian-disable-speed-hack.patch
Normal file
@@ -0,0 +1,13 @@
|
||||
# This is the culprit that removes `-fPIC` flag for i686 build.
|
||||
|
||||
--- ghc-9.12.1/hadrian/src/Settings/Packages.hs 2025-02-24 22:46:43.668323779 +0530
|
||||
+++ ghc-9.12.1.mod/hadrian/src/Settings/Packages.hs 2025-02-25 23:06:51.153991428 +0530
|
||||
@@ -510,7 +510,7 @@
|
||||
speedHack :: Action Bool
|
||||
speedHack = do
|
||||
i386 <- anyTargetArch [ArchX86]
|
||||
- goodOS <- not <$> anyTargetOs [OSSolaris2]
|
||||
+ goodOS <- not <$> anyTargetOs [OSSolaris2, OSLinux]
|
||||
return $ i386 && goodOS
|
||||
|
||||
-- See @rts/ghc.mk@.
|
||||
11
packages/ghc/hadrian-do-not-add-cross-prefix.patch
Normal file
11
packages/ghc/hadrian-do-not-add-cross-prefix.patch
Normal file
@@ -0,0 +1,11 @@
|
||||
--- ghc-9.12.1/hadrian/src/Packages.hs 2025-02-24 22:46:43.665442228 +0530
|
||||
+++ ghc-9.12.1.mod/hadrian/src/Packages.hs 2025-02-26 14:41:51.865132206 +0530
|
||||
@@ -171,7 +171,7 @@
|
||||
crossPrefix = do
|
||||
cross <- flag CrossCompiling
|
||||
targetPlatform <- setting TargetPlatformFull
|
||||
- return $ if cross then targetPlatform ++ "-" else ""
|
||||
+ return ""
|
||||
|
||||
-- | Given a 'Context', compute the name of the program that is built in it
|
||||
-- assuming that the corresponding package's type is 'Program'. For example, GHC
|
||||
18
packages/ghc/hadrian-enable-disabled-packages.patch
Normal file
18
packages/ghc/hadrian-enable-disabled-packages.patch
Normal file
@@ -0,0 +1,18 @@
|
||||
--- ghc-9.12.2/hadrian/src/Settings/Default.hs 2025-03-29 15:32:47.000000000 +0530
|
||||
+++ ghc-9.12.2.mod/hadrian/src/Settings/Default.hs 2025-04-07 15:04:48.724844187 +0530
|
||||
@@ -172,13 +172,11 @@
|
||||
, unlit
|
||||
, xhtml
|
||||
, if winTarget then win32 else unix
|
||||
- ]
|
||||
- , when (not cross)
|
||||
- [ haddock
|
||||
+ , haddock
|
||||
, hpcBin
|
||||
, iserv
|
||||
, runGhc
|
||||
- , ghcToolchainBin
|
||||
+ , terminfo
|
||||
]
|
||||
, when (winTarget && not cross)
|
||||
[ -- See Note [Hadrian's ghci-wrapper package]
|
||||
46
packages/ghc/hadrian-fix-packages-settings.patch
Normal file
46
packages/ghc/hadrian-fix-packages-settings.patch
Normal file
@@ -0,0 +1,46 @@
|
||||
--- ghc-9.12.2/hadrian/src/Settings/Packages.hs 2025-03-29 15:32:47.000000000 +0530
|
||||
+++ ghc-9.12.2.mod/hadrian/src/Settings/Packages.hs 2025-04-07 15:06:41.398290889 +0530
|
||||
@@ -85,8 +85,8 @@
|
||||
-- (#14335) and completely untested in CI for cross
|
||||
-- backends at the moment, so we might as well disable it
|
||||
-- for cross GHC.
|
||||
- [ andM [expr ghcWithInterpreter, notStage0, notCross] `cabalFlag` "internal-interpreter"
|
||||
- , notM cross `cabalFlag` "terminfo"
|
||||
+ [ andM [expr ghcWithInterpreter, notStage0] `cabalFlag` "internal-interpreter"
|
||||
+ , notStage0 `cabalFlag` "terminfo"
|
||||
, arg "-build-tool-depends"
|
||||
, flag UseLibzstd `cabalFlag` "with-libzstd"
|
||||
-- ROMES: While the boot compiler is not updated wrt -this-unit-id
|
||||
@@ -121,7 +121,7 @@
|
||||
|
||||
-------------------------------- ghcPkg --------------------------------
|
||||
, package ghcPkg ?
|
||||
- builder (Cabal Flags) ? notM cross `cabalFlag` "terminfo"
|
||||
+ builder (Cabal Flags) ? notStage0 `cabalFlag` "terminfo"
|
||||
|
||||
-------------------------------- ghcPrim -------------------------------
|
||||
, package ghcPrim ? mconcat
|
||||
@@ -213,7 +213,7 @@
|
||||
-- dependencies.
|
||||
-- TODO: Perhaps the user should rather be responsible for this?
|
||||
, package haskeline ?
|
||||
- builder (Cabal Flags) ? notM cross `cabalFlag` "terminfo"
|
||||
+ builder (Cabal Flags) ? notStage0 `cabalFlag` "terminfo"
|
||||
|
||||
-------------------------------- terminfo ------------------------------
|
||||
, package terminfo ?
|
||||
@@ -374,10 +374,10 @@
|
||||
|
||||
, input "**/RtsUtils.c" ? pure
|
||||
[ "-DProjectVersion=" ++ show projectVersion
|
||||
- , "-DHostPlatform=" ++ show hostPlatform
|
||||
- , "-DHostArch=" ++ show hostArch
|
||||
- , "-DHostOS=" ++ show hostOs
|
||||
- , "-DHostVendor=" ++ show hostVendor
|
||||
+ , "-DHostPlatform=" ++ show targetPlatform
|
||||
+ , "-DHostArch=" ++ show targetArch
|
||||
+ , "-DHostOS=" ++ show targetOs
|
||||
+ , "-DHostVendor=" ++ show targetVendor
|
||||
, "-DBuildPlatform=" ++ show buildPlatform
|
||||
, "-DBuildArch=" ++ show buildArch
|
||||
, "-DBuildOS=" ++ show buildOs
|
||||
12
packages/ghc/hadrian-fix-program-rule.patch
Normal file
12
packages/ghc/hadrian-fix-program-rule.patch
Normal file
@@ -0,0 +1,12 @@
|
||||
--- ghc-9.12.2/hadrian/src/Rules/Program.hs 2025-03-29 15:32:47.000000000 +0530
|
||||
+++ ghc-9.12.2.mod/hadrian/src/Rules/Program.hs 2025-04-07 23:55:57.642949426 +0530
|
||||
@@ -102,9 +102,6 @@
|
||||
cross <- flag CrossCompiling
|
||||
-- For cross compiler, copy @stage0/bin/<pgm>@ to @stage1/bin/@.
|
||||
case (cross, stage) of
|
||||
- (True, s) | s > stage0InTree -> do
|
||||
- srcDir <- buildRoot <&> (-/- (stageString stage0InTree -/- "bin"))
|
||||
- copyFile (srcDir -/- takeFileName bin) bin
|
||||
_ -> buildBinary rs bin ctx
|
||||
|
||||
buildBinary :: [(Resource, Int)] -> FilePath -> Context -> Action ()
|
||||
132
packages/ghc/rts-heap-reservation.patch
Normal file
132
packages/ghc/rts-heap-reservation.patch
Normal file
@@ -0,0 +1,132 @@
|
||||
From fdd0c67a38ef8435b9aa46c0d3c9d4460191cdcf Mon Sep 17 00:00:00 2001
|
||||
From: Robert Kirkman <rkirkman@termux.dev>
|
||||
Date: Fri, 28 Mar 2025 16:53:16 -0500
|
||||
Subject: [PATCH] rts: reattempt heap reservation recursively before unmapping
|
||||
addresses below the 8GB mark
|
||||
|
||||
This patch works around Android's mmap() occasionally repeatedly mapping the exact
|
||||
same block of memory at an address below the 8GB mark that was just
|
||||
unmapped, which would cause the 'ghc --help' command to fall into an infinite loop while
|
||||
osTryReserveHeapMemory() repeatedly returned the same unwanted address. This
|
||||
moves the heap reservation attempt logic into a recursive function that
|
||||
runs osTryReserveHeapMemory() multiple times without unmapping the
|
||||
undesired addresses, to force the mapping of new, unique addresses
|
||||
until an address above the 8GB mark is obtained,
|
||||
after which each recursive call unmaps its undesired address before
|
||||
returning the desired address, in order from last mapped to first mapped.
|
||||
|
||||
First discussed here: https://github.com/termux/termux-packages/pull/22991
|
||||
---
|
||||
rts/posix/OSMem.c | 88 +++++++++++++++++++++++++----------------------
|
||||
1 file changed, 46 insertions(+), 42 deletions(-)
|
||||
|
||||
diff --git a/rts/posix/OSMem.c b/rts/posix/OSMem.c
|
||||
index 94c60f441ac9..2f1638bb5123 100644
|
||||
--- a/rts/posix/OSMem.c
|
||||
+++ b/rts/posix/OSMem.c
|
||||
@@ -493,11 +493,53 @@ osTryReserveHeapMemory (W_ len, void *hint)
|
||||
return start;
|
||||
}
|
||||
|
||||
-void *osReserveHeapMemory(void *startAddressPtr, W_ *len)
|
||||
+static void *
|
||||
+osTryReserveHeapMemoryRecursive(W_ minimumAddress, W_ startAddress, int attempt, W_ *len)
|
||||
{
|
||||
- int attempt;
|
||||
- void *at;
|
||||
+ *len &= ~MBLOCK_MASK;
|
||||
+
|
||||
+ if (*len < MBLOCK_SIZE) {
|
||||
+ // Give up if the system won't even give us 16 blocks worth of heap
|
||||
+ barf("osReserveHeapMemory: Failed to allocate heap storage");
|
||||
+ }
|
||||
+
|
||||
+ void *hint = (void*)(startAddress + attempt * BLOCK_SIZE);
|
||||
+ void *at = osTryReserveHeapMemory(*len, hint);
|
||||
+ attempt++;
|
||||
+
|
||||
+ if (at == NULL) {
|
||||
+ // This means that mmap failed which we take to mean that we asked
|
||||
+ // for too much memory. This can happen due to POSIX resource
|
||||
+ // limits. In this case we reduce our allocation request by a
|
||||
+ // fraction of the current size and try again.
|
||||
+ //
|
||||
+ // Note that the previously would instead decrease the request size
|
||||
+ // by a factor of two; however, this meant that significant amounts
|
||||
+ // of memory will be wasted (e.g. imagine a machine with 512GB of
|
||||
+ // physical memory but a 511GB ulimit). See #14492.
|
||||
+ *len -= *len / 8;
|
||||
+ // debugBelch("Limit hit, reduced len: %zu\n", *len);
|
||||
+ return osTryReserveHeapMemoryRecursive(minimumAddress, startAddress, attempt, len);
|
||||
+ } else if ((W_)at >= minimumAddress) {
|
||||
+ // Success! We were given a block of memory starting above the 8 GB
|
||||
+ // mark, which is what we were looking for.
|
||||
+
|
||||
+ return at;
|
||||
+ } else {
|
||||
+ // We got addressing space but it wasn't above the 8GB mark.
|
||||
+ // Try again recursively first, unmap after, because on aarch64 Android,
|
||||
+ // sometimes mmap() will continuously map the same address regardless of
|
||||
+ // the hint changing, if that address has already been unmapped.
|
||||
+ void *next_at = osTryReserveHeapMemoryRecursive(minimumAddress, startAddress, attempt, len);
|
||||
+ if (munmap(at, *len) < 0) {
|
||||
+ sysErrorBelch("unable to release reserved heap");
|
||||
+ }
|
||||
+ return next_at;
|
||||
+ }
|
||||
+}
|
||||
|
||||
+void *osReserveHeapMemory(void *startAddressPtr, W_ *len)
|
||||
+{
|
||||
/* We want to ensure the heap starts at least 8 GB inside the address space,
|
||||
since we want to reserve the address space below that address for code.
|
||||
Specifically, we need to make sure that any dynamically loaded code will
|
||||
@@ -585,45 +627,7 @@ void *osReserveHeapMemory(void *startAddressPtr, W_ *len)
|
||||
}
|
||||
#endif
|
||||
|
||||
- attempt = 0;
|
||||
- while (1) {
|
||||
- *len &= ~MBLOCK_MASK;
|
||||
-
|
||||
- if (*len < MBLOCK_SIZE) {
|
||||
- // Give up if the system won't even give us 16 blocks worth of heap
|
||||
- barf("osReserveHeapMemory: Failed to allocate heap storage");
|
||||
- }
|
||||
-
|
||||
- void *hint = (void*)(startAddress + attempt * BLOCK_SIZE);
|
||||
- at = osTryReserveHeapMemory(*len, hint);
|
||||
- if (at == NULL) {
|
||||
- // This means that mmap failed which we take to mean that we asked
|
||||
- // for too much memory. This can happen due to POSIX resource
|
||||
- // limits. In this case we reduce our allocation request by a
|
||||
- // fraction of the current size and try again.
|
||||
- //
|
||||
- // Note that the previously would instead decrease the request size
|
||||
- // by a factor of two; however, this meant that significant amounts
|
||||
- // of memory will be wasted (e.g. imagine a machine with 512GB of
|
||||
- // physical memory but a 511GB ulimit). See #14492.
|
||||
- *len -= *len / 8;
|
||||
- // debugBelch("Limit hit, reduced len: %zu\n", *len);
|
||||
- } else if ((W_)at >= minimumAddress) {
|
||||
- // Success! We were given a block of memory starting above the 8 GB
|
||||
- // mark, which is what we were looking for.
|
||||
-
|
||||
- break;
|
||||
- } else {
|
||||
- // We got addressing space but it wasn't above the 8GB mark.
|
||||
- // Try again.
|
||||
- if (munmap(at, *len) < 0) {
|
||||
- sysErrorBelch("unable to release reserved heap");
|
||||
- }
|
||||
- }
|
||||
- attempt++;
|
||||
- }
|
||||
-
|
||||
- return at;
|
||||
+ return osTryReserveHeapMemoryRecursive(minimumAddress, startAddress, 0, len);
|
||||
}
|
||||
|
||||
void osCommitMemory(void *at, W_ size)
|
||||
--
|
||||
GitLab
|
||||
Reference in New Issue
Block a user