Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
-
05586983
by Peng Fan at 2026-04-01T05:14:50-04:00
-
501f6520
by Duncan Coutts at 2026-04-01T05:14:51-04:00
-
efee2a42
by Duncan Coutts at 2026-04-01T05:14:51-04:00
-
7a5dbd06
by Duncan Coutts at 2026-04-01T05:14:51-04:00
-
8557b4e4
by Duncan Coutts at 2026-04-01T05:14:51-04:00
-
4cbcb41d
by Duncan Coutts at 2026-04-01T05:14:51-04:00
-
e8547953
by Simon Jakobi at 2026-04-01T05:14:52-04:00
15 changed files:
- 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/tests/perf/compiler/T13960.hs
- testsuite/tests/perf/compiler/all.T
Changes:
| ... | ... | @@ -57,6 +57,12 @@ import Control.Monad |
| 57 | 57 | import GHC.Cmm.Dataflow.Label
|
| 58 | 58 | import GHC.Types.Unique.DSM
|
| 59 | 59 | import GHC.Types.Literal.Floating
|
| 60 | +import GHC.Unit.Types ( ghcInternalUnitId )
|
|
| 61 | + |
|
| 62 | +la664Enabled :: NatM Bool
|
|
| 63 | +la664Enabled = do
|
|
| 64 | + config <- getConfig
|
|
| 65 | + return (ncgLa664Enabled config)
|
|
| 60 | 66 | |
| 61 | 67 | -- [General layout of an NCG]
|
| 62 | 68 | cmmTopCodeGen ::
|
| ... | ... | @@ -1651,6 +1657,10 @@ genPrim (MO_Prefetch_Data _n) [] [_] = return nilOL |
| 1651 | 1657 | genPrim (MO_AtomicRead w mo) [dst] [addr] = genAtomicRead w mo dst addr
|
| 1652 | 1658 | genPrim (MO_AtomicWrite w mo) [] [addr,val] = genAtomicWrite w mo addr val
|
| 1653 | 1659 | |
| 1660 | +genPrim (MO_AtomicRMW width amop) [dst] [addr,n] = genLibCCall (atomicRMWLabel width amop) [dst] [addr,n]
|
|
| 1661 | +genPrim (MO_Cmpxchg width) [dst] [addr,expe,new] = genCmpxchg width dst addr expe new
|
|
| 1662 | +genPrim (MO_Xchg width) [dst] [addr,value] = genXchg width dst addr value
|
|
| 1663 | + |
|
| 1654 | 1664 | genPrim mop@(MO_S_Mul2 _w) _ _ = unsupported mop
|
| 1655 | 1665 | genPrim mop@(MO_S_QuotRem _w) _ _ = unsupported mop
|
| 1656 | 1666 | genPrim mop@(MO_U_QuotRem _w) _ _ = unsupported mop
|
| ... | ... | @@ -1674,9 +1684,6 @@ genPrim (MO_PopCnt width) [dst] [src] = genLibCCall (popCntLabel w |
| 1674 | 1684 | genPrim (MO_Pdep width) [dst] [src,mask] = genLibCCall (pdepLabel width) [dst] [src,mask]
|
| 1675 | 1685 | genPrim (MO_Pext width) [dst] [src,mask] = genLibCCall (pextLabel width) [dst] [src,mask]
|
| 1676 | 1686 | genPrim (MO_UF_Conv width) [dst] [src] = genLibCCall (word2FloatLabel width) [dst] [src]
|
| 1677 | -genPrim (MO_AtomicRMW width amop) [dst] [addr,n] = genLibCCall (atomicRMWLabel width amop) [dst] [addr,n]
|
|
| 1678 | -genPrim (MO_Cmpxchg width) [dst] [addr,old,new] = genLibCCall (cmpxchgLabel width) [dst] [addr,old,new]
|
|
| 1679 | -genPrim (MO_Xchg width) [dst] [addr,val] = genLibCCall (xchgLabel width) [dst] [addr,val]
|
|
| 1680 | 1687 | genPrim (MO_Memcpy _align) [] [dst,src,n] = genLibCCall (fsLit "memcpy") [] [dst,src,n]
|
| 1681 | 1688 | genPrim (MO_Memmove _align) [] [dst,src,n] = genLibCCall (fsLit "memmove") [] [dst,src,n]
|
| 1682 | 1689 | genPrim (MO_Memcmp _align) [rst] [dst,src,n] = genLibCCall (fsLit "memcmp") [rst] [dst,src,n]
|
| ... | ... | @@ -1872,6 +1879,20 @@ genBitRev w dst src = do |
| 1872 | 1879 | )
|
| 1873 | 1880 | _ -> return ( code_x `snocOL` BITREV (OpReg w dst_reg) (OpReg w reg_x))
|
| 1874 | 1881 | |
| 1882 | +genPrimCCall
|
|
| 1883 | + :: FastString
|
|
| 1884 | + -> [CmmFormal]
|
|
| 1885 | + -> [CmmActual]
|
|
| 1886 | + -> NatM InstrBlock
|
|
| 1887 | + |
|
| 1888 | +genPrimCCall name dsts args = do
|
|
| 1889 | + config <- getConfig
|
|
| 1890 | + target <-
|
|
| 1891 | + cmmMakeDynamicReference config CallReference
|
|
| 1892 | + $ mkCmmCodeLabel ghcInternalUnitId name
|
|
| 1893 | + let cconv = ForeignConvention CCallConv [NoHint] [NoHint] CmmMayReturn
|
|
| 1894 | + genCCall target cconv dsts args
|
|
| 1895 | + |
|
| 1875 | 1896 | -- Generate C call to the given function in libc
|
| 1876 | 1897 | genLibCCall :: FastString -> [CmmFormal] -> [CmmActual] -> NatM InstrBlock
|
| 1877 | 1898 | genLibCCall name dsts args = do
|
| ... | ... | @@ -1945,6 +1966,52 @@ genAtomicWrite w mo addr val = do |
| 1945 | 1966 | )
|
| 1946 | 1967 | _ -> panic $ "Unexpected MemOrderAcquire on an AtomicWrite" ++ show mo
|
| 1947 | 1968 | |
| 1969 | +genCmpxchg :: Width -> LocalReg -> CmmExpr -> CmmExpr -> CmmExpr -> NatM InstrBlock
|
|
| 1970 | +genCmpxchg w dst addr expe new = do
|
|
| 1971 | + config <- getConfig
|
|
| 1972 | + let
|
|
| 1973 | + platform = ncgPlatform config
|
|
| 1974 | + format = intFormat w
|
|
| 1975 | + |
|
| 1976 | + la664Enabled >>= \case
|
|
| 1977 | + |
|
| 1978 | + True -> do
|
|
| 1979 | + (addr_reg, _, code_addr) <- getSomeReg addr
|
|
| 1980 | + (expe_reg, _, code_expe) <- getSomeReg expe
|
|
| 1981 | + (new_reg, _, code_new) <- getSomeReg new
|
|
| 1982 | + let dst_reg = getRegisterReg platform (CmmLocal dst)
|
|
| 1983 | + return $ code_addr `appOL` code_expe `appOL` code_new `appOL` toOL
|
|
| 1984 | + [
|
|
| 1985 | + -- Behave like the GCC builtin CAS operation
|
|
| 1986 | + AMCASDB format (OpReg w expe_reg) (OpReg w new_reg) (OpReg w addr_reg),
|
|
| 1987 | + MOV (OpReg w dst_reg) (OpReg w expe_reg)
|
|
| 1988 | + ]
|
|
| 1989 | + |
|
| 1990 | + False ->
|
|
| 1991 | + genPrimCCall (cmpxchgLabel w) [dst] [addr,expe,new]
|
|
| 1992 | + |
|
| 1993 | +genXchg :: Width -> LocalReg -> CmmExpr -> CmmExpr -> NatM InstrBlock
|
|
| 1994 | +genXchg w dst addr val = do
|
|
| 1995 | + config <- getConfig
|
|
| 1996 | + tmp <- getNewRegNat II64
|
|
| 1997 | + let
|
|
| 1998 | + platform = ncgPlatform config
|
|
| 1999 | + format = intFormat w
|
|
| 2000 | + |
|
| 2001 | + la664Enabled >>= \case
|
|
| 2002 | + |
|
| 2003 | + True -> do
|
|
| 2004 | + (addr_reg, _, code_addr) <- getSomeReg addr
|
|
| 2005 | + (val_reg, _, code_val) <- getSomeReg val
|
|
| 2006 | + let dst_reg = getRegisterReg platform (CmmLocal dst)
|
|
| 2007 | + return $ code_addr `appOL` code_val `appOL` toOL
|
|
| 2008 | + [
|
|
| 2009 | + AMSWAPDB format (OpReg w tmp) (OpReg w val_reg) (OpReg w addr_reg),
|
|
| 2010 | + MOV (OpReg W64 dst_reg) (OpReg W64 tmp)
|
|
| 2011 | + ]
|
|
| 2012 | + False ->
|
|
| 2013 | + genPrimCCall (xchgLabel w) [dst] [addr,val]
|
|
| 2014 | + |
|
| 1948 | 2015 | -- -----------------------------------------------------------------------------
|
| 1949 | 2016 | {-
|
| 1950 | 2017 | Generating C calls
|
| ... | ... | @@ -1977,6 +2044,7 @@ member of a structure or union argument, or a vector/floating-point argument |
| 1977 | 2044 | wider than FRLEN may be passed in a GAR.
|
| 1978 | 2045 | -}
|
| 1979 | 2046 | |
| 2047 | +-- Generate C call to the given function in ghc-prim
|
|
| 1980 | 2048 | genCCall
|
| 1981 | 2049 | :: CmmExpr -- address of func call
|
| 1982 | 2050 | -> ForeignConvention -- calling convention
|
| ... | ... | @@ -150,10 +150,11 @@ regUsageOfInstr platform instr = case instr of |
| 150 | 150 | -- ranges, corresponding to 2 and 1 instruction implementations respectively.
|
| 151 | 151 | --
|
| 152 | 152 | -- BCOND1 is selected by default.
|
| 153 | - BCOND1 _ j d t -> usage (regTarget t ++ regOp j ++ regOp d, [])
|
|
| 154 | - BCOND _ j d t -> usage (regTarget t ++ regOp j ++ regOp d, [])
|
|
| 155 | - BEQZ j t -> usage (regTarget t ++ regOp j, [])
|
|
| 156 | - BNEZ j t -> usage (regTarget t ++ regOp j, [])
|
|
| 153 | + BCOND1 _ j d t -> usage (regTarget t ++ regOp j ++ regOp d, [])
|
|
| 154 | + BCOND _ j d t -> usage (regTarget t ++ regOp j ++ regOp d, [])
|
|
| 155 | + BEQZ1 o1 o2 -> usage (regOp o1 ++ regOp o2, [])
|
|
| 156 | + BEQZ j t -> usage (regTarget t ++ regOp j, [])
|
|
| 157 | + BNEZ j t -> usage (regTarget t ++ regOp j, [])
|
|
| 157 | 158 | -- 5. Common Memory Access Instructions --------------------------------------
|
| 158 | 159 | LD _ dst src -> usage (regOp src, regOp dst)
|
| 159 | 160 | LDU _ dst src -> usage (regOp src, regOp dst)
|
| ... | ... | @@ -168,7 +169,17 @@ regUsageOfInstr platform instr = case instr of |
| 168 | 169 | -- LDCOND dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
|
| 169 | 170 | -- STCOND dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
|
| 170 | 171 | -- 7. Atomic Memory Access Instructions --------------------------------------
|
| 172 | + -- In LoongArch, if the AM* atomic memory access instruction has the same register number as rd and rj,
|
|
| 173 | + -- the execution will trigger an Instruction Non-defined Exception. Here should be avoided.
|
|
| 171 | 174 | AMSWAPDB _ dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
|
| 175 | + AMADDDB _ dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
|
|
| 176 | + AMANDDB _ dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
|
|
| 177 | + AMORDB _ dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
|
|
| 178 | + AMXORDB _ dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
|
|
| 179 | + --AMCASDB _ dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp src1 ++ regOp src2 ++ regOp dst)
|
|
| 180 | + AMCASDB _ dst src1 src2 -> usage (regOp dst ++ regOp src1 ++ regOp src2, regOp dst)
|
|
| 181 | + LL _ dst src1 _ -> usage (regOp src1, regOp dst)
|
|
| 182 | + SC _ dst src1 _ -> usage (regOp src1, regOp dst)
|
|
| 172 | 183 | -- 8. Barrier Instructions ---------------------------------------------------
|
| 173 | 184 | DBAR _hint -> usage ([], [])
|
| 174 | 185 | IBAR _hint -> usage ([], [])
|
| ... | ... | @@ -330,6 +341,7 @@ patchRegsOfInstr instr env = case instr of |
| 330 | 341 | TAIL36 r t -> TAIL36 (patchOp r) (patchTarget t)
|
| 331 | 342 | BCOND1 c j d t -> BCOND1 c (patchOp j) (patchOp d) (patchTarget t)
|
| 332 | 343 | BCOND c j d t -> BCOND c (patchOp j) (patchOp d) (patchTarget t)
|
| 344 | + BEQZ1 o1 o2 -> BEQZ1 (patchOp o1) (patchOp o2)
|
|
| 333 | 345 | BEQZ j t -> BEQZ (patchOp j) (patchTarget t)
|
| 334 | 346 | BNEZ j t -> BNEZ (patchOp j) (patchTarget t)
|
| 335 | 347 | -- 5. Common Memory Access Instructions --------------------------------------
|
| ... | ... | @@ -348,6 +360,13 @@ patchRegsOfInstr instr env = case instr of |
| 348 | 360 | -- STCOND o1 o2 o3 -> STCOND (patchOp o1) (patchOp o2) (patchOp o3)
|
| 349 | 361 | -- 7. Atomic Memory Access Instructions --------------------------------------
|
| 350 | 362 | AMSWAPDB f o1 o2 o3 -> AMSWAPDB f (patchOp o1) (patchOp o2) (patchOp o3)
|
| 363 | + AMADDDB f o1 o2 o3 -> AMADDDB f (patchOp o1) (patchOp o2) (patchOp o3)
|
|
| 364 | + AMANDDB f o1 o2 o3 -> AMANDDB f (patchOp o1) (patchOp o2) (patchOp o3)
|
|
| 365 | + AMORDB f o1 o2 o3 -> AMORDB f (patchOp o1) (patchOp o2) (patchOp o3)
|
|
| 366 | + AMXORDB f o1 o2 o3 -> AMXORDB f (patchOp o1) (patchOp o2) (patchOp o3)
|
|
| 367 | + AMCASDB f o1 o2 o3 -> AMCASDB f (patchOp o1) (patchOp o2) (patchOp o3)
|
|
| 368 | + LL f o1 o2 o3 -> LL f (patchOp o1) (patchOp o2) (patchOp o3)
|
|
| 369 | + SC f o1 o2 o3 -> SC f (patchOp o1) (patchOp o2) (patchOp o3)
|
|
| 351 | 370 | -- 8. Barrier Instructions ---------------------------------------------------
|
| 352 | 371 | DBAR o1 -> DBAR o1
|
| 353 | 372 | IBAR o1 -> IBAR o1
|
| ... | ... | @@ -398,6 +417,7 @@ isJumpishInstr instr = case instr of |
| 398 | 417 | TAIL36 {} -> True
|
| 399 | 418 | BCOND1 {} -> True
|
| 400 | 419 | BCOND {} -> True
|
| 420 | + BEQZ1 {} -> True
|
|
| 401 | 421 | BEQZ {} -> True
|
| 402 | 422 | BNEZ {} -> True
|
| 403 | 423 | _ -> False
|
| ... | ... | @@ -718,6 +738,7 @@ data Instr |
| 718 | 738 | | TAIL36 Operand Target
|
| 719 | 739 | | BCOND1 Cond Operand Operand Target
|
| 720 | 740 | | BCOND Cond Operand Operand Target
|
| 741 | + | BEQZ1 Operand Operand
|
|
| 721 | 742 | | BEQZ Operand Target
|
| 722 | 743 | | BNEZ Operand Target
|
| 723 | 744 | -- 5. Common Memory Access Instructions --------------------------------------
|
| ... | ... | @@ -733,6 +754,13 @@ data Instr |
| 733 | 754 | -- 6. Bound Check Memory Access Instructions ---------------------------------
|
| 734 | 755 | -- 7. Atomic Memory Access Instructions --------------------------------------
|
| 735 | 756 | | AMSWAPDB Format Operand Operand Operand
|
| 757 | + | AMADDDB Format Operand Operand Operand
|
|
| 758 | + | AMANDDB Format Operand Operand Operand
|
|
| 759 | + | AMORDB Format Operand Operand Operand
|
|
| 760 | + | AMXORDB Format Operand Operand Operand
|
|
| 761 | + | AMCASDB Format Operand Operand Operand
|
|
| 762 | + | LL Format Operand Operand Operand
|
|
| 763 | + | SC Format Operand Operand Operand
|
|
| 736 | 764 | -- 8. Barrier Instructions ---------------------------------------------------
|
| 737 | 765 | | DBAR BarrierType
|
| 738 | 766 | | IBAR BarrierType
|
| ... | ... | @@ -839,6 +867,7 @@ instrCon i = |
| 839 | 867 | TAIL36{} -> "TAIL36"
|
| 840 | 868 | BCOND1{} -> "BCOND1"
|
| 841 | 869 | BCOND{} -> "BCOND"
|
| 870 | + BEQZ1{} -> "BEQZ1"
|
|
| 842 | 871 | BEQZ{} -> "BEQZ"
|
| 843 | 872 | BNEZ{} -> "BNEZ"
|
| 844 | 873 | LD{} -> "LD"
|
| ... | ... | @@ -851,6 +880,13 @@ instrCon i = |
| 851 | 880 | STPTR{} -> "STPTR"
|
| 852 | 881 | PRELD{} -> "PRELD"
|
| 853 | 882 | AMSWAPDB{} -> "AMSWAPDB"
|
| 883 | + AMADDDB{} -> "AMADDDB"
|
|
| 884 | + AMANDDB{} -> "AMANDDB"
|
|
| 885 | + AMORDB{} -> "AMORDB"
|
|
| 886 | + AMXORDB{} -> "AMXORDB"
|
|
| 887 | + AMCASDB{} -> "AMCASDB"
|
|
| 888 | + LL{} -> "LL"
|
|
| 889 | + SC{} -> "SC"
|
|
| 854 | 890 | DBAR{} -> "DBAR"
|
| 855 | 891 | IBAR{} -> "IBAR"
|
| 856 | 892 | FCVT{} -> "FCVT"
|
| ... | ... | @@ -852,6 +852,7 @@ pprInstr platform instr = case instr of |
| 852 | 852 | line $ text "\tbgeu" <+> pprOp platform d <> comma <+> pprOp platform j <> comma <+> pprAsmLabel platform (mkLocalBlockLabel (getUnique bid))
|
| 853 | 853 | UGT ->
|
| 854 | 854 | line $ text "\tbltu" <+> pprOp platform d <> comma <+> pprOp platform j <> comma <+> pprAsmLabel platform (mkLocalBlockLabel (getUnique bid))
|
| 855 | + |
|
| 855 | 856 | _ -> line $ text "\t" <> pprBcond c <+> pprOp platform j <> comma <+> pprOp platform d <> comma <+> pprAsmLabel platform (mkLocalBlockLabel (getUnique bid))
|
| 856 | 857 | |
| 857 | 858 | BCOND1 _ _ _ (TLabel _) -> panic "LA64.ppr: BCOND1: No conditional branching to TLabel!"
|
| ... | ... | @@ -916,17 +917,18 @@ pprInstr platform instr = case instr of |
| 916 | 917 | |
| 917 | 918 | BCOND _ _ _ (TReg _) -> panic "LA64.ppr: BCOND: No conditional branching to registers!"
|
| 918 | 919 | |
| 920 | + BEQZ1 o1 o2 | isImmOp o2 -> op2 (text "\tbeqz") o1 o2
|
|
| 919 | 921 | BEQZ j (TBlock bid) ->
|
| 920 | 922 | line $ text "\tbeqz" <+> pprOp platform j <> comma <+> pprAsmLabel platform (mkLocalBlockLabel (getUnique bid))
|
| 921 | 923 | BEQZ j (TLabel lbl) ->
|
| 922 | 924 | line $ text "\tbeqz" <+> pprOp platform j <> comma <+> pprAsmLabel platform lbl
|
| 923 | - BEQZ _ (TReg _) -> panic "LA64.ppr: BEQZ: No conditional branching to registers!"
|
|
| 925 | + BEQZ _ (TReg _) -> panic "LA64.ppr: BEQZ: No conditional branching to registers!"
|
|
| 924 | 926 | |
| 925 | 927 | BNEZ j (TBlock bid) ->
|
| 926 | 928 | line $ text "\tbnez" <+> pprOp platform j <> comma <+> pprAsmLabel platform (mkLocalBlockLabel (getUnique bid))
|
| 927 | 929 | BNEZ j (TLabel lbl) ->
|
| 928 | 930 | line $ text "\tbnez" <+> pprOp platform j <> comma <+> pprAsmLabel platform lbl
|
| 929 | - BNEZ _ (TReg _) -> panic "LA64.ppr: BNEZ: No conditional branching to registers!"
|
|
| 931 | + BNEZ _ (TReg _) -> panic "LA64.ppr: BNEZ: No conditional branching to registers!"
|
|
| 930 | 932 | |
| 931 | 933 | -- 5. Common Memory Access Instructions --------------------------------------
|
| 932 | 934 | -- LD.{B[U]/H[U]/W[U]/D}, ST.{B/H/W/D}: AddrRegImm
|
| ... | ... | @@ -1020,8 +1022,29 @@ pprInstr platform instr = case instr of |
| 1020 | 1022 | AMSWAPDB II32 o1 o2 o3 -> op3 (text "\tamswap_db.w") o1 o2 o3
|
| 1021 | 1023 | AMSWAPDB II64 o1 o2 o3 -> op3 (text "\tamswap_db.d") o1 o2 o3
|
| 1022 | 1024 | -- AM.{SWAP/ADD}[_DB].{B/H}
|
| 1025 | + AMADDDB II8 o1 o2 o3 -> op3 (text "\tamadd_db.b") o1 o2 o3
|
|
| 1026 | + AMADDDB II16 o1 o2 o3 -> op3 (text "\tamadd_db.h") o1 o2 o3
|
|
| 1027 | + AMADDDB II32 o1 o2 o3 -> op3 (text "\tamadd_db.w") o1 o2 o3
|
|
| 1028 | + AMADDDB II64 o1 o2 o3 -> op3 (text "\tamadd_db.d") o1 o2 o3
|
|
| 1029 | + |
|
| 1030 | + AMANDDB II32 o1 o2 o3 -> op3 (text "\tamand_db.w") o1 o2 o3
|
|
| 1031 | + AMANDDB II64 o1 o2 o3 -> op3 (text "\tamand_db.d") o1 o2 o3
|
|
| 1032 | + |
|
| 1033 | + AMORDB II32 o1 o2 o3 -> op3 (text "\tamor_db.w") o1 o2 o3
|
|
| 1034 | + AMORDB II64 o1 o2 o3 -> op3 (text "\tamor_db.d") o1 o2 o3
|
|
| 1035 | + |
|
| 1036 | + AMXORDB II32 o1 o2 o3 -> op3 (text "\tamxor_db.w") o1 o2 o3
|
|
| 1037 | + AMXORDB II64 o1 o2 o3 -> op3 (text "\tamxor_db.d") o1 o2 o3
|
|
| 1023 | 1038 | -- AMCAS[_DB].{B/H/W/D}
|
| 1039 | + AMCASDB II8 o1 o2 o3 -> op3 (text "\tamcas_db.b") o1 o2 o3
|
|
| 1040 | + AMCASDB II16 o1 o2 o3 -> op3 (text "\tamcas_db.h") o1 o2 o3
|
|
| 1041 | + AMCASDB II32 o1 o2 o3 -> op3 (text "\tamcas_db.w") o1 o2 o3
|
|
| 1042 | + AMCASDB II64 o1 o2 o3 -> op3 (text "\tamcas_db.d") o1 o2 o3
|
|
| 1024 | 1043 | -- LL.{W/D}, SC.{W/D}
|
| 1044 | + LL II32 o1 o2 o3 -> op3 (text "\tll.w") o1 o2 o3
|
|
| 1045 | + SC II32 o1 o2 o3 -> op3 (text "\tsc.w") o1 o2 o3
|
|
| 1046 | + LL II64 o1 o2 o3 -> op3 (text "\tll.d") o1 o2 o3
|
|
| 1047 | + SC II64 o1 o2 o3 -> op3 (text "\tsc.d") o1 o2 o3
|
|
| 1025 | 1048 | -- SC.Q
|
| 1026 | 1049 | -- LL.ACQ.{W/D}, SC.REL.{W/D}
|
| 1027 | 1050 | -- 8. Barrier Instructions ---------------------------------------------------
|
| 1 | -# Check for a working timer_create(). We need a pretty detailed check
|
|
| 2 | -# here, because there exist partially-working implementations of
|
|
| 3 | -# timer_create() in certain versions of Linux (see bug #1933).
|
|
| 4 | -#
|
|
| 5 | -AC_DEFUN([FP_CHECK_TIMER_CREATE],[
|
|
| 6 | -AC_CHECK_FUNC([timer_create],[HAVE_timer_create=yes],[HAVE_timer_create=no])
|
|
| 7 | - |
|
| 8 | -if test "$HAVE_timer_create" = "yes"
|
|
| 9 | -then
|
|
| 10 | - if test "$cross_compiling" = "yes"
|
|
| 11 | - then
|
|
| 12 | - # We can't test timer_create when we're cross-compiling, so we
|
|
| 13 | - # optimistiaclly assume that it actually works properly.
|
|
| 14 | - AC_DEFINE([USE_TIMER_CREATE], 1, [Define to 1 if we can use timer_create(CLOCK_REALTIME,...)])
|
|
| 15 | - else
|
|
| 16 | - AC_CACHE_CHECK([for a working timer_create(CLOCK_REALTIME)],
|
|
| 17 | - [fptools_cv_timer_create_works],
|
|
| 18 | - [AC_TRY_RUN([
|
|
| 19 | -#include <stdio.h>
|
|
| 20 | -#if defined(HAVE_STDLIB_H)
|
|
| 21 | -#include <stdlib.h>
|
|
| 22 | -#endif
|
|
| 23 | -#include <time.h>
|
|
| 24 | -#if defined(HAVE_SIGNAL_H)
|
|
| 25 | -#include <signal.h>
|
|
| 26 | -#endif
|
|
| 27 | -#if defined(HAVE_UNISTD_H)
|
|
| 28 | -#include <unistd.h>
|
|
| 29 | -#endif
|
|
| 30 | - |
|
| 31 | -static volatile int tock = 0;
|
|
| 32 | -static void handler(int i)
|
|
| 33 | -{
|
|
| 34 | - tock = 1;
|
|
| 35 | -}
|
|
| 36 | - |
|
| 37 | -static void timeout(int i)
|
|
| 38 | -{
|
|
| 39 | - // timer_settime() has been known to hang, so just in case
|
|
| 40 | - // we install a 1-second timeout (see #2257)
|
|
| 41 | - exit(99);
|
|
| 42 | -}
|
|
| 43 | - |
|
| 44 | -int main(int argc, char *argv[])
|
|
| 45 | -{
|
|
| 46 | - |
|
| 47 | - struct sigevent ev;
|
|
| 48 | - timer_t timer;
|
|
| 49 | - struct itimerspec it;
|
|
| 50 | - struct sigaction action;
|
|
| 51 | - int m,n,count = 0;
|
|
| 52 | - |
|
| 53 | - ev.sigev_notify = SIGEV_SIGNAL;
|
|
| 54 | - ev.sigev_signo = SIGVTALRM;
|
|
| 55 | - |
|
| 56 | - action.sa_handler = handler;
|
|
| 57 | - action.sa_flags = 0;
|
|
| 58 | - sigemptyset(&action.sa_mask);
|
|
| 59 | - if (sigaction(SIGVTALRM, &action, NULL) == -1) {
|
|
| 60 | - fprintf(stderr,"SIGVTALRM problem\n");
|
|
| 61 | - exit(3);
|
|
| 62 | - }
|
|
| 63 | - |
|
| 64 | - action.sa_handler = timeout;
|
|
| 65 | - action.sa_flags = 0;
|
|
| 66 | - sigemptyset(&action.sa_mask);
|
|
| 67 | - if (sigaction(SIGALRM, &action, NULL) == -1) {
|
|
| 68 | - fprintf(stderr,"SIGALRM problem\n");
|
|
| 69 | - exit(3);
|
|
| 70 | - }
|
|
| 71 | - alarm(1);
|
|
| 72 | - |
|
| 73 | - if (timer_create(CLOCK_REALTIME, &ev, &timer) != 0) {
|
|
| 74 | - fprintf(stderr,"No CLOCK_REALTIME timer\n");
|
|
| 75 | - exit(2);
|
|
| 76 | - }
|
|
| 77 | - |
|
| 78 | - tock = 0;
|
|
| 79 | - |
|
| 80 | - it.it_value.tv_sec = 0;
|
|
| 81 | - it.it_value.tv_nsec = 1000000; // 1ms
|
|
| 82 | - it.it_interval = it.it_value;
|
|
| 83 | - if (timer_settime(timer, 0, &it, NULL) != 0) {
|
|
| 84 | - fprintf(stderr,"settime problem\n");
|
|
| 85 | - exit(4);
|
|
| 86 | - }
|
|
| 87 | - |
|
| 88 | - // some environments have coarse scheduler/timer granularity of ~10ms and worse
|
|
| 89 | - usleep(100000); // 100ms
|
|
| 90 | - |
|
| 91 | - if (!tock) {
|
|
| 92 | - fprintf(stderr,"no CLOCK_REALTIME signal\n");
|
|
| 93 | - exit(5);
|
|
| 94 | - }
|
|
| 95 | - |
|
| 96 | - timer_delete(timer);
|
|
| 97 | - |
|
| 98 | - exit(0);
|
|
| 99 | -}
|
|
| 100 | - ],
|
|
| 101 | - [fptools_cv_timer_create_works=yes],
|
|
| 102 | - [fptools_cv_timer_create_works=no])
|
|
| 103 | - ])
|
|
| 104 | -case $fptools_cv_timer_create_works in
|
|
| 105 | - yes) AC_DEFINE([USE_TIMER_CREATE], 1,
|
|
| 106 | - [Define to 1 if we can use timer_create(CLOCK_REALTIME,...)]);;
|
|
| 107 | -esac
|
|
| 108 | - fi
|
|
| 109 | -fi
|
|
| 110 | -]) |
| ... | ... | @@ -7,12 +7,14 @@ |
| 7 | 7 | * ---------------------------------------------------------------------------*/
|
| 8 | 8 | |
| 9 | 9 | /*
|
| 10 | - * The interval timer is used for profiling and for context switching in the
|
|
| 11 | - * threaded build.
|
|
| 10 | + * The interval timer is used for profiling and for context switching.
|
|
| 12 | 11 | *
|
| 13 | 12 | * This file defines the platform-independent view of interval timing, relying
|
| 14 | - * on platform-specific services to install and run the timers.
|
|
| 13 | + * on platform-specific services to install and run the timers. See
|
|
| 14 | + * posix/Ticker.c and win32/Ticker.c for the platform specific parts.
|
|
| 15 | 15 | *
|
| 16 | + * If you are looking for Itimer.c then you either file or one of the
|
|
| 17 | + * platform-specific Ticker.c files.
|
|
| 16 | 18 | */
|
| 17 | 19 | |
| 18 | 20 | #include "rts/PosixSource.h"
|
| ... | ... | @@ -204,7 +204,6 @@ FP_MUSTTAIL |
| 204 | 204 | |
| 205 | 205 | dnl ** check for librt
|
| 206 | 206 | AC_CHECK_FUNCS(clock_gettime timer_settime)
|
| 207 | -FP_CHECK_TIMER_CREATE
|
|
| 208 | 207 | |
| 209 | 208 | dnl ** check for Apple's "interesting" long double compatibility scheme
|
| 210 | 209 | AC_MSG_CHECKING(for printf\$LDBLStub)
|
| ... | ... | @@ -15,4 +15,4 @@ |
| 15 | 15 | |
| 16 | 16 | void startTimer (void);
|
| 17 | 17 | void stopTimer (void);
|
| 18 | -int rtsTimerSignal (void); |
|
| 18 | +int rtsTimerSignal (void); // Deprecated: see issue #27073 |
| ... | ... | @@ -21,7 +21,7 @@ void arm_atomic_spin_unlock(void); |
| 21 | 21 | // Unconditionally atomic operations
|
| 22 | 22 | // These are atomic even in the non-threaded RTS. These are necessary in the
|
| 23 | 23 | // Proftimer implementation, which may be called from the pthreads-based
|
| 24 | -// ITimer implementation.
|
|
| 24 | +// Ticker implementation.
|
|
| 25 | 25 | #define RELAXED_LOAD_ALWAYS(ptr) __atomic_load_n(ptr, __ATOMIC_RELAXED)
|
| 26 | 26 | #define RELAXED_STORE_ALWAYS(ptr,val) __atomic_store_n(ptr, val, __ATOMIC_RELAXED)
|
| 27 | 27 | #define RELAXED_ADD_ALWAYS(ptr,val) __atomic_add_fetch(ptr, val, __ATOMIC_RELAXED)
|
| ... | ... | @@ -640,35 +640,6 @@ set_sigtstp_action (bool handle) |
| 640 | 640 | }
|
| 641 | 641 | }
|
| 642 | 642 | |
| 643 | -/* Used by ItimerTimerCreate and ItimerSetitimer implementations */
|
|
| 644 | -void
|
|
| 645 | -install_vtalrm_handler(int sig, TickProc handle_tick)
|
|
| 646 | -{
|
|
| 647 | - struct sigaction action;
|
|
| 648 | - memset(&action, 0, sizeof(struct sigaction));
|
|
| 649 | - |
|
| 650 | - action.sa_handler = handle_tick;
|
|
| 651 | - |
|
| 652 | - sigemptyset(&action.sa_mask);
|
|
| 653 | - |
|
| 654 | -#if defined(SA_RESTART)
|
|
| 655 | - // specify SA_RESTART. One consequence if we don't do this is
|
|
| 656 | - // that readline gets confused by the -threaded RTS. It seems
|
|
| 657 | - // that if a SIGALRM handler is installed without SA_RESTART,
|
|
| 658 | - // readline installs its own SIGALRM signal handler (see
|
|
| 659 | - // readline's signals.c), and this somehow causes readline to go
|
|
| 660 | - // wrong when the input exceeds a single line (try it).
|
|
| 661 | - action.sa_flags = SA_RESTART;
|
|
| 662 | -#else
|
|
| 663 | - action.sa_flags = 0;
|
|
| 664 | -#endif
|
|
| 665 | - |
|
| 666 | - if (sigaction(sig, &action, NULL) == -1) {
|
|
| 667 | - sysErrorBelch("sigaction");
|
|
| 668 | - stg_exit(EXIT_FAILURE);
|
|
| 669 | - }
|
|
| 670 | -}
|
|
| 671 | - |
|
| 672 | 643 | /* -----------------------------------------------------------------------------
|
| 673 | 644 | * Install default signal handlers.
|
| 674 | 645 | *
|
| ... | ... | @@ -25,8 +25,6 @@ extern siginfo_t *next_pending_handler; |
| 25 | 25 | void startSignalHandlers(Capability *cap);
|
| 26 | 26 | #endif
|
| 27 | 27 | |
| 28 | -void install_vtalrm_handler(int sig, TickProc handle_tick);
|
|
| 29 | - |
|
| 30 | 28 | /* Communicating with the IO manager thread (see GHC.Conc).
|
| 31 | 29 | *
|
| 32 | 30 | * TODO: these I/O manager things are not related to signals and ought to live
|
| ... | ... | @@ -2,116 +2,38 @@ |
| 2 | 2 | *
|
| 3 | 3 | * (c) The GHC Team, 1995-2007
|
| 4 | 4 | *
|
| 5 | - * Interval timer for profiling and pre-emptive scheduling.
|
|
| 5 | + * Posix implementation(s) of the interval timer for profiling and pre-emptive
|
|
| 6 | + * scheduling.
|
|
| 6 | 7 | *
|
| 7 | 8 | * ---------------------------------------------------------------------------*/
|
| 8 | 9 | |
| 9 | -/*
|
|
| 10 | - * The interval timer is used for profiling and for context switching in the
|
|
| 11 | - * threaded build. Though POSIX 1003.1b includes a standard interface for
|
|
| 12 | - * such things, no one really seems to be implementing them yet. Even
|
|
| 13 | - * Solaris 2.3 only seems to provide support for @CLOCK_REAL@, whereas we're
|
|
| 14 | - * keen on getting access to @CLOCK_VIRTUAL@.
|
|
| 15 | - *
|
|
| 16 | - * Hence, we often use the old-fashioned @setitimer@ that just about everyone
|
|
| 17 | - * seems to support. So much for standards.
|
|
| 18 | - *
|
|
| 19 | - * If you are looking for Itimer.c then this is the right file. I renamed it
|
|
| 20 | - * Ticker.c for consistency.
|
|
| 10 | +/* The interval timer is used for profiling and for context switching.
|
|
| 11 | + * This file defines the platform-specific services to install and run the
|
|
| 12 | + * timers, and we call this the ticker. See rts/Timer.c for the
|
|
| 13 | + * platform-dependent view of interval timing.
|
|
| 14 | + *
|
|
| 15 | + * Historically we had ticker implementations using signals. This was always a
|
|
| 16 | + * rather shakey thing to do but we had few alternatives.
|
|
| 17 | + * - One problem with using signals is that there are severe limits on what
|
|
| 18 | + * code can be called from signal handlers. In particular it's not possible
|
|
| 19 | + * to take locks in a signal handler contex. This was enough for contex
|
|
| 20 | + * switching, but it's no good for things like flushing the eventlog, or
|
|
| 21 | + * waking up rts tasks.
|
|
| 22 | + * - We also want to avoid using alarm signals, as these can interrupt system
|
|
| 23 | + * calls (#10840) or can be overwritten by user code.
|
|
| 21 | 24 | */
|
| 22 | 25 | |
| 23 | -#include "rts/PosixSource.h"
|
|
| 24 | - |
|
| 25 | -/* We've defined _POSIX_SOURCE via "rts/PosixSource.h", and yet still use
|
|
| 26 | - some non-POSIX features. With _POSIX_SOURCE defined, visibility of
|
|
| 27 | - non-POSIX extension prototypes requires _DARWIN_C_SOURCE on Mac OS X,
|
|
| 28 | - __BSD_VISIBLE on FreeBSD and DragonflyBSD, and _NetBSD_SOURCE on
|
|
| 29 | - NetBSD. Otherwise, for example, code using pthread_setname_np(3) and
|
|
| 30 | - variants will not compile. We must therefore define the additional
|
|
| 31 | - macros that expose non-POSIX APIs early, before any of the relevant
|
|
| 32 | - system headers are included via "Rts.h".
|
|
| 33 | - |
|
| 34 | - An alternative approach could be to write portable wrappers or stubs for all
|
|
| 35 | - the non-posix functions in a C-module that does not include "rts/PosixSource.h",
|
|
| 36 | - and then use only POSIX features and the portable wrapper functions in all
|
|
| 37 | - other C-modules. */
|
|
| 38 | -#include "ghcconfig.h"
|
|
| 39 | -#if defined(freebsd_HOST_OS) || defined(dragonfly_HOST_OS)
|
|
| 40 | -#define __BSD_VISIBLE 1
|
|
| 41 | -#endif
|
|
| 42 | -#if defined(darwin_HOST_OS)
|
|
| 43 | -#define _DARWIN_C_SOURCE 1
|
|
| 44 | -#endif
|
|
| 45 | -#if defined(netbsd_HOST_OS)
|
|
| 46 | -#define _NETBSD_SOURCE 1
|
|
| 47 | -#endif
|
|
| 48 | - |
|
| 49 | -#include "Rts.h"
|
|
| 50 | - |
|
| 51 | -/*
|
|
| 52 | - * It used to be that timer_create doesn't exist on iOS and setitimer doesn't fire on iOS
|
|
| 53 | - * during debugging. See #7723. Seems to be an issue with signals.
|
|
| 54 | - *
|
|
| 55 | - * We also want to avoid using alarm signals, as these can interrupt system calls (#10840)
|
|
| 56 | - * or can be overwritten by user code.
|
|
| 26 | +/* Select a ticker implementation to use:
|
|
| 57 | 27 | *
|
| 58 | - * So we are using the pthread based implementation.
|
|
| 59 | - */
|
|
| 60 | -#if defined(ios_HOST_OS) || defined(darwin_HOST_OS)
|
|
| 61 | -#define USE_PTHREAD_FOR_ITIMER
|
|
| 62 | -#endif
|
|
| 63 | - |
|
| 64 | -/*
|
|
| 65 | - * On Linux we can use timerfd_* (introduced in Linux
|
|
| 66 | - * 2.6.25) and a thread instead of alarm signals. It avoids the risk of
|
|
| 67 | - * interrupting syscalls (see #10840) and the risk of being accidentally
|
|
| 68 | - * modified in user code using signals. NetBSD has also added timerfd
|
|
| 69 | - * support since version 10.
|
|
| 28 | + * On modern Linux, FreeBSD and NetBSD we can use timerfd_create and a thread
|
|
| 29 | + * that waits on it using poll. Linux has had timerfd since version 2.6.25.
|
|
| 30 | + * NetBSD has had timerfd since version 10, and FreeBSD since version 15.
|
|
| 70 | 31 | *
|
| 71 | - * For older version of linux/netbsd without timerfd we fall back to the
|
|
| 72 | - * pthread based implementation.
|
|
| 32 | + * For older version of linux/bsd without timerfd, and for all other posix
|
|
| 33 | + * platforms, we use the implementation using posix pthreads and nanosleep().
|
|
| 73 | 34 | */
|
| 74 | 35 | #if defined(HAVE_SYS_TIMERFD_H)
|
| 75 | -#define USE_TIMERFD_FOR_ITIMER
|
|
| 76 | -#endif
|
|
| 77 | - |
|
| 78 | -#if defined(linux_HOST_OS)
|
|
| 79 | -#define USE_PTHREAD_FOR_ITIMER
|
|
| 80 | -#endif
|
|
| 81 | - |
|
| 82 | -#if defined(netbsd_HOST_OS)
|
|
| 83 | -#define USE_PTHREAD_FOR_ITIMER
|
|
| 84 | -#endif
|
|
| 85 | - |
|
| 86 | -#if defined(freebsd_HOST_OS)
|
|
| 87 | -#define USE_PTHREAD_FOR_ITIMER
|
|
| 88 | -#endif
|
|
| 89 | - |
|
| 90 | -#if defined(solaris2_HOST_OS)
|
|
| 91 | -/* USE_TIMER_CREATE is usually disabled for Solaris. In fact it is
|
|
| 92 | - supported well on this OS, but requires additional privilege. When
|
|
| 93 | - user does not have it, then the testing configure program fails
|
|
| 94 | - which results in USE_TIMER_CREATE not defined.
|
|
| 95 | - On the other hand when we cross-compile, then we optimistically
|
|
| 96 | - assume usage of timer_create function. The problem is that if we
|
|
| 97 | - cross compile for example from i386-solaris2 to x86_64-solaris2,
|
|
| 98 | - then the build fails with error like this:
|
|
| 99 | - |
|
| 100 | -ghc-stage2: timer_create: Not owner
|
|
| 101 | - |
|
| 102 | - which happens on first ghc-stage2 invocation. So to support
|
|
| 103 | - cross-compilation to Solaris we manually undefine USE_TIMER_CREATE
|
|
| 104 | - here */
|
|
| 105 | -#undef USE_TIMER_CREATE
|
|
| 106 | -#endif /* solaris2_HOST_OS */
|
|
| 107 | - |
|
| 108 | -// Select the variant to use
|
|
| 109 | -#if defined(USE_TIMERFD_FOR_ITIMER)
|
|
| 110 | 36 | #include "ticker/TimerFd.c"
|
| 111 | -#elif defined(USE_PTHREAD_FOR_ITIMER)
|
|
| 112 | -#include "ticker/Pthread.c"
|
|
| 113 | -#elif defined(USE_TIMER_CREATE)
|
|
| 114 | -#include "ticker/TimerCreate.c"
|
|
| 115 | 37 | #else
|
| 116 | -#include "ticker/Setitimer.c"
|
|
| 38 | +#include "ticker/Pthread.c"
|
|
| 117 | 39 | #endif |
| 1 | -/* -----------------------------------------------------------------------------
|
|
| 2 | - *
|
|
| 3 | - * (c) The GHC Team, 1995-2007
|
|
| 4 | - *
|
|
| 5 | - * Interval timer for profiling and pre-emptive scheduling.
|
|
| 6 | - *
|
|
| 7 | - * ---------------------------------------------------------------------------*/
|
|
| 8 | - |
|
| 9 | -#include "rts/PosixSource.h"
|
|
| 10 | -#include "Rts.h"
|
|
| 11 | - |
|
| 12 | -#include "Ticker.h"
|
|
| 13 | -#include "Proftimer.h"
|
|
| 14 | -#include "Schedule.h"
|
|
| 15 | -#include "posix/Clock.h"
|
|
| 16 | -#include "posix/Signals.h"
|
|
| 17 | - |
|
| 18 | -#include <time.h>
|
|
| 19 | -#if HAVE_SYS_TIME_H
|
|
| 20 | -# include <sys/time.h>
|
|
| 21 | -#endif
|
|
| 22 | - |
|
| 23 | -#if defined(HAVE_SIGNAL_H)
|
|
| 24 | -# include <signal.h>
|
|
| 25 | -#endif
|
|
| 26 | - |
|
| 27 | -#include <string.h>
|
|
| 28 | - |
|
| 29 | -static Time itimer_interval = DEFAULT_TICK_INTERVAL;
|
|
| 30 | - |
|
| 31 | -void
|
|
| 32 | -initTicker (Time interval, TickProc handle_tick)
|
|
| 33 | -{
|
|
| 34 | - itimer_interval = interval;
|
|
| 35 | - install_vtalrm_handler(SIGALRM, handle_tick);
|
|
| 36 | -}
|
|
| 37 | - |
|
| 38 | -void
|
|
| 39 | -startTicker(void)
|
|
| 40 | -{
|
|
| 41 | - struct itimerval it;
|
|
| 42 | - |
|
| 43 | - it.it_value.tv_sec = TimeToSeconds(itimer_interval);
|
|
| 44 | - it.it_value.tv_usec = TimeToUS(itimer_interval) % 1000000;
|
|
| 45 | - it.it_interval = it.it_value;
|
|
| 46 | - |
|
| 47 | - if (setitimer(ITIMER_REAL, &it, NULL) != 0) {
|
|
| 48 | - sysErrorBelch("setitimer");
|
|
| 49 | - stg_exit(EXIT_FAILURE);
|
|
| 50 | - }
|
|
| 51 | -}
|
|
| 52 | - |
|
| 53 | -void
|
|
| 54 | -stopTicker(void)
|
|
| 55 | -{
|
|
| 56 | - struct itimerval it;
|
|
| 57 | - |
|
| 58 | - it.it_value.tv_sec = 0;
|
|
| 59 | - it.it_value.tv_usec = 0;
|
|
| 60 | - it.it_interval = it.it_value;
|
|
| 61 | - |
|
| 62 | - if (setitimer(ITIMER_REAL, &it, NULL) != 0) {
|
|
| 63 | - sysErrorBelch("setitimer");
|
|
| 64 | - stg_exit(EXIT_FAILURE);
|
|
| 65 | - }
|
|
| 66 | -}
|
|
| 67 | - |
|
| 68 | -void
|
|
| 69 | -exitTicker (bool wait STG_UNUSED)
|
|
| 70 | -{
|
|
| 71 | - return;
|
|
| 72 | -}
|
|
| 73 | - |
|
| 74 | -int
|
|
| 75 | -rtsTimerSignal(void)
|
|
| 76 | -{
|
|
| 77 | - return SIGALRM;
|
|
| 78 | - // Using SIGALRM can leads to problems, see #850. But we have no
|
|
| 79 | - // option if timer_create() is not available.
|
|
| 80 | -} |
| 1 | -/* -----------------------------------------------------------------------------
|
|
| 2 | - *
|
|
| 3 | - * (c) The GHC Team, 1995-2007
|
|
| 4 | - *
|
|
| 5 | - * Interval timer for profiling and pre-emptive scheduling.
|
|
| 6 | - *
|
|
| 7 | - * ---------------------------------------------------------------------------*/
|
|
| 8 | - |
|
| 9 | -#include "rts/PosixSource.h"
|
|
| 10 | -#include "Rts.h"
|
|
| 11 | - |
|
| 12 | -#include "Ticker.h"
|
|
| 13 | -#include "Proftimer.h"
|
|
| 14 | -#include "Schedule.h"
|
|
| 15 | -#include "posix/Clock.h"
|
|
| 16 | -#include "posix/Signals.h"
|
|
| 17 | - |
|
| 18 | -#if defined(HAVE_SIGNAL_H)
|
|
| 19 | -# include <signal.h>
|
|
| 20 | -#endif
|
|
| 21 | - |
|
| 22 | -#include <string.h>
|
|
| 23 | - |
|
| 24 | -static Time itimer_interval = DEFAULT_TICK_INTERVAL;
|
|
| 25 | -static timer_t timer;
|
|
| 26 | - |
|
| 27 | -void
|
|
| 28 | -initTicker (Time interval, TickProc handle_tick)
|
|
| 29 | -{
|
|
| 30 | - itimer_interval = interval;
|
|
| 31 | - |
|
| 32 | - struct sigevent ev;
|
|
| 33 | - |
|
| 34 | - // Keep programs like valgrind happy
|
|
| 35 | - memset(&ev, 0, sizeof(ev));
|
|
| 36 | - |
|
| 37 | - ev.sigev_notify = SIGEV_SIGNAL;
|
|
| 38 | - ev.sigev_signo = SIGVTALRM;
|
|
| 39 | - |
|
| 40 | - if (timer_create(CLOCK_ID, &ev, &timer) != 0) {
|
|
| 41 | - sysErrorBelch("timer_create");
|
|
| 42 | - stg_exit(EXIT_FAILURE);
|
|
| 43 | - }
|
|
| 44 | - |
|
| 45 | - install_vtalrm_handler(SIGVTALRM, handle_tick);
|
|
| 46 | -}
|
|
| 47 | - |
|
| 48 | -void
|
|
| 49 | -startTicker(void)
|
|
| 50 | -{
|
|
| 51 | - struct itimerspec it;
|
|
| 52 | - |
|
| 53 | - it.it_value.tv_sec = TimeToSeconds(itimer_interval);
|
|
| 54 | - it.it_value.tv_nsec = TimeToNS(itimer_interval) % 1000000000;
|
|
| 55 | - it.it_interval = it.it_value;
|
|
| 56 | - |
|
| 57 | - if (timer_settime(timer, 0, &it, NULL) != 0) {
|
|
| 58 | - sysErrorBelch("timer_settime");
|
|
| 59 | - stg_exit(EXIT_FAILURE);
|
|
| 60 | - }
|
|
| 61 | -}
|
|
| 62 | - |
|
| 63 | -void
|
|
| 64 | -stopTicker(void)
|
|
| 65 | -{
|
|
| 66 | - struct itimerspec it;
|
|
| 67 | - |
|
| 68 | - it.it_value.tv_sec = 0;
|
|
| 69 | - it.it_value.tv_nsec = 0;
|
|
| 70 | - it.it_interval = it.it_value;
|
|
| 71 | - |
|
| 72 | - if (timer_settime(timer, 0, &it, NULL) != 0) {
|
|
| 73 | - sysErrorBelch("timer_settime");
|
|
| 74 | - stg_exit(EXIT_FAILURE);
|
|
| 75 | - }
|
|
| 76 | -}
|
|
| 77 | - |
|
| 78 | -void
|
|
| 79 | -exitTicker (bool wait STG_UNUSED)
|
|
| 80 | -{
|
|
| 81 | - // Before deleting the timer set the signal to ignore to avoid the
|
|
| 82 | - // possibility of the signal being delivered after the timer is deleted.
|
|
| 83 | - signal(SIGVTALRM, SIG_IGN);
|
|
| 84 | - timer_delete(timer);
|
|
| 85 | - // ignore errors - we don't really care if it fails.
|
|
| 86 | -}
|
|
| 87 | - |
|
| 88 | -int
|
|
| 89 | -rtsTimerSignal(void)
|
|
| 90 | -{
|
|
| 91 | - return SIGVTALRM;
|
|
| 92 | -} |
| 1 | +{-# LANGUAGE OverloadedStrings #-}
|
|
| 2 | + |
|
| 3 | +-- GHC used to run out of simplifier ticks due to inlining the internals of
|
|
| 4 | +-- `toStrict . toLazyByteString`.
|
|
| 5 | +module T13960 (breaks) where
|
|
| 6 | + |
|
| 7 | +import Data.ByteString (ByteString)
|
|
| 8 | +import Data.ByteString.Builder (Builder, stringUtf8, toLazyByteString)
|
|
| 9 | +import Data.ByteString.Lazy (toStrict)
|
|
| 10 | +import Data.String (IsString(..))
|
|
| 11 | + |
|
| 12 | +newtype Query = Query ByteString
|
|
| 13 | + |
|
| 14 | +toByteString :: Builder -> ByteString
|
|
| 15 | +toByteString x = toStrict (toLazyByteString x)
|
|
| 16 | + |
|
| 17 | +instance IsString Query where
|
|
| 18 | + fromString = Query . toByteString . stringUtf8
|
|
| 19 | + |
|
| 20 | +breaks :: [(Query, Query)]
|
|
| 21 | +breaks =
|
|
| 22 | + [ ("query001a", "query001b")
|
|
| 23 | + , ("query002a", "query002b")
|
|
| 24 | + , ("query003a", "query003b")
|
|
| 25 | + , ("query004a", "query004b")
|
|
| 26 | + , ("query005a", "query005b")
|
|
| 27 | + , ("query006a", "query006b")
|
|
| 28 | + , ("query007a", "query007b")
|
|
| 29 | + , ("query008a", "query008b")
|
|
| 30 | + , ("query009a", "query009b")
|
|
| 31 | + , ("query010a", "query010b")
|
|
| 32 | + , ("query011a", "query011b")
|
|
| 33 | + , ("query012a", "query012b")
|
|
| 34 | + , ("query013a", "query013b")
|
|
| 35 | + , ("query014a", "query014b")
|
|
| 36 | + , ("query015a", "query015b")
|
|
| 37 | + , ("query016a", "query016b")
|
|
| 38 | + , ("query017a", "query017b")
|
|
| 39 | + , ("query018a", "query018b")
|
|
| 40 | + , ("query019a", "query019b")
|
|
| 41 | + , ("query020a", "query020b")
|
|
| 42 | + , ("query021a", "query021b")
|
|
| 43 | + , ("query022a", "query022b")
|
|
| 44 | + , ("query023a", "query023b")
|
|
| 45 | + , ("query024a", "query024b")
|
|
| 46 | + , ("query025a", "query025b")
|
|
| 47 | + , ("query026a", "query026b")
|
|
| 48 | + , ("query027a", "query027b")
|
|
| 49 | + , ("query028a", "query028b")
|
|
| 50 | + , ("query029a", "query029b")
|
|
| 51 | + , ("query030a", "query030b")
|
|
| 52 | + , ("query031a", "query031b")
|
|
| 53 | + , ("query032a", "query032b")
|
|
| 54 | + , ("query033a", "query033b")
|
|
| 55 | + , ("query034a", "query034b")
|
|
| 56 | + , ("query035a", "query035b")
|
|
| 57 | + , ("query036a", "query036b")
|
|
| 58 | + , ("query037a", "query037b")
|
|
| 59 | + , ("query038a", "query038b")
|
|
| 60 | + , ("query039a", "query039b")
|
|
| 61 | + , ("query040a", "query040b")
|
|
| 62 | + , ("query041a", "query041b")
|
|
| 63 | + , ("query042a", "query042b")
|
|
| 64 | + , ("query043a", "query043b")
|
|
| 65 | + , ("query044a", "query044b")
|
|
| 66 | + , ("query045a", "query045b")
|
|
| 67 | + , ("query046a", "query046b")
|
|
| 68 | + , ("query047a", "query047b")
|
|
| 69 | + , ("query048a", "query048b")
|
|
| 70 | + , ("query049a", "query049b")
|
|
| 71 | + , ("query050a", "query050b")
|
|
| 72 | + ] |
| ... | ... | @@ -686,6 +686,12 @@ test ('T13820', |
| 686 | 686 | ],
|
| 687 | 687 | compile,
|
| 688 | 688 | ['-v0'])
|
| 689 | +test ('T13960',
|
|
| 690 | + [ collect_compiler_stats('peak_megabytes_allocated', 20),
|
|
| 691 | + collect_compiler_stats('bytes allocated', 2),
|
|
| 692 | + ],
|
|
| 693 | + compile,
|
|
| 694 | + ['-O'])
|
|
| 689 | 695 | test ('T14766',
|
| 690 | 696 | [ collect_compiler_stats('bytes allocated',2),
|
| 691 | 697 | pre_cmd('python3 genT14766.py > T14766.hs'),
|