X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fdocs%2Fusers_guide%2Fruntime_control.sgml;h=b7668a00a10d4e1ebe6ee35555658c2e75ddba18;hb=2dfd507259664e6f28df4a9467a8de34d01d70a0;hp=2871f76589bf6f887da0af2c5ec74ce9a87eb6a9;hpb=4d8884a56b4db905584070b0225729145cacd603;p=ghc-hetmet.git
diff --git a/ghc/docs/users_guide/runtime_control.sgml b/ghc/docs/users_guide/runtime_control.sgml
index 2871f76..b7668a0 100644
--- a/ghc/docs/users_guide/runtime_control.sgml
+++ b/ghc/docs/users_guide/runtime_control.sgml
@@ -1,578 +1,543 @@
-
-Running a compiled program
-
-
-
-runtime control of Haskell programs
-running, compiled program
-RTS options
-
-
-
-To make an executable program, the GHC system compiles your code and
-then links it with a non-trivial runtime system (RTS), which handles
-storage management, profiling, etc.
-
-
-
-You have some control over the behaviour of the RTS, by giving special
-command-line arguments to your program.
-
-
-
-When your Haskell program starts up, its RTS extracts command-line
-arguments bracketed between +RTS option and
--RTS option as its own. For example:
-
-
-
-
-
-% ./a.out -f +RTS -p -S -RTS -h foo bar
-
+
+ Running a compiled program
+
+ runtime control of Haskell programs
+ running, compiled program
+ RTS options
+
+ To make an executable program, the GHC system compiles your
+ code and then links it with a non-trivial runtime system (RTS),
+ which handles storage management, profiling, etc.
-
+ You have some control over the behaviour of the RTS, by giving
+ special command-line arguments to your program.
-
-The RTS will snaffle for itself, and the remaining arguments
- will be handed to your program if/when it calls
-System.getArgs.
-
+ When your Haskell program starts up, its RTS extracts
+ command-line arguments bracketed between
+
+ and
+
+ as its own. For example:
+
+
+% ./a.out -f +RTS -p -S -RTS -h foo bar
+
-
-No option is required if the runtime-system options extend to
-the end of the command line, as in this example:
-
+ The RTS will snaffle
+ for itself, and the remaining arguments -f -h foo bar
+ will be handed to your program if/when it calls
+ System.getArgs.
-
+ No option is required if the
+ runtime-system options extend to the end of the command line, as in
+ this example:
-
+
% hls -ltr /usr/etc +RTS -A5m
-
-
-
-
-
-If you absolutely positively want all the rest of the options in a
-command line to go to the program (and not the RTS), use a
---RTS option.
-
-
-
-As always, for RTS options that take <size>s: If the last
-character of size is a K or k, multiply by 1000; if an M or m, by
-1,000,000; if a G or G, by 1,000,000,000. (And any wraparound in the
-counters is your fault!)
-
-
-
-Giving a -f RTS option option will print out the
-RTS options actually available in your program (which vary, depending
-on how you compiled).
-
-
-
-NOTE: to send RTS options to the compiler itself, you need to prefix
-the option with , eg. to increase the maximum heap size for
-a compilation to 128M, you would add to the command
-line. The compiler understands some options directly without needing
-: these are and .
-
-
-
-RTS options to control the garbage-collector
-
-
-
-RTS options, garbage-collection
-
-
-
-There are several options to give you precise control over garbage
-collection. Hopefully, you won't need any of these in normal
-operation, but there are several things that can be tweaked for
-maximum performance.
-
-
-
-
-
-
-:
-
-
--A<size> RTS option
-allocation area, size
-
-
-
-[Default: 256k] Set the allocation area size used by the garbage
-collector. The allocation area (actually generation 0 step 0) is
-fixed and is never resized (unless you use , below).
-
-
-
-Increasing the allocation area size may or may not give better
-performance (a bigger allocation area means worse cache behaviour but
-fewer garbage collections and less promotion).
-
-
-
-With only 1 generation () the option specifies the
-minimum allocation area, since the actual size of the allocation area
-will be resized according to the amount of data in the heap (see
-, below).
-
-
-
-
-:
-
-
--F<factor> RTS option
-heap size, factor
-
-
-
-[Default: 2] This option controls the amount of memory reserved for
-the older generations (and in the case of a two space collector the
-size of the allocation area) as a factor of the amount of live data.
-For example, if there was 2M of live data in the oldest generation
-when we last collected it, then by default we'll wait until it grows
-to 4M before collecting it again.
-
-
-
-The default seems to work well here. If you have plenty of memory, it
-is usually better to use than to increase
-.
-
-
-
-The setting will be automatically reduced by the garbage
-collector when the maximum heap size (the setting)
-is approaching.
-
-
-
-
-:
-
-
--G<generations> RTS option
-generations, number of
-
-
-
-[Default: 2] Set the number of generations used by the garbage
-collector. The default of 2 seems to be good, but the garbage
-collector can support any number of generations. Anything larger than
-about 4 is probably not a good idea unless your program runs for a
-long time, because the oldest generation will never get
-collected.
-
-
-
-Specifying 1 generation with gives you a simple 2-space
-collector, as you would expect. In a 2-space collector, the
-option (see above) specifies the minimum allocation area size,
-since the allocation area will grow with the amount of live data in
-the heap. In a multi-generational collector the allocation area is a
-fixed size (unless you use the option, see below).
-
-
-
-
-:
-
-
--H<size> RTS option
-heap size, suggested
-
-
-
-[Default: 0] This option provides a "suggested heap size" for the
-garbage collector. The garbage collector will use about this much
-memory until the program residency grows and the heap size needs to be
-expanded to retain reasonable performance.
-
-
-
-By default, the heap will start small, and grow and shrink as
-necessary. This can be bad for performance, so if you have plenty of
-memory it's worthwhile supplying a big . For
-improving GC performance, using is usually a better
-bet than .
-
-
-
-
-:
-
-
--k<size> RTS option
-stack, minimum size
-
-
-
-[Default: 1k] Set the initial stack size for new threads. Thread
-stacks (including the main thread's stack) live on the heap, and grow
-as required. The default value is good for concurrent applications
-with lots of small threads; if your program doesn't fit this model
-then increasing this option may help performance.
-
-
-
-The main thread is normally started with a slightly larger heap to cut
-down on unnecessary stack growth while the program is starting up.
-
-
-
-
-:
-
-
--K<size> RTS option
-stack, maximum size
-
-
-
-[Default: 1M] Set the maximum stack size for an individual thread to
-<size> bytes. This option is there purely to stop the program
-eating up all the available memory in the machine if it gets into an
-infinite loop.
-
-
-
-
-:
-
-
--m<n> RTS option
-Minimum % <n> of heap which must be available for allocation.
-The default is 3%.
-heap, minimum free
-
-
-
-
-:
-
-
--M<size> RTS option
-heap size, maximum
-
-
-
-[Default: 64M] Set the maximum heap size to <size> bytes. The heap
-normally grows and shrinks according to the memory requirements of the
-program. The only reason for having this option is to stop the heap
-growing without bound and filling up all the available swap space,
-which at the least will result in the program being summarily killed
-by the operating system.
-
-
-
-
- or :
-
-
--S<file> RTS option
--s<file> RTS option
-Write modest () or verbose () garbage-collector
-statistics into file <file>. The default <file> is
-<program>@.stat. The <file>stderr is treated
-specially, with the output really being sent to stderr.
-
-
-
-This option is useful for watching how the storage manager adjusts the
-heap size based on the current amount of live data.
-
-
-
-
-
-
-
-
-
-RTS options for profiling and Concurrent/Parallel Haskell
-
-
-The RTS options related to profiling are described in ; and those for concurrent/parallel stuff, in
-.
-
-
-
-
-
-RTS options for hackers, debuggers, and over-interested souls
-
-
-RTS options, hacking/debugging
-
-
-
-These RTS options might be used (a) to avoid a GHC bug, (b) to see
-“what's really happening”, or (c) because you feel like it. Not
-recommended for everyday use!
-
-
-
-
-
-
-:
-
-
--B RTS option
-Sound the bell at the start of each (major) garbage collection.
-
-
-
-Oddly enough, people really do use this option! Our pal in Durham
-(England), Paul Callaghan, writes: “Some people here use it for a
-variety of purposes—honestly!—e.g., confirmation that the
-code/machine is doing something, infinite loop detection, gauging cost
-of recently added code. Certain people can even tell what stage [the
-program] is in by the beep pattern. But the major use is for annoying
-others in the same office…”
-
-
-
-
-:
-
-
--r <file> RTS option
-ticky ticky profiling
-Produce “ticky-ticky” statistics at the end of the program run.
-The <file> business works just like on the RTS option (above).
-
-
-
-“Ticky-ticky” statistics are counts of various program actions
-(updates, enters, etc.) The program must have been compiled using
--ticky option (a.k.a. “ticky-ticky profiling”),
-and, for it to be really useful, linked with suitable system
-libraries. Not a trivial undertaking: consult the installation guide
-on how to set things up for easy “ticky-ticky” profiling. For more
-information, see .
-
-
-
-
-:
-
-
--D RTS option
-An RTS debugging flag; varying quantities of output depending on which
-bits are set in <num>. Only works if the RTS was compiled with the
- option.
-
-
-
-
-:
-
-
--Z RTS option
-Turn off “update-frame squeezing” at garbage-collection
-time. (There's no particularly good reason to turn it off, except to
-ensure the accuracy of certain data collected regarding thunk entry
-counts.)
-
-
-
-
-
-
-
-
-
-“Hooks” to change RTS behaviour
-
-
-
-hooks, RTS
-RTS hooks
-RTS behaviour, changing
-
-
-
-GHC lets you exercise rudimentary control over the RTS settings for
-any given program, by compiling in a “hook” that is called by the
-run-time system. The RTS contains stub definitions for all these
-hooks, but by writing your own version and linking it on the GHC
-command line, you can override the defaults.
-
-
-
-Owing to the vagaries of DLL linking, these hooks don't work under Windows when
-the compiler is built dynamically.
-
-
-
-The function defaultsHookdefaultHook lets you change various
-RTS options. The commonest use for this is to give your program a
-default heap and/or stack size that is greater than the default. For
-example, to set :
-
-
-
-
-
-#include "Rts.h"
-#include "RtsFlags.h"
-void defaultsHook (void) {
- RTSflags.GcFlags.stksSize = 1000002 / sizeof(W_);
- RTSflags.GcFlags.heapSize = 8000002 / sizeof(W_);
-}
-
-
-
-
-
-Don't use powers of two for heap/stack sizes: these are more likely to
-interact badly with direct-mapped caches. The full set of flags is
-defined in ghc/rts/RtsFlags.h the the GHC source tree.
-
-
-
-You can also change the messages printed when the runtime system
-“blows up,” e.g., on stack overflow. The hooks for these are as
-follows:
-
-
-
-
-
-
-void ErrorHdrHook (FILE *):
-
-
-ErrorHdrHook
-What's printed out before the message from error.
-
-
-
-
-void OutOfHeapHook (unsigned long, unsigned long):
-
-
-OutOfHeapHook
-The heap-overflow message.
-
-
-
-
-void StackOverflowHook (long int):
-
-
-StackOverflowHook
-The stack-overflow message.
-
-
-
-
-void MallocFailHook (long int):
-
-
-MallocFailHook
-The message printed if malloc fails.
-
-
-
-
-void PatErrorHdrHook (FILE *):
-
-
-PatErrorHdrHook
-The message printed if a pattern-match fails (the failures
-that were not handled by the Haskell programmer).
-
-
-
-
-void PreTraceHook (FILE *):
-
-
-PreTraceHook
-What's printed out before a trace message.
-
-
-
-
-void PostTraceHook (FILE *):
-
-
-PostTraceHook
-What's printed out after a trace message.
-
-
-
-
-
-
-
-For example, here is the “hooks” code used by GHC itself:
-
-
-#include <stdio.h>
-#define W_ unsigned long int
-#define I_ long int
-
-void
-ErrorHdrHook (FILE *where)
-{
- fprintf(where, "\n"); /* no "Fail: " */
-}
-
-void
-OutOfHeapHook (W_ request_size, W_ heap_size) /* both sizes in bytes */
-{
- fprintf(stderr, "GHC's heap exhausted;\nwhile trying to
- allocate %lu bytes in a %lu-byte heap;\nuse the `-H<size>'
- option to increase the total heap size.\n",
- request_size,
- heap_size);
-}
-
-void
-StackOverflowHook (I_ stack_size) /* in bytes */
-{
- fprintf(stderr, "GHC stack-space overflow: current size
- %ld bytes.\nUse the `-K<size>' option to increase it.\n",
- stack_size);
-}
-
-void
-PatErrorHdrHook (FILE *where)
-{
- fprintf(where, "\n*** Pattern-matching error within GHC!\n\n
- This is a compiler bug; please report it to
- glasgow-haskell-bugs@haskell.org.\n\nFail: ");
-}
-
-void
-PreTraceHook (FILE *where)
-{
- fprintf(where, "\n"); /* not "Trace On" */
-}
-
-void
-PostTraceHook (FILE *where)
-{
- fprintf(where, "\n"); /* not "Trace Off" */
-}
-
-
-
-
-
-
-
+
+
+ If you absolutely positively want all the rest of the options
+ in a command line to go to the program (and not the RTS), use a
+ .
+
+ As always, for RTS options that take
+ sizes: If the last character of
+ size is a K or k, multiply by 1000; if an
+ M or m, by 1,000,000; if a G or G, by 1,000,000,000. (And any
+ wraparound in the counters is your
+ fault!)
+
+ Giving a +RTS -f
+ RTS option option
+ will print out the RTS options actually available in your program
+ (which vary, depending on how you compiled).
+
+ NOTE: since GHC is itself compiled by GHC, you can change RTS
+ options in the compiler using the normal
+ +RTS ... -RTS
+ combination. eg. to increase the maximum heap
+ size for a compilation to 128M, you would add
+ +RTS -M128m -RTS
+ to the command line.
+
+
+ Setting global RTS options
+
+ RTS optionsfrom the environment
+ environment variablefor
+ setting RTS options
+
+ RTS options are also taken from the environment variable
+ GHCRTSGHCRTS
+ . For example, to set the maximum heap size
+ to 128M for all GHC-compiled programs (using an
+ sh-like shell):
+
+
+ GHCRTS='-M128m'
+ export GHCRTS
+
+
+ RTS options taken from the GHCRTS environment
+ variable can be overriden by options given on the command
+ line.
+
+
+
+
+ RTS options to control the garbage collector
+
+ garbage collectoroptions
+ RTS optionsgarbage collection
+
+ There are several options to give you precise control over
+ garbage collection. Hopefully, you won't need any of these in
+ normal operation, but there are several things that can be tweaked
+ for maximum performance.
+
+
+
+
+ size
+ RTS option
+ allocation area, size
+
+ [Default: 256k] Set the allocation area size
+ used by the garbage collector. The allocation area
+ (actually generation 0 step 0) is fixed and is never resized
+ (unless you use , below).
+
+ Increasing the allocation area size may or may not
+ give better performance (a bigger allocation area means
+ worse cache behaviour but fewer garbage collections and less
+ promotion).
+
+ With only 1 generation () the
+ option specifies the minimum allocation
+ area, since the actual size of the allocation area will be
+ resized according to the amount of data in the heap (see
+ , below).
+
+
+
+
+
+ RTS option
+
+ garbage collectioncompacting
+
+ compacting garbage collection
+
+
+ Use a compacting algorithm for collecting the oldest
+ generation. By default, the oldest generation is collected
+ using a copying algorithm; this option causes it to be
+ compacted in-place instead. The compaction algorithm is
+ slower than the copying algorithm, but the savings in memory
+ use can be considerable.
+
+ For a given heap size (using the
+ option), compaction can in fact reduce the GC cost by
+ allowing fewer GCs to be performed. This is more likely
+ when the ratio of live data to heap size is high, say
+ >30%.
+
+ NOTE: compaction doesn't currently work when a single
+ generation is requested using the
+ option.
+
+
+
+
+ n
+
+
+ [Default: 30] Automatically enable
+ compacting collection when the live data exceeds
+ n% of the maximum heap size
+ (see the option). Note that the maximum
+ heap size is unlimited by default, so this option has no
+ effect unless the maximum heap size is set with
+ size.
+
+
+
+
+ factor
+
+ RTS option
+ heap size, factor
+
+ [Default: 2] This option controls the amount
+ of memory reserved for the older generations (and in the
+ case of a two space collector the size of the allocation
+ area) as a factor of the amount of live data. For example,
+ if there was 2M of live data in the oldest generation when
+ we last collected it, then by default we'll wait until it
+ grows to 4M before collecting it again.
+
+ The default seems to work well here. If you have
+ plenty of memory, it is usually better to use
+ size than to
+ increase
+ factor.
+
+ The setting will be automatically
+ reduced by the garbage collector when the maximum heap size
+ (the size
+ setting) is approaching.
+
+
+
+
+ generations
+ RTS option
+ generations, number
+ of
+
+ [Default: 2] Set the number of generations
+ used by the garbage collector. The default of 2 seems to be
+ good, but the garbage collector can support any number of
+ generations. Anything larger than about 4 is probably not a
+ good idea unless your program runs for a
+ long time, because the oldest
+ generation will hardly ever get collected.
+
+ Specifying 1 generation with
+ gives you a simple 2-space collector, as you would expect.
+ In a 2-space collector, the option (see
+ above) specifies the minimum allocation
+ area size, since the allocation area will grow with the
+ amount of live data in the heap. In a multi-generational
+ collector the allocation area is a fixed size (unless you
+ use the option, see below).
+
+
+
+
+ size
+ RTS option
+ heap size, suggested
+
+ [Default: 0] This option provides a
+ “suggested heap size” for the garbage collector. The
+ garbage collector will use about this much memory until the
+ program residency grows and the heap size needs to be
+ expanded to retain reasonable performance.
+
+ By default, the heap will start small, and grow and
+ shrink as necessary. This can be bad for performance, so if
+ you have plenty of memory it's worthwhile supplying a big
+ size. For
+ improving GC performance, using
+ size is
+ usually a better bet than
+ size.
+
+
+
+
+ size
+ RTS option
+ stack, minimum size
+
+ [Default: 1k] Set the initial stack size for
+ new threads. Thread stacks (including the main thread's
+ stack) live on the heap, and grow as required. The default
+ value is good for concurrent applications with lots of small
+ threads; if your program doesn't fit this model then
+ increasing this option may help performance.
+
+ The main thread is normally started with a slightly
+ larger heap to cut down on unnecessary stack growth while
+ the program is starting up.
+
+
+
+
+ size
+ RTS option
+ stack, maximum size
+
+ [Default: 8M] Set the maximum stack size for
+ an individual thread to size
+ bytes. This option is there purely to stop the program
+ eating up all the available memory in the machine if it gets
+ into an infinite loop.
+
+
+
+
+ n
+ RTS option
+ heap, minimum free
+
+ Minimum % n of heap
+ which must be available for allocation. The default is
+ 3%.
+
+
+
+
+ size
+ RTS option
+ heap size, maximum
+
+ [Default: unlimited] Set the maximum heap size to
+ size bytes. The heap normally
+ grows and shrinks according to the memory requirements of
+ the program. The only reason for having this option is to
+ stop the heap growing without bound and filling up all the
+ available swap space, which at the least will result in the
+ program being summarily killed by the operating
+ system.
+
+ The maximum heap size also affects other garbage
+ collection parameters: when the amount of live data in the
+ heap exceeds a certain fraction of the maximum heap size,
+ compacting collection will be automatically enabled for the
+ oldest generation, and the parameter
+ will be reduced in order to avoid exceeding the maximum heap
+ size.
+
+
+
+
+ file
+ file
+ RTS option
+ RTS option
+
+ Write modest () or verbose
+ () garbage-collector statistics into file
+ file. The default
+ file is
+ program.stat. The
+ filestderr
+ is treated specially, with the output really being sent to
+ stderr.
+
+ This option is useful for watching how the storage
+ manager adjusts the heap size based on the current amount of
+ live data.
+
+
+
+
+
+ RTS option
+
+ Write a one-line GC stats summary after running the
+ program. This output is in the same format as that produced
+ by the option.
+
+
+
+
+
+
+
+ RTS options for profiling and Concurrent/Parallel Haskell
+
+ The RTS options related to profiling are described in ; and those for concurrent/parallel
+ stuff, in .
+
+
+
+ RTS options for hackers, debuggers, and over-interested
+ souls
+
+ RTS options, hacking/debugging
+
+ These RTS options might be used (a) to avoid a GHC bug,
+ (b) to see “what's really happening”, or
+ (c) because you feel like it. Not recommended for everyday
+ use!
+
+
+
+
+
+ RTS option
+
+ Sound the bell at the start of each (major) garbage
+ collection.
+
+ Oddly enough, people really do use this option! Our
+ pal in Durham (England), Paul Callaghan, writes: “Some
+ people here use it for a variety of
+ purposes—honestly!—e.g., confirmation that the
+ code/machine is doing something, infinite loop detection,
+ gauging cost of recently added code. Certain people can even
+ tell what stage [the program] is in by the beep
+ pattern. But the major use is for annoying others in the
+ same office…”
+
+
+
+
+ num
+ -DRTS option
+
+ An RTS debugging flag; varying quantities of output
+ depending on which bits are set in
+ num. Only works if the RTS was
+ compiled with the option.
+
+
+
+
+ file
+ RTS option
+ ticky ticky profiling
+ profilingticky ticky
+
+ Produce “ticky-ticky” statistics at the
+ end of the program run. The file
+ business works just like on the RTS
+ option (above).
+
+ “Ticky-ticky” statistics are counts of
+ various program actions (updates, enters, etc.) The program
+ must have been compiled using
+
+ (a.k.a. “ticky-ticky profiling”), and, for it to
+ be really useful, linked with suitable system libraries.
+ Not a trivial undertaking: consult the installation guide on
+ how to set things up for easy “ticky-ticky”
+ profiling. For more information, see .
+
+
+
+
+
+ RTS
+ option
+
+ (Only available when the program is compiled for
+ profiling.) When an exception is raised in the program,
+ this option causes the current cost-centre-stack to be
+ dumped to stderr.
+
+ This can be particularly useful for debugging: if your
+ program is complaining about a head []
+ error and you haven't got a clue which bit of code is
+ causing it, compiling with -prof
+ -auto-all and running with +RTS -xc
+ -RTS will tell you exactly the call stack at the
+ point the error was raised.
+
+ The output contains one line for each exception raised
+ in the program (the program might raise and catch several
+ exceptions during its execution), where each line is of the
+ form:
+
+
+< cc1, ..., ccn >
+
+ each cci is
+ a cost centre in the program (see ), and the sequence represents the
+ “call stack” at the point the exception was
+ raised. The leftmost item is the innermost function in the
+ call stack, and the rightmost item is the outermost
+ function.
+
+
+
+
+
+
+ RTS
+ option
+
+ Turn off “update-frame
+ squeezing” at garbage-collection time. (There's no
+ particularly good reason to turn it off, except to ensure
+ the accuracy of certain data collected regarding thunk entry
+ counts.)
+
+
+
+
+
+
+
+ “Hooks” to change RTS behaviour
+
+ hooksRTS
+ RTS hooks
+ RTS behaviour, changing
+
+ GHC lets you exercise rudimentary control over the RTS
+ settings for any given program, by compiling in a
+ “hook” that is called by the run-time system. The RTS
+ contains stub definitions for all these hooks, but by writing your
+ own version and linking it on the GHC command line, you can
+ override the defaults.
+
+ Owing to the vagaries of DLL linking, these hooks don't work
+ under Windows when the program is built dynamically.
+
+ The hook ghc_rts_optsghc_rts_opts
+ lets you set RTS
+ options permanently for a given program. A common use for this is
+ to give your program a default heap and/or stack size that is
+ greater than the default. For example, to set -H128m
+ -K1m, place the following definition in a C source
+ file:
+
+
+char *ghc_rts_opts = "-H128m -K1m";
+
+
+ Compile the C file, and include the object file on the
+ command line when you link your Haskell program.
+
+ These flags are interpreted first, before any RTS flags from
+ the GHCRTS environment variable and any flags
+ on the command line.
+
+ You can also change the messages printed when the runtime
+ system “blows up,” e.g., on stack overflow. The hooks
+ for these are as follows:
+
+
+
+
+ void OutOfHeapHook (unsigned long, unsigned long)
+ OutOfHeapHook
+
+ The heap-overflow message.
+
+
+
+
+ void StackOverflowHook (long int)
+ StackOverflowHook
+
+ The stack-overflow message.
+
+
+
+
+ void MallocFailHook (long int)
+ MallocFailHook
+
+ The message printed if malloc
+ fails.
+
+
+
+
+ For examples of the use of these hooks, see GHC's own
+ versions in the file
+ ghc/compiler/parser/hschooks.c in a GHC
+ source tree.
+
+