[Git][ghc/ghc][wip/T22965-9.2] 3 commits: rts: Statically assert alignment of Capability
Ben Gamari (@bgamari)
gitlab at gitlab.haskell.org
Mon Feb 20 20:29:28 UTC 2023
Ben Gamari pushed to branch wip/T22965-9.2 at Glasgow Haskell Compiler / GHC
Commits:
1de404a6 by Ben Gamari at 2023-02-20T15:29:22-05:00
rts: Statically assert alignment of Capability
In #22965 we noticed that changes in the size of `Capability` can result
in unsound behavior due to the `align` pragma claiming an alignment
which we don't in practice observe. Avoid this by statically asserting
that the size is a multiple of the alignment.
- - - - -
48ecd4b4 by Ben Gamari at 2023-02-20T15:29:22-05:00
rts: Introduce stgMallocAlignedBytes
(cherry picked from commit 04336d2f11e49f7d00392f05d4fd48abdd231fc0)
- - - - -
cdb39b95 by Ben Gamari at 2023-02-20T15:29:22-05:00
rts: Correctly align Capability allocations
Previously we failed to tell the C allocator that `Capability`s needed
to be aligned, resulting in #22965.
(cherry picked from commit 4af27feabf482cf6b611951443e05ee7e53acb39)
- - - - -
4 changed files:
- rts/Capability.c
- rts/Capability.h
- rts/RtsUtils.c
- rts/RtsUtils.h
Changes:
=====================================
rts/Capability.c
=====================================
@@ -439,8 +439,9 @@ moreCapabilities (uint32_t from USED_IF_THREADS, uint32_t to USED_IF_THREADS)
if (i < from) {
new_capabilities[i] = capabilities[i];
} else {
- new_capabilities[i] = stgMallocBytes(sizeof(Capability),
- "moreCapabilities");
+ new_capabilities[i] = stgMallocAlignedBytes(sizeof(Capability),
+ CAPABILITY_ALIGNMENT,
+ "moreCapabilities");
initCapability(new_capabilities[i], i);
}
}
@@ -1287,7 +1288,7 @@ freeCapabilities (void)
for (i=0; i < getNumCapabilities(); i++) {
freeCapability(capabilities[i]);
if (capabilities[i] != &MainCapability)
- stgFree(capabilities[i]);
+ stgFreeAligned(capabilities[i]);
}
#else
freeCapability(&MainCapability);
=====================================
rts/Capability.h
=====================================
@@ -27,6 +27,17 @@
#include "BeginPrivate.h"
+// We never want a Capability to overlap a cache line with
+// anything else, so round it up to a cache line size:
+#if defined(s390x_HOST_ARCH)
+#define CAPABILITY_ALIGNMENT 256
+#elif defined(mingw32_HOST_OS)
+// N.B. it's quite unclear why this special case exists
+#define CAPABILITY_ALIGNMENT 1
+#else
+#define CAPABILITY_ALIGNMENT 64
+#endif
+
/* N.B. This must be consistent with CapabilityPublic in RtsAPI.h */
struct Capability_ {
// State required by the STG virtual machine when running Haskell
@@ -172,14 +183,12 @@ struct Capability_ {
StgTRecHeader *free_trec_headers;
uint32_t transaction_tokens;
} // typedef Capability is defined in RtsAPI.h
- // We never want a Capability to overlap a cache line with anything
- // else, so round it up to a cache line size:
-#if defined(s390x_HOST_ARCH)
- ATTRIBUTE_ALIGNED(256)
-#elif !defined(mingw32_HOST_OS)
- ATTRIBUTE_ALIGNED(64)
-#endif
- ;
+ ATTRIBUTE_ALIGNED(CAPABILITY_ALIGNMENT)
+;
+
+// We allocate arrays of Capabilities therefore we must ensure that the size is
+// a multiple of the claimed alignment
+GHC_STATIC_ASSERT(sizeof(struct Capability_) % CAPABILITY_ALIGNMENT == 0, "Capability size does not match cache size");
#if defined(THREADED_RTS)
#define ASSERT_TASK_ID(task) ASSERT(task->id == osThreadId())
=====================================
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
-------------------------------------------------------------------------- */
=====================================
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
* -------------------------------------------------------------------------- */
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/6c037b1d972e993b61da83fb7418b9d045918e4e...cdb39b95fe6d562abc6c1af9a8c0b208dd81681b
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/6c037b1d972e993b61da83fb7418b9d045918e4e...cdb39b95fe6d562abc6c1af9a8c0b208dd81681b
You're receiving this email because of your account on gitlab.haskell.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20230220/1e663f24/attachment-0001.html>
More information about the ghc-commits
mailing list