[project @ 1998-11-26 09:17:22 by sof]
[ghc-hetmet.git] / ghc / includes / Threads.lh
1 %
2 % (c) The GRASP Project, Glasgow University, 1994-1995
3 %
4 \section[Thread]{Thread support macros used in \tr{.hc} files}
5
6 \begin{code}
7 #ifndef THREADS_H
8 #define THREADS_H
9 \end{code}
10
11 \begin{code}
12 #if defined(GRAN)
13
14 #define sparkq sparkq 
15 #define TYPE_OF_SPARK    struct spark
16 #define TYPE_OF_SPARK_PTR sparkq
17 #define SIZE_OF_SPARK    (sizeof(TYPE_OF_SPARK))
18
19 typedef struct spark
20 {
21   struct spark *prev, *next;
22   P_ node;
23   I_ name, global;
24   I_ gran_info;
25 } *sparkq;
26
27 #endif 
28
29 #ifndef CONCURRENT
30
31 #define OR_CONTEXT_SWITCH
32
33 #else
34
35 extern I_ do_gr_sim;                            /* Are we simulating granularity? */
36 extern FILE *gr_file;
37
38 extern I_ do_qp_prof;                           /* Are we quasi-parallel profiling? */
39 extern FILE *qp_file;
40
41 #ifdef PAR
42 #define DO_QP_PROF 0
43 #else
44 #define DO_QP_PROF do_qp_prof
45 #endif
46
47 extern I_ context_switch;                       /* Flag set by signal handler */
48 #if defined(i386_TARGET_ARCH)
49 extern I_ entersFromC;                          /* Counter set by enterStablePtr
50                                                    (see comments in c-as-asm/StablePtrOps.lc) */
51 #endif
52
53 #define CS_MAX_FREQUENCY 100                    /* context switches per second */
54 #define CS_MIN_MILLISECS (1000/CS_MAX_FREQUENCY)/* milliseconds per slice */
55
56 #ifdef __STG_GCC_REGS__
57 # if defined(i386_TARGET_ARCH)
58 # define OR_CONTEXT_SWITCH || (context_switch && !entersFromC)
59 # else
60 # define OR_CONTEXT_SWITCH || context_switch
61 # endif
62 #else
63 #define OR_CONTEXT_SWITCH /* in miniInterpret */
64 #endif
65
66 #define REQUIRED_POOL   0
67 #define ADVISORY_POOL   1
68 #define SPARK_POOLS     2
69
70 #if !defined(GRAN) 
71
72 #define TYPE_OF_SPARK    PP_
73 #define SIZE_OF_SPARK    (sizeof(TYPE_OF_SPARK))
74
75 extern TYPE_OF_SPARK PendingSparksBase[SPARK_POOLS], 
76                      PendingSparksLim[SPARK_POOLS];
77 extern TYPE_OF_SPARK PendingSparksHd[SPARK_POOLS], 
78                      PendingSparksTl[SPARK_POOLS];
79
80 extern I_ SparkLimit[SPARK_POOLS];
81
82 extern P_ RunnableThreadsHd, RunnableThreadsTl;
83 extern P_ WaitingThreadsHd, WaitingThreadsTl;
84
85 #if defined(PAR) 
86 extern I_ sparksIgnored, sparksCreated;
87 #endif
88
89 IF_RTS(extern void AwaitEvent(I_);)
90
91 #else /* GRAN */
92
93 extern TYPE_OF_SPARK_PTR PendingSparksBase[][SPARK_POOLS], 
94                          PendingSparksLim[][SPARK_POOLS];
95 extern TYPE_OF_SPARK_PTR PendingSparksHd[][SPARK_POOLS], 
96                          PendingSparksTl[][SPARK_POOLS];
97 extern P_ RunnableThreadsHd[], RunnableThreadsTl[],
98           WaitThreadsHd[], WaitThreadsTl[];
99
100 #define SparkQueueHd    PendingSparksHd[CurrentProc][ADVISORY_POOL]
101 #define SparkQueueTl    PendingSparksTl[CurrentProc][ADVISORY_POOL]
102 #define ThreadQueueHd   RunnableThreadsHd[CurrentProc]
103 #define ThreadQueueTl   RunnableThreadsTl[CurrentProc]
104 #define WaitingThreadsHd  WaitThreadsHd[CurrentProc]
105 #define WaitingThreadsTl  WaitThreadsTl[CurrentProc]
106
107 #endif  /* GRAN */
108
109 IF_RTS(extern void PruneSparks(STG_NO_ARGS);)
110
111 #if defined(GRAN)
112
113 /* Codes that can be used as params for ReSchedule */
114 /* I distinguish them from the values 0/1 in the -UGRAN setup for security */
115 /* reasons */
116 #define FIND_THREAD     10
117 #define SAME_THREAD     11
118 #define NEW_THREAD      SAME_THREAD
119 #define CHANGE_THREAD   13
120 #define END_OF_WORLD    14
121
122 extern W_ SparksAvail, SurplusThreads;
123
124 extern W_ CurrentTime[];
125 extern I_ OutstandingFetches[], OutstandingFishes[];
126 extern enum proc_status procStatus[];
127
128 #  if defined(GRAN_CHECK) && defined(GRAN) /* Just for testing */
129 # define FETCH_MASK_TSO  0x08000000      /* only bits 0, 1, 2 should be used */
130                                         /* normally */
131 extern P_ BlockedOnFetch[];
132 #  endif
133
134 #endif     /* GRAN */
135
136 extern P_ CurrentTSO;                    /* thread state object now in use */
137
138 extern P_ AvailableStack;
139 extern P_ AvailableTSO;
140
141 extern I_ threadId;
142
143 void ScheduleThreads PROTO((P_ topClosure));
144
145 #if defined(GRAN)
146 void ReSchedule PROTO((int what_next)) STG_NORETURN;
147 void add_to_spark_queue PROTO((sparkq));
148 int set_sparkname PROTO((P_, int));
149 int reset_sparkname PROTO((P_)); 
150 I_ spark_queue_len PROTO((PROC, I_));
151 sparkq delete_from_spark_queue PROTO((sparkq, sparkq));
152 I_ thread_queue_len PROTO((PROC));
153 void DisposeSparkQ PROTO((sparkq));
154
155 #else /* !GRAN */
156
157 void ReSchedule PROTO((int again)) STG_NORETURN;
158
159 #endif
160
161 void EndThread(STG_NO_ARGS) STG_NORETURN;
162
163 /* ToDo: Check if these are still needed -- HWL */
164 void QP_Event0 PROTO((I_, P_));
165 void QP_Event1 PROTO((char *, P_));
166 void QP_Event2 PROTO((char *, P_, P_));
167 long qp_elapsed_time(STG_NO_ARGS);
168 \end{code}
169
170 %************************************************************************
171 %*                                                                      *
172 \subsection[thread-heap-objs]{Special threads-only heap objects (`closures')}
173 %*                                                                      *
174 %************************************************************************
175
176 %************************************************************************
177 %*                                                                      *
178 \subsubsection[TSO-closures]{@TSO@ (thread state object) heap objects}
179 %*                                                                      *
180 %************************************************************************
181
182 We now enter the realm of the Deeply Magical.
183
184 Reduction threads come and go, resume and suspend, etc., in the threaded
185 world.  Obviously, there must be a place to squirrel away state information
186 when a thread is suspended.  Hence these {\em thread state objects} (TSOs).
187
188 Rather than manage TSOs' alloc/dealloc, etc., in some {\em ad hoc} way, we
189 instead alloc/dealloc/etc them in the heap; then we can use all the
190 standard garbage-collection/fetching/flushing/etc machinery on them.
191 So that's why TSOs are ``heap objects,'' albeit very special ones.
192
193 We use all the standard heap-object/closure jargon... (e.g.,
194 @SET_TSO_HDR@, fixed headers, variable-hdr size, ...).
195
196 A TSO is a fixed-size object with (post-header) words arranged like
197 the main register table, and enough slop so that the register table
198 can be properly aligned.  The last header word of the TSO is
199 a pointer to the (internal) start of the interesting data.
200
201 Note that the heap and stack pointers in the TSO are only valid while
202 the thread is executing, and only if the corresponding values are not
203 stored in machine registers (i.e. the TSO becomes the backing register
204 table for those values).
205
206 \begin{code}
207 #define TSO_INFO_WORDS 10
208
209 #ifdef TICKY_TICKY
210 #define TSO_REDN_WORDS 2
211 #else
212 #define TSO_REDN_WORDS 0
213 #endif
214
215 #if defined(GRAN) || defined(PAR)
216            /* do we really need a whole statistics buffer in PAR setup? HWL*/
217 #define TSO_GRAN_WORDS 17
218 #else
219 #define TSO_GRAN_WORDS 0
220 #endif
221
222 #define TSO_VHS \
223         (GC_MUT_RESERVED_WORDS + TSO_INFO_WORDS + TSO_REDN_WORDS + TSO_GRAN_WORDS)
224
225 #define TSO_HS          (FIXED_HS + TSO_VHS)
226 #define TSO_CTS_SIZE    (BYTES_TO_STGWORDS(sizeof(STGRegisterTable) + sizeof(StgDouble)))
227
228 #define TSO_PTRS        (MAX_VANILLA_REG + 2)
229
230 /* std start-filling-in macro: */
231 #define SET_TSO_HDR(closure,infolbl,cc)         \
232 { SET_FIXED_HDR(closure,infolbl,cc);            \
233   SET_MUT_RESERVED_WORDS(closure);              \
234 }
235
236 #define TSO_INFO_START          (FIXED_HS + GC_MUT_RESERVED_WORDS)
237 #define TSO_LINK_LOCN           (TSO_INFO_START + 0)
238 #define TSO_CCC_LOCN            (TSO_INFO_START + 1)
239 #define TSO_NAME_LOCN           (TSO_INFO_START + 2)
240 #define TSO_ID_LOCN             (TSO_INFO_START + 3)
241 #define TSO_TYPE_LOCN           (TSO_INFO_START + 4)
242 #define TSO_PC1_LOCN            (TSO_INFO_START + 5)
243 #define TSO_PC2_LOCN            (TSO_INFO_START + 6)
244 #define TSO_ARG1_LOCN           (TSO_INFO_START + 7)
245 #define TSO_EVENT_LOCN          (TSO_INFO_START + 8)
246 #define TSO_SWITCH_LOCN         (TSO_INFO_START + 9)
247
248 #define TSO_REDN_START          (TSO_INFO_START + TSO_INFO_WORDS)
249 #ifdef TICKY_TICKY
250 #define TSO_AHWM_LOCN           (TSO_REDN_START + 0)
251 #define TSO_BHWM_LOCN           (TSO_REDN_START + 1)
252 #endif
253
254 #define TSO_GRAN_START          (TSO_REDN_START + TSO_REDN_WORDS)
255 #if defined(GRAN) || defined(PAR)
256 #define TSO_LOCKED_LOCN         (TSO_GRAN_START + 0)
257 #define TSO_SPARKNAME_LOCN      (TSO_GRAN_START + 1)
258 #define TSO_STARTEDAT_LOCN      (TSO_GRAN_START + 2)
259 #define TSO_EXPORTED_LOCN       (TSO_GRAN_START + 3)
260 #define TSO_BASICBLOCKS_LOCN    (TSO_GRAN_START + 4)
261 #define TSO_ALLOCS_LOCN         (TSO_GRAN_START + 5)
262 #define TSO_EXECTIME_LOCN       (TSO_GRAN_START + 6)
263 #define TSO_FETCHTIME_LOCN      (TSO_GRAN_START + 7)
264 #define TSO_FETCHCOUNT_LOCN     (TSO_GRAN_START + 8)
265 #define TSO_BLOCKTIME_LOCN      (TSO_GRAN_START + 9)
266 #define TSO_BLOCKCOUNT_LOCN     (TSO_GRAN_START + 10)
267 #define TSO_BLOCKEDAT_LOCN      (TSO_GRAN_START + 11)
268 #define TSO_GLOBALSPARKS_LOCN   (TSO_GRAN_START + 12)
269 #define TSO_LOCALSPARKS_LOCN    (TSO_GRAN_START + 13)
270 #define TSO_QUEUE_LOCN          (TSO_GRAN_START + 14)
271 #define TSO_PRI_LOCN            (TSO_GRAN_START + 15)
272 #define TSO_CLOCK_LOCN          (TSO_GRAN_START + 16)
273 #endif
274
275 #define TSO_LINK(closure)           (((PP_)closure)[TSO_LINK_LOCN])
276 #define TSO_CCC(closure)            (((CostCentre *)closure)[TSO_CCC_LOCN])
277 #define TSO_NAME(closure)           (((PP_)closure)[TSO_NAME_LOCN])
278 #define TSO_ID(closure)             (((P_)closure)[TSO_ID_LOCN])
279 #define TSO_TYPE(closure)           (((P_)closure)[TSO_TYPE_LOCN])
280 #define TSO_PC1(closure)            (((FP_)closure)[TSO_PC1_LOCN])
281 #define TSO_PC2(closure)            (((FP_)closure)[TSO_PC2_LOCN])
282 #define TSO_ARG1(closure)           (((P_)closure)[TSO_ARG1_LOCN])
283 #define TSO_EVENT(closure)          (((P_)closure)[TSO_EVENT_LOCN])
284 #define TSO_SWITCH(closure)         (((FP_)closure)[TSO_SWITCH_LOCN])
285
286 #define TSO_AHWM(closure)           (((I_ *)closure)[TSO_AHWM_LOCN])
287 #define TSO_BHWM(closure)           (((I_ *)closure)[TSO_BHWM_LOCN])
288
289 #define TSO_LOCKED(closure)         (((P_)closure)[TSO_LOCKED_LOCN])
290 #define TSO_SPARKNAME(closure)      (((P_)closure)[TSO_SPARKNAME_LOCN])
291 #define TSO_STARTEDAT(closure)      (((P_)closure)[TSO_STARTEDAT_LOCN])
292 #define TSO_EXPORTED(closure)       (((P_)closure)[TSO_EXPORTED_LOCN])
293 #define TSO_BASICBLOCKS(closure)    (((P_)closure)[TSO_BASICBLOCKS_LOCN])
294 #define TSO_ALLOCS(closure)         (((P_)closure)[TSO_ALLOCS_LOCN])
295 #define TSO_EXECTIME(closure)       (((P_)closure)[TSO_EXECTIME_LOCN])
296 #define TSO_FETCHTIME(closure)      (((P_)closure)[TSO_FETCHTIME_LOCN])
297 #define TSO_FETCHCOUNT(closure)     (((P_)closure)[TSO_FETCHCOUNT_LOCN])
298 #define TSO_BLOCKTIME(closure)      (((P_)closure)[TSO_BLOCKTIME_LOCN])
299 #define TSO_BLOCKCOUNT(closure)     (((P_)closure)[TSO_BLOCKCOUNT_LOCN])
300 #define TSO_BLOCKEDAT(closure)      (((P_)closure)[TSO_BLOCKEDAT_LOCN])
301 #define TSO_GLOBALSPARKS(closure)   (((P_)closure)[TSO_GLOBALSPARKS_LOCN])
302 #define TSO_LOCALSPARKS(closure)    (((P_)closure)[TSO_LOCALSPARKS_LOCN])
303 #define TSO_QUEUE(closure)          (((P_)closure)[TSO_QUEUE_LOCN])
304 #define TSO_PRI(closure)            (((P_)closure)[TSO_PRI_LOCN])
305 /* TSO_CLOCK is only needed in GrAnSim-Light */
306 #define TSO_CLOCK(closure)          (((P_)closure)[TSO_CLOCK_LOCN])
307
308 #define TSO_INTERNAL_PTR(closure)           \
309   ((STGRegisterTable *)(((W_)(((P_)closure) \
310     + TSO_HS + BYTES_TO_STGWORDS(sizeof(StgDouble)))) & ~(sizeof(StgDouble) - 1)))
311
312 #if defined(CONCURRENT) && defined(GRAN)        /* HWL */
313 /* Per definitionem a tso is really awake if it has met a first */
314 /* GRAN_RESCHEDULE macro after having been rescheduled. */
315 #define REALLY_AWAKE(tso)       (TSO_SWITCH(tso) != TSO_PC2(tso))
316 #define SET_AWAKE_FLAG(tso)     TSO_SWITCH(tso) = NULL
317 #define RESET_AWAKE_FLAG(tso)   TSO_SWITCH(tso) = TSO_PC2(tso)
318 #endif
319
320 \end{code}
321
322 The types of threads (TSO_TYPE):
323 \begin{code}
324 #define T_MAIN                  0       /* Must be executed locally */
325 #define T_REQUIRED              1       /* A required thread  -- may be exported */
326 #define T_ADVISORY              2       /* An advisory thread -- may be exported */
327 #define T_FAIL                  3       /* A failure thread   -- may be exported */
328 \end{code}
329
330 The total space required to start a new thread (See NewThread in
331 Threads.lc):
332 \begin{code}
333 #define THREAD_SPACE_REQUIRED (TSO_HS + TSO_CTS_SIZE + STKO_HS + RTSflags.ConcFlags.stkChunkSize)
334 \end{code}
335
336 Here are the various queues for GrAnSim-type events.
337 \begin{code}
338 #define Q_RUNNING   'G'
339 #define Q_RUNNABLE  'A'
340 #define Q_BLOCKED   'R'
341 #define Q_FETCHING  'Y'
342 #define Q_MIGRATING 'B'
343 \end{code}
344
345 %************************************************************************
346 %*                                                                      *
347 \subsubsection[spark-closures]{Pending Sparks}
348 %*                                                                      *
349 %************************************************************************
350
351 \begin{code}
352 #ifdef PAR
353
354 P_ FindLocalSpark PROTO((rtsBool forexport));
355
356 void DisposeSpark PROTO((P_ spark));
357 rtsBool Spark PROTO((P_ closure, rtsBool required));
358
359 #endif /*PAR*/
360
361 #ifdef GRAN   /* For GrAnSim sparks are currently mallocated -- HWL */
362
363 void DisposeSpark PROTO((sparkq spark));
364 sparkq NewSpark PROTO((P_,I_,I_,I_,I_,I_));
365
366 /* # define MAX_EVENTS          1000 */  /* For GC Roots Purposes */
367 # define MAX_SPARKS             0        /* i.e. infinite */
368
369 #if defined(GRAN_JSM_SPARKS)
370 /* spark is a pointer into some sparkq (which is for JSM sparls just an 
371    array of (struct sparks) */
372
373 # define SPARK_PREV(spark)      { fprintf(stderr,"Error: SPARK_PREV not supported for JSM sparks") \
374                                   EXIT(EXIT_FAILURE); }
375 /* NB: SPARK_NEXT may only be used as a rhs but NOT as a lhs */
376 # define SPARK_NEXT(spark)      (spark++)
377 # define SPARK_NODE(spark)      (P_)(spark->node)
378 # define SPARK_NAME(spark)      (spark->name)
379 # define SPARK_GRAN_INFO(spark) (spark->gran_info)
380 # define SPARK_GLOBAL(spark)    (spark->global)
381 # define SPARK_EXPORTED(spark)  (SPARK_GLOBAL(spark) > 1)
382 #else
383 # define SPARK_PREV(spark)      (spark->prev)
384 # define SPARK_NEXT(spark)      (sparkq)(spark->next)
385 # define SPARK_NODE(spark)      (spark->node)
386 # define SPARK_NAME(spark)      (spark->name)
387 # define SPARK_GRAN_INFO(spark) (spark->gran_info)
388 # define SPARK_GLOBAL(spark)    (spark->global)
389 # define SPARK_EXPORTED(spark)  (SPARK_GLOBAL(spark) > 1)
390 #endif
391
392 #endif      /* GRAN */
393 \end{code}
394
395 %************************************************************************
396 %*                                                                      *
397 \subsubsection[STKO-closures]{@STKO@ (stack object) heap objects}
398 %*                                                                      *
399 %************************************************************************
400
401 We linger in the Deeply Magical...
402
403 Each reduction thread has to have its own stack space.  As there may
404 be many such threads, and as any given one may need quite a big stack,
405 a naive give-'em-a-big-stack-and-let-'em-run approach will cost a {\em
406 lot} of memory.
407
408 Our approach is to give a thread a small stack space, and then link
409 on/off extra ``chunks'' as the need arises.  Again, this is a
410 storage-management problem, and, yet again, we choose to graft the
411 whole business onto the existing heap-management machinery.  So stack
412 objects will live in the heap, be garbage collected, etc., etc..
413
414 So, as with TSOs, we use the standard heap-object (`closure') jargon.
415
416 Here is the picture of how a stack object is arranged:
417 \begin{verbatim}
418     <-----  var hdr -------->                    v ---- FirstPtr --- v
419 ---------------------------------------------------------------------
420 ...|| SpB | SuB | SpA | SuA || B stk -> ... | ... <- A stk || PREV ||
421 ---------------------------------------------------------------------
422                               XX->                     <-YY 
423 \end{verbatim}
424
425 We keep the following state-of-stack info in the {\em variable-header}
426 part of a STKO:
427 \begin{tabular}{ll}
428 SpB, SuB & their {\em offsets} from 1st non-hdr word (marked \tr{XX} above)\\
429 SpA, SuA & their {\em offsets} from the next-to-last word (marked \tr{YY} above)\\
430 ctr field??? & (GC\_GEN\_WHATNOT may serve instead)\\
431 \end{tabular}
432
433 The stack-pointer offsets are from the points indicated and are {\em
434 non-negative} for pointers to this chunk of the stack space.
435
436 At the {\em end} of the stack object, we have a {\em link} to the
437 previous part of the overall stack.  The link is \tr{NULL} if this is
438 the bottom of the overall stack.
439
440 After the header, we have @STKO_CHUNK_SIZE-1@ words of actual stack
441 stuff.  The B-stack part begins at the lowest address and grows
442 upwards; the A-stack parts begins at the highest address and grows
443 downwards.
444
445 From a storage-manager point of view, these are {\em very special}
446 objects.
447
448 \begin{code}
449 #ifdef TICKY_TICKY
450 #define STKO_VHS        (GC_MUT_RESERVED_WORDS + 9)
451 #else
452 #define STKO_VHS        (GC_MUT_RESERVED_WORDS + 7)
453 #endif
454 #define STKO_HS         (FIXED_HS + STKO_VHS)
455
456 #define MIN_STKO_CHUNK_SIZE 16  /* Rather arbitrary */
457
458 #define STKO_CLOSURE_SIZE(closure)      STKO_SIZE(closure)
459
460 #define STKO_CLOSURE_CTS_SIZE(closure)  (STKO_CLOSURE_SIZE(closure) - STKO_VHS)
461 #define STKO_CLOSURE_PTR(closure, no)   (*STKO_CLOSURE_ADDR(closure, no))
462
463 #define STKO_CLOSURE_ADDR(s, n)     (((P_)(s)) + STKO_HS + (n) - 1)
464 #define STKO_CLOSURE_OFFSET(s, p)   (((P_)(p) - (P_)(s)) - STKO_HS + 1)
465
466 /* std start-filling-in macro: */
467 #define SET_STKO_HDR(s,infolbl,cc)      \
468         { SET_FIXED_HDR(s,infolbl,cc);  \
469           SET_MUT_RESERVED_WORDS(s);    \
470           /* the other header words filled in some other way */ }
471
472 /* now we have the STKO-specific stuff 
473
474    Note: The S[pu][AB] registers are put in this order so that
475          they will appear in monotonically increasing order in
476          the StkO...just as an aid to the poor wee soul who has
477          to debug things.
478  */
479
480 #ifdef TICKY_TICKY
481 #define STKO_ADEP_LOCN      (STKO_HS - 9)
482 #define STKO_BDEP_LOCN      (STKO_HS - 8)
483 #endif
484 #define STKO_SIZE_LOCN      (STKO_HS - 7)
485 #define STKO_RETURN_LOCN    (STKO_HS - 6)
486 #define STKO_LINK_LOCN      (STKO_HS - 5)
487 #define STKO_SuB_LOCN       (STKO_HS - 4)
488 #define STKO_SpB_LOCN       (STKO_HS - 3)
489 #define STKO_SpA_LOCN       (STKO_HS - 2)
490 #define STKO_SuA_LOCN       (STKO_HS - 1)
491
492 #define STKO_ADEP(s)        (((I_ *)(s))[STKO_ADEP_LOCN])
493 #define STKO_BDEP(s)        (((I_ *)(s))[STKO_BDEP_LOCN])
494 #define STKO_SIZE(s)        (((P_)(s))[STKO_SIZE_LOCN])
495 #define STKO_RETURN(s)      (((StgRetAddr *)(s))[STKO_RETURN_LOCN])
496 #define STKO_LINK(s)        (((PP_)(s))[STKO_LINK_LOCN])
497 #define STKO_SpB(s)         (((PP_)(s))[STKO_SpB_LOCN])
498 #define STKO_SuB(s)         (((PP_)(s))[STKO_SuB_LOCN])
499 #define STKO_SpA(s)         (((PP_ *)(s))[STKO_SpA_LOCN])
500 #define STKO_SuA(s)         (((PP_ *)(s))[STKO_SuA_LOCN])
501
502 #define STKO_BSTK_OFFSET(closure) (STKO_HS)
503 #define STKO_ASTK_OFFSET(closure) (FIXED_HS + STKO_CLOSURE_SIZE(closure) - 1)
504 #define STKO_BSTK_BOT(closure)    (((P_)(closure)) + STKO_BSTK_OFFSET(closure))
505 #define STKO_ASTK_BOT(closure)    (((PP_)(closure)) + STKO_ASTK_OFFSET(closure))
506 \end{code}
507
508 These are offsets into the stack object proper (starting at 1 for
509 the first word after the header).
510
511 \begin{code}
512 #define STKO_SpA_OFFSET(s)  (STKO_CLOSURE_OFFSET(s,STKO_SpA(s)))
513 #define STKO_SuA_OFFSET(s)  (STKO_CLOSURE_OFFSET(s,STKO_SuA(s)))
514 #define STKO_SpB_OFFSET(s)  (STKO_CLOSURE_OFFSET(s,STKO_SpB(s)))
515 #define STKO_SuB_OFFSET(s)  (STKO_CLOSURE_OFFSET(s,STKO_SuB(s)))
516 \end{code}
517
518 %************************************************************************
519 %*                                                                      *
520 \subsubsection[BQ-closures]{@BQ@ (blocking queue) heap objects (`closures')}
521 %*                                                                      *
522 %************************************************************************
523
524 Blocking queues are built in the parallel system when a local thread
525 enters a non-global node.  They are similar to black holes, except
526 that when they are updated, the blocking queue must be enlivened
527 too.  A blocking queue closure thus has the following structure.
528
529 \begin{onlylatex}
530 \begin{center}
531 \end{onlylatex}
532 \begin{tabular}{||l|l|l|l||}\hline
533 GA      &       Info ptr.       & $\ldots$              &       Blocking Queue  \\ \hline
534 \end{tabular}
535 \begin{onlylatex}
536 \begin{center}
537 \end{onlylatex}
538
539 The blocking queue itself is a pointer to a list of blocking queue entries.
540 The list is formed from TSO closures.  For the generational garbage collectors,
541 the BQ must have the same structure as an IND, with the blocking queue hanging
542 off of the indirection pointer.  (This has to do with treating the BQ as an old
543 root if it gets updated while in the old generation.)
544
545 \begin{code}
546 #define BQ_VHS                      IND_VHS
547 #define BQ_HS                       IND_HS
548
549 #define BQ_CLOSURE_SIZE(closure)    IND_CLOSURE_SIZE(closure)
550 #define BQ_CLOSURE_NoPTRS(closure)  IND_CLOSURE_NoPTRS(closure)
551 #define BQ_CLOSURE_NoNONPTRS(closure)   IND_CLOSURE_NoNONPTRS(closure)
552 #define BQ_CLOSURE_PTR(closure, no) (((P_)(closure))[BQ_HS + (no) - 1])
553 \end{code}
554
555 Blocking queues store a pointer to a list of blocking queue entries.
556
557 \begin{code}
558 #define BQ_ENTRIES(closure)         IND_CLOSURE_PTR(closure)
559 #define BQ_LINK(closure)            IND_CLOSURE_LINK(closure)
560 \end{code}
561
562 We have only one kind of blocking queue closure, so we test the info pointer
563 for a specific value rather than looking in the info table for a special bit.
564
565 \begin{code}
566 EXTDATA_RO(BQ_info);
567 EXTFUN(BQ_entry);
568 #define IS_BQ_CLOSURE(closure)     (INFO_PTR(closure) == (W_) BQ_info)
569 \end{code}
570
571 %************************************************************************
572 %*                                                                      *
573 \subsubsection[TSO_ITBL]{@TSO_ITBL@}
574 %*                                                                      *
575 %************************************************************************
576
577 The special info table used for thread state objects (TSOs).
578
579 \begin{code}
580
581 #define TSO_ITBL()                                  \
582     CAT_DECLARE(TSO,INTERNAL_KIND,"TSO","<TSO>")    \
583     EXTFUN(TSO_entry);                              \
584     EXTDATA_RO(MK_REP_LBL(TSO,,));                  \
585     const W_ TSO_info[] = {                         \
586         (W_) TSO_entry                              \
587         ,(W_) INFO_OTHER_TAG                        \
588         ,(W_) MK_REP_REF(TSO,,)                     \
589         INCLUDE_PROFILING_INFO(TSO)                 \
590         }
591
592 #define TSO_RTBL() \
593     const W_ MK_REP_LBL(TSO,,)[] = { \
594         INCLUDE_TYPE_INFO(TSO)                                  \
595         INCLUDE_SIZE_INFO(INFO_UNUSED,INFO_UNUSED)              \
596         INCLUDE_PAR_INFO                                        \
597         INCLUDE_COPYING_INFO(_Evacuate_TSO,_Scavenge_TSO)       \
598         INCLUDE_COMPACTING_INFO(_ScanLink_TSO,_PRStart_TSO,_ScanMove_TSO,_PRIn_TSO) \
599         }
600
601 \end{code}
602
603 %************************************************************************
604 %*                                                                      *
605 \subsubsection[STKO_ITBL]{@STKO_ITBL@}
606 %*                                                                      *
607 %************************************************************************
608
609 The special info table used for stack objects (STKOs).
610
611 \begin{code}
612 #define STKO_ITBL()                                     \
613     CAT_DECLARE(StkO,INTERNAL_KIND,"STKO","<STKO>")     \
614     EXTFUN(StkO_entry);                                 \
615     EXTDATA_RO(MK_REP_LBL(StkO,,));                     \
616     const W_ StkO_info[] = {                            \
617         (W_) StkO_entry                                 \
618         ,(W_) INFO_OTHER_TAG                            \
619         ,(W_) MK_REP_REF(StkO,,)                        \
620         INCLUDE_PROFILING_INFO(StkO)                    \
621     }
622
623 #define STKO_RTBL() \
624     const W_ MK_REP_LBL(StkO,,)[] = { \
625         INCLUDE_TYPE_INFO(STKO_DYNAMIC)                         \
626         INCLUDE_SIZE_INFO(INFO_UNUSED,INFO_UNUSED)              \
627         INCLUDE_PAR_INFO                                        \
628         INCLUDE_COPYING_INFO(_Evacuate_StkO,_Scavenge_StkO)     \
629         INCLUDE_COMPACTING_INFO(_ScanLink_StkO,_PRStart_StkO,_ScanMove_StkO,_PRIn_StkO) \
630     }
631
632 #define STKO_STATIC_ITBL()                              \
633     CAT_DECLARE(StkO_static,INTERNAL_KIND,"STKO","<STKO>")      \
634     EXTFUN(StkO_static_entry);                          \
635     EXTDATA_RO(MK_REP_LBL(StkO_static,,));              \
636     const W_ StkO_static_info[] = {                     \
637         (W_) StkO_static_entry                          \
638         ,(W_) INFO_OTHER_TAG                            \
639         ,(W_) MK_REP_REF(StkO_static,,)                 \
640         INCLUDE_PROFILING_INFO(StkO_static)             \
641     }
642
643 #define STKO_STATIC_RTBL() \
644     const W_ MK_REP_LBL(StkO_static,,)[] = { \
645         INCLUDE_TYPE_INFO(STKO_STATIC)                          \
646         INCLUDE_SIZE_INFO(INFO_UNUSED,INFO_UNUSED)              \
647         INCLUDE_PAR_INFO                                        \
648         INCLUDE_COPYING_INFO(_Evacuate_Static,_Dummy_Static_entry) \
649         INCLUDE_COMPACTING_INFO(_Dummy_Static_entry,_PRStart_Static, \
650                                 _Dummy_Static_entry,_PRIn_Error)    \
651     }
652
653 \end{code}
654
655 %************************************************************************
656 %*                                                                      *
657 \subsubsection[BQ_ITBL]{@BQ_ITBL@}
658 %*                                                                      *
659 %************************************************************************
660
661 Special info-table for local blocking queues.
662
663 \begin{code}
664 #define BQ_ITBL()                               \
665     CAT_DECLARE(BQ,INTERNAL_KIND,"BQ","<BQ>")   \
666     EXTFUN(BQ_entry);                           \
667     EXTDATA_RO(MK_REP_LBL(BQ,,));               \
668     const W_ BQ_info[] = {                      \
669         (W_) BQ_entry                           \
670         ,(W_) INFO_OTHER_TAG                    \
671         ,(W_) MK_REP_REF(BQ,,)                  \
672         INCLUDE_PROFILING_INFO(BQ)              \
673     }
674
675 #define BQ_RTBL() \
676     const W_ MK_REP_LBL(BQ,,)[] = {                             \
677         INCLUDE_TYPE_INFO(BQ)                                   \
678         INCLUDE_SIZE_INFO(MIN_UPD_SIZE,INFO_UNUSED)             \
679         INCLUDE_PAR_INFO                                        \
680         INCLUDE_COPYING_INFO(_Evacuate_BQ,_Scavenge_BQ)         \
681         SPEC_COMPACTING_INFO(_ScanLink_BQ,_PRStart_BQ,_ScanMove_BQ,_PRIn_BQ) \
682     }
683
684 \end{code}
685
686 \begin{code}
687 #endif  /* CONCURRENT */
688 \end{code}
689
690 Even the sequential system gets to play with SynchVars, though it really
691 doesn't make too much sense (if any).  Okay; maybe it makes some sense.
692 (See the 1.3 I/O stuff.)
693
694 %************************************************************************
695 %*                                                                      *
696 \subsubsection[SVar-closures]{@SynchVar@ heap objects}
697 %*                                                                      *
698 %************************************************************************
699
700 \begin{code}
701 #define SVAR_HS                     (MUTUPLE_HS)
702
703 #define SVAR_CLOSURE_SIZE(closure)  3
704
705 #define SET_SVAR_HDR(closure,infolbl,cc)   \
706     SET_MUTUPLE_HDR(closure,infolbl,cc,MUTUPLE_VHS+3,3)
707
708 /* The value must come first, because we shrink the other two fields off
709    when writing an IVar */
710
711 #define SVAR_VALUE_LOCN         (SVAR_HS+0)
712 #define SVAR_HEAD_LOCN          (SVAR_HS+1)
713 #define SVAR_TAIL_LOCN          (SVAR_HS+2)
714
715 #define SVAR_VALUE(closure)     ((PP_)(closure))[SVAR_VALUE_LOCN]
716 #define SVAR_HEAD(closure)      ((PP_)(closure))[SVAR_HEAD_LOCN]
717 #define SVAR_TAIL(closure)      ((PP_)(closure))[SVAR_TAIL_LOCN]
718 \end{code}
719
720 End multi-slurp protection:
721
722 \begin{code}
723 #endif  /* THREADS_H */
724 \end{code}
725
726