Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC Commits: 5ae43275 by Peng Fan at 2026-04-01T19:01:06-04:00 NCG/LA64: add cmpxchg and xchg primops And append some new instructions for LA664 uarch. Apply fix to cmpxchg-prim by Andreas Klebinger. Suggestions in https://gitlab.haskell.org/ghc/ghc/-/merge_requests/15515 - - - - - 8f95534a by Duncan Coutts at 2026-04-01T19:01:52-04:00 Remove signal-based ticker implementations Fixes issue #27073 All supported platforms should work with the pthreads + nanosleep based ticker implementation. This avoids all the problems with using signals. In practice, all supported platforms were probably using the non-signal tickers already, which is probably why we do not get lots of reports about deadlocks and other weirdness: we were definately using functions that are not async signal safe in the tick handler (such as fflush to flussh the eventlog). Only Solaris was explicitly using the timer_create ticker impl, and even Solaris could probably use the pthreads one (if anyone cared: Solaris is no longer a Teir 3 supported platform). Plausibly the only supported platform that this will change will be AIX, which should now use the pthreads impl. - - - - - 51b32b0d by Duncan Coutts at 2026-04-01T19:01:52-04:00 Tidy up some timer/ticker comments elsewhere - - - - - 7562bcd7 by Duncan Coutts at 2026-04-01T19:01:52-04:00 Remove now-unused install_vtalrm_handler Support function used by both of the signal-based ticker implementations. - - - - - 6da127c7 by Duncan Coutts at 2026-04-01T19:01:52-04:00 No longer probe for timer_create in rts/configure It was only used by the TimerCreate.c ticker impl. - - - - - 3fd490fa by Duncan Coutts at 2026-04-01T19:01:53-04:00 Note that rtsTimerSignal is deprecated. - - - - - 63099b0f by Simon Jakobi at 2026-04-01T19:02:39-04:00 Add perf test for #13960 Closes #13960. - - - - - f3082d66 by mangoiv at 2026-04-02T04:50:33-04:00 testsuite: filter stderr for static001 on darwin This reactivates the test on x86_64 darwin as this should have been done long ago and ignores warnings emitted by ranlib on newer version of the darwin toolchain since they are benign. (no symbols for stub libraries) Fixes #27116 - - - - - 9f075c7c by mangoiv at 2026-04-02T04:50:34-04:00 issue template: fix add bug label - - - - - 18 changed files: - .gitlab/issue_templates/default.md - compiler/GHC/CmmToAsm/LA64/CodeGen.hs - compiler/GHC/CmmToAsm/LA64/Instr.hs - compiler/GHC/CmmToAsm/LA64/Ppr.hs - − m4/fp_check_timer_create.m4 - rts/Timer.c - rts/configure.ac - rts/include/rts/Timer.h - rts/include/stg/SMP.h - rts/posix/Signals.c - rts/posix/Signals.h - rts/posix/Ticker.c - − rts/posix/ticker/Setitimer.c - − rts/posix/ticker/TimerCreate.c - testsuite/driver/testlib.py - testsuite/tests/driver/all.T - + testsuite/tests/perf/compiler/T13960.hs - testsuite/tests/perf/compiler/all.T Changes: ===================================== .gitlab/issue_templates/default.md ===================================== @@ -20,5 +20,5 @@ Optional: * System Architecture: -/label ~bug +/label ~"T::bug" /label ~"needs triage" ===================================== compiler/GHC/CmmToAsm/LA64/CodeGen.hs ===================================== @@ -57,6 +57,12 @@ import Control.Monad import GHC.Cmm.Dataflow.Label import GHC.Types.Unique.DSM import GHC.Types.Literal.Floating +import GHC.Unit.Types ( ghcInternalUnitId ) + +la664Enabled :: NatM Bool +la664Enabled = do + config <- getConfig + return (ncgLa664Enabled config) -- [General layout of an NCG] cmmTopCodeGen :: @@ -1651,6 +1657,10 @@ genPrim (MO_Prefetch_Data _n) [] [_] = return nilOL genPrim (MO_AtomicRead w mo) [dst] [addr] = genAtomicRead w mo dst addr genPrim (MO_AtomicWrite w mo) [] [addr,val] = genAtomicWrite w mo addr val +genPrim (MO_AtomicRMW width amop) [dst] [addr,n] = genLibCCall (atomicRMWLabel width amop) [dst] [addr,n] +genPrim (MO_Cmpxchg width) [dst] [addr,expe,new] = genCmpxchg width dst addr expe new +genPrim (MO_Xchg width) [dst] [addr,value] = genXchg width dst addr value + genPrim mop@(MO_S_Mul2 _w) _ _ = unsupported mop genPrim mop@(MO_S_QuotRem _w) _ _ = unsupported mop genPrim mop@(MO_U_QuotRem _w) _ _ = unsupported mop @@ -1674,9 +1684,6 @@ genPrim (MO_PopCnt width) [dst] [src] = genLibCCall (popCntLabel w genPrim (MO_Pdep width) [dst] [src,mask] = genLibCCall (pdepLabel width) [dst] [src,mask] genPrim (MO_Pext width) [dst] [src,mask] = genLibCCall (pextLabel width) [dst] [src,mask] genPrim (MO_UF_Conv width) [dst] [src] = genLibCCall (word2FloatLabel width) [dst] [src] -genPrim (MO_AtomicRMW width amop) [dst] [addr,n] = genLibCCall (atomicRMWLabel width amop) [dst] [addr,n] -genPrim (MO_Cmpxchg width) [dst] [addr,old,new] = genLibCCall (cmpxchgLabel width) [dst] [addr,old,new] -genPrim (MO_Xchg width) [dst] [addr,val] = genLibCCall (xchgLabel width) [dst] [addr,val] genPrim (MO_Memcpy _align) [] [dst,src,n] = genLibCCall (fsLit "memcpy") [] [dst,src,n] genPrim (MO_Memmove _align) [] [dst,src,n] = genLibCCall (fsLit "memmove") [] [dst,src,n] genPrim (MO_Memcmp _align) [rst] [dst,src,n] = genLibCCall (fsLit "memcmp") [rst] [dst,src,n] @@ -1872,6 +1879,20 @@ genBitRev w dst src = do ) _ -> return ( code_x `snocOL` BITREV (OpReg w dst_reg) (OpReg w reg_x)) +genPrimCCall + :: FastString + -> [CmmFormal] + -> [CmmActual] + -> NatM InstrBlock + +genPrimCCall name dsts args = do + config <- getConfig + target <- + cmmMakeDynamicReference config CallReference + $ mkCmmCodeLabel ghcInternalUnitId name + let cconv = ForeignConvention CCallConv [NoHint] [NoHint] CmmMayReturn + genCCall target cconv dsts args + -- Generate C call to the given function in libc genLibCCall :: FastString -> [CmmFormal] -> [CmmActual] -> NatM InstrBlock genLibCCall name dsts args = do @@ -1945,6 +1966,52 @@ genAtomicWrite w mo addr val = do ) _ -> panic $ "Unexpected MemOrderAcquire on an AtomicWrite" ++ show mo +genCmpxchg :: Width -> LocalReg -> CmmExpr -> CmmExpr -> CmmExpr -> NatM InstrBlock +genCmpxchg w dst addr expe new = do + config <- getConfig + let + platform = ncgPlatform config + format = intFormat w + + la664Enabled >>= \case + + True -> do + (addr_reg, _, code_addr) <- getSomeReg addr + (expe_reg, _, code_expe) <- getSomeReg expe + (new_reg, _, code_new) <- getSomeReg new + let dst_reg = getRegisterReg platform (CmmLocal dst) + return $ code_addr `appOL` code_expe `appOL` code_new `appOL` toOL + [ + -- Behave like the GCC builtin CAS operation + AMCASDB format (OpReg w expe_reg) (OpReg w new_reg) (OpReg w addr_reg), + MOV (OpReg w dst_reg) (OpReg w expe_reg) + ] + + False -> + genPrimCCall (cmpxchgLabel w) [dst] [addr,expe,new] + +genXchg :: Width -> LocalReg -> CmmExpr -> CmmExpr -> NatM InstrBlock +genXchg w dst addr val = do + config <- getConfig + tmp <- getNewRegNat II64 + let + platform = ncgPlatform config + format = intFormat w + + la664Enabled >>= \case + + True -> do + (addr_reg, _, code_addr) <- getSomeReg addr + (val_reg, _, code_val) <- getSomeReg val + let dst_reg = getRegisterReg platform (CmmLocal dst) + return $ code_addr `appOL` code_val `appOL` toOL + [ + AMSWAPDB format (OpReg w tmp) (OpReg w val_reg) (OpReg w addr_reg), + MOV (OpReg W64 dst_reg) (OpReg W64 tmp) + ] + False -> + genPrimCCall (xchgLabel w) [dst] [addr,val] + -- ----------------------------------------------------------------------------- {- Generating C calls @@ -1977,6 +2044,7 @@ member of a structure or union argument, or a vector/floating-point argument wider than FRLEN may be passed in a GAR. -} +-- Generate C call to the given function in ghc-prim genCCall :: CmmExpr -- address of func call -> ForeignConvention -- calling convention ===================================== compiler/GHC/CmmToAsm/LA64/Instr.hs ===================================== @@ -150,10 +150,11 @@ regUsageOfInstr platform instr = case instr of -- ranges, corresponding to 2 and 1 instruction implementations respectively. -- -- BCOND1 is selected by default. - BCOND1 _ j d t -> usage (regTarget t ++ regOp j ++ regOp d, []) - BCOND _ j d t -> usage (regTarget t ++ regOp j ++ regOp d, []) - BEQZ j t -> usage (regTarget t ++ regOp j, []) - BNEZ j t -> usage (regTarget t ++ regOp j, []) + BCOND1 _ j d t -> usage (regTarget t ++ regOp j ++ regOp d, []) + BCOND _ j d t -> usage (regTarget t ++ regOp j ++ regOp d, []) + BEQZ1 o1 o2 -> usage (regOp o1 ++ regOp o2, []) + BEQZ j t -> usage (regTarget t ++ regOp j, []) + BNEZ j t -> usage (regTarget t ++ regOp j, []) -- 5. Common Memory Access Instructions -------------------------------------- LD _ dst src -> usage (regOp src, regOp dst) LDU _ dst src -> usage (regOp src, regOp dst) @@ -168,7 +169,17 @@ regUsageOfInstr platform instr = case instr of -- LDCOND dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst) -- STCOND dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst) -- 7. Atomic Memory Access Instructions -------------------------------------- + -- In LoongArch, if the AM* atomic memory access instruction has the same register number as rd and rj, + -- the execution will trigger an Instruction Non-defined Exception. Here should be avoided. AMSWAPDB _ dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst) + AMADDDB _ dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst) + AMANDDB _ dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst) + AMORDB _ dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst) + AMXORDB _ dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst) + --AMCASDB _ dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp src1 ++ regOp src2 ++ regOp dst) + AMCASDB _ dst src1 src2 -> usage (regOp dst ++ regOp src1 ++ regOp src2, regOp dst) + LL _ dst src1 _ -> usage (regOp src1, regOp dst) + SC _ dst src1 _ -> usage (regOp src1, regOp dst) -- 8. Barrier Instructions --------------------------------------------------- DBAR _hint -> usage ([], []) IBAR _hint -> usage ([], []) @@ -330,6 +341,7 @@ patchRegsOfInstr instr env = case instr of TAIL36 r t -> TAIL36 (patchOp r) (patchTarget t) BCOND1 c j d t -> BCOND1 c (patchOp j) (patchOp d) (patchTarget t) BCOND c j d t -> BCOND c (patchOp j) (patchOp d) (patchTarget t) + BEQZ1 o1 o2 -> BEQZ1 (patchOp o1) (patchOp o2) BEQZ j t -> BEQZ (patchOp j) (patchTarget t) BNEZ j t -> BNEZ (patchOp j) (patchTarget t) -- 5. Common Memory Access Instructions -------------------------------------- @@ -348,6 +360,13 @@ patchRegsOfInstr instr env = case instr of -- STCOND o1 o2 o3 -> STCOND (patchOp o1) (patchOp o2) (patchOp o3) -- 7. Atomic Memory Access Instructions -------------------------------------- AMSWAPDB f o1 o2 o3 -> AMSWAPDB f (patchOp o1) (patchOp o2) (patchOp o3) + AMADDDB f o1 o2 o3 -> AMADDDB f (patchOp o1) (patchOp o2) (patchOp o3) + AMANDDB f o1 o2 o3 -> AMANDDB f (patchOp o1) (patchOp o2) (patchOp o3) + AMORDB f o1 o2 o3 -> AMORDB f (patchOp o1) (patchOp o2) (patchOp o3) + AMXORDB f o1 o2 o3 -> AMXORDB f (patchOp o1) (patchOp o2) (patchOp o3) + AMCASDB f o1 o2 o3 -> AMCASDB f (patchOp o1) (patchOp o2) (patchOp o3) + LL f o1 o2 o3 -> LL f (patchOp o1) (patchOp o2) (patchOp o3) + SC f o1 o2 o3 -> SC f (patchOp o1) (patchOp o2) (patchOp o3) -- 8. Barrier Instructions --------------------------------------------------- DBAR o1 -> DBAR o1 IBAR o1 -> IBAR o1 @@ -398,6 +417,7 @@ isJumpishInstr instr = case instr of TAIL36 {} -> True BCOND1 {} -> True BCOND {} -> True + BEQZ1 {} -> True BEQZ {} -> True BNEZ {} -> True _ -> False @@ -718,6 +738,7 @@ data Instr | TAIL36 Operand Target | BCOND1 Cond Operand Operand Target | BCOND Cond Operand Operand Target + | BEQZ1 Operand Operand | BEQZ Operand Target | BNEZ Operand Target -- 5. Common Memory Access Instructions -------------------------------------- @@ -733,6 +754,13 @@ data Instr -- 6. Bound Check Memory Access Instructions --------------------------------- -- 7. Atomic Memory Access Instructions -------------------------------------- | AMSWAPDB Format Operand Operand Operand + | AMADDDB Format Operand Operand Operand + | AMANDDB Format Operand Operand Operand + | AMORDB Format Operand Operand Operand + | AMXORDB Format Operand Operand Operand + | AMCASDB Format Operand Operand Operand + | LL Format Operand Operand Operand + | SC Format Operand Operand Operand -- 8. Barrier Instructions --------------------------------------------------- | DBAR BarrierType | IBAR BarrierType @@ -839,6 +867,7 @@ instrCon i = TAIL36{} -> "TAIL36" BCOND1{} -> "BCOND1" BCOND{} -> "BCOND" + BEQZ1{} -> "BEQZ1" BEQZ{} -> "BEQZ" BNEZ{} -> "BNEZ" LD{} -> "LD" @@ -851,6 +880,13 @@ instrCon i = STPTR{} -> "STPTR" PRELD{} -> "PRELD" AMSWAPDB{} -> "AMSWAPDB" + AMADDDB{} -> "AMADDDB" + AMANDDB{} -> "AMANDDB" + AMORDB{} -> "AMORDB" + AMXORDB{} -> "AMXORDB" + AMCASDB{} -> "AMCASDB" + LL{} -> "LL" + SC{} -> "SC" DBAR{} -> "DBAR" IBAR{} -> "IBAR" FCVT{} -> "FCVT" ===================================== compiler/GHC/CmmToAsm/LA64/Ppr.hs ===================================== @@ -852,6 +852,7 @@ pprInstr platform instr = case instr of line $ text "\tbgeu" <+> pprOp platform d <> comma <+> pprOp platform j <> comma <+> pprAsmLabel platform (mkLocalBlockLabel (getUnique bid)) UGT -> line $ text "\tbltu" <+> pprOp platform d <> comma <+> pprOp platform j <> comma <+> pprAsmLabel platform (mkLocalBlockLabel (getUnique bid)) + _ -> line $ text "\t" <> pprBcond c <+> pprOp platform j <> comma <+> pprOp platform d <> comma <+> pprAsmLabel platform (mkLocalBlockLabel (getUnique bid)) BCOND1 _ _ _ (TLabel _) -> panic "LA64.ppr: BCOND1: No conditional branching to TLabel!" @@ -916,17 +917,18 @@ pprInstr platform instr = case instr of BCOND _ _ _ (TReg _) -> panic "LA64.ppr: BCOND: No conditional branching to registers!" + BEQZ1 o1 o2 | isImmOp o2 -> op2 (text "\tbeqz") o1 o2 BEQZ j (TBlock bid) -> line $ text "\tbeqz" <+> pprOp platform j <> comma <+> pprAsmLabel platform (mkLocalBlockLabel (getUnique bid)) BEQZ j (TLabel lbl) -> line $ text "\tbeqz" <+> pprOp platform j <> comma <+> pprAsmLabel platform lbl - BEQZ _ (TReg _) -> panic "LA64.ppr: BEQZ: No conditional branching to registers!" + BEQZ _ (TReg _) -> panic "LA64.ppr: BEQZ: No conditional branching to registers!" BNEZ j (TBlock bid) -> line $ text "\tbnez" <+> pprOp platform j <> comma <+> pprAsmLabel platform (mkLocalBlockLabel (getUnique bid)) BNEZ j (TLabel lbl) -> line $ text "\tbnez" <+> pprOp platform j <> comma <+> pprAsmLabel platform lbl - BNEZ _ (TReg _) -> panic "LA64.ppr: BNEZ: No conditional branching to registers!" + BNEZ _ (TReg _) -> panic "LA64.ppr: BNEZ: No conditional branching to registers!" -- 5. Common Memory Access Instructions -------------------------------------- -- LD.{B[U]/H[U]/W[U]/D}, ST.{B/H/W/D}: AddrRegImm @@ -1020,8 +1022,29 @@ pprInstr platform instr = case instr of AMSWAPDB II32 o1 o2 o3 -> op3 (text "\tamswap_db.w") o1 o2 o3 AMSWAPDB II64 o1 o2 o3 -> op3 (text "\tamswap_db.d") o1 o2 o3 -- AM.{SWAP/ADD}[_DB].{B/H} + AMADDDB II8 o1 o2 o3 -> op3 (text "\tamadd_db.b") o1 o2 o3 + AMADDDB II16 o1 o2 o3 -> op3 (text "\tamadd_db.h") o1 o2 o3 + AMADDDB II32 o1 o2 o3 -> op3 (text "\tamadd_db.w") o1 o2 o3 + AMADDDB II64 o1 o2 o3 -> op3 (text "\tamadd_db.d") o1 o2 o3 + + AMANDDB II32 o1 o2 o3 -> op3 (text "\tamand_db.w") o1 o2 o3 + AMANDDB II64 o1 o2 o3 -> op3 (text "\tamand_db.d") o1 o2 o3 + + AMORDB II32 o1 o2 o3 -> op3 (text "\tamor_db.w") o1 o2 o3 + AMORDB II64 o1 o2 o3 -> op3 (text "\tamor_db.d") o1 o2 o3 + + AMXORDB II32 o1 o2 o3 -> op3 (text "\tamxor_db.w") o1 o2 o3 + AMXORDB II64 o1 o2 o3 -> op3 (text "\tamxor_db.d") o1 o2 o3 -- AMCAS[_DB].{B/H/W/D} + AMCASDB II8 o1 o2 o3 -> op3 (text "\tamcas_db.b") o1 o2 o3 + AMCASDB II16 o1 o2 o3 -> op3 (text "\tamcas_db.h") o1 o2 o3 + AMCASDB II32 o1 o2 o3 -> op3 (text "\tamcas_db.w") o1 o2 o3 + AMCASDB II64 o1 o2 o3 -> op3 (text "\tamcas_db.d") o1 o2 o3 -- LL.{W/D}, SC.{W/D} + LL II32 o1 o2 o3 -> op3 (text "\tll.w") o1 o2 o3 + SC II32 o1 o2 o3 -> op3 (text "\tsc.w") o1 o2 o3 + LL II64 o1 o2 o3 -> op3 (text "\tll.d") o1 o2 o3 + SC II64 o1 o2 o3 -> op3 (text "\tsc.d") o1 o2 o3 -- SC.Q -- LL.ACQ.{W/D}, SC.REL.{W/D} -- 8. Barrier Instructions --------------------------------------------------- ===================================== m4/fp_check_timer_create.m4 deleted ===================================== @@ -1,110 +0,0 @@ -# Check for a working timer_create(). We need a pretty detailed check -# here, because there exist partially-working implementations of -# timer_create() in certain versions of Linux (see bug #1933). -# -AC_DEFUN([FP_CHECK_TIMER_CREATE],[ -AC_CHECK_FUNC([timer_create],[HAVE_timer_create=yes],[HAVE_timer_create=no]) - -if test "$HAVE_timer_create" = "yes" -then - if test "$cross_compiling" = "yes" - then - # We can't test timer_create when we're cross-compiling, so we - # optimistiaclly assume that it actually works properly. - AC_DEFINE([USE_TIMER_CREATE], 1, [Define to 1 if we can use timer_create(CLOCK_REALTIME,...)]) - else - AC_CACHE_CHECK([for a working timer_create(CLOCK_REALTIME)], - [fptools_cv_timer_create_works], - [AC_TRY_RUN([ -#include <stdio.h> -#if defined(HAVE_STDLIB_H) -#include <stdlib.h> -#endif -#include <time.h> -#if defined(HAVE_SIGNAL_H) -#include <signal.h> -#endif -#if defined(HAVE_UNISTD_H) -#include <unistd.h> -#endif - -static volatile int tock = 0; -static void handler(int i) -{ - tock = 1; -} - -static void timeout(int i) -{ - // timer_settime() has been known to hang, so just in case - // we install a 1-second timeout (see #2257) - exit(99); -} - -int main(int argc, char *argv[]) -{ - - struct sigevent ev; - timer_t timer; - struct itimerspec it; - struct sigaction action; - int m,n,count = 0; - - ev.sigev_notify = SIGEV_SIGNAL; - ev.sigev_signo = SIGVTALRM; - - action.sa_handler = handler; - action.sa_flags = 0; - sigemptyset(&action.sa_mask); - if (sigaction(SIGVTALRM, &action, NULL) == -1) { - fprintf(stderr,"SIGVTALRM problem\n"); - exit(3); - } - - action.sa_handler = timeout; - action.sa_flags = 0; - sigemptyset(&action.sa_mask); - if (sigaction(SIGALRM, &action, NULL) == -1) { - fprintf(stderr,"SIGALRM problem\n"); - exit(3); - } - alarm(1); - - if (timer_create(CLOCK_REALTIME, &ev, &timer) != 0) { - fprintf(stderr,"No CLOCK_REALTIME timer\n"); - exit(2); - } - - tock = 0; - - it.it_value.tv_sec = 0; - it.it_value.tv_nsec = 1000000; // 1ms - it.it_interval = it.it_value; - if (timer_settime(timer, 0, &it, NULL) != 0) { - fprintf(stderr,"settime problem\n"); - exit(4); - } - - // some environments have coarse scheduler/timer granularity of ~10ms and worse - usleep(100000); // 100ms - - if (!tock) { - fprintf(stderr,"no CLOCK_REALTIME signal\n"); - exit(5); - } - - timer_delete(timer); - - exit(0); -} - ], - [fptools_cv_timer_create_works=yes], - [fptools_cv_timer_create_works=no]) - ]) -case $fptools_cv_timer_create_works in - yes) AC_DEFINE([USE_TIMER_CREATE], 1, - [Define to 1 if we can use timer_create(CLOCK_REALTIME,...)]);; -esac - fi -fi -]) ===================================== rts/Timer.c ===================================== @@ -7,12 +7,14 @@ * ---------------------------------------------------------------------------*/ /* - * The interval timer is used for profiling and for context switching in the - * threaded build. + * The interval timer is used for profiling and for context switching. * * This file defines the platform-independent view of interval timing, relying - * on platform-specific services to install and run the timers. + * on platform-specific services to install and run the timers. See + * posix/Ticker.c and win32/Ticker.c for the platform specific parts. * + * If you are looking for Itimer.c then you either file or one of the + * platform-specific Ticker.c files. */ #include "rts/PosixSource.h" ===================================== rts/configure.ac ===================================== @@ -204,7 +204,6 @@ FP_MUSTTAIL dnl ** check for librt AC_CHECK_FUNCS(clock_gettime timer_settime) -FP_CHECK_TIMER_CREATE dnl ** check for Apple's "interesting" long double compatibility scheme AC_MSG_CHECKING(for printf\$LDBLStub) ===================================== rts/include/rts/Timer.h ===================================== @@ -15,4 +15,4 @@ void startTimer (void); void stopTimer (void); -int rtsTimerSignal (void); +int rtsTimerSignal (void); // Deprecated: see issue #27073 ===================================== rts/include/stg/SMP.h ===================================== @@ -21,7 +21,7 @@ void arm_atomic_spin_unlock(void); // Unconditionally atomic operations // These are atomic even in the non-threaded RTS. These are necessary in the // Proftimer implementation, which may be called from the pthreads-based -// ITimer implementation. +// Ticker implementation. #define RELAXED_LOAD_ALWAYS(ptr) __atomic_load_n(ptr, __ATOMIC_RELAXED) #define RELAXED_STORE_ALWAYS(ptr,val) __atomic_store_n(ptr, val, __ATOMIC_RELAXED) #define RELAXED_ADD_ALWAYS(ptr,val) __atomic_add_fetch(ptr, val, __ATOMIC_RELAXED) ===================================== rts/posix/Signals.c ===================================== @@ -640,35 +640,6 @@ set_sigtstp_action (bool handle) } } -/* Used by ItimerTimerCreate and ItimerSetitimer implementations */ -void -install_vtalrm_handler(int sig, TickProc handle_tick) -{ - struct sigaction action; - memset(&action, 0, sizeof(struct sigaction)); - - action.sa_handler = handle_tick; - - sigemptyset(&action.sa_mask); - -#if defined(SA_RESTART) - // specify SA_RESTART. One consequence if we don't do this is - // that readline gets confused by the -threaded RTS. It seems - // that if a SIGALRM handler is installed without SA_RESTART, - // readline installs its own SIGALRM signal handler (see - // readline's signals.c), and this somehow causes readline to go - // wrong when the input exceeds a single line (try it). - action.sa_flags = SA_RESTART; -#else - action.sa_flags = 0; -#endif - - if (sigaction(sig, &action, NULL) == -1) { - sysErrorBelch("sigaction"); - stg_exit(EXIT_FAILURE); - } -} - /* ----------------------------------------------------------------------------- * Install default signal handlers. * ===================================== rts/posix/Signals.h ===================================== @@ -25,8 +25,6 @@ extern siginfo_t *next_pending_handler; void startSignalHandlers(Capability *cap); #endif -void install_vtalrm_handler(int sig, TickProc handle_tick); - /* Communicating with the IO manager thread (see GHC.Conc). * * TODO: these I/O manager things are not related to signals and ought to live ===================================== rts/posix/Ticker.c ===================================== @@ -2,116 +2,38 @@ * * (c) The GHC Team, 1995-2007 * - * Interval timer for profiling and pre-emptive scheduling. + * Posix implementation(s) of the interval timer for profiling and pre-emptive + * scheduling. * * ---------------------------------------------------------------------------*/ -/* - * The interval timer is used for profiling and for context switching in the - * threaded build. Though POSIX 1003.1b includes a standard interface for - * such things, no one really seems to be implementing them yet. Even - * Solaris 2.3 only seems to provide support for @CLOCK_REAL@, whereas we're - * keen on getting access to @CLOCK_VIRTUAL@. - * - * Hence, we often use the old-fashioned @setitimer@ that just about everyone - * seems to support. So much for standards. - * - * If you are looking for Itimer.c then this is the right file. I renamed it - * Ticker.c for consistency. +/* The interval timer is used for profiling and for context switching. + * This file defines the platform-specific services to install and run the + * timers, and we call this the ticker. See rts/Timer.c for the + * platform-dependent view of interval timing. + * + * Historically we had ticker implementations using signals. This was always a + * rather shakey thing to do but we had few alternatives. + * - One problem with using signals is that there are severe limits on what + * code can be called from signal handlers. In particular it's not possible + * to take locks in a signal handler contex. This was enough for contex + * switching, but it's no good for things like flushing the eventlog, or + * waking up rts tasks. + * - We also want to avoid using alarm signals, as these can interrupt system + * calls (#10840) or can be overwritten by user code. */ -#include "rts/PosixSource.h" - -/* We've defined _POSIX_SOURCE via "rts/PosixSource.h", and yet still use - some non-POSIX features. With _POSIX_SOURCE defined, visibility of - non-POSIX extension prototypes requires _DARWIN_C_SOURCE on Mac OS X, - __BSD_VISIBLE on FreeBSD and DragonflyBSD, and _NetBSD_SOURCE on - NetBSD. Otherwise, for example, code using pthread_setname_np(3) and - variants will not compile. We must therefore define the additional - macros that expose non-POSIX APIs early, before any of the relevant - system headers are included via "Rts.h". - - An alternative approach could be to write portable wrappers or stubs for all - the non-posix functions in a C-module that does not include "rts/PosixSource.h", - and then use only POSIX features and the portable wrapper functions in all - other C-modules. */ -#include "ghcconfig.h" -#if defined(freebsd_HOST_OS) || defined(dragonfly_HOST_OS) -#define __BSD_VISIBLE 1 -#endif -#if defined(darwin_HOST_OS) -#define _DARWIN_C_SOURCE 1 -#endif -#if defined(netbsd_HOST_OS) -#define _NETBSD_SOURCE 1 -#endif - -#include "Rts.h" - -/* - * It used to be that timer_create doesn't exist on iOS and setitimer doesn't fire on iOS - * during debugging. See #7723. Seems to be an issue with signals. - * - * We also want to avoid using alarm signals, as these can interrupt system calls (#10840) - * or can be overwritten by user code. +/* Select a ticker implementation to use: * - * So we are using the pthread based implementation. - */ -#if defined(ios_HOST_OS) || defined(darwin_HOST_OS) -#define USE_PTHREAD_FOR_ITIMER -#endif - -/* - * On Linux we can use timerfd_* (introduced in Linux - * 2.6.25) and a thread instead of alarm signals. It avoids the risk of - * interrupting syscalls (see #10840) and the risk of being accidentally - * modified in user code using signals. NetBSD has also added timerfd - * support since version 10. + * On modern Linux, FreeBSD and NetBSD we can use timerfd_create and a thread + * that waits on it using poll. Linux has had timerfd since version 2.6.25. + * NetBSD has had timerfd since version 10, and FreeBSD since version 15. * - * For older version of linux/netbsd without timerfd we fall back to the - * pthread based implementation. + * For older version of linux/bsd without timerfd, and for all other posix + * platforms, we use the implementation using posix pthreads and nanosleep(). */ #if defined(HAVE_SYS_TIMERFD_H) -#define USE_TIMERFD_FOR_ITIMER -#endif - -#if defined(linux_HOST_OS) -#define USE_PTHREAD_FOR_ITIMER -#endif - -#if defined(netbsd_HOST_OS) -#define USE_PTHREAD_FOR_ITIMER -#endif - -#if defined(freebsd_HOST_OS) -#define USE_PTHREAD_FOR_ITIMER -#endif - -#if defined(solaris2_HOST_OS) -/* USE_TIMER_CREATE is usually disabled for Solaris. In fact it is - supported well on this OS, but requires additional privilege. When - user does not have it, then the testing configure program fails - which results in USE_TIMER_CREATE not defined. - On the other hand when we cross-compile, then we optimistically - assume usage of timer_create function. The problem is that if we - cross compile for example from i386-solaris2 to x86_64-solaris2, - then the build fails with error like this: - -ghc-stage2: timer_create: Not owner - - which happens on first ghc-stage2 invocation. So to support - cross-compilation to Solaris we manually undefine USE_TIMER_CREATE - here */ -#undef USE_TIMER_CREATE -#endif /* solaris2_HOST_OS */ - -// Select the variant to use -#if defined(USE_TIMERFD_FOR_ITIMER) #include "ticker/TimerFd.c" -#elif defined(USE_PTHREAD_FOR_ITIMER) -#include "ticker/Pthread.c" -#elif defined(USE_TIMER_CREATE) -#include "ticker/TimerCreate.c" #else -#include "ticker/Setitimer.c" +#include "ticker/Pthread.c" #endif ===================================== rts/posix/ticker/Setitimer.c deleted ===================================== @@ -1,80 +0,0 @@ -/* ----------------------------------------------------------------------------- - * - * (c) The GHC Team, 1995-2007 - * - * Interval timer for profiling and pre-emptive scheduling. - * - * ---------------------------------------------------------------------------*/ - -#include "rts/PosixSource.h" -#include "Rts.h" - -#include "Ticker.h" -#include "Proftimer.h" -#include "Schedule.h" -#include "posix/Clock.h" -#include "posix/Signals.h" - -#include <time.h> -#if HAVE_SYS_TIME_H -# include <sys/time.h> -#endif - -#if defined(HAVE_SIGNAL_H) -# include <signal.h> -#endif - -#include <string.h> - -static Time itimer_interval = DEFAULT_TICK_INTERVAL; - -void -initTicker (Time interval, TickProc handle_tick) -{ - itimer_interval = interval; - install_vtalrm_handler(SIGALRM, handle_tick); -} - -void -startTicker(void) -{ - struct itimerval it; - - it.it_value.tv_sec = TimeToSeconds(itimer_interval); - it.it_value.tv_usec = TimeToUS(itimer_interval) % 1000000; - it.it_interval = it.it_value; - - if (setitimer(ITIMER_REAL, &it, NULL) != 0) { - sysErrorBelch("setitimer"); - stg_exit(EXIT_FAILURE); - } -} - -void -stopTicker(void) -{ - struct itimerval it; - - it.it_value.tv_sec = 0; - it.it_value.tv_usec = 0; - it.it_interval = it.it_value; - - if (setitimer(ITIMER_REAL, &it, NULL) != 0) { - sysErrorBelch("setitimer"); - stg_exit(EXIT_FAILURE); - } -} - -void -exitTicker (bool wait STG_UNUSED) -{ - return; -} - -int -rtsTimerSignal(void) -{ - return SIGALRM; - // Using SIGALRM can leads to problems, see #850. But we have no - // option if timer_create() is not available. -} ===================================== rts/posix/ticker/TimerCreate.c deleted ===================================== @@ -1,92 +0,0 @@ -/* ----------------------------------------------------------------------------- - * - * (c) The GHC Team, 1995-2007 - * - * Interval timer for profiling and pre-emptive scheduling. - * - * ---------------------------------------------------------------------------*/ - -#include "rts/PosixSource.h" -#include "Rts.h" - -#include "Ticker.h" -#include "Proftimer.h" -#include "Schedule.h" -#include "posix/Clock.h" -#include "posix/Signals.h" - -#if defined(HAVE_SIGNAL_H) -# include <signal.h> -#endif - -#include <string.h> - -static Time itimer_interval = DEFAULT_TICK_INTERVAL; -static timer_t timer; - -void -initTicker (Time interval, TickProc handle_tick) -{ - itimer_interval = interval; - - struct sigevent ev; - - // Keep programs like valgrind happy - memset(&ev, 0, sizeof(ev)); - - ev.sigev_notify = SIGEV_SIGNAL; - ev.sigev_signo = SIGVTALRM; - - if (timer_create(CLOCK_ID, &ev, &timer) != 0) { - sysErrorBelch("timer_create"); - stg_exit(EXIT_FAILURE); - } - - install_vtalrm_handler(SIGVTALRM, handle_tick); -} - -void -startTicker(void) -{ - struct itimerspec it; - - it.it_value.tv_sec = TimeToSeconds(itimer_interval); - it.it_value.tv_nsec = TimeToNS(itimer_interval) % 1000000000; - it.it_interval = it.it_value; - - if (timer_settime(timer, 0, &it, NULL) != 0) { - sysErrorBelch("timer_settime"); - stg_exit(EXIT_FAILURE); - } -} - -void -stopTicker(void) -{ - struct itimerspec it; - - it.it_value.tv_sec = 0; - it.it_value.tv_nsec = 0; - it.it_interval = it.it_value; - - if (timer_settime(timer, 0, &it, NULL) != 0) { - sysErrorBelch("timer_settime"); - stg_exit(EXIT_FAILURE); - } -} - -void -exitTicker (bool wait STG_UNUSED) -{ - // Before deleting the timer set the signal to ignore to avoid the - // possibility of the signal being delivered after the timer is deleted. - signal(SIGVTALRM, SIG_IGN); - timer_delete(timer); - // ignore errors - we don't really care if it fails. -} - -int -rtsTimerSignal(void) -{ - return SIGVTALRM; -} ===================================== testsuite/driver/testlib.py ===================================== @@ -3043,6 +3043,12 @@ def normalise_errmsg(s: str) -> str: # Old emcc warns when we export HEAP8 but new one requires it (see #26290) s = s.replace('warning: invalid item in EXPORTED_RUNTIME_METHODS: HEAP8\nwarning: invalid item in EXPORTED_RUNTIME_METHODS: HEAPU8\nemcc: warning: warnings in JS library compilation [-Wjs-compiler]\n','') + # on newer versions of MacOS X, the shipped ranlib warns about object files with no symbols, + # however, these are completely benign stubs. + # See https://gitlab.haskell.org/ghc/ghc/-/issues/27116 + if opsys('darwin'): + modify_lines(s, lambda l: re.sub(r'.*ranlib:.*has no symbols', '', l)) + return s # normalise a .prof file, so that we can reasonably compare it against ===================================== testsuite/tests/driver/all.T ===================================== @@ -120,9 +120,7 @@ if config.os == 'darwin': else: only_darwin = skip -test('static001', [extra_files(['Static001.hs']), - only_darwin, - when(arch('x86_64'), expect_broken(8127))], +test('static001', [extra_files(['Static001.hs']), only_darwin], makefile_test, ['static001']) test('dynHelloWorld', ===================================== testsuite/tests/perf/compiler/T13960.hs ===================================== @@ -0,0 +1,72 @@ +{-# LANGUAGE OverloadedStrings #-} + +-- GHC used to run out of simplifier ticks due to inlining the internals of +-- `toStrict . toLazyByteString`. +module T13960 (breaks) where + +import Data.ByteString (ByteString) +import Data.ByteString.Builder (Builder, stringUtf8, toLazyByteString) +import Data.ByteString.Lazy (toStrict) +import Data.String (IsString(..)) + +newtype Query = Query ByteString + +toByteString :: Builder -> ByteString +toByteString x = toStrict (toLazyByteString x) + +instance IsString Query where + fromString = Query . toByteString . stringUtf8 + +breaks :: [(Query, Query)] +breaks = + [ ("query001a", "query001b") + , ("query002a", "query002b") + , ("query003a", "query003b") + , ("query004a", "query004b") + , ("query005a", "query005b") + , ("query006a", "query006b") + , ("query007a", "query007b") + , ("query008a", "query008b") + , ("query009a", "query009b") + , ("query010a", "query010b") + , ("query011a", "query011b") + , ("query012a", "query012b") + , ("query013a", "query013b") + , ("query014a", "query014b") + , ("query015a", "query015b") + , ("query016a", "query016b") + , ("query017a", "query017b") + , ("query018a", "query018b") + , ("query019a", "query019b") + , ("query020a", "query020b") + , ("query021a", "query021b") + , ("query022a", "query022b") + , ("query023a", "query023b") + , ("query024a", "query024b") + , ("query025a", "query025b") + , ("query026a", "query026b") + , ("query027a", "query027b") + , ("query028a", "query028b") + , ("query029a", "query029b") + , ("query030a", "query030b") + , ("query031a", "query031b") + , ("query032a", "query032b") + , ("query033a", "query033b") + , ("query034a", "query034b") + , ("query035a", "query035b") + , ("query036a", "query036b") + , ("query037a", "query037b") + , ("query038a", "query038b") + , ("query039a", "query039b") + , ("query040a", "query040b") + , ("query041a", "query041b") + , ("query042a", "query042b") + , ("query043a", "query043b") + , ("query044a", "query044b") + , ("query045a", "query045b") + , ("query046a", "query046b") + , ("query047a", "query047b") + , ("query048a", "query048b") + , ("query049a", "query049b") + , ("query050a", "query050b") + ] ===================================== testsuite/tests/perf/compiler/all.T ===================================== @@ -686,6 +686,12 @@ test ('T13820', ], compile, ['-v0']) +test ('T13960', + [ collect_compiler_stats('peak_megabytes_allocated', 20), + collect_compiler_stats('bytes allocated', 2), + ], + compile, + ['-O']) test ('T14766', [ collect_compiler_stats('bytes allocated',2), pre_cmd('python3 genT14766.py > T14766.hs'), View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/5c2c832e5f40352538992bd32746a54... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/5c2c832e5f40352538992bd32746a54... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
Marge Bot (@marge-bot)