diff mbox series

[committed] libphobos: Add Thread/Fiber support code for Darwin (PR98058)

Message ID 20210419174139.3760984-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] libphobos: Add Thread/Fiber support code for Darwin (PR98058) | expand

Commit Message

Iain Buclaw April 19, 2021, 5:41 p.m. UTC
Hi,

This patch fixes the thread support when building libphobos on Darwin,
this is enough to get the library built, and most tests to pass on a
fairly modern platform.

Testsuite hasn't been confirmed to pass cleanly on as broad a targets as
I'd like, so support is still very much experimental.

Bootstrapped and regression tested on x86_64-linux-gnu/-m32/-mx32, as
well as x86_64-apple-darwin for testing the initial port, and committed
to mainline.

Regards,
Iain.

---
libphobos/ChangeLog:

	PR d/98058
	* configure: Regenerate.
	* libdruntime/Makefile.am (DRUNTIME_DSOURCES_DARWIN): Add
	core/sys/darwin/config.d
	* libdruntime/Makefile.in: Regenerate.
	* libdruntime/config/powerpc/switchcontext.S: Implement
	fiber_switchContext for __MACH__.
	* libdruntime/config/x86/switchcontext.S: Likewise.
	* libdruntime/core/sys/darwin/config.d: New file.
	* libdruntime/core/thread/fiber.d (Fiber.getThis): Mark noinline.
	(UnsafeFiberMigration): Define for OSX/X86 and OSX/X86_64.
	* libdruntime/core/thread/osthread.d (callWithStackShell): Add inline
	assembler implementation for X86, X86_64, PPC, and PPC64.
	* libdruntime/core/thread/threadbase.d (ThreadBase.getThis): Mark
	noinline.
	* libdruntime/gcc/deh.d (FuncTable): Remove definition.
	* m4/druntime/os.m4 (DRUNTIME_OS_MINFO_BRACKETING): Check for right
	bracket symbol on darwin* targets.
	* testsuite/libphobos.thread/fiber_guard_page.d: Update test to
	support ucontext-based Fibers.
---
 libphobos/configure                           |  22 +-
 libphobos/libdruntime/Makefile.am             |  26 +-
 libphobos/libdruntime/Makefile.in             |  37 +--
 .../config/powerpc/switchcontext.S            | 278 +++++++++++++++++-
 .../libdruntime/config/x86/switchcontext.S    | 159 +++++++++-
 .../libdruntime/core/sys/darwin/config.d      |  53 ++++
 libphobos/libdruntime/core/thread/fiber.d     |   6 +
 libphobos/libdruntime/core/thread/osthread.d  |  94 +++++-
 .../libdruntime/core/thread/threadbase.d      |   1 +
 libphobos/libdruntime/gcc/deh.d               |   5 -
 libphobos/m4/druntime/os.m4                   |  22 +-
 .../libphobos.thread/fiber_guard_page.d       |   6 +-
 12 files changed, 656 insertions(+), 53 deletions(-)
 create mode 100644 libphobos/libdruntime/core/sys/darwin/config.d
diff mbox series

Patch

diff --git a/libphobos/configure b/libphobos/configure
index 2c0f57cef03..b1c8ecb5673 100755
--- a/libphobos/configure
+++ b/libphobos/configure
@@ -14422,6 +14422,8 @@  ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
+
+
   ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -14430,17 +14432,29 @@  ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for minfo section bracketing" >&5
 $as_echo_n "checking for minfo section bracketing... " >&6; }
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
 
 _ACEOF
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index fdac627364d..a2e2bff9e44 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -206,19 +206,19 @@  DRUNTIME_DSOURCES_BIONIC = core/sys/bionic/err.d \
 	core/sys/bionic/fcntl.d core/sys/bionic/stdlib.d \
 	core/sys/bionic/string.d core/sys/bionic/unistd.d
 
-DRUNTIME_DSOURCES_DARWIN = core/sys/darwin/crt_externs.d \
-	core/sys/darwin/dlfcn.d core/sys/darwin/err.d \
-	core/sys/darwin/execinfo.d core/sys/darwin/fcntl.d \
-	core/sys/darwin/ifaddrs.d core/sys/darwin/mach/dyld.d \
-	core/sys/darwin/mach/getsect.d core/sys/darwin/mach/kern_return.d \
-	core/sys/darwin/mach/loader.d core/sys/darwin/mach/nlist.d \
-	core/sys/darwin/mach/port.d core/sys/darwin/mach/semaphore.d \
-	core/sys/darwin/mach/stab.d core/sys/darwin/mach/thread_act.d \
-	core/sys/darwin/netinet/in_.d core/sys/darwin/pthread.d \
-	core/sys/darwin/stdlib.d core/sys/darwin/string.d \
-	core/sys/darwin/sys/attr.d core/sys/darwin/sys/cdefs.d \
-	core/sys/darwin/sys/event.d core/sys/darwin/sys/mman.d \
-	core/sys/darwin/sys/sysctl.d
+DRUNTIME_DSOURCES_DARWIN = core/sys/darwin/config.d \
+	core/sys/darwin/crt_externs.d core/sys/darwin/dlfcn.d \
+	core/sys/darwin/err.d core/sys/darwin/execinfo.d \
+	core/sys/darwin/fcntl.d core/sys/darwin/ifaddrs.d \
+	core/sys/darwin/mach/dyld.d core/sys/darwin/mach/getsect.d \
+	core/sys/darwin/mach/kern_return.d core/sys/darwin/mach/loader.d \
+	core/sys/darwin/mach/nlist.d core/sys/darwin/mach/port.d \
+	core/sys/darwin/mach/semaphore.d core/sys/darwin/mach/stab.d \
+	core/sys/darwin/mach/thread_act.d core/sys/darwin/netinet/in_.d \
+	core/sys/darwin/pthread.d core/sys/darwin/stdlib.d \
+	core/sys/darwin/string.d core/sys/darwin/sys/attr.d \
+	core/sys/darwin/sys/cdefs.d core/sys/darwin/sys/event.d \
+	core/sys/darwin/sys/mman.d core/sys/darwin/sys/sysctl.d
 
 DRUNTIME_DSOURCES_DRAGONFLYBSD = core/sys/dragonflybsd/dlfcn.d \
 	core/sys/dragonflybsd/err.d core/sys/dragonflybsd/execinfo.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 1ff2ac665ee..cb2e372bca0 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -256,11 +256,11 @@  am__objects_3 = core/sys/posix/aio.lo core/sys/posix/arpa/inet.lo \
 	core/sys/posix/time.lo core/sys/posix/ucontext.lo \
 	core/sys/posix/unistd.lo core/sys/posix/utime.lo
 @DRUNTIME_OS_POSIX_TRUE@am__objects_4 = $(am__objects_3)
-am__objects_5 = core/sys/darwin/crt_externs.lo \
-	core/sys/darwin/dlfcn.lo core/sys/darwin/err.lo \
-	core/sys/darwin/execinfo.lo core/sys/darwin/fcntl.lo \
-	core/sys/darwin/ifaddrs.lo core/sys/darwin/mach/dyld.lo \
-	core/sys/darwin/mach/getsect.lo \
+am__objects_5 = core/sys/darwin/config.lo \
+	core/sys/darwin/crt_externs.lo core/sys/darwin/dlfcn.lo \
+	core/sys/darwin/err.lo core/sys/darwin/execinfo.lo \
+	core/sys/darwin/fcntl.lo core/sys/darwin/ifaddrs.lo \
+	core/sys/darwin/mach/dyld.lo core/sys/darwin/mach/getsect.lo \
 	core/sys/darwin/mach/kern_return.lo \
 	core/sys/darwin/mach/loader.lo core/sys/darwin/mach/nlist.lo \
 	core/sys/darwin/mach/port.lo core/sys/darwin/mach/semaphore.lo \
@@ -843,19 +843,19 @@  DRUNTIME_DSOURCES_BIONIC = core/sys/bionic/err.d \
 	core/sys/bionic/fcntl.d core/sys/bionic/stdlib.d \
 	core/sys/bionic/string.d core/sys/bionic/unistd.d
 
-DRUNTIME_DSOURCES_DARWIN = core/sys/darwin/crt_externs.d \
-	core/sys/darwin/dlfcn.d core/sys/darwin/err.d \
-	core/sys/darwin/execinfo.d core/sys/darwin/fcntl.d \
-	core/sys/darwin/ifaddrs.d core/sys/darwin/mach/dyld.d \
-	core/sys/darwin/mach/getsect.d core/sys/darwin/mach/kern_return.d \
-	core/sys/darwin/mach/loader.d core/sys/darwin/mach/nlist.d \
-	core/sys/darwin/mach/port.d core/sys/darwin/mach/semaphore.d \
-	core/sys/darwin/mach/stab.d core/sys/darwin/mach/thread_act.d \
-	core/sys/darwin/netinet/in_.d core/sys/darwin/pthread.d \
-	core/sys/darwin/stdlib.d core/sys/darwin/string.d \
-	core/sys/darwin/sys/attr.d core/sys/darwin/sys/cdefs.d \
-	core/sys/darwin/sys/event.d core/sys/darwin/sys/mman.d \
-	core/sys/darwin/sys/sysctl.d
+DRUNTIME_DSOURCES_DARWIN = core/sys/darwin/config.d \
+	core/sys/darwin/crt_externs.d core/sys/darwin/dlfcn.d \
+	core/sys/darwin/err.d core/sys/darwin/execinfo.d \
+	core/sys/darwin/fcntl.d core/sys/darwin/ifaddrs.d \
+	core/sys/darwin/mach/dyld.d core/sys/darwin/mach/getsect.d \
+	core/sys/darwin/mach/kern_return.d core/sys/darwin/mach/loader.d \
+	core/sys/darwin/mach/nlist.d core/sys/darwin/mach/port.d \
+	core/sys/darwin/mach/semaphore.d core/sys/darwin/mach/stab.d \
+	core/sys/darwin/mach/thread_act.d core/sys/darwin/netinet/in_.d \
+	core/sys/darwin/pthread.d core/sys/darwin/stdlib.d \
+	core/sys/darwin/string.d core/sys/darwin/sys/attr.d \
+	core/sys/darwin/sys/cdefs.d core/sys/darwin/sys/event.d \
+	core/sys/darwin/sys/mman.d core/sys/darwin/sys/sysctl.d
 
 DRUNTIME_DSOURCES_DRAGONFLYBSD = core/sys/dragonflybsd/dlfcn.d \
 	core/sys/dragonflybsd/err.d core/sys/dragonflybsd/execinfo.d \
@@ -1352,6 +1352,7 @@  core/sys/posix/utime.lo: core/sys/posix/$(am__dirstamp)
 core/sys/darwin/$(am__dirstamp):
 	@$(MKDIR_P) core/sys/darwin
 	@: > core/sys/darwin/$(am__dirstamp)
+core/sys/darwin/config.lo: core/sys/darwin/$(am__dirstamp)
 core/sys/darwin/crt_externs.lo: core/sys/darwin/$(am__dirstamp)
 core/sys/darwin/dlfcn.lo: core/sys/darwin/$(am__dirstamp)
 core/sys/darwin/err.lo: core/sys/darwin/$(am__dirstamp)
diff --git a/libphobos/libdruntime/config/powerpc/switchcontext.S b/libphobos/libdruntime/config/powerpc/switchcontext.S
index d4ea577c463..74395b04014 100644
--- a/libphobos/libdruntime/config/powerpc/switchcontext.S
+++ b/libphobos/libdruntime/config/powerpc/switchcontext.S
@@ -24,7 +24,7 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
 #include "../common/threadasm.S"
 
-#if !defined(__PPC64__)
+#if !defined(__PPC64__) && !defined(__MACH__)
 
 /**
  * Performs a context switch.
@@ -151,4 +151,278 @@  CSYM(fiber_switchContext):
     .cfi_endproc
     .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
 
-#endif /* !defined(__PPC64__) */
+#elif defined(__MACH__)
+
+/* Implementation for Darwin/macOS preserving callee-saved regs.
+
+   FIXME : There is no unwind frame.
+   FIXME : not sure if we should save the vsave reg (perhaps using the slot we have
+           r11 in at present).  */
+
+/* Darwin has a red zone (220 bytes for PPC 288 for PPC64) which we can write
+   to before the stack is updated without worrying about it being clobbered by
+   signals or hardware interrupts.
+
+   The stack will be 16byte aligned on entry with:
+						  PPC	PPC64
+   SP-> +---------------------------------------+
+	| back chain to caller			| 0	  0
+	+---------------------------------------+
+	| slot to save CR			| 4       8
+	+---------------------------------------+
+	| slot to save LR			| 8       16
+	+---------------------------------------+
+	| etc.. etc.. as per C calling conv.    |  */
+
+# if __PPC64__
+#  define LD ld
+#  define ST std
+#  define STU stdu
+#  define SZ 8
+#  define MACHINE ppc64
+#  define RED_ZONE 288
+# else
+#  define LD lwz
+#  define ST stw
+#  define STU stwu
+#  define SZ 4
+#  define MACHINE ppc7400
+#  define RED_ZONE 220
+# endif
+
+# define SAVE_VECTORS 0
+/**
+ * Performs a context switch.
+ *
+ * r3 - old context pointer
+ * r4 - new context pointer
+ *
+ */
+    .machine MACHINE
+    .text
+    .globl CSYM(fiber_switchContext)
+    .align 2
+CSYM(fiber_switchContext):
+LFB0:
+    /* Get the link reg. */
+    mflr  r0
+    /* Get the callee-saved crs (well all of them, actually). */
+    mfcr  r12
+
+    /* Save GPRs, we save the static chain here too although it is not clear if we need to.  */
+    ST    r31, ( -1 * SZ)(r1)
+    ST    r30, ( -2 * SZ)(r1)
+    ST    r29, ( -3 * SZ)(r1)
+    ST    r28, ( -4 * SZ)(r1)
+    ST    r27, ( -5 * SZ)(r1)
+    ST    r26, ( -6 * SZ)(r1)
+    ST    r25, ( -7 * SZ)(r1)
+    ST    r24, ( -8 * SZ)(r1)
+    ST    r23, ( -9 * SZ)(r1)
+    ST    r22, (-10 * SZ)(r1)
+    ST    r21, (-11 * SZ)(r1)
+    ST    r20, (-12 * SZ)(r1)
+    ST    r19, (-13 * SZ)(r1)
+    ST    r18, (-14 * SZ)(r1)
+    ST    r17, (-15 * SZ)(r1)
+    ST    r16, (-16 * SZ)(r1)
+    ST    r15, (-17 * SZ)(r1)
+    ST    r14, (-18 * SZ)(r1)
+    ST    r13, (-19 * SZ)(r1)
+
+    /* Save the lr and cr into the normal function linkage area.  */
+    ST    r0, 2*SZ(r1)
+    ST    r12, SZ(r1)
+
+    /* We update the stack pointer here, since we do not want the GC to
+       scan the floating point registers. We are still 16-byte aligned. */
+    STU   r11, (-20 * SZ)(r1)
+
+    /* Update the stack pointer in the old context as per comment above. */
+    ST    r1, 0(r3)
+
+    /* Save FPRs - same for PPC and PPC64 */
+    stfd  f14, (-18 * 8)(r1)
+    stfd  f15, (-17 * 8)(r1)
+    stfd  f16, (-16 * 8)(r1)
+    stfd  f17, (-15 * 8)(r1)
+    stfd  f18, (-14 * 8)(r1)
+    stfd  f19, (-13 * 8)(r1)
+    stfd  f20, (-12 * 8)(r1)
+    stfd  f21, (-11 * 8)(r1)
+    stfd  f22, (-10 * 8)(r1)
+    stfd  f23, ( -9 * 8)(r1)
+    stfd  f24, ( -8 * 8)(r1)
+    stfd  f25, ( -7 * 8)(r1)
+    stfd  f26, ( -6 * 8)(r1)
+    stfd  f27, ( -5 * 8)(r1)
+    stfd  f28, ( -4 * 8)(r1)
+    stfd  f29, ( -3 * 8)(r1)
+    stfd  f30, ( -2 * 8)(r1)
+    stfd  f31, ( -1 * 8)(r1)
+
+#if SAVE_VECTORS
+    /* We are still 16byte aligned - so we are ok for vector saves.
+       but the combined size of the vectors (12 x 16) + the FPRs (144) exceeds the
+       red zone size so we need to adjust the stack again - note this means careful
+       ordering is needed on the restore.  */
+
+    addi  r1, r1, -(12*16+18*8)
+    li    r11, 0
+    stvx  v20,r11,r1
+    addi  r11, r11, 16
+    stvx  v21,r11,r1
+    addi  r11, r11, 16
+    stvx  v22,r11,r1
+    addi  r11, r11, 16
+    stvx  v23,r11,r1
+    addi  r11, r11, 16
+    stvx  v24,r11,r1
+    addi  r11, r11, 16
+    stvx  v25,r11,r1
+    addi  r11, r11, 16
+    stvx  v26,r11,r1
+    addi  r11, r11, 16
+    stvx  v27,r11,r1
+    addi  r11, r11, 16
+    stvx  v28,r11,r1
+    addi  r11, r11, 16
+    stvx  v29,r11,r1
+    addi  r11, r11, 16
+    stvx  v30,r11,r1
+    addi  r11, r11, 16
+    stvx  v31,r11,r1
+
+    /* Now do the same thing in reverse - starting with r4 pointing to
+       the block of GPRs - stage 1 point to the saved vectors and fprs. */
+
+    addi  r1, r4, -(12*16+18*8)
+    li    r11, 0
+    lvx   v20,r11,r1
+    addi  r11, r11, 16
+    lvx   v21,r11,r1
+    addi  r11, r11, 16
+    lvx   v22,r11,r1
+    addi  r11, r11, 16
+    lvx   v23,r11,r1
+    addi  r11, r11, 16
+    lvx   v24,r11,r1
+    addi  r11, r11, 16
+    lvx   v25,r11,r1
+    addi  r11, r11, 16
+    lvx   v26,r11,r1
+    addi  r11, r11, 16
+    lvx   v27,r11,r1
+    addi  r11, r11, 16
+    lvx   v28,r11,r1
+    addi  r11, r11, 16
+    lvx   v29,r11,r1
+    addi  r11, r11, 16
+    lvx   v30,r11,r1
+    addi  r11, r11, 16
+    lvx   v31,r11,r1
+#endif
+
+    /* Now it is safe to update the stack pointer since the combined
+       size of the GPRs and FPRs will not exceed the red zone.  */
+
+    addi  r1, r4, 20 * SZ
+
+    /* Restore FPRs */
+    lfd  f14, (-18 * 8)(r4)
+    lfd  f15, (-17 * 8)(r4)
+    lfd  f16, (-16 * 8)(r4)
+    lfd  f17, (-15 * 8)(r4)
+    lfd  f18, (-14 * 8)(r4)
+    lfd  f19, (-13 * 8)(r4)
+    lfd  f20, (-12 * 8)(r4)
+    lfd  f21, (-11 * 8)(r4)
+    lfd  f22, (-10 * 8)(r4)
+    lfd  f23, ( -9 * 8)(r4)
+    lfd  f24, ( -8 * 8)(r4)
+    lfd  f25, ( -7 * 8)(r4)
+    lfd  f26, ( -6 * 8)(r4)
+    lfd  f27, ( -5 * 8)(r4)
+    lfd  f28, ( -4 * 8)(r4)
+    lfd  f29, ( -3 * 8)(r4)
+    lfd  f30, ( -2 * 8)(r4)
+    lfd  f31, ( -1 * 8)(r4)
+
+    /* Pick up lr and cr */
+    LD    r0, 2*SZ(r1)
+    LD    r12, SZ(r1)
+
+    /* Restore GPRs */
+    LD     r11, (-20 * SZ)(r1)
+    LD     r13, (-19 * SZ)(r1)
+    LD     r14, (-18 * SZ)(r1)
+    LD     r15, (-17 * SZ)(r1)
+    LD     r16, (-16 * SZ)(r1)
+    LD     r17, (-15 * SZ)(r1)
+    LD     r18, (-14 * SZ)(r1)
+    LD     r19, (-13 * SZ)(r1)
+    LD     r20, (-12 * SZ)(r1)
+    LD     r21, (-11 * SZ)(r1)
+    LD     r22, (-10 * SZ)(r1)
+    LD     r23, ( -9 * SZ)(r1)
+    LD     r24, ( -8 * SZ)(r1)
+    LD     r25, ( -7 * SZ)(r1)
+    LD     r26, ( -6 * SZ)(r1)
+    LD     r27, ( -5 * SZ)(r1)
+    LD     r28, ( -4 * SZ)(r1)
+    LD     r29, ( -3 * SZ)(r1)
+    LD     r30, ( -2 * SZ)(r1)
+    LD     r31, ( -1 * SZ)(r1)
+
+    /* Set cr and lr */
+    mtcr  r12
+    mtlr  r0
+
+    /* Return and switch context */
+    blr
+LFE0:
+
+/* Minimal CFI / FDE which does not describe the stacking of the GPRs - but only that
+   the routine has been entered/exited.  */
+
+# if __PPC64__
+#  define DATA_ALIGN 0x78
+#  define ALIGN_SIZE 3
+#  define ADDRD .quad
+# else
+#  define DATA_ALIGN 0x7c
+#  define ALIGN_SIZE 3
+#  define ADDRD .long
+# endif
+
+	.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
+EH_frame1:
+	.set L$set$0,LECIE1-LSCIE1
+	.long L$set$0	; Length of Common Information Entry
+LSCIE1:
+	.long	0	; CIE Identifier Tag
+	.byte	0x3	; CIE Version
+	.ascii "zR\0"	; CIE Augmentation
+	.byte	0x1	; uleb128 0x1; CIE Code Alignment Factor
+	.byte	DATA_ALIGN	; sleb128 -4/-8; CIE Data Alignment Factor
+	.byte	0x41	; uleb128 0x41; CIE RA Column
+	.byte	0x1	; uleb128 0x1; Augmentation size
+	.byte	0x10	; FDE Encoding (pcrel)
+	.byte	0xc	; DW_CFA_def_cfa
+	.byte	0x1	; uleb128 0x1
+	.byte	0	; uleb128 0
+	.p2align ALIGN_SIZE,0
+LECIE1:
+LSFDE1:
+	.set L$set$1,LEFDE1-LASFDE1
+	.long L$set$1	; FDE Length
+LASFDE1:
+	.long	LASFDE1-EH_frame1	; FDE CIE offset
+	ADDRD	LFB0-.	; FDE initial location
+	.set L$set$2,LFE0-LFB0
+	ADDRD L$set$2	; FDE address range
+	.byte	0	; uleb128 0; Augmentation size
+	.p2align ALIGN_SIZE,0
+LEFDE1:
+
+#endif /* defined(__MACH__) */
diff --git a/libphobos/libdruntime/config/x86/switchcontext.S b/libphobos/libdruntime/config/x86/switchcontext.S
index 82420c6159c..9f4befdb49c 100644
--- a/libphobos/libdruntime/config/x86/switchcontext.S
+++ b/libphobos/libdruntime/config/x86/switchcontext.S
@@ -29,7 +29,11 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 # include <cet.h>
 #endif
 
-#if defined(__i386__) && !defined(__CET__)
+#if !defined(__CET__)
+
+# if defined(__ELF__)
+
+#  if defined(__i386__)
 
     .text
     .globl CSYM(fiber_switchContext)
@@ -63,7 +67,9 @@  CSYM(fiber_switchContext):
     .cfi_endproc
     .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
 
-#elif defined(__x86_64__) && !defined(__ILP32__) && !defined(__CET__)
+#  endif /* defined(__ELF__) && defined(__i386__) */
+
+#  if defined(__x86_64__) && !defined(__ILP32__)
 
     .text
     .globl CSYM(fiber_switchContext)
@@ -98,4 +104,151 @@  CSYM(fiber_switchContext):
     .cfi_endproc
    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
 
-#endif
+#  endif /* defined(__ELF__) && defined(__x86_64__) && !defined(__ILP32__) */
+
+# endif /* defined(__ELF__) */
+
+# if defined(__MACH__)
+
+#  if defined(__i386__)
+
+    .text
+    .globl CSYM(fiber_switchContext)
+    .p2align 4
+CSYM(fiber_switchContext):
+LFB0:
+    // save current stack state
+    push %ebp
+    mov  %esp, %ebp
+    push %edi
+    push %esi
+    push %ebx
+    push %eax
+
+    // store oldp again with more accurate address
+    mov 8(%ebp), %eax
+    mov %esp, (%eax)
+    // load newp to begin context switch
+    mov 12(%ebp), %esp
+
+    // load saved state from new stack
+    pop %eax
+    pop %ebx
+    pop %esi
+    pop %edi
+    pop %ebp
+
+    // 'return' to complete switch
+    ret
+LFE0:
+
+/* CFI */
+        .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
+EH_frame1:
+        .set L$set$0,LECIE1-LSCIE1
+        .long L$set$0   # Length of Common Information Entry
+LSCIE1:
+        .long   0       # CIE Identifier Tag
+        .byte   0x1     # CIE Version
+        .ascii "zR\0"   # CIE Augmentation
+        .byte   0x1     # uleb128 0x1; CIE Code Alignment Factor
+        .byte   0x7c    # sleb128 -4; CIE Data Alignment Factor
+        .byte   0x8     # CIE RA Column
+        .byte   0x1     # uleb128 0x1; Augmentation size
+        .byte   0x10    # FDE Encoding (pcrel)
+        .byte   0xc     # DW_CFA_def_cfa
+        .byte   0x5     # uleb128 0x5
+        .byte   0x4     # uleb128 0x4
+        .byte   0x88    # DW_CFA_offset, column 0x8
+        .byte   0x1     # uleb128 0x1
+        .p2align 2,0
+LECIE1:
+
+/* minimal FDE - does not record the stack frame changes. */
+LSFDE1:
+        .set L$set$1,LEFDE1-LASFDE1
+        .long L$set$1   # FDE Length
+LASFDE1:
+        .long   LASFDE1-EH_frame1       # FDE CIE offset
+        .long   LFB0-.  # FDE initial location
+        .set L$set$2,LFE0-LFB0
+        .long L$set$2   # FDE address range
+        .byte   0       # uleb128 0; Augmentation size
+        .p2align 2,0
+LEFDE1:
+
+#  endif /* defined(__MACH__) && defined(__i386__) */
+
+#  if defined(__x86_64__) && !defined(__ILP32__)
+
+    .text
+    .globl CSYM(fiber_switchContext)
+    .p2align 4
+CSYM(fiber_switchContext):
+LFB0:
+    // Save current stack state.save current stack state
+    push %rbp
+    mov  %rsp, %rbp
+    push %r15
+    push %r14
+    push %r13
+    push %r12
+    push %rbx
+
+    // store oldp again with more accurate address
+    mov %rsp, (%rdi)
+    // load newp to begin context switch
+    mov %rsi, %rsp
+
+    // load saved state from new stack
+    pop %rbx
+    pop %r12
+    pop %r13
+    pop %r14
+    pop %r15
+    pop %rbp
+
+    // 'return' to complete switch
+    ret
+LFE0:
+
+/* CFI */
+        .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
+EH_frame1:
+        .set L$set$0,LECIE1-LSCIE1
+        .long L$set$0   # Length of Common Information Entry
+LSCIE1:
+        .long   0       # CIE Identifier Tag
+        .byte   0x1     # CIE Version
+        .ascii "zR\0"   # CIE Augmentation
+        .byte   0x1     # uleb128 0x1; CIE Code Alignment Factor
+        .byte   0x78    # sleb128 -8; CIE Data Alignment Factor
+        .byte   0x10    # CIE RA Column
+        .byte   0x1     # uleb128 0x1; Augmentation size
+        .byte   0x10    # FDE Encoding (pcrel)
+        .byte   0xc     # DW_CFA_def_cfa
+        .byte   0x7     # uleb128 0x7
+        .byte   0x8     # uleb128 0x8
+        .byte   0x90    # DW_CFA_offset, column 0x10
+        .byte   0x1     # uleb128 0x1
+        .p2align 3,0
+LECIE1:
+
+/* minimal FDE - does not record the stack frame changes. */
+LSFDE1:
+        .set L$set$1,LEFDE1-LASFDE1
+        .long L$set$1   # FDE Length
+LASFDE1:
+        .long   LASFDE1-EH_frame1       # FDE CIE offset
+        .quad   LFB0-.  # FDE initial location
+        .set L$set$2,LFE0-LFB0
+        .quad L$set$2   # FDE address range
+        .byte   0       # uleb128 0; Augmentation size
+        .p2align 3,0
+LEFDE1:
+
+#  endif /* defined(__MACH__) && defined(__x86_64__) && !defined(__ILP32__) */
+
+# endif /* defined (__MACH__) */
+
+#endif /* !defined(__CET__) */
diff --git a/libphobos/libdruntime/core/sys/darwin/config.d b/libphobos/libdruntime/core/sys/darwin/config.d
new file mode 100644
index 00000000000..87f3fd4dae6
--- /dev/null
+++ b/libphobos/libdruntime/core/sys/darwin/config.d
@@ -0,0 +1,53 @@ 
+/**
+ * D header file for Darwin.
+ *
+ * Copyright: Copyright (c) 2021 D Language Foundation
+ * Authors: Iain Buclaw
+ */
+module core.sys.darwin.config;
+
+version (OSX)
+    version = Darwin;
+else version (iOS)
+    version = Darwin;
+else version (TVOS)
+    version = Darwin;
+else version (WatchOS)
+    version = Darwin;
+
+version (Darwin):
+
+public import core.sys.posix.config;
+
+enum __MAC_10_0    = 100000;
+enum __MAC_10_1    = 100100;
+enum __MAC_10_2    = 100200;
+enum __MAC_10_3    = 100300;
+enum __MAC_10_4    = 100400;
+enum __MAC_10_5    = 100500;
+enum __MAC_10_6    = 100600;
+enum __MAC_10_7    = 100700;
+enum __MAC_10_8    = 100800;
+enum __MAC_10_9    = 100900;
+enum __MAC_10_10   = 101000;
+enum __MAC_10_10_2 = 101002;
+enum __MAC_10_10_3 = 101003;
+enum __MAC_10_11   = 101100;
+enum __MAC_10_11_2 = 101102;
+enum __MAC_10_11_3 = 101103;
+enum __MAC_10_11_4 = 101104;
+enum __MAC_10_12   = 101200;
+enum __MAC_10_12_1 = 101201;
+enum __MAC_10_12_2 = 101202;
+enum __MAC_10_12_4 = 101204;
+enum __MAC_10_13   = 101300;
+enum __MAC_10_13_1 = 101301;
+enum __MAC_10_13_2 = 101302;
+enum __MAC_10_13_4 = 101304;
+enum __MAC_10_14   = 101400;
+enum __MAC_10_14_1 = 101401;
+enum __MAC_10_14_4 = 101404;
+enum __MAC_10_15   = 101500;
+enum __MAC_10_15_1 = 101501;
+enum __MAC_10_16   = 101501;
+enum __MAC_11_0    = 110000;
diff --git a/libphobos/libdruntime/core/thread/fiber.d b/libphobos/libdruntime/core/thread/fiber.d
index 3270f2e7094..67d9937e31a 100644
--- a/libphobos/libdruntime/core/thread/fiber.d
+++ b/libphobos/libdruntime/core/thread/fiber.d
@@ -883,6 +883,7 @@  class Fiber
      */
     static Fiber getThis() @safe nothrow @nogc
     {
+        version (GNU) pragma(inline, false);
         return sm_this;
     }
 
@@ -1731,6 +1732,11 @@  unittest
 // Multiple threads running shared fibers
 version (PPC)   version = UnsafeFiberMigration;
 version (PPC64) version = UnsafeFiberMigration;
+version (OSX)
+{
+    version (X86)    version = UnsafeFiberMigration;
+    version (X86_64) version = UnsafeFiberMigration;
+}
 
 version (UnsafeFiberMigration)
 {
diff --git a/libphobos/libdruntime/core/thread/osthread.d b/libphobos/libdruntime/core/thread/osthread.d
index 880836e3a25..0fffc7ed3f7 100644
--- a/libphobos/libdruntime/core/thread/osthread.d
+++ b/libphobos/libdruntime/core/thread/osthread.d
@@ -1396,8 +1396,98 @@  in (fn)
     void *sp = void;
     version (GNU)
     {
-        __builtin_unwind_init();
-        sp = &sp;
+        // The generic solution below using a call to __builtin_unwind_init ()
+        // followed by an assignment to sp has two issues:
+        // 1) On some archs it stores a huge amount of FP and Vector state which
+        //    is not the subject of the scan - and, indeed might produce false
+        //    hits.
+        // 2) Even on archs like X86, where there are no callee-saved FPRs/VRs there
+        //    tend to be 'holes' in the frame allocations (to deal with alignment) which
+        //    also will  contain random data which could produce false positives.
+        // This solution stores only the integer callee-saved registers.
+        version (X86)
+        {
+            void*[3] regs = void;
+            asm pure nothrow @nogc
+            {
+                "movl   %%ebx, %0" : "=m" (regs[0]);
+                "movl   %%esi, %0" : "=m" (regs[1]);
+                "movl   %%edi, %0" : "=m" (regs[2]);
+            }
+            sp = cast(void*)&regs[0];
+        }
+        else version (X86_64)
+        {
+            void*[5] regs = void;
+            asm pure nothrow @nogc
+            {
+                "movq   %%rbx, %0" : "=m" (regs[0]);
+                "movq   %%r12, %0" : "=m" (regs[1]);
+                "movq   %%r13, %0" : "=m" (regs[2]);
+                "movq   %%r14, %0" : "=m" (regs[3]);
+                "movq   %%r15, %0" : "=m" (regs[4]);
+            }
+            sp = cast(void*)&regs[0];
+        }
+        else version (PPC)
+        {
+            void*[19] regs = void;
+            asm pure nothrow @nogc
+            {
+                "stw r13, %0" : "=m" (regs[ 0]);
+                "stw r14, %0" : "=m" (regs[ 1]);
+                "stw r15, %0" : "=m" (regs[ 2]);
+                "stw r16, %0" : "=m" (regs[ 3]);
+                "stw r17, %0" : "=m" (regs[ 4]);
+                "stw r18, %0" : "=m" (regs[ 5]);
+                "stw r19, %0" : "=m" (regs[ 6]);
+                "stw r20, %0" : "=m" (regs[ 7]);
+                "stw r21, %0" : "=m" (regs[ 9]);
+                "stw r22, %0" : "=m" (regs[ 9]);
+                "stw r23, %0" : "=m" (regs[10]);
+                "stw r24, %0" : "=m" (regs[11]);
+                "stw r25, %0" : "=m" (regs[12]);
+                "stw r26, %0" : "=m" (regs[13]);
+                "stw r27, %0" : "=m" (regs[14]);
+                "stw r28, %0" : "=m" (regs[15]);
+                "stw r29, %0" : "=m" (regs[16]);
+                "stw r30, %0" : "=m" (regs[17]);
+                "stw r31, %0" : "=m" (regs[18]);
+            }
+            sp = cast(void*)&regs[0];
+        }
+        else version (PPC64)
+        {
+            void*[19] regs = void;
+            asm pure nothrow @nogc
+            {
+                "std r13, %0" : "=m" (regs[ 0]);
+                "std r14, %0" : "=m" (regs[ 1]);
+                "std r15, %0" : "=m" (regs[ 2]);
+                "std r16, %0" : "=m" (regs[ 3]);
+                "std r17, %0" : "=m" (regs[ 4]);
+                "std r18, %0" : "=m" (regs[ 5]);
+                "std r19, %0" : "=m" (regs[ 6]);
+                "std r20, %0" : "=m" (regs[ 7]);
+                "std r21, %0" : "=m" (regs[ 8]);
+                "std r22, %0" : "=m" (regs[ 9]);
+                "std r23, %0" : "=m" (regs[10]);
+                "std r24, %0" : "=m" (regs[11]);
+                "std r25, %0" : "=m" (regs[12]);
+                "std r26, %0" : "=m" (regs[13]);
+                "std r27, %0" : "=m" (regs[14]);
+                "std r28, %0" : "=m" (regs[15]);
+                "std r29, %0" : "=m" (regs[16]);
+                "std r30, %0" : "=m" (regs[17]);
+                "std r31, %0" : "=m" (regs[18]);
+            }
+            sp = cast(void*)&regs[0];
+        }
+        else
+        {
+            __builtin_unwind_init();
+            sp = &sp;
+        }
     }
     else version (AsmX86_Posix)
     {
diff --git a/libphobos/libdruntime/core/thread/threadbase.d b/libphobos/libdruntime/core/thread/threadbase.d
index c2c2333efe9..50795e444be 100644
--- a/libphobos/libdruntime/core/thread/threadbase.d
+++ b/libphobos/libdruntime/core/thread/threadbase.d
@@ -313,6 +313,7 @@  class ThreadBase
         // NOTE: This function may not be called until thread_init has
         //       completed.  See thread_suspendAll for more information
         //       on why this might occur.
+        version (GNU) pragma(inline, false);
         return sm_this;
     }
 
diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d
index 5ce4869d096..712f5d7bc9d 100644
--- a/libphobos/libdruntime/gcc/deh.d
+++ b/libphobos/libdruntime/gcc/deh.d
@@ -34,11 +34,6 @@  extern(C)
 {
     int _d_isbaseof(ClassInfo, ClassInfo);
     void _d_createTrace(Object, void*);
-
-    // Not used in GDC but declaration required by rt/sections.d
-    struct FuncTable
-    {
-    }
 }
 
 /**
diff --git a/libphobos/m4/druntime/os.m4 b/libphobos/m4/druntime/os.m4
index ed93e30f1e9..351558dbcda 100644
--- a/libphobos/m4/druntime/os.m4
+++ b/libphobos/m4/druntime/os.m4
@@ -149,17 +149,31 @@  AC_DEFUN([DRUNTIME_OS_ARM_EABI_UNWINDER],
 # substitute DCFG_MINFO_BRACKETING.
 AC_DEFUN([DRUNTIME_OS_MINFO_BRACKETING],
 [
+  AC_REQUIRE([DRUNTIME_OS_DETECT])
+
   AC_LANG_PUSH([C])
   AC_MSG_CHECKING([for minfo section bracketing])
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   AC_LINK_IFELSE([AC_LANG_SOURCE([
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
   ])],
     [AC_MSG_RESULT([yes])
diff --git a/libphobos/testsuite/libphobos.thread/fiber_guard_page.d b/libphobos/testsuite/libphobos.thread/fiber_guard_page.d
index 9f754e155d2..ca54a19857f 100644
--- a/libphobos/testsuite/libphobos.thread/fiber_guard_page.d
+++ b/libphobos/testsuite/libphobos.thread/fiber_guard_page.d
@@ -1,13 +1,15 @@ 
 // { dg-options "-O0" }
 // { dg-shouldfail "segv or bus error" }
 import core.thread;
+import core.sys.posix.signal;
 import core.sys.posix.sys.mman;
 
 // this should be true for most architectures
 // (taken from core.thread)
-version = StackGrowsDown;
+version (GNU_StackGrowsDown)
+    version = StackGrowsDown;
 
-enum stackSize = 4096;
+enum stackSize = MINSIGSTKSZ;
 
 // Simple method that causes a stack overflow
 void stackMethod()