summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/users_guide/7.12.1-notes.rst5
-rw-r--r--docs/users_guide/using-concurrent.rst9
-rw-r--r--rts/RtsFlags.c54
-rw-r--r--testsuite/.gitignore1
-rw-r--r--testsuite/tests/rts/T10728.hs40
-rw-r--r--testsuite/tests/rts/T10728.stdout1
-rw-r--r--testsuite/tests/rts/all.T13
7 files changed, 100 insertions, 23 deletions
diff --git a/docs/users_guide/7.12.1-notes.rst b/docs/users_guide/7.12.1-notes.rst
index caa1d897a8..678a9778a8 100644
--- a/docs/users_guide/7.12.1-notes.rst
+++ b/docs/users_guide/7.12.1-notes.rst
@@ -40,6 +40,8 @@ The highlights, since the 7.10 branch, are:
- A rewritten (and greatly improved) pattern exhaustiveness checker
+- ``-maxN(x)`` added to compliment ``-N``
+
- GHC can run the interpreter in a separate process (see
:ref:`external-interpreter`), and the interpreter can now run profiled
code.
@@ -332,6 +334,9 @@ Runtime system
- Support for performance monitoring with PAPI has been dropped.
+- ``-maxN(x)`` flag added to compliment ``-N``, it will choose to use at most
+ (x) capabilities, limited by the number of processors as ``-N`` is.
+
Build system
~~~~~~~~~~~~
diff --git a/docs/users_guide/using-concurrent.rst b/docs/users_guide/using-concurrent.rst
index 2621afce0f..b2b235ad3e 100644
--- a/docs/users_guide/using-concurrent.rst
+++ b/docs/users_guide/using-concurrent.rst
@@ -110,11 +110,11 @@ There are two ways to run a program on multiple processors: call
RTS ``-N`` options.
``-N⟨x⟩``
-``-Nmax⟨x⟩``
+``-maxN⟨x⟩``
.. index::
single: -N⟨x⟩; RTS option
- single: -Nmax(x); RTS option
+ single: -maxN(x); RTS option
Use ⟨x⟩ simultaneous threads when running the program.
@@ -136,8 +136,9 @@ RTS ``-N`` options.
value of ⟨x⟩ itself based on how many processors are in your
machine.
- With Nmax⟨x⟩, i.e. ``+RTS -Nmax3 -RTS``, the runtime will choose at
- most (x), also limited by the number of processors on the system.
+ With ``-maxN⟨x⟩``, i.e. ``+RTS -maxN3 -RTS``, the runtime will choose
+ at most (x), also limited by the number of processors on the system.
+ Omitting (x) is an error, if you need a default use option ``-N``.
Be careful when using all the processors in your machine: if some of
your processors are in use by other programs, this can actually harm
diff --git a/rts/RtsFlags.c b/rts/RtsFlags.c
index bd60591f33..56f4420142 100644
--- a/rts/RtsFlags.c
+++ b/rts/RtsFlags.c
@@ -393,7 +393,7 @@ usage_text[] = {
#if defined(THREADED_RTS) && !defined(NOSMP)
" -N[<n>] Use <n> processors (default: 1, -N alone determines",
" the number of processors to use automatically)",
-" -Nmax[<n>] Use up to n processors automatically",
+" -maxN[<n>] Use up to <n> processors automatically",
" -qg[<n>] Use parallel GC only for generations >= <n>",
" (default: 0, -qg alone turns off parallel GC)",
" -qb[<n>] Use load-balancing in the parallel GC only for generations >= <n>",
@@ -846,14 +846,46 @@ error = rtsTrue;
break;
case 'm':
- OPTION_UNSAFE;
- RtsFlags.GcFlags.pcFreeHeap = atof(rts_argv[arg]+2);
+ /* Case for maxN feature request ticket #10728, it's a little
+ odd being so far from the N case. */
+#if !defined(NOSMP)
+ if (strncmp("maxN", &rts_argv[arg][1], 4) == 0) {
+ OPTION_SAFE;
+ THREADED_BUILD_ONLY(
+ int nNodes;
+ int proc = (int)getNumberOfProcessors();
+ OPTION_SAFE;
+
+ nNodes = strtol(rts_argv[arg]+5, (char **) NULL, 10);
+ if (nNodes > proc) { nNodes = proc; }
- if (RtsFlags.GcFlags.pcFreeHeap < 0 ||
- RtsFlags.GcFlags.pcFreeHeap > 100)
+ if (nNodes <= 0) {
+ errorBelch("bad value for -maxN");
+ error = rtsTrue;
+ }
+#if defined(PROFILING)
+ RtsFlags.ParFlags.nNodes = 1;
+#else
+ RtsFlags.ParFlags.nNodes = (nat)nNodes;
+#endif
+ ) break;
+ } else {
+#endif
+ OPTION_UNSAFE;
+ RtsFlags.GcFlags.pcFreeHeap = atof(rts_argv[arg]+2);
+
+ /* -m was allowing bad flags to go unreported */
+ if (RtsFlags.GcFlags.pcFreeHeap == 0.0 &&
+ rts_argv[arg][2] != '0')
bad_option( rts_argv[arg] );
- break;
+ if (RtsFlags.GcFlags.pcFreeHeap < 0 ||
+ RtsFlags.GcFlags.pcFreeHeap > 100)
+ bad_option( rts_argv[arg] );
+ break;
+#if !defined(NOSMP)
+ }
+#endif
case 'G':
OPTION_UNSAFE;
RtsFlags.GcFlags.generations =
@@ -1043,14 +1075,8 @@ error = rtsTrue;
int nNodes;
OPTION_SAFE; /* but see extra checks below... */
- // <=n feature request ticket #10728
- if (strncmp("max", &rts_argv[arg][2], 3) == 0) {
- int proc = (int)getNumberOfProcessors();
- nNodes = strtol(rts_argv[arg]+5, (char **) NULL, 10);
- if (nNodes > proc) { nNodes = proc; }
- } else {
- nNodes = strtol(rts_argv[arg]+2, (char **) NULL, 10);
- }
+ nNodes = strtol(rts_argv[arg]+2, (char **) NULL, 10);
+
if (nNodes <= 0) {
errorBelch("bad value for -N");
error = rtsTrue;
diff --git a/testsuite/.gitignore b/testsuite/.gitignore
index 2886400681..e8cb351fcc 100644
--- a/testsuite/.gitignore
+++ b/testsuite/.gitignore
@@ -1389,6 +1389,7 @@ mk/ghcconfig*_test___spaces_ghc*.exe.mk
/tests/rts/T8242
/tests/rts/T9045
/tests/rts/T9078
+/tests/rts/T10728
/tests/rts/atomicinc
/tests/rts/bug1010
/tests/rts/derefnull
diff --git a/testsuite/tests/rts/T10728.hs b/testsuite/tests/rts/T10728.hs
new file mode 100644
index 0000000000..056124d0ca
--- /dev/null
+++ b/testsuite/tests/rts/T10728.hs
@@ -0,0 +1,40 @@
+-- T10728 test case for ``-maxN<n>``
+
+module Main where
+
+import GHC.Conc (getNumProcessors, getNumCapabilities)
+import GHC.Environment
+import Data.Char
+
+main :: IO ()
+main = do
+ -- We're parsing args passed in to make sure things are proper between the
+ -- cli and the program.
+ n <- getN
+
+ c <- getNumCapabilities
+ p <- getNumProcessors
+
+ putStr $ check n c p
+
+-----
+
+check :: Int -> Int -> Int -> String
+check n c p
+ | n /= 0 && c /= 0 && p /= 0 -- These should never be 0
+ -- Capabilities are equal to n, are they also within processor count?
+ && (n == c && c <= p)
+ -- Capabilities are equal to processor count, are they also within n?
+ || (c == p && c <= n)
+ = "maxN Successful"
+check _n _c _p = "maxN Error"
+
+-- Parsing ``-maxN<n>`` from Args to be sure of it.
+getN :: IO Int
+getN = getFullArgs >>= return . go
+ where
+ go :: [String] -> Int
+ go as = case reads (
+ dropWhile (not . isDigit) . (!! 1) $ as ) :: [(Int, String)] of
+ [x] -> fst x
+ _ -> 0
diff --git a/testsuite/tests/rts/T10728.stdout b/testsuite/tests/rts/T10728.stdout
new file mode 100644
index 0000000000..715329ea3c
--- /dev/null
+++ b/testsuite/tests/rts/T10728.stdout
@@ -0,0 +1 @@
+maxN Successful
diff --git a/testsuite/tests/rts/all.T b/testsuite/tests/rts/all.T
index 9892050b34..c88bd62267 100644
--- a/testsuite/tests/rts/all.T
+++ b/testsuite/tests/rts/all.T
@@ -1,9 +1,9 @@
test('testblockalloc',
- [c_src, only_ways(['normal','threaded1']), extra_run_opts('+RTS -I0')],
+ [c_src, only_ways(['normal','threaded1']), extra_run_opts('+RTS -I0')],
compile_and_run, [''])
test('testmblockalloc',
- [c_src, only_ways(['normal','threaded1']), extra_run_opts('+RTS -I0')],
+ [c_src, only_ways(['normal','threaded1']), extra_run_opts('+RTS -I0')],
compile_and_run, [''])
# -I0 is important: the idle GC will run the memory leak detector,
# which will crash because the mblocks we allocate are not in a state
@@ -53,7 +53,7 @@ test('divbyzero',
when(opsys('mingw32'), omit_ways(prof_ways))],
compile_and_run, [''])
-test('outofmem', when(opsys('darwin'), skip),
+test('outofmem', when(opsys('darwin'), skip),
run_command, ['$MAKE -s --no-print-directory outofmem'])
test('outofmem2', extra_run_opts('+RTS -M5m -RTS'),
run_command, ['$MAKE -s --no-print-directory outofmem2'])
@@ -111,8 +111,8 @@ test('T2615',
# omit dyn and profiling ways, because we don't build dyn_l or p_l
# variants of the RTS by default
-test('traceEvent', [ omit_ways(['dyn'] + prof_ways),
- extra_run_opts('+RTS -ls -RTS') ],
+test('traceEvent', [ omit_ways(['dyn'] + prof_ways),
+ extra_run_opts('+RTS -ls -RTS') ],
compile_and_run, ['-eventlog'])
test('T4059',
@@ -333,3 +333,6 @@ test('T10590', [ignore_output, when(opsys('mingw32'),skip)], compile_and_run, ['
# 20000 was easily enough to trigger the bug with 7.10
test('T10904', [ omit_ways(['ghci']), extra_run_opts('20000') ],
compile_and_run, ['T10904lib.c'])
+
+test('T10728', [extra_run_opts('+RTS -maxN3 -RTS'), req_smp],
+ compile_and_run, ['-threaded'])