Ticket #7606: ghc-stride-scheduling-sorted-list-2.10.patch
| File ghc-stride-scheduling-sorted-list-2.10.patch, 27.3 KB (added by ezyang, 4 months ago) |
|---|
-
compiler/llvmGen/LlvmCodeGen/CodeGen.hs
diff --git a/compiler/llvmGen/LlvmCodeGen/CodeGen.hs b/compiler/llvmGen/LlvmCodeGen/CodeGen.hs index 763656a..f6cd118 100644
a b 31 31 import Unique 32 32 import Util 33 33 34 import Data.List ( partition )35 34 import Data.List ( partition ) 35 import Data.Maybe ( fromMaybe ) 36 36 37 37 type LlvmStatements = OrdList LlvmStatement 38 38 … … 706 706 genCondBranch env cond idT idF = do 707 707 let labelT = blockIdToLlvm idT 708 708 let labelF = blockIdToLlvm idF 709 -- See Note [Literals and branch conditions] 709 710 (env', vc, stmts, top) <- exprToVarOpt env i1Option cond 710 711 if getVarType vc == i1 711 712 then do … … 714 715 else 715 716 panic $ "genCondBranch: Cond expr not bool! (" ++ show vc ++ ")" 716 717 718 {- Note [Literals and branch conditions] 719 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 720 721 It is important that whenever we generate branch conditions for 722 literals like '1', they are properly narrowed to an LLVM expression of 723 type 'i1' (for bools.) Otherwise, nobody is happy. So when we convert 724 a CmmExpr to an LLVM expression for a branch conditional, exprToVarOpt 725 must be certain to return a properly narrowed type. genLit is 726 responsible for this, in the case of literal integers. 727 728 Often, we won't see direct statements like: 729 730 if(1) { 731 ... 732 } else { 733 ... 734 } 735 736 at this point in the pipeline, because the Glorious Code Generator 737 will do trivial branch elimination in the sinking pass (among others,) 738 which will eliminate the expression entirely. 739 740 However, it's certainly possible and reasonable for this to occur in 741 hand-written C-- code. Consider something like: 742 743 #ifndef SOME_CONDITIONAL 744 #define CHECK_THING(x) 1 745 #else 746 #define CHECK_THING(x) some_operation((x)) 747 #endif 748 749 f() { 750 751 if (CHECK_THING(xyz)) { 752 ... 753 } else { 754 ... 755 } 756 757 } 758 759 In such an instance, CHECK_THING might result in an *expression* in 760 one case, and a *literal* in the other, depending on what in 761 particular was #define'd. So we must be sure to properly narrow the 762 literal in this case to i1 as it won't be eliminated beforehand. 763 764 For a real example of this, see ./rts/StgStdThunks.cmm 765 766 -} 767 768 717 769 718 770 -- | Switch branch 719 771 -- … … 770 822 exprToVarOpt env opt e = case e of 771 823 772 824 CmmLit lit 773 -> genLit env lit825 -> genLit opt env lit -- See Note [Literals and branch conditions] 774 826 775 827 CmmLoad e' ty 776 828 -> genLoad env e' ty … … 1206 1258 1207 1259 1208 1260 -- | Generate code for a literal 1209 genLit :: LlvmEnv -> CmmLit -> UniqSM ExprData 1210 genLit env (CmmInt i w) 1211 = return (env, mkIntLit (LMInt $ widthInBits w) i, nilOL, []) 1261 genLit :: EOption -> LlvmEnv -> CmmLit -> UniqSM ExprData 1262 genLit (EOption opt) env (CmmInt i w) 1263 -- See Note [Literals and branch conditions] 1264 = let width = fromMaybe (LMInt $ widthInBits w) opt 1265 in return (env, mkIntLit width i, nilOL, []) 1212 1266 1213 genLit env (CmmFloat r w)1267 genLit _ env (CmmFloat r w) 1214 1268 = return (env, LMLitVar $ LMFloatLit (fromRational r) (widthToLlvmFloat w), 1215 1269 nilOL, []) 1216 1270 1217 genLit env cmm@(CmmLabel l)1271 genLit _ env cmm@(CmmLabel l) 1218 1272 = let dflags = getDflags env 1219 1273 label = strCLabel_llvm env l 1220 1274 ty = funLookup label env … … 1236 1290 (v1, s1) <- doExpr lmty $ Cast LM_Ptrtoint var (llvmWord dflags) 1237 1291 return (env, v1, unitOL s1, []) 1238 1292 1239 genLit env (CmmLabelOff label off) = do1293 genLit opt env (CmmLabelOff label off) = do 1240 1294 let dflags = getDflags env 1241 (env', vlbl, stmts, stat) <- genLit env (CmmLabel label)1295 (env', vlbl, stmts, stat) <- genLit opt env (CmmLabel label) 1242 1296 let voff = toIWord dflags off 1243 1297 (v1, s1) <- doExpr (getVarType vlbl) $ LlvmOp LM_MO_Add vlbl voff 1244 1298 return (env', v1, stmts `snocOL` s1, stat) 1245 1299 1246 genLit env (CmmLabelDiffOff l1 l2 off) = do1300 genLit opt env (CmmLabelDiffOff l1 l2 off) = do 1247 1301 let dflags = getDflags env 1248 (env1, vl1, stmts1, stat1) <- genLit env (CmmLabel l1)1249 (env2, vl2, stmts2, stat2) <- genLit env1 (CmmLabel l2)1302 (env1, vl1, stmts1, stat1) <- genLit opt env (CmmLabel l1) 1303 (env2, vl2, stmts2, stat2) <- genLit opt env1 (CmmLabel l2) 1250 1304 let voff = toIWord dflags off 1251 1305 let ty1 = getVarType vl1 1252 1306 let ty2 = getVarType vl2 … … 1262 1316 else 1263 1317 panic "genLit: CmmLabelDiffOff encountered with different label ty!" 1264 1318 1265 genLit env (CmmBlock b)1266 = genLit env (CmmLabel $ infoTblLbl b)1319 genLit opt env (CmmBlock b) 1320 = genLit opt env (CmmLabel $ infoTblLbl b) 1267 1321 1268 genLit _ CmmHighStackMark1322 genLit _ _ CmmHighStackMark 1269 1323 = panic "genStaticLit - CmmHighStackMark unsupported!" 1270 1324 1271 1325 -
compiler/prelude/primops.txt.pp
diff --git a/compiler/prelude/primops.txt.pp b/compiler/prelude/primops.txt.pp index 6d551d9..0ff7e2c 100644
a b 1839 1839 out_of_line = True 1840 1840 has_side_effects = True 1841 1841 1842 primop SetTicketsOp "setTickets#" GenPrimOp 1843 ThreadId# -> Int# -> State# RealWorld -> State# RealWorld 1844 with 1845 out_of_line = True 1846 has_side_effects = True 1847 1848 primop GetTicketsOp "getTickets#" GenPrimOp 1849 ThreadId# -> State# RealWorld -> (# State# RealWorld, Int# #) 1850 with 1851 out_of_line = True 1852 has_side_effects = True 1853 1854 primop ModifyTicketsOp "modifyTickets#" GenPrimOp 1855 ThreadId# -> Int# -> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #) 1856 with 1857 out_of_line = True 1858 has_side_effects = True 1859 1842 1860 ------------------------------------------------------------------------ 1843 1861 section "Weak pointers" 1844 1862 ------------------------------------------------------------------------ -
docs/users_guide/intro.xml
diff --git a/docs/users_guide/intro.xml b/docs/users_guide/intro.xml index 5ec013f..b21b793 100644
a b 130 130 </varlistentry> 131 131 132 132 <varlistentry> 133 <term>g lasgow-haskell-bugs:</term>133 <term>ghc-devs:</term> 134 134 <listitem> 135 <para>This list is for reporting and discussing GHC bugs. 136 However, please see <xref linkend="bug-reporting" /> before 137 posting here.</para> 135 <para>The hardcore GHC developers hang out here.</para> 138 136 139 137 <variablelist> 140 138 <varlistentry> 141 139 <term>list email address:</term> 142 140 <listitem> 143 <para><email>g lasgow-haskell-bugs@haskell.org</email></para>141 <para><email>ghc-devs@haskell.org</email></para> 144 142 </listitem> 145 143 </varlistentry> 146 144 … … 148 146 <term>subscribe at:</term> 149 147 <listitem> 150 148 <para><ulink 151 url="http://www.haskell.org/mailman/listinfo/g lasgow-haskell-bugs"><literal>http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs</literal></ulink>.</para>149 url="http://www.haskell.org/mailman/listinfo/ghc-devs"><literal>http://www.haskell.org/mailman/listinfo/ghc-devs</literal></ulink>.</para> 152 150 </listitem> 153 151 </varlistentry> 154 152 155 153 <varlistentry> 156 154 <term>admin email address:</term> 157 155 <listitem> 158 <para><email>g lasgow-haskell-bugs-admin@haskell.org</email></para>156 <para><email>ghc-devs-admin@haskell.org</email></para> 159 157 </listitem> 160 158 </varlistentry> 161 159 … … 163 161 <term>list archives:</term> 164 162 <listitem> 165 163 <para><ulink 166 url="http://www.haskell.org/pipermail/glasgow-haskell-bugs/"><literal>http://www.haskell.org/pipermail/glasgow-haskell-bugs/</literal></ulink></para> 167 </listitem> 168 </varlistentry> 169 </variablelist> 170 </listitem> 171 </varlistentry> 172 173 <varlistentry> 174 <term>cvs-ghc:</term> 175 <listitem> 176 <para>The hardcore GHC developers hang out here. This list 177 also gets commit message from the GHC darcs repository. There are 178 other lists for other darcs 179 repositories (most notably <literal>cvs-libraries</literal>). 180 </para> 181 182 <variablelist> 183 <varlistentry> 184 <term>list email address:</term> 185 <listitem> 186 <para><email>cvs-ghc@haskell.org</email></para> 187 </listitem> 188 </varlistentry> 189 190 <varlistentry> 191 <term>subscribe at:</term> 192 <listitem> 193 <para><ulink 194 url="http://www.haskell.org/mailman/listinfo/cvs-ghc"><literal>http://www.haskell.org/mailman/listinfo/cvs-ghc</literal></ulink>.</para> 195 </listitem> 196 </varlistentry> 197 198 <varlistentry> 199 <term>admin email address:</term> 200 <listitem> 201 <para><email>cvs-ghc-admin@haskell.org</email></para> 202 </listitem> 203 </varlistentry> 204 205 <varlistentry> 206 <term>list archives:</term> 207 <listitem> 208 <para><ulink 209 url="http://www.haskell.org/pipermail/cvs-ghc/"><literal>http://www.haskell.org/pipermail/cvs-ghc/</literal></ulink></para> 164 url="http://www.haskell.org/pipermail/ghc-devs/"><literal>http://www.haskell.org/pipermail/ghc-devs/</literal></ulink></para> 210 165 </listitem> 211 166 </varlistentry> 212 167 </variablelist> -
docs/users_guide/ug-book.xml.in
diff --git a/docs/users_guide/ug-book.xml.in b/docs/users_guide/ug-book.xml.in index 4d4489f..dc5d4f7 100644
a b 3 3 <title>@ProjectName@ User's Guide, Version @ProjectVersion@</title> 4 4 <author><othername>The GHC Team</othername></author> 5 5 <address> 6 <email>glasgow-haskell- {bugs,users}-request@haskell.org</email>6 <email>glasgow-haskell-users-request@haskell.org</email> 7 7 </address> 8 8 </bookinfo> 9 9 -
includes/rts/Constants.h
diff --git a/includes/rts/Constants.h b/includes/rts/Constants.h index 5ff4d4e..5ec5e11 100644
a b 273 273 */ 274 274 #define TSO_SQUEEZED 128 275 275 276 /** 277 * Used to indicate that the TSO got promoted in the run queue, and thus 278 * that its ss_pass is not indicative of the true state of the system. 279 */ 280 #define TSO_PROMOTED 256 281 276 282 /* 277 283 * The number of times we spin in a spin lock before yielding (see 278 284 * #3758). To tune this value, use the benchmark in #3758: run the -
includes/rts/storage/TSO.h
diff --git a/includes/rts/storage/TSO.h b/includes/rts/storage/TSO.h index 82f5a75..583c7e1 100644
a b 168 168 */ 169 169 StgWord32 tot_stack_size; 170 170 171 // These are bounded above by STRIDE1, which is less than a max 172 // 32-bit word. 173 StgWord32 ss_tickets, ss_stride, ss_remain; 174 // 64-bit to prevent overflows; only ever accessed by the task which owns TSO. 175 StgWord64 ss_pass; 176 171 177 } *StgTSOPtr; 172 178 173 179 typedef struct StgStack_ { -
includes/stg/MiscClosures.h
diff --git a/includes/stg/MiscClosures.h b/includes/stg/MiscClosures.h index 61e6b09..e6d5fcd 100644
a b 402 402 RTS_FUN_DECL(stg_unmaskAsyncExceptionszh); 403 403 RTS_FUN_DECL(stg_myThreadIdzh); 404 404 RTS_FUN_DECL(stg_labelThreadzh); 405 RTS_FUN_DECL(stg_getTicketszh); 406 RTS_FUN_DECL(stg_setTicketszh); 407 RTS_FUN_DECL(stg_modifyTicketszh); 405 408 RTS_FUN_DECL(stg_isCurrentThreadBoundzh); 406 409 RTS_FUN_DECL(stg_threadStatuszh); 407 410 -
rts/Capability.c
diff --git a/rts/Capability.c b/rts/Capability.c index 811df58..903f6ad 100644
a b 276 276 cap->pinned_object_block = NULL; 277 277 cap->pinned_object_blocks = NULL; 278 278 279 cap->ss_pass = 1; 280 279 281 #ifdef PROFILING 280 282 cap->r.rCCCS = CCS_SYSTEM; 281 283 #else -
rts/Capability.h
diff --git a/rts/Capability.h b/rts/Capability.h index 3348f88..81322c8 100644
a b 58 58 StgTSO *run_queue_hd; 59 59 StgTSO *run_queue_tl; 60 60 61 // [SSS] Stride scheduling extensions. The Task with this 62 // Capability has exclusive access to this variable. 63 StgWord64 ss_pass; 64 61 65 // Tasks currently making safe foreign calls. Doubly-linked. 62 66 // When returning, a task first acquires the Capability before 63 67 // removing itself from this list, so that the GC can find all -
rts/Linker.c
diff --git a/rts/Linker.c b/rts/Linker.c index fa1de89..c673bac 100644
a b 1130 1130 SymI_HasProto(stg_mkApUpd0zh) \ 1131 1131 SymI_HasProto(stg_myThreadIdzh) \ 1132 1132 SymI_HasProto(stg_labelThreadzh) \ 1133 SymI_HasProto(stg_getTicketszh) \ 1134 SymI_HasProto(stg_setTicketszh) \ 1135 SymI_HasProto(stg_modifyTicketszh) \ 1133 1136 SymI_HasProto(stg_newArrayzh) \ 1134 1137 SymI_HasProto(stg_newArrayArrayzh) \ 1135 1138 SymI_HasProto(stg_newBCOzh) \ -
rts/PrimOps.cmm
diff --git a/rts/PrimOps.cmm b/rts/PrimOps.cmm index ebcee6a..a737508 100644
a b 628 628 return (); 629 629 } 630 630 631 stg_setTicketszh ( gcptr threadid, W_ n ) 632 { 633 ccall setTickets(threadid "ptr", n); 634 return (); 635 } 636 637 stg_getTicketszh ( gcptr threadid ) 638 { 639 W_ r; 640 (r) = ccall getTickets(threadid "ptr"); 641 return (r); 642 } 643 644 stg_modifyTicketszh ( gcptr threadid, W_ n, W_ d, W_ x ) 645 { 646 W_ r; 647 (r) = ccall modifyTickets(threadid "ptr", n, d, x); 648 return (r); 649 } 650 631 651 stg_isCurrentThreadBoundzh (/* no args */) 632 652 { 633 653 W_ r; -
rts/Schedule.c
diff --git a/rts/Schedule.c b/rts/Schedule.c index a21b312..96cfebc 100644
a b 148 148 static rtsBool scheduleHandleHeapOverflow( Capability *cap, StgTSO *t ); 149 149 static rtsBool scheduleHandleYield( Capability *cap, StgTSO *t, 150 150 nat prev_what_next ); 151 static void scheduleHandleThreadBlocked( StgTSO *t );151 static void scheduleHandleThreadBlocked( Capability *cap, StgTSO *t ); 152 152 static rtsBool scheduleHandleThreadFinished( Capability *cap, Task *task, 153 153 StgTSO *t ); 154 154 static rtsBool scheduleNeedHeapProfile(rtsBool ready_to_gc); … … 537 537 break; 538 538 539 539 case ThreadBlocked: 540 scheduleHandleThreadBlocked( t);540 scheduleHandleThreadBlocked(cap, t); 541 541 break; 542 542 543 543 case ThreadFinished: … … 575 575 setTSOPrev(cap, tso->_link, tso->block_info.prev); 576 576 } 577 577 tso->_link = tso->block_info.prev = END_TSO_QUEUE; 578 tso->flags &= ~TSO_PROMOTED; 578 579 579 580 IF_DEBUG(sanity, checkRunQueue(cap)); 580 581 } … … 781 782 setTSOPrev(cap, t, prev); 782 783 prev = t; 783 784 } else { 784 appendToRunQueue(free_caps[i],t); 785 leaveRunQueue(cap,t); 786 joinRunQueue(free_caps[i],t); 785 787 786 788 traceEventMigrateThread (cap, t, free_caps[i]->no); 787 789 … … 1217 1219 * -------------------------------------------------------------------------- */ 1218 1220 1219 1221 static void 1220 scheduleHandleThreadBlocked( StgTSO *t 1221 #if !defined(DEBUG) 1222 STG_UNUSED 1223 #endif 1224 ) 1222 scheduleHandleThreadBlocked( Capability *cap, StgTSO *t ) 1225 1223 { 1226 1224 1227 1225 // We don't need to do anything. The thread is blocked, and it … … 1234 1232 // threadPaused() might have raised a blocked throwTo 1235 1233 // exception, see maybePerformBlockedException(). 1236 1234 1235 leaveRunQueue(cap, t); 1236 1237 1237 #ifdef DEBUG 1238 1238 traceThreadStatus(DEBUG_sched, t); 1239 1239 #endif … … 1257 1257 // blocked mode (see #2910). 1258 1258 awakenBlockedExceptionQueue (cap, t); 1259 1259 1260 leaveRunQueue(cap, t); 1261 1260 1262 // 1261 1263 // Check whether the thread that just completed was a bound 1262 1264 // thread, and if so return with the result. … … 2296 2298 { 2297 2299 // The thread goes at the *end* of the run-queue, to avoid possible 2298 2300 // starvation of any threads already on the queue. 2299 appendToRunQueue(cap,tso);2301 joinRunQueue(cap,tso); 2300 2302 } 2301 2303 2302 2304 void … … 2307 2309 #if defined(THREADED_RTS) 2308 2310 cpu %= enabled_capabilities; 2309 2311 if (cpu == cap->no) { 2310 appendToRunQueue(cap,tso);2312 joinRunQueue(cap,tso); 2311 2313 } else { 2312 2314 migrateThread(cap, tso, &capabilities[cpu]); 2313 2315 } 2314 2316 #else 2315 appendToRunQueue(cap,tso);2317 joinRunQueue(cap,tso); 2316 2318 #endif 2317 2319 } 2318 2320 … … 2337 2339 task->incall->ret = ret; 2338 2340 task->incall->stat = NoStatus; 2339 2341 2340 appendToRunQueue(cap,tso);2342 joinRunQueue(cap,tso); 2341 2343 2342 2344 DEBUG_ONLY( id = tso->id ); 2343 2345 debugTrace(DEBUG_sched, "new bound thread (%lu)", (unsigned long)id); -
rts/Schedule.h
diff --git a/rts/Schedule.h b/rts/Schedule.h index 8b7caea..0677295 100644
a b 116 116 117 117 void resurrectThreads (StgTSO *); 118 118 119 // STRIDE1 defines the maximum resolution we can achieve in scheduling. 120 #define STRIDE1 (1 << 20) 121 // Defualt tickets is set to STRIDE1, so that the IO manager gets 122 // maximum priority. 123 #define DEFAULT_TICKETS (1 << 20) 124 119 125 /* ----------------------------------------------------------------------------- 120 126 * Some convenient macros/inline functions... 121 127 */ … … 135 141 appendToRunQueue (Capability *cap, StgTSO *tso) 136 142 { 137 143 ASSERT(tso->_link == END_TSO_QUEUE); 144 tso->ss_pass += tso->ss_stride; 138 145 if (cap->run_queue_hd == END_TSO_QUEUE) { 139 146 cap->run_queue_hd = tso; 140 147 tso->block_info.prev = END_TSO_QUEUE; 148 cap->run_queue_tl = tso; 141 149 } else { 142 setTSOLink(cap, cap->run_queue_tl, tso); 143 setTSOPrev(cap, tso, cap->run_queue_tl); 150 StgTSO *t, *next; 151 next = END_TSO_QUEUE; 152 for (t = cap->run_queue_tl; t != END_TSO_QUEUE; next = t, t = t->block_info.prev) { 153 if (tso->ss_pass >= t->ss_pass || t->flags & TSO_PROMOTED) { 154 if (next == END_TSO_QUEUE) { 155 // it's the last one! 156 // this should overwhelmingly be the case when priorities 157 // are not being set 158 setTSOLink(cap, cap->run_queue_tl, tso); 159 setTSOPrev(cap, tso, cap->run_queue_tl); 160 cap->run_queue_tl = tso; 161 } else { 162 // XXX is there like a necessary order or something? 163 setTSOLink(cap, tso, next); 164 setTSOPrev(cap, tso, t); 165 setTSOLink(cap, t, tso); 166 setTSOPrev(cap, next, tso); 167 } 168 break; 169 } 170 } 171 if (t == END_TSO_QUEUE) { 172 setTSOLink(cap, tso, cap->run_queue_hd); 173 tso->block_info.prev = END_TSO_QUEUE; 174 cap->run_queue_hd = tso; 175 } 144 176 } 145 cap->run_queue_tl = tso; 177 } 178 179 INLINE_HEADER void 180 joinRunQueue(Capability *cap, StgTSO *tso) { 181 tso->ss_pass = cap->ss_pass + tso->ss_remain; 182 tso->flags &= ~TSO_PROMOTED; 183 appendToRunQueue(cap, tso); 146 184 } 147 185 148 186 /* Push a thread on the beginning of the run queue. … … 151 189 EXTERN_INLINE void 152 190 pushOnRunQueue (Capability *cap, StgTSO *tso); 153 191 192 // This code is a little dangerous, since it temporarily bypasses 193 // stride scheduling. However, since we do increase ss_pass, 194 // as long as the process doesn't continually get rescheduled with 195 // pushOn, it will eventually be penalized for the time it took. 196 // Since I think the old code was written to avoid this kid of 197 // starvation, deferred punishment should be OK. (Also, failing 198 // to put threads in front after they allocate causes massive 199 // performance problems.) 154 200 EXTERN_INLINE void 155 201 pushOnRunQueue (Capability *cap, StgTSO *tso) 156 202 { 203 tso->ss_pass += tso->ss_stride; 204 tso->flags |= TSO_PROMOTED; 157 205 setTSOLink(cap, tso, cap->run_queue_hd); 158 206 tso->block_info.prev = END_TSO_QUEUE; 159 207 if (cap->run_queue_hd != END_TSO_QUEUE) { … … 161 209 } 162 210 cap->run_queue_hd = tso; 163 211 if (cap->run_queue_tl == END_TSO_QUEUE) { 164 cap->run_queue_tl = tso;212 cap->run_queue_tl = tso; 165 213 } 166 214 } 167 215 216 INLINE_HEADER void 217 fastJoinRunQueue(Capability *cap, StgTSO *tso) { 218 tso->ss_pass = cap->ss_pass + tso->ss_remain; 219 pushOnRunQueue(cap, tso); 220 } 221 168 222 /* Pop the first thread off the runnable queue. 169 223 */ 170 224 INLINE_HEADER StgTSO * … … 180 234 if (cap->run_queue_hd == END_TSO_QUEUE) { 181 235 cap->run_queue_tl = END_TSO_QUEUE; 182 236 } 237 if (t->flags & TSO_PROMOTED) { 238 t->flags &= ~TSO_PROMOTED; 239 // its pass is nonsense, don't count it 240 } else { 241 if (cap->run_queue_hd != END_TSO_QUEUE) { 242 // relies on a PROMOTED invariant: promoted elements 243 // are ALWAYS in the front of the queue 244 ASSERT(cap->run_queue_hd->flags & TSO_PROMOTED == 0); 245 cap->ss_pass = cap->run_queue_hd->ss_pass; 246 } 247 } 183 248 return t; 184 249 } 185 250 … … 189 254 return cap->run_queue_hd; 190 255 } 191 256 257 INLINE_HEADER void 258 leaveRunQueue (Capability *cap STG_UNUSED, StgTSO *tso STG_UNUSED) 259 { 260 int r = tso->ss_pass - cap->ss_pass; 261 if (r > 0) { 262 tso->ss_remain = (StgWord32)r; 263 } else { 264 tso->ss_remain = 0; 265 } 266 } 267 192 268 void removeFromRunQueue (Capability *cap, StgTSO *tso); 193 269 extern void promoteInRunQueue (Capability *cap, StgTSO *tso); 194 270 -
rts/Sparks.c
diff --git a/rts/Sparks.c b/rts/Sparks.c index 4241656..4e9b5a5 100644
a b 45 45 46 46 traceEventCreateSparkThread(cap, tso->id); 47 47 48 appendToRunQueue(cap,tso);48 joinRunQueue(cap,tso); 49 49 } 50 50 51 51 /* -------------------------------------------------------------------------- -
rts/Threads.c
diff --git a/rts/Threads.c b/rts/Threads.c index b617616..a8f38fb 100644
a b 112 112 113 113 tso->trec = NO_TREC; 114 114 115 tso->ss_tickets = DEFAULT_TICKETS; 116 tso->ss_stride = STRIDE1 / tso->ss_tickets; 117 tso->ss_remain = tso->ss_stride; // avoid starvation when lots of new threads are being created 118 115 119 #ifdef PROFILING 116 120 tso->prof.cccs = CCS_MAIN; 117 121 #endif … … 136 140 } 137 141 138 142 /* --------------------------------------------------------------------------- 143 * Ticket allocations on threads 144 * ------------------------------------------------------------------------ */ 145 146 #define TICKET_ERROR (STRIDE1 + 1) 147 148 void 149 setTickets(StgTSO *tso, W_ tickets) 150 { 151 if (tickets > STRIDE1) { 152 barf("setTickets: too many tickets"); 153 } else if (tickets <= 0) { 154 barf("setTickets: too few tickets"); 155 } 156 ACQUIRE_LOCK(&sched_mutex); 157 StgWord64 stride = STRIDE1 / tickets; 158 StgWord64 remain = (tso->ss_remain * stride) / tso->ss_stride; 159 tso->ss_tickets = tickets; 160 tso->ss_stride = stride; 161 tso->ss_remain = remain; 162 RELEASE_LOCK(&sched_mutex); 163 } 164 165 W_ 166 modifyTickets(StgTSO *tso, W_ n, W_ d, W_ x) 167 { 168 ACQUIRE_LOCK(&sched_mutex); 169 W_ tickets = (tso->ss_tickets * n) / d + x; 170 W_ delta; 171 if (tickets > STRIDE1 || tickets <= 0) { 172 delta = TICKET_ERROR; 173 goto cleanup; 174 } 175 StgWord64 stride = STRIDE1 / tickets; 176 StgWord64 remain = (tso->ss_remain * stride) / tso->ss_stride; 177 delta = tso->ss_tickets - tickets; 178 tso->ss_tickets = tickets; 179 tso->ss_stride = stride; 180 tso->ss_remain = remain; 181 cleanup: 182 RELEASE_LOCK(&sched_mutex); 183 return delta; 184 } 185 186 W_ 187 getTickets(StgTSO *tso) 188 { 189 return tso->ss_tickets; 190 } 191 192 /* --------------------------------------------------------------------------- 139 193 * Comparing Thread ids. 140 194 * 141 195 * This is used from STG land in the implementation of the … … 236 290 void 237 291 tryWakeupThread (Capability *cap, StgTSO *tso) 238 292 { 293 rtsBool migrating = rtsFalse; 239 294 traceEventThreadWakeup (cap, tso, tso->cap->no); 240 295 241 296 #ifdef THREADED_RTS … … 282 337 goto unblock; 283 338 } 284 339 340 case ThreadMigrating: 341 migrating = rtsTrue; 285 342 case BlockedOnBlackHole: 286 343 case BlockedOnSTM: 287 case ThreadMigrating:288 344 goto unblock; 289 345 290 346 default: … … 296 352 // just run the thread now, if the BH is not really available, 297 353 // we'll block again. 298 354 tso->why_blocked = NotBlocked; 299 appendToRunQueue(cap,tso); 355 if (migrating) { 356 joinRunQueue(cap, tso); 357 } else { 358 appendToRunQueue(cap,tso); 359 } 300 360 301 361 // We used to set the context switch flag here, which would 302 362 // trigger a context switch a short time in the future (at the end … … 322 382 traceEventMigrateThread (from, tso, to->no); 323 383 // ThreadMigrating tells the target cap that it needs to be added to 324 384 // the run queue when it receives the MSG_TRY_WAKEUP. 385 leaveRunQueue(from, tso); 325 386 tso->why_blocked = ThreadMigrating; 326 387 tso->cap = to; 327 388 tryWakeupThread(from, tso); -
rts/Threads.h
diff --git a/rts/Threads.h b/rts/Threads.h index 6d26610..39794f3 100644
a b 13 13 14 14 #define END_BLOCKED_EXCEPTIONS_QUEUE ((MessageThrowTo*)END_TSO_QUEUE) 15 15 16 void setTickets(StgTSO *tso, W_ n); 17 W_ modifyTickets(StgTSO *tso, W_ n, W_ d, W_ x); 18 W_ getTickets(StgTSO *tso); 19 16 20 StgTSO * unblockOne (Capability *cap, StgTSO *tso); 17 21 StgTSO * unblockOne_ (Capability *cap, StgTSO *tso, rtsBool allow_migrate); 18 22 -
rts/posix/Select.c
diff --git a/rts/posix/Select.c b/rts/posix/Select.c index 3d92a46..b39338b 100644
a b 107 107 tso->_link = END_TSO_QUEUE; 108 108 IF_DEBUG(scheduler,debugBelch("Waking up sleeping thread %lu\n", (unsigned long)tso->id)); 109 109 // MainCapability: this code is !THREADED_RTS 110 pushOnRunQueue(&MainCapability,tso);110 fastJoinRunQueue(&MainCapability,tso); 111 111 flag = rtsTrue; 112 112 } 113 113 return flag; … … 305 305 IF_DEBUG(scheduler,debugBelch("Waking up blocked thread %lu\n", (unsigned long)tso->id)); 306 306 tso->why_blocked = NotBlocked; 307 307 tso->_link = END_TSO_QUEUE; 308 pushOnRunQueue(&MainCapability,tso);308 fastJoinRunQueue(&MainCapability,tso); 309 309 } else { 310 310 if (prev == NULL) 311 311 blocked_queue_hd = tso; -
rts/win32/AsyncIO.c
diff --git a/rts/win32/AsyncIO.c b/rts/win32/AsyncIO.c index 979df0c..cfd2c0f 100644
a b 303 303 // save the StgAsyncIOResult in the 304 304 // stg_block_async_info stack frame, because 305 305 // the block_info field will be overwritten by 306 // pushOnRunQueue().306 // fastJoinRunQueue(). 307 307 tso->stackobj->sp[1] = (W_)tso->block_info.async_result; 308 pushOnRunQueue(&MainCapability, tso);308 fastJoinRunQueue(&MainCapability, tso); 309 309 break; 310 310 } 311 311 break;
