1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
<html>
<head>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1">
<title>The GHC Commentary - The Multi-threaded runtime, and multiprocessor execution</title>
</head>
<body>
<h1>The GHC Commentary - The Multi-threaded runtime, and multiprocessor execution</h1>
<p>This section of the commentary explains the structure of the runtime system
when used in threaded or SMP mode.</p>
<p>The <em>threaded</em> version of the runtime supports
bound threads and non-blocking foreign calls, and an overview of its
design can be found in the paper <a
href="http://www.haskell.org/~simonmar/papers/conc-ffi.pdf">Extending
the Haskell Foreign Function Interface with Concurrency</a>. To
compile the runtime with threaded support, add the line
<pre>GhcRTSWays += thr</pre>
to <tt>mk/build.mk</tt>. When building C code in the runtime for the threaded way,
the symbol <tt>THREADED_RTS</tt> is defined (this is arranged by the
build system when building for way <tt>thr</tt>, see
<tt>mk/config.mk</tt>). To build a Haskell program
with the threaded runtime, pass the flag <tt>-threaded</tt> to GHC (this
can be used in conjunction with <tt>-prof</tt>, and possibly
<tt>-debug</tt> and others depending on which versions of the RTS have
been built.</p>
<p>The <em>SMP</em> version runtime supports the same facilities as the
threaded version, and in addition supports execution of Haskell code by
multiple simultaneous OS threads. For SMP support, both the runtime and
the libraries must be built a special way: add the lines
<pre>
GhcRTSWays += thr
GhcLibWays += s</pre>
to <tt>mk/build.mk</tt>. To build Haskell code for
SMP execution, use the flag <tt>-smp</tt> to GHC (this can be used in
conjunction with <tt>-debug</tt>, but no other way-flags at this time).
When building C code in the runtime for SMP
support, the symbol <tt>SMP</tt> is defined (this is arranged by the
compiler when the <tt>-smp</tt> flag is given, see
<tt>ghc/compiler/main/StaticFlags.hs</tt>).</p>
<p>When building the runtime in either the threaded or SMP ways, the symbol
<tt>RTS_SUPPORTS_THREADS</tt> will be defined (see <tt>Rts.h</tt>).</p>
<h2>Overall design</h2>
<p>The system is based around the notion of a <tt>Capability</tt>. A
<tt>Capability</tt> is an object that represents both the permission to
execute some Haskell code, and the state required to do so. In order
to execute some Haskell code, a thread must therefore hold a
<tt>Capability</tt>. The available pool of capabilities is managed by
the <tt>Capability</tt> API, described below.</p>
<p>In the threaded runtime, there is only a single <tt>Capabililty</tt> in the
system, indicating that only a single thread can be executing Haskell
code at any one time. In the SMP runtime, there can be an arbitrary
number of capabilities selectable at runtime with the <tt>+RTS -N<em>n</em></tt>
flag; in practice the number is best chosen to be the same as the number of
processors on the host machine.</p>
<p>There are a number of OS threads running code in the runtime. We call
these <em>tasks</em> to avoid confusion with Haskell <em>threads</em>.
Tasks are managed by the <tt>Task</tt> subsystem, which is mainly
concerned with keeping track of statistics such as how much time each
task spends executing Haskell code, and also keeping track of how many
tasks are around when we want to shut down the runtime.</p>
<p>Some tasks are created by the runtime itself, and some may be here
as a result of a call to Haskell from foreign code (we
call this an in-call). The
runtime can support any number of concurrent foreign in-calls, but the
number of these calls that will actually run Haskell code in parallel is
determined by the number of available capabilities. Each in-call creates
a <em>bound thread</em>, as described in the FFI/Concurrency paper (cited
above).</p>
<p>In the future we may want to bind a <tt>Capability</tt> to a particular
processor, so that we can support a notion of affinity - avoiding
accidental migration of work from one CPU to another, so that we can make
best use of a CPU's local cache. For now, the design ignores this
issue.</p>
<h2>The <tt>OSThreads</tt> interface</h2>
<p>This interface is merely an abstraction layer over the OS-specific APIs
for managing threads. It has two main implementations: Win32 and
POSIX.</p>
<p>This is the entirety of the interface:</p>
<pre>
/* Various abstract types */
typedef Mutex;
typedef Condition;
typedef OSThreadId;
extern OSThreadId osThreadId ( void );
extern void shutdownThread ( void );
extern void yieldThread ( void );
extern int createOSThread ( OSThreadId* tid,
void (*startProc)(void) );
extern void initCondition ( Condition* pCond );
extern void closeCondition ( Condition* pCond );
extern rtsBool broadcastCondition ( Condition* pCond );
extern rtsBool signalCondition ( Condition* pCond );
extern rtsBool waitCondition ( Condition* pCond,
Mutex* pMut );
extern void initMutex ( Mutex* pMut );
</pre>
<h2>The Task interface</h2>
<h2>The Capability interface</h2>
<h2>Multiprocessor Haskell Execution</h2>
</body>
</html>
|