Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
-
a46a1bb1
by Cheng Shao at 2026-03-09T04:50:30-04:00
-
4afc65b1
by Cheng Shao at 2026-03-09T04:50:30-04:00
8 changed files:
- compiler/GHC/Cmm/Utils.hs
- compiler/GHC/StgToCmm/Prim.hs
- rts/PrimOps.cmm
- rts/RtsSymbols.c
- rts/Threads.c
- rts/Threads.h
- rts/include/rts/Threads.h
- rts/include/stg/MiscClosures.h
Changes:
| ... | ... | @@ -37,6 +37,7 @@ module GHC.Cmm.Utils( |
| 37 | 37 | |
| 38 | 38 | baseExpr, spExpr, hpExpr, spLimExpr, hpLimExpr,
|
| 39 | 39 | currentTSOExpr, currentNurseryExpr, cccsExpr,
|
| 40 | + myCapabilityExpr,
|
|
| 40 | 41 | |
| 41 | 42 | -- Tagging
|
| 42 | 43 | cmmTagMask, cmmPointerMask, cmmUntag, cmmIsTagged, cmmIsNotTagged,
|
| ... | ... | @@ -569,7 +570,7 @@ blockTicks b = reverse $ foldBlockNodesF goStmt b [] |
| 569 | 570 | -- Access to common global registers
|
| 570 | 571 | |
| 571 | 572 | baseExpr, spExpr, hpExpr, currentTSOExpr, currentNurseryExpr,
|
| 572 | - spLimExpr, hpLimExpr, cccsExpr :: Platform -> CmmExpr
|
|
| 573 | + spLimExpr, hpLimExpr, cccsExpr, myCapabilityExpr :: Platform -> CmmExpr
|
|
| 573 | 574 | baseExpr p = CmmReg $ baseReg p
|
| 574 | 575 | spExpr p = CmmReg $ spReg p
|
| 575 | 576 | spLimExpr p = CmmReg $ spLimReg p
|
| ... | ... | @@ -578,3 +579,5 @@ hpLimExpr p = CmmReg $ hpLimReg p |
| 578 | 579 | currentTSOExpr p = CmmReg $ currentTSOReg p
|
| 579 | 580 | currentNurseryExpr p = CmmReg $ currentNurseryReg p
|
| 580 | 581 | cccsExpr p = CmmReg $ cccsReg p
|
| 582 | +myCapabilityExpr p =
|
|
| 583 | + cmmRegOff (baseReg p) $ negate $ pc_OFFSET_Capability_r $ platformConstants p |
| ... | ... | @@ -345,6 +345,25 @@ emitPrimOp cfg primop = |
| 345 | 345 | emitPrimCall [res] (MO_Xchg (wordWidth platform)) [dst, val]
|
| 346 | 346 | emitDirtyMutVar mutv (CmmReg (CmmLocal res))
|
| 347 | 347 | |
| 348 | + TryPutMVarOp -> \[mvar, val] -> inlinePrimop $ \[res] -> do
|
|
| 349 | + cres <- newTemp b8
|
|
| 350 | + emitCCall
|
|
| 351 | + [(cres, NoHint)]
|
|
| 352 | + ( CmmLit
|
|
| 353 | + ( CmmLabel
|
|
| 354 | + ( mkForeignLabel
|
|
| 355 | + (fsLit "performTryPutMVar")
|
|
| 356 | + ForeignLabelInExternalPackage
|
|
| 357 | + IsFunction
|
|
| 358 | + )
|
|
| 359 | + )
|
|
| 360 | + )
|
|
| 361 | + [(myCapabilityExpr platform, AddrHint), (mvar, AddrHint), (val, AddrHint)]
|
|
| 362 | + emitAssign (CmmLocal res) $
|
|
| 363 | + CmmMachOp
|
|
| 364 | + (MO_UU_Conv W8 (wordWidth platform))
|
|
| 365 | + [CmmReg (CmmLocal cres)]
|
|
| 366 | + |
|
| 348 | 367 | -- #define sizzeofByteArrayzh(r,a) \
|
| 349 | 368 | -- r = ((StgArrBytes *)(a))->bytes
|
| 350 | 369 | SizeofByteArrayOp -> \[arg] -> inlinePrimop $ \[res] ->
|
| ... | ... | @@ -1777,7 +1796,6 @@ emitPrimOp cfg primop = |
| 1777 | 1796 | TakeMVarOp -> alwaysExternal
|
| 1778 | 1797 | TryTakeMVarOp -> alwaysExternal
|
| 1779 | 1798 | PutMVarOp -> alwaysExternal
|
| 1780 | - TryPutMVarOp -> alwaysExternal
|
|
| 1781 | 1799 | ReadMVarOp -> alwaysExternal
|
| 1782 | 1800 | TryReadMVarOp -> alwaysExternal
|
| 1783 | 1801 | IsEmptyMVarOp -> alwaysExternal
|
| ... | ... | @@ -1927,95 +1927,6 @@ loop: |
| 1927 | 1927 | }
|
| 1928 | 1928 | |
| 1929 | 1929 | |
| 1930 | -// NOTE: there is another implementation of this function in
|
|
| 1931 | -// Threads.c:performTryPutMVar(). Keep them in sync! It was
|
|
| 1932 | -// measurably slower to call the C function from here (70% for a
|
|
| 1933 | -// tight loop doing tryPutMVar#).
|
|
| 1934 | -//
|
|
| 1935 | -// TODO: we could kill the duplication by making tryPutMVar# into an
|
|
| 1936 | -// inline primop that expands into a C call to performTryPutMVar().
|
|
| 1937 | -stg_tryPutMVarzh ( P_ mvar, /* :: MVar a */
|
|
| 1938 | - P_ val, /* :: a */ )
|
|
| 1939 | -{
|
|
| 1940 | - W_ info, tso, q, qinfo;
|
|
| 1941 | - |
|
| 1942 | - LOCK_CLOSURE(mvar, info);
|
|
| 1943 | - |
|
| 1944 | - if (StgMVar_value(mvar) != stg_END_TSO_QUEUE_closure) {
|
|
| 1945 | -#if defined(THREADED_RTS)
|
|
| 1946 | - unlockClosure(mvar, info);
|
|
| 1947 | -#endif
|
|
| 1948 | - return (0);
|
|
| 1949 | - }
|
|
| 1950 | - |
|
| 1951 | - q = StgMVar_head(mvar);
|
|
| 1952 | -loop:
|
|
| 1953 | - if (q == stg_END_TSO_QUEUE_closure) {
|
|
| 1954 | - /* No further takes, the MVar is now full. */
|
|
| 1955 | - if (info == stg_MVAR_CLEAN_info) {
|
|
| 1956 | - ccall dirty_MVAR(BaseReg "ptr", mvar "ptr", StgMVar_value(mvar) "ptr");
|
|
| 1957 | - }
|
|
| 1958 | - |
|
| 1959 | - StgMVar_value(mvar) = val;
|
|
| 1960 | - unlockClosure(mvar, stg_MVAR_DIRTY_info);
|
|
| 1961 | - return (1);
|
|
| 1962 | - }
|
|
| 1963 | - |
|
| 1964 | - qinfo = GET_INFO_ACQUIRE(q);
|
|
| 1965 | - |
|
| 1966 | - if (qinfo == stg_IND_info ||
|
|
| 1967 | - qinfo == stg_MSG_NULL_info) {
|
|
| 1968 | - q = %acquire StgInd_indirectee(q);
|
|
| 1969 | - goto loop;
|
|
| 1970 | - }
|
|
| 1971 | - |
|
| 1972 | - // There are takeMVar(s) waiting: wake up the first one
|
|
| 1973 | - |
|
| 1974 | - tso = StgMVarTSOQueue_tso(q);
|
|
| 1975 | - q = StgMVarTSOQueue_link(q);
|
|
| 1976 | - StgMVar_head(mvar) = q;
|
|
| 1977 | - if (q == stg_END_TSO_QUEUE_closure) {
|
|
| 1978 | - StgMVar_tail(mvar) = stg_END_TSO_QUEUE_closure;
|
|
| 1979 | - } else {
|
|
| 1980 | - if (info == stg_MVAR_CLEAN_info) {
|
|
| 1981 | - // Resolve #18919.
|
|
| 1982 | - ccall dirty_MVAR(BaseReg "ptr", mvar "ptr",
|
|
| 1983 | - StgMVar_value(mvar) "ptr");
|
|
| 1984 | - info = stg_MVAR_DIRTY_info;
|
|
| 1985 | - }
|
|
| 1986 | - }
|
|
| 1987 | - |
|
| 1988 | - // save why_blocked here, because waking up the thread destroys
|
|
| 1989 | - // this information
|
|
| 1990 | - W_ why_blocked;
|
|
| 1991 | - why_blocked = TO_W_(StgTSO_why_blocked(tso)); // TODO: Missing barrier
|
|
| 1992 | - ASSERT(StgTSO_block_info(tso) == mvar);
|
|
| 1993 | - |
|
| 1994 | - // actually perform the takeMVar
|
|
| 1995 | - W_ stack;
|
|
| 1996 | - stack = StgTSO_stackobj(tso);
|
|
| 1997 | - if (IS_STACK_CLEAN(stack)) {
|
|
| 1998 | - ccall dirty_STACK(MyCapability() "ptr", stack "ptr");
|
|
| 1999 | - }
|
|
| 2000 | - PerformTake(stack, val);
|
|
| 2001 | - |
|
| 2002 | - // indicate that the MVar operation has now completed.
|
|
| 2003 | - StgTSO__link(tso) = stg_END_TSO_QUEUE_closure;
|
|
| 2004 | - |
|
| 2005 | - ccall tryWakeupThread(MyCapability() "ptr", tso);
|
|
| 2006 | - |
|
| 2007 | - // If it was a readMVar, then we can still do work,
|
|
| 2008 | - // so loop back. (XXX: This could take a while)
|
|
| 2009 | - if (why_blocked == BlockedOnMVarRead)
|
|
| 2010 | - goto loop;
|
|
| 2011 | - |
|
| 2012 | - ASSERT(why_blocked == BlockedOnMVar);
|
|
| 2013 | - |
|
| 2014 | - unlockClosure(mvar, info);
|
|
| 2015 | - return (1);
|
|
| 2016 | -}
|
|
| 2017 | - |
|
| 2018 | - |
|
| 2019 | 1930 | stg_readMVarzh ( P_ mvar, /* :: MVar a */ )
|
| 2020 | 1931 | {
|
| 2021 | 1932 | W_ val, info, tso, q;
|
| ... | ... | @@ -678,6 +678,7 @@ extern char **environ; |
| 678 | 678 | SymI_HasDataProto(stg_readTVarIOzh) \
|
| 679 | 679 | SymI_HasProto(resumeThread) \
|
| 680 | 680 | SymI_HasProto(setNumCapabilities) \
|
| 681 | + SymI_HasProto(performTryPutMVar) \
|
|
| 681 | 682 | SymI_HasProto(getNumberOfProcessors) \
|
| 682 | 683 | SymI_HasProto(resolveObjs) \
|
| 683 | 684 | SymI_HasDataProto(stg_retryzh) \
|
| ... | ... | @@ -869,7 +870,6 @@ extern char **environ; |
| 869 | 870 | SymI_HasDataProto(stg_takeMVarzh) \
|
| 870 | 871 | SymI_HasDataProto(stg_readMVarzh) \
|
| 871 | 872 | SymI_HasDataProto(stg_threadStatuszh) \
|
| 872 | - SymI_HasDataProto(stg_tryPutMVarzh) \
|
|
| 873 | 873 | SymI_HasDataProto(stg_tryTakeMVarzh) \
|
| 874 | 874 | SymI_HasDataProto(stg_tryReadMVarzh) \
|
| 875 | 875 | SymI_HasDataProto(stg_unmaskAsyncExceptionszh) \
|
| ... | ... | @@ -795,8 +795,6 @@ threadStackUnderflow (Capability *cap, StgTSO *tso) |
| 795 | 795 | |
| 796 | 796 | /* ----------------------------------------------------------------------------
|
| 797 | 797 | Implementation of tryPutMVar#
|
| 798 | - |
|
| 799 | - NOTE: this should be kept in sync with stg_tryPutMVarzh in PrimOps.cmm
|
|
| 800 | 798 | ------------------------------------------------------------------------- */
|
| 801 | 799 | |
| 802 | 800 | bool performTryPutMVar(Capability *cap, StgMVar *mvar, StgClosure *value)
|
| ... | ... | @@ -24,7 +24,7 @@ void migrateThread (Capability *from, StgTSO *tso, Capability *to); |
| 24 | 24 | //
|
| 25 | 25 | #if defined(THREADED_RTS)
|
| 26 | 26 | void wakeupThreadOnCapability (Capability *cap,
|
| 27 | - Capability *other_cap,
|
|
| 27 | + Capability *other_cap,
|
|
| 28 | 28 | StgTSO *tso);
|
| 29 | 29 | #endif
|
| 30 | 30 | |
| ... | ... | @@ -40,8 +40,6 @@ StgBool isThreadBound (StgTSO* tso); |
| 40 | 40 | void threadStackOverflow (Capability *cap, StgTSO *tso);
|
| 41 | 41 | W_ threadStackUnderflow (Capability *cap, StgTSO *tso);
|
| 42 | 42 | |
| 43 | -bool performTryPutMVar(Capability *cap, StgMVar *mvar, StgClosure *value);
|
|
| 44 | - |
|
| 45 | 43 | #if defined(DEBUG)
|
| 46 | 44 | void printThreadBlockage (StgTSO *tso);
|
| 47 | 45 | void printThreadStatus (StgTSO *t);
|
| ... | ... | @@ -90,3 +90,5 @@ extern Capability MainCapability; |
| 90 | 90 | // current value at the moment).
|
| 91 | 91 | //
|
| 92 | 92 | extern void setNumCapabilities (uint32_t new_);
|
| 93 | + |
|
| 94 | +bool performTryPutMVar(Capability *cap, StgMVar *mvar, StgClosure *value); |
| ... | ... | @@ -512,7 +512,6 @@ RTS_FUN_DECL(stg_takeMVarzh); |
| 512 | 512 | RTS_FUN_DECL(stg_putMVarzh);
|
| 513 | 513 | RTS_FUN_DECL(stg_readMVarzh);
|
| 514 | 514 | RTS_FUN_DECL(stg_tryTakeMVarzh);
|
| 515 | -RTS_FUN_DECL(stg_tryPutMVarzh);
|
|
| 516 | 515 | RTS_FUN_DECL(stg_tryReadMVarzh);
|
| 517 | 516 | |
| 518 | 517 | RTS_FUN_DECL(stg_waitReadzh);
|