2 % (c) The GRASP Project, Glasgow University, 1994-1995
4 \section[Thread]{Thread support macros used in \tr{.hc} files}
15 #define TYPE_OF_SPARK struct spark
16 #define TYPE_OF_SPARK_PTR sparkq
17 #define SIZE_OF_SPARK (sizeof(TYPE_OF_SPARK))
21 struct spark *prev, *next;
31 #define OR_CONTEXT_SWITCH
35 extern I_ do_gr_sim; /* Are we simulating granularity? */
38 extern I_ do_qp_prof; /* Are we quasi-parallel profiling? */
44 #define DO_QP_PROF do_qp_prof
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) */
53 #define CS_MAX_FREQUENCY 100 /* context switches per second */
54 #define CS_MIN_MILLISECS (1000/CS_MAX_FREQUENCY)/* milliseconds per slice */
56 #ifdef __STG_GCC_REGS__
57 # if defined(i386_TARGET_ARCH)
58 # define OR_CONTEXT_SWITCH || (context_switch && !entersFromC)
60 # define OR_CONTEXT_SWITCH || context_switch
63 #define OR_CONTEXT_SWITCH /* in miniInterpret */
66 #define REQUIRED_POOL 0
67 #define ADVISORY_POOL 1
72 #define TYPE_OF_SPARK PP_
73 #define SIZE_OF_SPARK (sizeof(TYPE_OF_SPARK))
75 extern TYPE_OF_SPARK PendingSparksBase[SPARK_POOLS],
76 PendingSparksLim[SPARK_POOLS];
77 extern TYPE_OF_SPARK PendingSparksHd[SPARK_POOLS],
78 PendingSparksTl[SPARK_POOLS];
80 extern I_ SparkLimit[SPARK_POOLS];
82 extern P_ RunnableThreadsHd, RunnableThreadsTl;
83 extern P_ WaitingThreadsHd, WaitingThreadsTl;
86 extern I_ sparksIgnored, sparksCreated;
89 IF_RTS(extern void AwaitEvent(I_);)
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[];
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]
109 IF_RTS(extern void PruneSparks(STG_NO_ARGS);)
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 */
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
122 extern W_ SparksAvail, SurplusThreads;
124 extern W_ CurrentTime[];
125 extern I_ OutstandingFetches[], OutstandingFishes[];
126 extern enum proc_status procStatus[];
128 # if defined(GRAN_CHECK) && defined(GRAN) /* Just for testing */
129 # define FETCH_MASK_TSO 0x08000000 /* only bits 0, 1, 2 should be used */
131 extern P_ BlockedOnFetch[];
136 extern P_ CurrentTSO; /* thread state object now in use */
138 extern P_ AvailableStack;
139 extern P_ AvailableTSO;
143 void ScheduleThreads PROTO((P_ topClosure));
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));
157 void ReSchedule PROTO((int again)) STG_NORETURN;
161 void EndThread(STG_NO_ARGS) STG_NORETURN;
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);
170 %************************************************************************
172 \subsection[thread-heap-objs]{Special threads-only heap objects (`closures')}
174 %************************************************************************
176 %************************************************************************
178 \subsubsection[TSO-closures]{@TSO@ (thread state object) heap objects}
180 %************************************************************************
182 We now enter the realm of the Deeply Magical.
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).
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.
193 We use all the standard heap-object/closure jargon... (e.g.,
194 @SET_TSO_HDR@, fixed headers, variable-hdr size, ...).
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.
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).
207 #define TSO_INFO_WORDS 10
210 #define TSO_REDN_WORDS 2
212 #define TSO_REDN_WORDS 0
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
219 #define TSO_GRAN_WORDS 0
223 (GC_MUT_RESERVED_WORDS + TSO_INFO_WORDS + TSO_REDN_WORDS + TSO_GRAN_WORDS)
225 #define TSO_HS (FIXED_HS + TSO_VHS)
226 #define TSO_CTS_SIZE (BYTES_TO_STGWORDS(sizeof(STGRegisterTable) + sizeof(StgDouble)))
228 #define TSO_PTRS (MAX_VANILLA_REG + 2)
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); \
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)
248 #define TSO_REDN_START (TSO_INFO_START + TSO_INFO_WORDS)
250 #define TSO_AHWM_LOCN (TSO_REDN_START + 0)
251 #define TSO_BHWM_LOCN (TSO_REDN_START + 1)
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)
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])
286 #define TSO_AHWM(closure) (((I_ *)closure)[TSO_AHWM_LOCN])
287 #define TSO_BHWM(closure) (((I_ *)closure)[TSO_BHWM_LOCN])
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])
308 #define TSO_INTERNAL_PTR(closure) \
309 ((STGRegisterTable *)(((W_)(((P_)closure) \
310 + TSO_HS + BYTES_TO_STGWORDS(sizeof(StgDouble)))) & ~(sizeof(StgDouble) - 1)))
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)
322 The types of threads (TSO_TYPE):
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 */
330 The total space required to start a new thread (See NewThread in
333 #define THREAD_SPACE_REQUIRED (TSO_HS + TSO_CTS_SIZE + STKO_HS + RTSflags.ConcFlags.stkChunkSize)
336 Here are the various queues for GrAnSim-type events.
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'
345 %************************************************************************
347 \subsubsection[spark-closures]{Pending Sparks}
349 %************************************************************************
354 P_ FindLocalSpark PROTO((rtsBool forexport));
356 void DisposeSpark PROTO((P_ spark));
357 rtsBool Spark PROTO((P_ closure, rtsBool required));
361 #ifdef GRAN /* For GrAnSim sparks are currently mallocated -- HWL */
363 void DisposeSpark PROTO((sparkq spark));
364 sparkq NewSpark PROTO((P_,I_,I_,I_,I_,I_));
366 /* # define MAX_EVENTS 1000 */ /* For GC Roots Purposes */
367 # define MAX_SPARKS 0 /* i.e. infinite */
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) */
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)
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)
395 %************************************************************************
397 \subsubsection[STKO-closures]{@STKO@ (stack object) heap objects}
399 %************************************************************************
401 We linger in the Deeply Magical...
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
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..
414 So, as with TSOs, we use the standard heap-object (`closure') jargon.
416 Here is the picture of how a stack object is arranged:
418 <----- var hdr --------> v ---- FirstPtr --- v
419 ---------------------------------------------------------------------
420 ...|| SpB | SuB | SpA | SuA || B stk -> ... | ... <- A stk || PREV ||
421 ---------------------------------------------------------------------
425 We keep the following state-of-stack info in the {\em variable-header}
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)\\
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.
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.
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
445 From a storage-manager point of view, these are {\em very special}
450 #define STKO_VHS (GC_MUT_RESERVED_WORDS + 9)
452 #define STKO_VHS (GC_MUT_RESERVED_WORDS + 7)
454 #define STKO_HS (FIXED_HS + STKO_VHS)
456 #define MIN_STKO_CHUNK_SIZE 16 /* Rather arbitrary */
458 #define STKO_CLOSURE_SIZE(closure) STKO_SIZE(closure)
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))
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)
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 */ }
472 /* now we have the STKO-specific stuff
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
481 #define STKO_ADEP_LOCN (STKO_HS - 9)
482 #define STKO_BDEP_LOCN (STKO_HS - 8)
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)
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])
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))
508 These are offsets into the stack object proper (starting at 1 for
509 the first word after the header).
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)))
518 %************************************************************************
520 \subsubsection[BQ-closures]{@BQ@ (blocking queue) heap objects (`closures')}
522 %************************************************************************
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.
532 \begin{tabular}{||l|l|l|l||}\hline
533 GA & Info ptr. & $\ldots$ & Blocking Queue \\ \hline
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.)
546 #define BQ_VHS IND_VHS
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])
555 Blocking queues store a pointer to a list of blocking queue entries.
558 #define BQ_ENTRIES(closure) IND_CLOSURE_PTR(closure)
559 #define BQ_LINK(closure) IND_CLOSURE_LINK(closure)
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.
568 #define IS_BQ_CLOSURE(closure) (INFO_PTR(closure) == (W_) BQ_info)
571 %************************************************************************
573 \subsubsection[TSO_ITBL]{@TSO_ITBL@}
575 %************************************************************************
577 The special info table used for thread state objects (TSOs).
582 CAT_DECLARE(TSO,INTERNAL_KIND,"TSO","<TSO>") \
584 EXTDATA_RO(MK_REP_LBL(TSO,,)); \
585 const W_ TSO_info[] = { \
587 ,(W_) INFO_OTHER_TAG \
588 ,(W_) MK_REP_REF(TSO,,) \
589 INCLUDE_PROFILING_INFO(TSO) \
593 const W_ MK_REP_LBL(TSO,,)[] = { \
594 INCLUDE_TYPE_INFO(TSO) \
595 INCLUDE_SIZE_INFO(INFO_UNUSED,INFO_UNUSED) \
597 INCLUDE_COPYING_INFO(_Evacuate_TSO,_Scavenge_TSO) \
598 INCLUDE_COMPACTING_INFO(_ScanLink_TSO,_PRStart_TSO,_ScanMove_TSO,_PRIn_TSO) \
603 %************************************************************************
605 \subsubsection[STKO_ITBL]{@STKO_ITBL@}
607 %************************************************************************
609 The special info table used for stack objects (STKOs).
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[] = { \
618 ,(W_) INFO_OTHER_TAG \
619 ,(W_) MK_REP_REF(StkO,,) \
620 INCLUDE_PROFILING_INFO(StkO) \
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) \
628 INCLUDE_COPYING_INFO(_Evacuate_StkO,_Scavenge_StkO) \
629 INCLUDE_COMPACTING_INFO(_ScanLink_StkO,_PRStart_StkO,_ScanMove_StkO,_PRIn_StkO) \
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) \
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) \
648 INCLUDE_COPYING_INFO(_Evacuate_Static,_Dummy_Static_entry) \
649 INCLUDE_COMPACTING_INFO(_Dummy_Static_entry,_PRStart_Static, \
650 _Dummy_Static_entry,_PRIn_Error) \
655 %************************************************************************
657 \subsubsection[BQ_ITBL]{@BQ_ITBL@}
659 %************************************************************************
661 Special info-table for local blocking queues.
665 CAT_DECLARE(BQ,INTERNAL_KIND,"BQ","<BQ>") \
667 EXTDATA_RO(MK_REP_LBL(BQ,,)); \
668 const W_ BQ_info[] = { \
670 ,(W_) INFO_OTHER_TAG \
671 ,(W_) MK_REP_REF(BQ,,) \
672 INCLUDE_PROFILING_INFO(BQ) \
676 const W_ MK_REP_LBL(BQ,,)[] = { \
677 INCLUDE_TYPE_INFO(BQ) \
678 INCLUDE_SIZE_INFO(MIN_UPD_SIZE,INFO_UNUSED) \
680 INCLUDE_COPYING_INFO(_Evacuate_BQ,_Scavenge_BQ) \
681 SPEC_COMPACTING_INFO(_ScanLink_BQ,_PRStart_BQ,_ScanMove_BQ,_PRIn_BQ) \
687 #endif /* CONCURRENT */
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.)
694 %************************************************************************
696 \subsubsection[SVar-closures]{@SynchVar@ heap objects}
698 %************************************************************************
701 #define SVAR_HS (MUTUPLE_HS)
703 #define SVAR_CLOSURE_SIZE(closure) 3
705 #define SET_SVAR_HDR(closure,infolbl,cc) \
706 SET_MUTUPLE_HDR(closure,infolbl,cc,MUTUPLE_VHS+3,3)
708 /* The value must come first, because we shrink the other two fields off
709 when writing an IVar */
711 #define SVAR_VALUE_LOCN (SVAR_HS+0)
712 #define SVAR_HEAD_LOCN (SVAR_HS+1)
713 #define SVAR_TAIL_LOCN (SVAR_HS+2)
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]
720 End multi-slurp protection:
723 #endif /* THREADS_H */