summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2023-02-13 13:13:05 -0500
committerZubin Duggal <zubin.duggal@gmail.com>2023-02-22 17:04:38 +0530
commit0978122d26a749e02a1c3b1a77649da82a1fbccd (patch)
tree5c62269189e5dc5156cbc380d3b72edd51c6e2cb
parent923afa2f51c2e03aef1cc3094a13dbd86d38a283 (diff)
downloadhaskell-0978122d26a749e02a1c3b1a77649da82a1fbccd.tar.gz
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. (cherry picked from commit 1de404a6528b44bb50927383cb1acf237d21ee03)
-rw-r--r--rts/Capability.h25
1 files changed, 17 insertions, 8 deletions
diff --git a/rts/Capability.h b/rts/Capability.h
index d7c1916ad7..6ccfdccf10 100644
--- a/rts/Capability.h
+++ b/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())