summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2022-11-16 09:48:19 -0500
committerBen Gamari <ben@smart-cactus.org>2022-12-21 15:46:41 -0500
commitb6a3ab00712ca40acd1d91ba910e18c972a345a8 (patch)
treedf3b2be0f9aed737e4d2079f7256096edb56a666
parent7570ae43218fbdee30f783af5a3f49fa3d8301e3 (diff)
downloadhaskell-b6a3ab00712ca40acd1d91ba910e18c972a345a8.tar.gz
nonmoving: Fix race in shortcutting
We must use an acquire load to read the info table pointer since if we find an indirection we must be certain that we see the indirectee.
-rw-r--r--rts/include/rts/storage/ClosureMacros.h6
-rw-r--r--rts/sm/NonMovingShortcut.c3
2 files changed, 8 insertions, 1 deletions
diff --git a/rts/include/rts/storage/ClosureMacros.h b/rts/include/rts/storage/ClosureMacros.h
index ba57df1699..ecfca8a81c 100644
--- a/rts/include/rts/storage/ClosureMacros.h
+++ b/rts/include/rts/storage/ClosureMacros.h
@@ -97,6 +97,12 @@ EXTERN_INLINE const StgInfoTable *get_itbl(const StgClosure *c)
return INFO_PTR_TO_STRUCT(RELAXED_LOAD(&c->header.info));
}
+EXTERN_INLINE const StgInfoTable *get_itbl_acquire(const StgClosure *c);
+EXTERN_INLINE const StgInfoTable *get_itbl_acquire(const StgClosure *c)
+{
+ return INFO_PTR_TO_STRUCT(ACQUIRE_LOAD(&c->header.info));
+}
+
EXTERN_INLINE const StgRetInfoTable *get_ret_itbl(const StgClosure *c);
EXTERN_INLINE const StgRetInfoTable *get_ret_itbl(const StgClosure *c)
{
diff --git a/rts/sm/NonMovingShortcut.c b/rts/sm/NonMovingShortcut.c
index 83c4857677..ee97ba1b70 100644
--- a/rts/sm/NonMovingShortcut.c
+++ b/rts/sm/NonMovingShortcut.c
@@ -153,7 +153,8 @@ selectee_changed:
// Selectee is a non-moving object, mark it.
markQueuePushClosure(queue, selectee, NULL);
- const StgInfoTable *selectee_info_tbl = get_itbl(selectee);
+ // This may synchronize with the release in updateWithIndirection.
+ const StgInfoTable *selectee_info_tbl = get_itbl_acquire(selectee);
switch (selectee_info_tbl->type) {
case WHITEHOLE: {
// Probably a loop. Abort.