summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2023-02-13 14:46:24 -0500
committerZubin Duggal <zubin.duggal@gmail.com>2023-02-22 17:04:46 +0530
commit512c37e77ae09fe2a7e47afa559ffb835f5b0267 (patch)
treea2a405722ebd8db8475b93a2ff66484d021167da
parent0978122d26a749e02a1c3b1a77649da82a1fbccd (diff)
downloadhaskell-512c37e77ae09fe2a7e47afa559ffb835f5b0267.tar.gz
rts: Introduce stgMallocAlignedBytes
(cherry picked from commit 04336d2f11e49f7d00392f05d4fd48abdd231fc0) (cherry picked from commit 48ecd4b4dca42cf482847d7629c91d2b44eae252)
-rw-r--r--rts/RtsUtils.c51
-rw-r--r--rts/RtsUtils.h4
2 files changed, 53 insertions, 2 deletions
diff --git a/rts/RtsUtils.c b/rts/RtsUtils.c
index ca01bdb6e0..d72a6a4be4 100644
--- a/rts/RtsUtils.c
+++ b/rts/RtsUtils.c
@@ -59,9 +59,9 @@ extern char *ctime_r(const time_t *, char *);
void *
stgMallocBytes (size_t n, char *msg)
{
- void *space;
+ void *space = malloc(n);
- if ((space = malloc(n)) == NULL) {
+ if (space == NULL) {
/* Quoting POSIX.1-2008 (which says more or less the same as ISO C99):
*
* "Upon successful completion with size not equal to 0, malloc() shall
@@ -130,6 +130,53 @@ stgFree(void* p)
free(p);
}
+// N.B. Allocations resulting from this function must be freed by
+// `stgFreeAligned`, not `stgFree`. This is necessary due to the properties of Windows' `_aligned_malloc`
+void *
+stgMallocAlignedBytes (size_t n, size_t align, char *msg)
+{
+ void *space;
+
+#if defined(mingw32_HOST_OS)
+ space = _aligned_malloc(n, align);
+#else
+ if (posix_memalign(&space, align, n)) {
+ space = NULL; // Allocation failed
+ }
+#endif
+
+ if (space == NULL) {
+ /* Quoting POSIX.1-2008 (which says more or less the same as ISO C99):
+ *
+ * "Upon successful completion with size not equal to 0, malloc() shall
+ * return a pointer to the allocated space. If size is 0, either a null
+ * pointer or a unique pointer that can be successfully passed to free()
+ * shall be returned. Otherwise, it shall return a null pointer and set
+ * errno to indicate the error."
+ *
+ * Consequently, a NULL pointer being returned by `malloc()` for a 0-size
+ * allocation is *not* to be considered an error.
+ */
+ if (n == 0) return NULL;
+
+ /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
+ rtsConfig.mallocFailHook((W_) n, msg);
+ stg_exit(EXIT_INTERNAL_ERROR);
+ }
+ IF_DEBUG(zero_on_gc, memset(space, 0xbb, n));
+ return space;
+}
+
+void
+stgFreeAligned (void *p)
+{
+#if defined(mingw32_HOST_OS)
+ _aligned_free(p);
+#else
+ free(p);
+#endif
+}
+
/* -----------------------------------------------------------------------------
Stack/heap overflow
-------------------------------------------------------------------------- */
diff --git a/rts/RtsUtils.h b/rts/RtsUtils.h
index c87aedb3a7..41120b0417 100644
--- a/rts/RtsUtils.h
+++ b/rts/RtsUtils.h
@@ -29,6 +29,10 @@ char *stgStrndup(const char *s, size_t n);
void stgFree(void* p);
+void *stgMallocAlignedBytes(size_t n, size_t align, char *msg);
+
+void stgFreeAligned(void *p);
+
/* -----------------------------------------------------------------------------
* Misc other utilities
* -------------------------------------------------------------------------- */