2 % (c) The AQUA/Parade Projects, Glasgow University, 1995
4 %************************************************************************
6 \section[RBH.lc]{Revertible Black Hole Manipulation}
8 %************************************************************************
11 #ifdef PAR /* whole file */
16 Turn a closure into a revertible black hole. After the conversion,
17 the first two words of the closure will be a link to the mutables
18 list (if appropriate for the garbage collector), and a pointer
19 to the blocking queue. The blocking queue is terminated by a 2-word
20 SPEC closure which holds the original contents of the first two
24 EXTFUN(RBH_Save_0_info);
25 EXTFUN(RBH_Save_1_info);
26 EXTFUN(RBH_Save_2_info);
32 P_ infoPtr, newInfoPtr;
33 W_ size, ptrs, nonptrs, vhs;
37 if ((rbh_save = AllocateHeap(SPEC_HS + 2)) == NULL)
40 infoPtr = get_closure_info(closure, &size, &ptrs, &nonptrs, &vhs);
41 ASSERT(size >= MIN_UPD_SIZE);
43 switch (BASE_INFO_TYPE(infoPtr)) {
51 fprintf(stderr, "Panic: turn %#lx (IP %#lx) into RBH\n", (W_)closure, (W_)infoPtr);
55 /* Fill in the RBH_Save closure with the original data */
56 rbh_save[SPEC_HS] = closure[isSpec ? SPEC_HS : GEN_HS];
57 rbh_save[SPEC_HS + 1] = closure[(isSpec ? SPEC_HS : GEN_HS) + 1];
60 * Set the info_ptr for the rbh_Save closure according to the number of pointers
64 newInfoPtr = (P_) (ptrs == 0 ? RBH_Save_0_info :
65 ptrs == 1 ? RBH_Save_1_info :
67 SET_INFO_PTR(rbh_save, newInfoPtr);
69 /* Do some magic garbage collection mangling on the first word */
71 #if defined(GCap) || defined(GCgn)
74 * If the closure's in the old generation, we have to make sure it goes on the
78 if (closure <= StorageMgrInfo.OldLim) {
79 MUT_LINK(closure) = (W_) StorageMgrInfo.OldMutables;
80 StorageMgrInfo.OldMutables = closure;
82 MUT_LINK(closure) = MUT_NOT_LINKED;
86 * Second word points to the RBH_Save closure with the original data. This may
87 * become a blocking queue terminated by the RBH_Save closure.
90 SPEC_RBH_BQ(closure) = (W_) rbh_save;
92 GEN_RBH_BQ(closure) = (W_) rbh_save;
94 /* OK, now actually turn it into a RBH (what a great system!) */
95 SET_INFO_PTR(closure, RBH_INFOPTR(INFO_PTR(closure)));
102 Converting a closure to a FetchMe is trivial, unless the closure has
103 acquired a blocking queue. If that has happened, we first have to
104 awaken the blocking queue. What a nuisance! Fortunately,
105 @AwakenBlockingQueue@ should now know what to do.
108 EXTDATA_RO(FetchMe_info);
111 convertToFetchMe(closure, ga)
115 P_ ip = (P_) INFO_PTR(closure);
117 #if defined(GCap) || defined(GCgn)
118 rtsBool linked = IS_MUTABLE(ip) && MUT_LINK(closure) != MUT_NOT_LINKED;
121 switch(INFO_TYPE(ip)) {
122 case INFO_SPEC_RBH_TYPE:
123 bqe = (P_) SPEC_RBH_BQ(closure);
125 case INFO_GEN_RBH_TYPE:
126 bqe = (P_) GEN_RBH_BQ(closure);
130 fprintf(stderr, "Weird...just tried to convert %#lx (IP %#lx) to FetchMe\n",
136 SET_INFO_PTR(closure, FetchMe_info);
138 #if defined(GCap) || defined(GCgn)
139 /* If we modify a fetchme in the old generation,
140 we have to make sure it goes on the mutables list */
142 if(closure <= StorageMgrInfo.OldLim) {
144 MUT_LINK(closure) = (W_) StorageMgrInfo.OldMutables;
145 StorageMgrInfo.OldMutables = closure;
148 MUT_LINK(closure) = MUT_NOT_LINKED;
151 FETCHME_GA(closure) = ga;
152 if (IS_MUTABLE(INFO_PTR(bqe)))
153 AwakenBlockingQueue(bqe);
156 #endif /* PAR -- whole file */