[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 6 commits: rts: ensure gc_thread/gen_workspace is allocated with proper alignment

Marge Bot (@marge-bot) gitlab at gitlab.haskell.org
Thu May 30 13:42:42 UTC 2024



Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC


Commits:
aa3bab32 by Cheng Shao at 2024-05-30T09:42:17-04:00
rts: ensure gc_thread/gen_workspace is allocated with proper alignment

gc_thread/gen_workspace are required to be aligned by 64 bytes.
However, this property has not been properly enforced before, and
numerous alignment violations at runtime has been caught by
UndefinedBehaviorSanitizer that look like:

```
rts/sm/GC.c:1167:8: runtime error: member access within misaligned address 0x0000027a3390 for type 'gc_thread' (aka 'struct gc_thread_'), which requires 64 byte alignment
0x0000027a3390: note: pointer points here
 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00
              ^
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior rts/sm/GC.c:1167:8

rts/sm/GC.c:1184:13: runtime error: member access within misaligned address 0x0000027a3450 for type 'gen_workspace' (aka 'struct gen_workspace_'), which requires 64 byte alignment
0x0000027a3450: note: pointer points here
 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00
              ^
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior rts/sm/GC.c:1184:13
```

This patch fixes the gc_thread/gen_workspace misalignment issue by
explicitly allocating them with alignment constraint.

- - - - -
a3c834cc by Cheng Shao at 2024-05-30T09:42:17-04:00
rts: fix an unaligned load in nonmoving gc

This patch fixes an unaligned load in nonmoving gc by ensuring the
closure address is properly untagged first before attempting to
prefetch its header. The unaligned load is reported by
UndefinedBehaviorSanitizer:

```
rts/sm/NonMovingMark.c:921:9: runtime error: member access within misaligned address 0x0042005f3a71 for type 'StgClosure' (aka 'struct StgClosure_'), which requires 8 byte alignment
0x0042005f3a71: note: pointer points here
 00 00 00  98 43 13 8e 12 7f 00 00  50 3c 5f 00 42 00 00 00  58 17 b7 92 12 7f 00 00  89 cb 5e 00 42
              ^
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior rts/sm/NonMovingMark.c:921:9
```

This issue had previously gone unnoticed since it didn't really harm
runtime correctness, the invalid header address directly loaded from a
tagged pointer is only used as prefetch address and will not cause
segfaults. However, it still should be corrected because the prefetch
would be rendered useless by this issue, and untagging only involves a
single bitwise operation without memory access so it's cheap enough to
add.

- - - - -
a4a80d74 by Cheng Shao at 2024-05-30T09:42:17-04:00
rts: use __builtin_offsetof to implement STG_FIELD_OFFSET

This patch fixes the STG_FIELD_OFFSET macro definition by using
__builtin_offsetof, which is what gcc/clang uses to implement offsetof
in standard C. The previous definition that uses NULL pointer involves
subtle undefined behavior in C and thus reported by
UndefinedBehaviorSanitizer as well:

```
rts/Capability.h:243:58: runtime error: member access within null pointer of type 'Capability' (aka 'struct Capability_')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior rts/Capability.h:243:58
```

- - - - -
91199d3f by Sylvain Henry at 2024-05-30T09:42:20-04:00
JS: remove useless h$CLOCK_REALTIME (#23202)

- - - - -
f7587ddb by Matthew Pickering at 2024-05-30T09:42:21-04:00
ghcup-metadata: Fix metadata generation

There were some syntax errors in the generation script which were
preventing it from running.

I have tested this with:

```
nix shell --extra-experimental-features nix-command -f .gitlab/rel_eng -c ghcup-metadata --metadata ghcup-0.0.7.yaml --date="2024-05-27" --pipeline-id=95534 --version=9.11.20240525
```

which completed successfully.

- - - - -
e6f8581e by Jakob Bruenker at 2024-05-30T09:42:21-04:00
Add diagrams to Arrows documentation

This adds diagrams to the documentation of Arrows, similar to the ones found on
https://www.haskell.org/arrows/.

It does not add diagrams for ArrowChoice for the time being, mainly because it's
not clear to me how to visually distinguish them from the ones for Arrow. Ideally,
you might want to do something like highlight the arrows belonging to the same
tuple or same Either in common colors, but that's not really possible with unicode.

- - - - -


6 changed files:

- .gitlab/rel_eng/mk-ghcup-metadata/mk_ghcup_metadata.py
- libraries/ghc-internal/src/GHC/Internal/Control/Arrow.hs
- rts/include/Stg.h
- rts/js/time.js
- rts/sm/GC.c
- rts/sm/NonMovingMark.c


Changes:

=====================================
.gitlab/rel_eng/mk-ghcup-metadata/mk_ghcup_metadata.py
=====================================
@@ -199,7 +199,7 @@ def mk_new_yaml(release_mode, version, date, pipeline_type, job_map):
     windows = mk(windowsArtifact)
     alpine3_12 = mk(alpine("3_12"))
     alpine3_18 = mk(alpine("3_18"))
-    alpine3_18_arm64 = mk(alpine("3_18"), arch='aarch64')
+    alpine3_18_arm64 = mk(alpine("3_18", arch='aarch64'))
     deb9 = mk(debian(9, "x86_64"))
     deb10 = mk(debian(10, "x86_64"))
     deb11 = mk(debian(11, "x86_64"))
@@ -233,8 +233,8 @@ def mk_new_yaml(release_mode, version, date, pipeline_type, job_map):
           , "Linux_UnknownLinux" : { "unknown_versioning": rocky8 }
           , "Darwin" : { "unknown_versioning" : darwin_x86 }
           , "Windows" : { "unknown_versioning" :  windows }
-          , "Linux_Alpine" : { "( >= 3.12 && < 3.18 )": alpine_3_12
-                             , ">= 3.18": alpine_3_18
+          , "Linux_Alpine" : { "( >= 3.12 && < 3.18 )": alpine3_12
+                             , ">= 3.18": alpine3_18
                              , "unknown_versioning": alpine3_12 }
 
           }


=====================================
libraries/ghc-internal/src/GHC/Internal/Control/Arrow.hs
=====================================
@@ -93,17 +93,35 @@ class Category a => Arrow a where
     {-# MINIMAL arr, (first | (***)) #-}
 
     -- | Lift a function to an arrow.
+    --
+    -- >   b ╭───╮ c
+    -- > >───┤ f ├───>
+    -- >     ╰───╯
     arr :: (b -> c) -> a b c
 
     -- | Send the first component of the input through the argument
     --   arrow, and copy the rest unchanged to the output.
+    --
+    --   The default definition may be overridden with a more efficient
+    --   version if desired.
+    --
+    -- >   b ╭─────╮ c
+    -- > >───┼─ f ─┼───>
+    -- > >───┼─────┼───>
+    -- >   d ╰─────╯ d
     first :: a b c -> a (b,d) (c,d)
     first = (*** id)
 
-    -- | A mirror image of 'first'.
+    -- | Send the second component of the input through the argument
+    --   arrow, and copy the rest unchanged to the output.
     --
     --   The default definition may be overridden with a more efficient
     --   version if desired.
+    --
+    -- >   d ╭─────╮ d
+    -- > >───┼─────┼───>
+    -- > >───┼─ f ─┼───>
+    -- >   b ╰─────╯ c
     second :: a b c -> a (d,b) (d,c)
     second = (id ***)
 
@@ -112,6 +130,11 @@ class Category a => Arrow a where
     --
     --   The default definition may be overridden with a more efficient
     --   version if desired.
+    --
+    -- >   b ╭─────╮ b'
+    -- > >───┼─ f ─┼───>
+    -- > >───┼─ g ─┼───>
+    -- >   c ╰─────╯ c'
     (***) :: a b c -> a b' c' -> a (b,b') (c,c')
     f *** g = first f >>> arr swap >>> first g >>> arr swap
       where swap ~(x,y) = (y,x)
@@ -121,6 +144,12 @@ class Category a => Arrow a where
     --
     --   The default definition may be overridden with a more efficient
     --   version if desired.
+    --
+    -- >     ╭───────╮ c
+    -- >   b │ ┌─ f ─┼───>
+    -- > >───┼─┤     │
+    -- >     │ └─ g ─┼───>
+    -- >     ╰───────╯ c'
     (&&&) :: a b c -> a b c' -> a b (c,c')
     f &&& g = arr (\b -> (b,b)) >>> f *** g
 
@@ -204,6 +233,9 @@ instance Monad m => Arrow (Kleisli m) where
     second (Kleisli f) = Kleisli (\ ~(d,b) -> f b >>= \c -> return (d,c))
 
 -- | The identity arrow, which plays the role of 'return' in arrow notation.
+--
+-- >   b
+-- > >───>
 returnA :: Arrow a => a b b
 returnA = id
 
@@ -416,6 +448,15 @@ leftApp f = arr ((\b -> (arr (\() -> b) >>> f >>> arr Left, ())) |||
 -- > unassoc (a,(b,c)) = ((a,b),c)
 --
 class Arrow a => ArrowLoop a where
+    -- |
+    --
+    -- >     ╭──────────────╮
+    -- >   b │     ╭───╮    │ c
+    -- > >───┼─────┤   ├────┼───>
+    -- >     │   ┌─┤   ├─┐  │
+    -- >     │ d │ ╰───╯ │  │
+    -- >     │   └───<───┘  │
+    -- >     ╰──────────────╯
     loop :: a (b,d) (c,d) -> a b c
 
 -- | @since base-2.01


=====================================
rts/include/Stg.h
=====================================
@@ -108,7 +108,7 @@
 
 /* Compute offsets of struct fields
  */
-#define STG_FIELD_OFFSET(s_type, field) ((StgWord)&(((s_type*)0)->field))
+#define STG_FIELD_OFFSET(s_type, field) __builtin_offsetof(s_type, field)
 
 /*
  * 'Portable' inlining:


=====================================
rts/js/time.js
=====================================
@@ -16,5 +16,3 @@ function h$clock_gettime(when, p_d, p_o) {
   }
   return 0;
 }
-
-function h$CLOCK_REALTIME() { return 0; }


=====================================
rts/sm/GC.c
=====================================
@@ -55,6 +55,7 @@
 #include "NonMoving.h"
 #include "Ticky.h"
 
+#include <stdalign.h>
 #include <string.h> // for memset()
 #include <unistd.h>
 
@@ -1242,8 +1243,9 @@ initGcThreads (uint32_t from USED_IF_THREADS, uint32_t to USED_IF_THREADS)
 
     for (i = from; i < to; i++) {
         gc_threads[i] =
-            stgMallocBytes(sizeof(gc_thread) +
+            stgMallocAlignedBytes(sizeof(gc_thread) +
                            RtsFlags.GcFlags.generations * sizeof(gen_workspace),
+                           alignof(gc_thread),
                            "alloc_gc_threads");
 
         new_gc_thread(i, gc_threads[i]);
@@ -1268,7 +1270,7 @@ freeGcThreads (void)
             {
                 freeWSDeque(gc_threads[i]->gens[g].todo_q);
             }
-            stgFree (gc_threads[i]);
+            stgFreeAligned (gc_threads[i]);
         }
         closeCondition(&gc_running_cv);
         closeMutex(&gc_running_mutex);


=====================================
rts/sm/NonMovingMark.c
=====================================
@@ -918,7 +918,7 @@ static MarkQueueEnt markQueuePop (MarkQueue *q)
         // The entry may not be a MARK_CLOSURE but it doesn't matter, our
         // MarkQueueEnt encoding always places the pointer to the object to be
         // marked first.
-        prefetchForRead(&new.mark_closure.p->header.info);
+        prefetchForRead(&(UNTAG_CLOSURE(new.mark_closure.p)->header.info));
 #if !defined(ASSERTS_ENABLED)
         prefetchForRead(Bdescr((StgPtr) new.mark_closure.p));
 #endif



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/1a4de64cd6be46c5db4a7a880a8da3214b4a606d...e6f8581efd3e4800e00ab64b6d5482afe3fb8501

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/1a4de64cd6be46c5db4a7a880a8da3214b4a606d...e6f8581efd3e4800e00ab64b6d5482afe3fb8501
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/20240530/01deb5ed/attachment-0001.html>


More information about the ghc-commits mailing list