From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1873) id 0F20A3851C1B; Mon, 19 Apr 2021 17:29:01 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 0F20A3851C1B MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Iain Buclaw To: gcc-cvs@gcc.gnu.org Subject: [gcc r11-8248] libphobos: Add Thread/Fiber support code for Darwin (PR98058) X-Act-Checkin: gcc X-Git-Author: Iain Buclaw X-Git-Refname: refs/heads/master X-Git-Oldrev: b66e72b43e1e8f402dc958ce3cca35f7c273340d X-Git-Newrev: 6eae7549b8a350b92435be904efed195bd190bae Message-Id: <20210419172901.0F20A3851C1B@sourceware.org> Date: Mon, 19 Apr 2021 17:29:01 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Apr 2021 17:29:01 -0000 https://gcc.gnu.org/g:6eae7549b8a350b92435be904efed195bd190bae commit r11-8248-g6eae7549b8a350b92435be904efed195bd190bae Author: Iain Buclaw Date: Mon Apr 19 14:48:32 2021 +0200 libphobos: Add Thread/Fiber support code for Darwin (PR98058) 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. Diff: --- libphobos/configure | 22 +- libphobos/libdruntime/Makefile.am | 26 +- libphobos/libdruntime/Makefile.in | 37 +-- .../libdruntime/config/powerpc/switchcontext.S | 278 ++++++++++++++++++++- libphobos/libdruntime/config/x86/switchcontext.S | 159 +++++++++++- libphobos/libdruntime/core/sys/darwin/config.d | 53 ++++ libphobos/libdruntime/core/thread/fiber.d | 6 + libphobos/libdruntime/core/thread/osthread.d | 94 ++++++- libphobos/libdruntime/core/thread/threadbase.d | 1 + libphobos/libdruntime/gcc/deh.d | 5 - libphobos/m4/druntime/os.m4 | 22 +- .../testsuite/libphobos.thread/fiber_guard_page.d | 6 +- 12 files changed, 656 insertions(+), 53 deletions(-) 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 #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*)®s[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*)®s[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*)®s[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*)®s[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()