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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
|
/* -----------------------------------------------------------------------------
*
* (c) The GHC Team, 1998-2009
*
* RTS external APIs. This file declares everything that the GHC RTS
* exposes externally.
*
* To understand the structure of the RTS headers, see the wiki:
* http://hackage.haskell.org/trac/ghc/wiki/Commentary/SourceTree/Includes
*
* ---------------------------------------------------------------------------*/
#ifndef RTS_H
#define RTS_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef IN_STG_CODE
#define IN_STG_CODE 0
#endif
#include "Stg.h"
#include "HsFFI.h"
#include "RtsAPI.h"
// Turn off inlining when debugging - it obfuscates things
#ifdef DEBUG
# undef STATIC_INLINE
# define STATIC_INLINE static
#endif
#include "rts/Types.h"
#if __GNUC__ >= 3
/* Assume that a flexible array member at the end of a struct
* can be defined thus: T arr[]; */
#define FLEXIBLE_ARRAY
#else
/* Assume that it must be defined thus: T arr[0]; */
#define FLEXIBLE_ARRAY 0
#endif
#if __GNUC__ >= 3
#define ATTRIBUTE_ALIGNED(n) __attribute__((aligned(n)))
#else
#define ATTRIBUTE_ALIGNED(n) /*nothing*/
#endif
// Symbols that are extern, but private to the RTS, are declared
// with visibility "hidden" to hide them outside the RTS shared
// library.
#if defined(HAS_VISIBILITY_HIDDEN)
#define RTS_PRIVATE GNUC3_ATTRIBUTE(visibility("hidden"))
#else
#define RTS_PRIVATE /* disabled: RTS_PRIVATE */
#endif
#if __GNUC__ >= 4
#define RTS_UNLIKELY(p) __builtin_expect((p),0)
#else
#define RTS_UNLIKELY(p) p
#endif
/* Fix for mingw stat problem (done here so it's early enough) */
#ifdef mingw32_HOST_OS
#define __MSVCRT__ 1
#endif
/* Needed to get the macro version of errno on some OSs, and also to
get prototypes for the _r versions of C library functions. */
#ifndef _REENTRANT
#define _REENTRANT 1
#endif
/*
* We often want to know the size of something in units of an
* StgWord... (rounded up, of course!)
*/
#define ROUNDUP_BYTES_TO_WDS(n) (((n) + sizeof(W_) - 1) / sizeof(W_))
#define sizeofW(t) ROUNDUP_BYTES_TO_WDS(sizeof(t))
/* -----------------------------------------------------------------------------
Assertions and Debuggery
CHECK(p) evaluates p and terminates with an error if p is false
ASSERT(p) like CHECK(p) if DEBUG is on, otherwise a no-op
-------------------------------------------------------------------------- */
void _assertFail(const char *filename, unsigned int linenum)
GNUC3_ATTRIBUTE(__noreturn__);
#define CHECK(predicate) \
if (predicate) \
/*null*/; \
else \
_assertFail(__FILE__, __LINE__)
#define CHECKM(predicate, msg, ...) \
if (predicate) \
/*null*/; \
else \
barf(msg, ##__VA_ARGS__)
#ifndef DEBUG
#define ASSERT(predicate) /* nothing */
#define ASSERTM(predicate,msg,...) /* nothing */
#else
#define ASSERT(predicate) CHECK(predicate)
#define ASSERTM(predicate,msg,...) CHECKM(predicate,msg,##__VA_ARGS__)
#endif /* DEBUG */
/*
* Use this on the RHS of macros which expand to nothing
* to make sure that the macro can be used in a context which
* demands a non-empty statement.
*/
#define doNothing() do { } while (0)
#ifdef DEBUG
#define USED_IF_DEBUG
#define USED_IF_NOT_DEBUG STG_UNUSED
#else
#define USED_IF_DEBUG STG_UNUSED
#define USED_IF_NOT_DEBUG
#endif
#ifdef THREADED_RTS
#define USED_IF_THREADS
#define USED_IF_NOT_THREADS STG_UNUSED
#else
#define USED_IF_THREADS STG_UNUSED
#define USED_IF_NOT_THREADS
#endif
/*
* Getting printf formats right for platform-dependent typedefs
*/
#if SIZEOF_LONG == 8
#define FMT_Word64 "lu"
#define FMT_Int64 "ld"
#else
#if defined(mingw32_HOST_OS)
/* mingw doesn't understand %llu/%lld - it treats them as 32-bit
rather than 64-bit */
#define FMT_Word64 "I64u"
#define FMT_Int64 "I64d"
#else
#define FMT_Word64 "llu"
#define FMT_Int64 "lld"
#endif
#endif
/* -----------------------------------------------------------------------------
Time values in the RTS
-------------------------------------------------------------------------- */
// For most time values in the RTS we use a fixed resolution of nanoseconds,
// normalising the time we get from platform-dependent APIs to this
// resolution.
#define TIME_RESOLUTION 1000000000
typedef StgInt64 Time;
#if TIME_RESOLUTION == 1000000000
// I'm being lazy, but it's awkward to define fully general versions of these
#define TimeToUS(t) (t / 1000)
#define TimeToNS(t) (t)
#define USToTime(t) ((Time)(t) * 1000)
#define NSToTime(t) ((Time)(t))
#else
#error Fix TimeToNS(), TimeToUS() etc.
#endif
#define SecondsToTime(t) ((Time)(t) * TIME_RESOLUTION)
#define TimeToSeconds(t) ((t) / TIME_RESOLUTION)
// Use instead of SecondsToTime() when we have a floating-point
// seconds value, to avoid truncating it.
INLINE_HEADER Time fsecondsToTime (double t)
{
return (Time)(t * TIME_RESOLUTION);
}
/* -----------------------------------------------------------------------------
Include everything STG-ish
-------------------------------------------------------------------------- */
/* System headers: stdlib.h is eeded so that we can use NULL. It must
* come after MachRegs.h, because stdlib.h might define some inline
* functions which may only be defined after register variables have
* been declared.
*/
#include <stdlib.h>
#include "rts/Config.h"
/* Global constaints */
#include "rts/Constants.h"
/* Profiling information */
#include "rts/prof/CCS.h"
#include "rts/prof/LDV.h"
/* Parallel information */
#include "rts/OSThreads.h"
#include "rts/SpinLock.h"
#include "rts/Messages.h"
/* Storage format definitions */
#include "rts/storage/FunTypes.h"
#include "rts/storage/InfoTables.h"
#include "rts/storage/Closures.h"
#include "rts/storage/Liveness.h"
#include "rts/storage/ClosureTypes.h"
#include "rts/storage/TSO.h"
#include "stg/MiscClosures.h" /* InfoTables, closures etc. defined in the RTS */
#include "rts/storage/SMPClosureOps.h"
#include "rts/storage/Block.h"
#include "rts/storage/ClosureMacros.h"
#include "rts/storage/MBlock.h"
#include "rts/storage/GC.h"
/* Other RTS external APIs */
#include "rts/Parallel.h"
#include "rts/Hooks.h"
#include "rts/Signals.h"
#include "rts/BlockSignals.h"
#include "rts/Hpc.h"
#include "rts/Flags.h"
#include "rts/Adjustor.h"
#include "rts/FileLock.h"
#include "rts/Globals.h"
#include "rts/IOManager.h"
#include "rts/Linker.h"
#include "rts/Threads.h"
#include "rts/Ticky.h"
#include "rts/Timer.h"
#include "rts/Stable.h"
#include "rts/TTY.h"
#include "rts/Utils.h"
#include "rts/PrimFloat.h"
#include "rts/Main.h"
/* Misc stuff without a home */
DLL_IMPORT_RTS extern char **prog_argv; /* so we can get at these from Haskell */
DLL_IMPORT_RTS extern int prog_argc;
DLL_IMPORT_RTS extern char *prog_name;
#ifdef mingw32_HOST_OS
// We need these two from Haskell too
void getWin32ProgArgv(int *argc, wchar_t **argv[]);
void setWin32ProgArgv(int argc, wchar_t *argv[]);
#endif
void stackOverflow(void);
void stg_exit(int n) GNU_ATTRIBUTE(__noreturn__);
#ifndef mingw32_HOST_OS
int stg_sig_install (int, int, void *);
#endif
/* -----------------------------------------------------------------------------
RTS Exit codes
-------------------------------------------------------------------------- */
/* 255 is allegedly used by dynamic linkers to report linking failure */
#define EXIT_INTERNAL_ERROR 254
#define EXIT_DEADLOCK 253
#define EXIT_INTERRUPTED 252
#define EXIT_HEAPOVERFLOW 251
#define EXIT_KILLED 250
/* -----------------------------------------------------------------------------
Miscellaneous garbage
-------------------------------------------------------------------------- */
#ifdef DEBUG
#define TICK_VAR(arity) \
extern StgInt SLOW_CALLS_##arity; \
extern StgInt RIGHT_ARITY_##arity; \
extern StgInt TAGGED_PTR_##arity;
extern StgInt TOTAL_CALLS;
TICK_VAR(1)
TICK_VAR(2)
#endif
/* -----------------------------------------------------------------------------
Assertions and Debuggery
-------------------------------------------------------------------------- */
#define IF_RTSFLAGS(c,s) if (RtsFlags.c) { s; }
#ifdef DEBUG
#if IN_STG_CODE
#define IF_DEBUG(c,s) if (RtsFlags[0].DebugFlags.c) { s; }
#else
#define IF_DEBUG(c,s) if (RtsFlags.DebugFlags.c) { s; }
#endif
#else
#define IF_DEBUG(c,s) doNothing()
#endif
#ifdef DEBUG
#define DEBUG_ONLY(s) s
#else
#define DEBUG_ONLY(s) doNothing()
#endif
/* -----------------------------------------------------------------------------
Useful macros and inline functions
-------------------------------------------------------------------------- */
#if defined(__GNUC__)
#define SUPPORTS_TYPEOF
#endif
#if defined(SUPPORTS_TYPEOF)
#define stg_min(a,b) ({typeof(a) _a = (a), _b = (b); _a <= _b ? _a : _b; })
#define stg_max(a,b) ({typeof(a) _a = (a), _b = (b); _a <= _b ? _b : _a; })
#else
#define stg_min(a,b) ((a) <= (b) ? (a) : (b))
#define stg_max(a,b) ((a) <= (b) ? (b) : (a))
#endif
/* -------------------------------------------------------------------------- */
#ifdef __cplusplus
}
#endif
#endif /* RTS_H */
|