summaryrefslogtreecommitdiff
path: root/rts/Capability.c
Commit message (Collapse)AuthorAgeFilesLines
* Expunge #ifdef and #ifndef from the codebaseJohn Ericson2019-07-141-3/+3
| | | | | | | | These are unexploded minds as far as the linter is concerned. I don't want to hit in my MRs by mistake! I did this with `sed`, and then rolled back some changes in the docs, config.guess, and the linter itself.
* Typo fix, replace a foldl with foldl'Ömer Sinan Ağacan2018-12-121-1/+1
|
* rts: Rip out support for STM invariantsBen Gamari2018-06-021-1/+0
| | | | | | | | | | | | | | | | | | | | | | | This feature has some very serious correctness issues (#14310), introduces a great deal of complexity, and hasn't seen wide usage. Consequently we are removing it, as proposed in Proposal #77 [1]. This is heavily based on a patch from fryguybob. Updates stm submodule. [1] https://github.com/ghc-proposals/ghc-proposals/pull/77 Test Plan: Validate Reviewers: erikd, simonmar, hvr Reviewed By: simonmar Subscribers: rwbarton, thomie, carter GHC Trac Issues: #14310 Differential Revision: https://phabricator.haskell.org/D4760
* rts: Note functions which must take all_tasks_mutex.Ben Gamari2018-03-021-0/+3
|
* rts: Add format attribute to barfBen Gamari2018-02-061-1/+1
| | | | | | | | | | | | Test Plan: Validate Reviewers: erikd, simonmar Reviewed By: simonmar Subscribers: rwbarton, thomie, carter Differential Revision: https://phabricator.haskell.org/D4374
* A bunch of typofixesGabor Greif2017-09-261-1/+1
|
* Prefer #if defined to #ifdefBen Gamari2017-04-281-5/+5
| | | | Our new CPP linter enforces this.
* Use C99's boolBen Gamari2016-11-291-37/+37
| | | | | | | | | | | | Test Plan: Validate on lots of platforms Reviewers: erikd, simonmar, austin Reviewed By: erikd, simonmar Subscribers: michalt, thomie Differential Revision: https://phabricator.haskell.org/D2699
* tryGrabCapability should be using TRY_ACQUIRE_LOCKSimon Marlow2016-09-151-1/+3
|
* Add hs_try_putmvar()Simon Marlow2016-09-121-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Summary: This is a fast, non-blocking, asynchronous, interface to tryPutMVar that can be called from C/C++. It's useful for callback-based C/C++ APIs: the idea is that the callback invokes hs_try_putmvar(), and the Haskell code waits for the callback to run by blocking in takeMVar. The callback doesn't block - this is often a requirement of callback-based APIs. The callback wakes up the Haskell thread with minimal overhead and no unnecessary context-switches. There are a couple of benchmarks in testsuite/tests/concurrent/should_run. Some example results comparing hs_try_putmvar() with using a standard foreign export: ./hs_try_putmvar003 1 64 16 100 +RTS -s -N4 0.49s ./hs_try_putmvar003 2 64 16 100 +RTS -s -N4 2.30s hs_try_putmvar() is 4x faster for this workload (see the source for hs_try_putmvar003.hs for details of the workload). An alternative solution is to use the IO Manager for this. We've tried it, but there are problems with that approach: * Need to create a new file descriptor for each callback * The IO Manger thread(s) become a bottleneck * More potential for things to go wrong, e.g. throwing an exception in an IO Manager callback kills the IO Manager thread. Test Plan: validate; new unit tests Reviewers: niteria, erikd, ezyang, bgamari, austin, hvr Subscribers: thomie Differential Revision: https://phabricator.haskell.org/D2501
* Fix an assertion that could randomly failSimon Marlow2016-08-051-0/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | Summary: ASSERT_THREADED_CAPABILITY_INVARIANTS was testing properties of the returning_tasks queue, but that requires cap->lock to access safely. This assertion would randomly fail if stressed enough. Instead I've removed it from the catch-all ASSERT_PARTIAL_CAPABILITIY_INVARIANTS and made it a separate assertion only called under cap->lock. Test Plan: ``` cd testsuite/tests/concurrent/should_run make TEST=setnumcapabilities001 WAY=threaded1 EXTRA_HC_OPTS=-with-rtsopts=-DS CLEANUP=0 while true; do ./setnumcapabilities001.run/setnumcapabilities001 4 9 2000 || break; done ``` Reviewers: niteria, bgamari, ezyang, austin, erikd Subscribers: thomie Differential Revision: https://phabricator.haskell.org/D2440 GHC Trac Issues: #10860
* Track the lengths of the thread queuesSimon Marlow2016-08-031-2/+7
| | | | | | | | | | | | | | | Summary: Knowing the length of the run queue in O(1) time is useful: for example we don't have to traverse the run queue to know how many threads we have to migrate in schedulePushWork(). Test Plan: validate Reviewers: ezyang, erikd, bgamari, austin Subscribers: thomie Differential Revision: https://phabricator.haskell.org/D2437
* NUMA cleanupsSimon Marlow2016-06-171-3/+35
| | | | | - Move the numaMap and nNumaNodes out of RtsFlags to Capability.c - Add a test to tests/rts
* NUMA supportSimon Marlow2016-06-101-15/+23
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Summary: The aim here is to reduce the number of remote memory accesses on systems with a NUMA memory architecture, typically multi-socket servers. Linux provides a NUMA API for doing two things: * Allocating memory local to a particular node * Binding a thread to a particular node When given the +RTS --numa flag, the runtime will * Determine the number of NUMA nodes (N) by querying the OS * Assign capabilities to nodes, so cap C is on node C%N * Bind worker threads on a capability to the correct node * Keep a separate free lists in the block layer for each node * Allocate the nursery for a capability from node-local memory * Allocate blocks in the GC from node-local memory For example, using nofib/parallel/queens on a 24-core 2-socket machine: ``` $ ./Main 15 +RTS -N24 -s -A64m Total time 173.960s ( 7.467s elapsed) $ ./Main 15 +RTS -N24 -s -A64m --numa Total time 150.836s ( 6.423s elapsed) ``` The biggest win here is expected to be allocating from node-local memory, so that means programs using a large -A value (as here). According to perf, on this program the number of remote memory accesses were reduced by more than 50% by using `--numa`. Test Plan: * validate * There's a new flag --debug-numa=<n> that pretends to do NUMA without actually making the OS calls, which is useful for testing the code on non-NUMA systems. * TODO: I need to add some unit tests Reviewers: erikd, austin, rwbarton, ezyang, bgamari, hvr, niteria Subscribers: thomie Differential Revision: https://phabricator.haskell.org/D2199
* rts: Replace `nat` with `uint32_t`Erik de Castro Lopo2016-05-051-17/+18
| | | | | | | | | | | | The `nat` type was an alias for `unsigned int` with a comment saying it was at least 32 bits. We keep the typedef in case client code is using it but mark it as deprecated. Test Plan: Validated on Linux, OS X and Windows Reviewers: simonmar, austin, thomie, hvr, bgamari, hsyl20 Differential Revision: https://phabricator.haskell.org/D2166
* Don't STATIC_INLINE giveCapabilityToTaskSimon Marlow2016-05-041-1/+1
| | | | This causes errors with some versions of gcc (4.4.7 here).
* Allow limiting the number of GC threads (+RTS -qn<n>)Simon Marlow2016-05-041-18/+30
| | | | | | | | | | | | | | | | | | This allows the GC to use fewer threads than the number of capabilities. At each GC, we choose some of the capabilities to be "idle", which means that the thread running on that capability (if any) will sleep for the duration of the GC, and the other threads will do its work. We choose capabilities that are already idle (if any) to be the idle capabilities. The idea is that this helps in the following situation: * We want to use a large -N value so as to make use of hyperthreaded cores * We use a large heap size, so GC is infrequent * But we don't want to use all -N threads in the GC, because that thrashes the memory too much. See docs for usage.
* RTS: Add setInCallCapability()Simon Marlow2016-04-261-14/+19
| | | | | | | | This allows an OS thread to specify which capability it should run on when it makes a call into Haskell. It is intended for a fairly specialised use case, when the client wants to have tighter control over the mapping between OS threads and Capabilities - perhaps 1:1 correspondence, for example.
* rts: mark 'shutdownCapability' as staticSergei Trofimovich2016-02-071-2/+2
| | | | | | | | | | Noticed by uselex.rb: last_free_capability: [R]: exported from: ./rts/dist/build/Capability.o shutdownCapability: [R]: exported from: ./rts/dist/build/Capability.o Signed-off-by: Sergei Trofimovich <siarheit@google.com>
* Some more typos in commentsGabor Greif2015-12-141-1/+1
|
* Fix deadlock (#10545)Simon Marlow2015-06-261-115/+186
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | yieldCapability() was not prepared to be called by a Task that is not either a worker or a bound Task. This could happen if we ended up in yieldCapability via this call stack: performGC() scheduleDoGC() requestSync() yieldCapability() and there were a few other ways this could happen via requestSync. The fix is to handle this case in yieldCapability(): when the Task is not a worker or a bound Task, we put it on the returning_workers queue, where it will be woken up again. Summary of changes: * `yieldCapability`: factored out subroutine waitForWorkerCapability` * `waitForReturnCapability` renamed to `waitForCapability`, and factored out subroutine `waitForReturnCapability` * `releaseCapabilityAndQueue` worker renamed to `enqueueWorker`, does not take a lock and no longer tests if `!isBoundTask()` * `yieldCapability` adjusted for refactorings, only change in behavior is when it is not a worker or bound task. Test Plan: * new test concurrent/should_run/performGC * validate Reviewers: niteria, austin, ezyang, bgamari Subscribers: thomie, bgamari Differential Revision: https://phabricator.haskell.org/D997 GHC Trac Issues: #10545
* Per-thread allocation counters and limitsSimon Marlow2014-11-121-0/+4
| | | | | | | | This reverts commit f0fcc41d755876a1b02d1c7c79f57515059f6417. New changes: now works on 32-bit platforms too. I added some basic support for 64-bit subtraction and comparison operations to the x86 NCG.
* [skip ci] rts: Detabify Capability.cAustin Seipp2014-10-211-148/+148
| | | | Signed-off-by: Austin Seipp <austin@well-typed.com>
* Revert "rts: add Emacs 'Local Variables' to every .c file"Simon Marlow2014-09-291-8/+0
| | | | This reverts commit 39b5c1cbd8950755de400933cecca7b8deb4ffcd.
* Revert "Revert "rts/base: Fix #9423"" and resolve issue that caused the revert.Andreas Voellmy2014-09-161-0/+19
| | | | | | | | | | | | | | | | | | | | | | | | | | | Summary: This reverts commit 4748f5936fe72d96edfa17b153dbfd84f2c4c053. The fix for #9423 was reverted because this commit introduced a C function setIOManagerControlFd() (defined in Schedule.c) defined for all OS types, while the prototype (in includes/rts/IOManager.h) was only included when mingw32_HOST_OS is not defined. This broke Windows builds. This commit reverts the original commit and resolves the problem by only defining setIOManagerControlFd() when mingw32_HOST_OS is defined. Hence the missing prototype error should not occur on Windows. In addition, since the io_manager_control_wr_fd field of the Capability struct is only usd by the setIOManagerControlFd, this commit includes the io_manager_control_wr_fd field in the Capability struct only when mingw32_HOST_OS is not defined. Test Plan: Try to compile successfully on all platforms. Reviewers: austin Reviewed By: austin Subscribers: simonmar, ezyang, carter Differential Revision: https://phabricator.haskell.org/D174
* Revert "Make sure that a prototype is included for 'setIOManagerControlFd'"Gabor Greif2014-08-301-1/+0
| | | | This reverts commit 7bf49f86a20f3beda0ee5fbea2db64cfef730d74.
* Revert "Comment why the include is necessary"Gabor Greif2014-08-301-1/+1
| | | | This reverts commit 15df6d98afb8c3813013c5b97efffe0ba8020d32.
* Revert "rts/base: Fix #9423"Austin Seipp2014-08-221-11/+0
| | | | | | | | | This should fix the Windows fallout, and hopefully this will be fixed once that's sorted out. This reverts commit f9f89b7884ccc8ee5047cf4fffdf2b36df6832df. Signed-off-by: Austin Seipp <austin@well-typed.com>
* Comment why the include is necessaryGabor Greif2014-08-201-1/+1
|
* Make sure that a prototype is included for 'setIOManagerControlFd'Gabor Greif2014-08-201-0/+1
|
* rts/base: Fix #9423Andreas Voellmy2014-08-191-0/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Summary: Fix #9423. The problem in #9423 is caused when code invoked by `hs_exit()` waits on all foreign calls to return, but some IO managers are in `safe` foreign calls and do not return. The previous design signaled to the timer manager (via its control pipe) that it should "die" and when the timer manager returned to Haskell-land, the Haskell code in timer manager then signalled to the IO manager threads that they should return from foreign calls and `die`. Unfortunately, in the shutdown sequence the timer manager is unable to return to Haskell-land fast enough and so the code that signals to the IO manager threads (via their control pipes) is never executed and the IO manager threads remain out in the foreign calls. This patch solves this problem by having the RTS signal to all the IO manager threads (via their control pipes; and in addition to signalling to the timer manager thread) that they should shutdown (in `ioManagerDie()` in `rts/Signals.c`. To do this, we arrange for each IO manager thread to register its control pipe with the RTS (in `GHC.Thread.startIOManagerThread`). In addition, `GHC.Thread.startTimerManagerThread` registers its control pipe. These are registered via C functions `setTimerManagerControlFd` (in `rts/Signals.c`) and `setIOManagerControlFd` (in `rts/Capability.c`). The IO manager control pipe file descriptors are stored in a new field of the `Capability_ struct`. Test Plan: See the notes on #9423 to recreate the problem and to verify that it no longer occurs with the fix. Auditors: simonmar Reviewers: simonmar, edsko, ezyang, austin Reviewed By: austin Subscribers: phaskell, simonmar, ezyang, carter, relrod Differential Revision: https://phabricator.haskell.org/D129 GHC Trac Issues: #9423, #9284
* rts: add Emacs 'Local Variables' to every .c fileAustin Seipp2014-07-281-0/+8
| | | | | | | | This will hopefully help ensure some basic consistency in the forward by overriding buffer variables. In particular, it sets the wrap length, the offset to 4, and turns off tabs. Signed-off-by: Austin Seipp <austin@well-typed.com>
* Per-capability nursery weak pointer lists, fixes #9075Edward Z. Yang2014-05-291-0/+2
| | | | Signed-off-by: Edward Z. Yang <ezyang@cs.stanford.edu>
* rts/Capability.c: fix crash in -threaded mode on UNREG buildSergei Trofimovich2014-02-171-9/+13
| | | | | | | | | | | | | UNREG mode has quite nasty invariant to maintain: capabilities[0] == &MainCapability and it's a non-heap memory, while other capabilities are dynamically allocated. Issue #8748 Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org> Signed-off-by: Austin Seipp <austin@well-typed.com>
* Don't move Capabilities in setNumCapabilities (#8209)Simon Marlow2013-09-041-40/+43
| | | | | | | | | | | | | We have various problems with reallocating the array of Capabilities, due to threads in waitForReturnCapability that are already holding a pointer to a Capability. Rather than add more locking to make this safer, I decided it would be easier to ensure that we never move the Capabilities at all. The capabilities array is now an array of pointers to Capabaility. There are extra indirections, but it rarely matters - we don't often access Capabilities via the array, normally we already have a pointer to one. I ran the parallel benchmarks and didn't see any difference.
* Better abstraction over run queues.Edward Z. Yang2013-01-161-2/+2
| | | | | | | | | This adds some new functions: peekRunQueue, promoteInRunQueue, singletonRunQueue and truncateRunQueue which help abstract away manual linked list manipulation, making it easier to swap in a new queue implementation. Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
* remove unused sched_shutting_downSimon Marlow2012-10-251-1/+1
|
* Merge taskId and serialisableTaskIdMikolaj Konarski2012-07-251-2/+2
| | | | A companion ghc-events pachakge commit displays task ids in the same format.
* Add a missing closing braceIan Lynagh2012-06-071-0/+1
|
* scheduleYield: avoid doing a GC again if we just did oneIan Lynagh2012-06-071-5/+8
| | | | | | If we are interrupted to do a GC, then we do not immediately do another one. This avoids a starvation situation where one Capability keeps forcing a GC and the other Capabilities make no progress at all.
* Fix warnings on Win64Ian Lynagh2012-04-261-2/+2
| | | | | | Mostly this meant getting pointer<->int conversions to use the right sizes. lnat is now size_t, rather than unsigned long, as that seems a better match for how it's used.
* Move trace of cap delete from shutdownCapability to freeCapabilityDuncan Coutts2012-04-041-21/+7
| | | | | | Will let us do final per-cap trace events from stat_exit(). Otherwise we would end up with eventlogs with events for caps that have already been deleted.
* Calculate the total memory allocated on a per-capability basisDuncan Coutts2012-04-041-0/+1
| | | | | | | In addition to the existing global method. For now we just do it both ways and assert they give the same grand total. At some stage we can simplify the global method to just take the sum of the per-cap counters.
* Add eventlog/trace stuff for capabilities: create/delete/enable/disableDuncan Coutts2012-04-041-4/+15
| | | | | | | | | | | | | | | | | | | | | | | Now that we can adjust the number of capabilities on the fly, we need this reflected in the eventlog. Previously the eventlog had a single startup event that declared a static number of capabilities. Obviously that's no good anymore. For compatability we're keeping the EVENT_STARTUP but adding new EVENT_CAP_CREATE/DELETE. The EVENT_CAP_DELETE is actually just the old EVENT_SHUTDOWN but renamed and extended (using the existing mechanism to extend eventlog events in a compatible way). So we now emit both EVENT_STARTUP and EVENT_CAP_CREATE. One day we will drop EVENT_STARTUP. Since reducing the number of capabilities at runtime does not really delete them, it just disables them, then we also have new events for disable/enable. The old EVENT_SHUTDOWN was in the scheduler class of events. The new EVENT_CAP_* events are in the unconditional class, along with the EVENT_CAPSET_* ones. Knowing when capabilities are created and deleted is crucial to making sense of eventlogs, you always want those events. In any case, they're extremely low volume.
* typoGabor Greif2012-02-271-5/+5
|
* Allocate pinned object blocks from the nursery, not the globalSimon Marlow2012-02-131-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | allocator. Prompted by a benchmark posted to parallel-haskell@haskell.org by Andreas Voellmy <andreas.voellmy@gmail.com>. This program exhibits contention for the block allocator when run with -N2 and greater without the fix: {-# LANGUAGE MagicHash, UnboxedTuples, BangPatterns #-} module Main where import Control.Monad import Control.Concurrent import System.Environment import GHC.IO import GHC.Exts import GHC.Conc main = do [m] <- fmap (fmap read) getArgs n <- getNumCapabilities ms <- replicateM n newEmptyMVar sequence [ forkIO $ busyWorkerB (m `quot` n) >> putMVar mv () | mv <- ms ] mapM takeMVar ms busyWorkerB :: Int -> IO () busyWorkerB n_loops = go 0 where go !n | n >= n_loops = return () | otherwise = do p <- (IO $ \s -> case newPinnedByteArray# 1024# s of { (# s', mbarr# #) -> (# s', () #) } ) go (n+1)
* Add missing initialisation of cap->disabledSimon Marlow2012-01-161-0/+1
|
* last_free_capability should never be NULLSimon Marlow2012-01-091-1/+1
|
* Support for reducing the number of Capabilities with setNumCapabilitiesSimon Marlow2011-12-151-2/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This patch allows setNumCapabilities to /reduce/ the number of active capabilities as well as increase it. This is particularly tricky to do, because a Capability is a large data structure and ties into the rest of the system in many ways. Trying to clean it all up would be extremely error prone. So instead, the solution is to mark the extra capabilities as "disabled". This has the following consequences: - threads on a disabled capability are migrated away by the scheduler loop - disabled capabilities do not participate in GC (see scheduleDoGC()) - No spark threads are created on this capability (see scheduleActivateSpark()) - We do not attempt to migrate threads *to* a disabled capability (see schedulePushWork()). So a disabled capability should do no work, and does not participate in GC, although it remains alive in other respects. For example, a blocked thread might wake up on a disabled capability, and it will get quickly migrated to a live capability. A disabled capability can still initiate GC if necessary. Indeed, it turns out to be hard to migrate bound threads, so we wait until the next GC to do this (see comments for details).
* New flag +RTS -qi<n>, avoid waking up idle Capabilities to do parallel GCSimon Marlow2011-12-131-0/+1
| | | | | | | | | | | | | | | | | This is an experimental tweak to the parallel GC that avoids waking up a Capability to do parallel GC if we know that the capability has been idle for a (tunable) number of GC cycles. The idea is that if you're only using a few Capabilities, there's no point waking up the ones that aren't busy. e.g. +RTS -qi3 says "A Capability will participate in parallel GC if it was running at all since the last 3 GC cycles." Results are a bit hit and miss, and I don't completely understand why yet. Hence, for now it is turned off by default, and also not documented except in the +RTS -? output.