YAP 7.1.0
or.sba_engine.c
1/************************************************************************
2** **
3** The YapTab/YapOr/OPTYap systems **
4** **
5** YapTab extends the Yap Prolog engine to support sequential tabling **
6** YapOr extends the Yap Prolog engine to support or-parallelism **
7** OPTYap extends the Yap Prolog engine to support or-parallel tabling **
8** **
9** **
10** Yap Prolog was developed at University of Porto, Portugal **
11** **
12************************************************************************/
13
14/* ------------------ **
15** Includes **
16** ------------------ */
17
18#include "Yap.h"
19#ifdef YAPOR_SBA
20#include <stdio.h>
21#include "Yatom.h"
22#include "YapHeap.h"
23#include "or.macros.h"
24#include "opt.mavar.h"
25
26
27
28/* ------------------------------------- **
29** Local functions declaration **
30** ------------------------------------- */
31
32static void share_private_nodes(int worker_q);
33
34static void
35reset_trail(tr_fr_ptr tr_top, tr_fr_ptr trp)
36{
37 register CELL aux_cell;
38
39 /* unbinding variables */
40 while (tr_top != trp) {
41 aux_cell = TrailTerm(--trp);
42 /* check for global or local variables */
43 if (IsVarTerm(aux_cell)) {
44 /* clean up the trail when we backtrack */
45 /* shouldn't this test always succeed? */
46 if (Unsigned((Int)(aux_cell)-(Int)(H_FZ)) >
47 Unsigned((Int)(B_FZ)-(Int)(H_FZ))) {
48 RESET_VARIABLE(STACK_TO_SBA(aux_cell));
49 } else {
50 RESET_VARIABLE(aux_cell);
51 }
52 }
53 else if (IsPairTerm(aux_cell)) {
54 /* avoid frozen segments */
55 if ((ADDR) RepPair(aux_cell) > HeapTop) {
56 trp = (tr_fr_ptr) RepPair(aux_cell);
57 }
58#ifdef MULTI_ASSIGNMENT_VARIABLES
59 } else {
60 CELL *aux_ptr = RepAppl(aux_cell);
61 trp--;
62 if (Unsigned((Int)(aux_ptr)-(Int)(H_FZ)) >
63 Unsigned((Int)(B_FZ)-(Int)(H_FZ))) {
64 *STACK_TO_SBA(aux_ptr) = TrailTerm(trp);
65 } else {
66 *aux_ptr = TrailTerm(trp);
67 }
68#endif /* MULTI_ASSIGNMENT_VARIABLES */
69 }
70 }
71}
72
73
74/* ---------------------- **
75** Local macros **
76** ---------------------- */
77
78#define COMPUTE_SEGMENTS_TO_COPY_TO(Q) \
79 REMOTE_end_local_copy(Q) = (CELL) (REMOTE_top_cp(Q)); \
80 REMOTE_start_local_copy(Q) = (CELL) (B)
81
82
83
84/* -------------------------- **
85** Global functions **
86** -------------------------- */
87
88void make_root_choice_point(void) {
89 if (worker_id == 0) {
90 LOCAL_top_cp = GLOBAL_root_cp = OrFr_node(GLOBAL_root_or_fr) = B;
91 B->cp_h = H0;
92 B->cp_ap = GETWORK;
93 B->cp_or_fr = GLOBAL_root_or_fr;
94 } else {
95 B = LOCAL_top_cp = GLOBAL_root_cp;
96 TR = B->cp_tr;
97 }
98 LOCAL_top_or_fr = GLOBAL_root_or_fr;
99 LOCAL_load = 0;
100 LOCAL_prune_request = NULL;
101 BRANCH(worker_id, 0) = 0;
102 H_FZ = (CELL *) LOCAL_GlobalBase;
103 B_FZ = (choiceptr) LOCAL_LocalBase;
104 TR_FZ = (tr_fr_ptr) LOCAL_TrailBase;
105}
106
107
108void free_root_choice_point(void) {
109 reset_trail(LOCAL_top_cp->cp_tr, TR);
110 TR = LOCAL_top_cp->cp_tr;
111 B = LOCAL_top_cp->cp_b;
112 LOCAL_top_cp = (choiceptr) LOCAL_LocalBase;
113 H_FZ = (CELL *) LOCAL_GlobalBase;
114 B_FZ = (choiceptr) LOCAL_LocalBase;
115 TR_FZ = (tr_fr_ptr) LOCAL_TrailBase;
116}
117
118
119void p_share_work(void) {
120 int worker_q = LOCAL_share_request;
121
122 if (! BITMAP_member(OrFr_members(REMOTE_top_or_fr(worker_q)), worker_id) ||
123 B == REMOTE_top_cp(worker_q) ||
124 (LOCAL_load <= GLOBAL_delayed_release_load && OrFr_nearest_livenode(LOCAL_top_or_fr) == NULL)) {
125 /* refuse sharing request */
126 REMOTE_reply_signal(LOCAL_share_request) = no_sharing;
127 LOCAL_share_request = MAX_WORKERS;
128 PUT_OUT_REQUESTABLE(worker_id);
129 return;
130 }
131 /* sharing request accepted */
132 /* LOCAL_reply_signal = sharing; */
133 COMPUTE_SEGMENTS_TO_COPY_TO(worker_q);
134 share_private_nodes(worker_q);
135 REMOTE_reply_signal(worker_q) = sharing;
136 /* REMOTE_reply_signal(worker_q) = nodes_shared; */
137 /* while (LOCAL_reply_signal == sharing); */
138 LOCAL_share_request = MAX_WORKERS;
139 PUT_IN_REQUESTABLE(worker_id);
140
141 return;
142}
143
144
145int q_share_work(int worker_p) {
146 register tr_fr_ptr aux_tr;
147 register CELL aux_cell;
148
149 LOCK_OR_FRAME(LOCAL_top_or_fr);
150 if (Get_REMOTE_prune_request(worker_p)) {
151 /* worker p with prune request */
152 UNLOCK_OR_FRAME(LOCAL_top_or_fr);
153 return FALSE;
154 }
155 YAPOR_ERROR_CHECKING(q_share_work, OrFr_pend_prune_cp(LOCAL_top_or_fr) && BRANCH_LTT(worker_p, OrFr_depth(LOCAL_top_or_fr)) < OrFr_pend_prune_ltt(LOCAL_top_or_fr));
156 /* there is no pending prune with worker p at right --> safe move to worker p branch */
157 BRANCH(worker_id, OrFr_depth(LOCAL_top_or_fr)) = BRANCH(worker_p, OrFr_depth(LOCAL_top_or_fr));
158 LOCAL_prune_request = NULL;
159 UNLOCK_OR_FRAME(LOCAL_top_or_fr);
160
161 reset_trail(LOCAL_top_cp->cp_tr, TR);
162 TR = LOCAL_top_cp->cp_tr;
163
164 /* make sharing request */
165 LOCK_WORKER(worker_p);
166 if (BITMAP_member(GLOBAL_bm_idle_workers, worker_p) ||
167 REMOTE_share_request(worker_p) != MAX_WORKERS) {
168 /* worker p is idle or has another request */
169 UNLOCK_WORKER(worker_p);
170 return FALSE;
171 }
172 REMOTE_share_request(worker_p) = worker_id;
173 UNLOCK_WORKER(worker_p);
174
175 /* wait for an answer */
176 while (LOCAL_reply_signal == worker_ready);
177 if (LOCAL_reply_signal == no_sharing) {
178 /* sharing request refused */
179 LOCAL_reply_signal = worker_ready;
180 return FALSE;
181 }
182
183 /* install fase --> TR and LOCAL_top_cp->cp_tr are equal */
184 TR = ((choiceptr)LOCAL_end_local_copy)->cp_tr;
185 aux_tr = ((choiceptr) LOCAL_start_local_copy)->cp_tr;
186 NEW_MAHASH((ma_h_inner_struct *)HR);
187 while (TR != aux_tr) {
188 aux_cell = TrailTerm(--aux_tr);
189 if (IsVarTerm(aux_cell)) {
190 CELL *ptr = STACK_TO_SBA(aux_cell);
191 *ptr = TrailVal(aux_tr);
192 } else if ((ADDR) RepPair(aux_cell) >= HeapTop) {
193 /* avoid frozen segments */
194 aux_tr = (tr_fr_ptr) RepPair(aux_cell);
195#ifdef MULTI_ASSIGNMENT_VARIABLES
196 } else if (IsApplTerm(aux_cell)) {
197 CELL *cell_ptr = RepAppl(aux_cell);
198 if (!lookup_ma_var(cell_ptr)) {
199 /* first time we found the variable, let's put the new value */
200 CELL *ptr = STACK_TO_SBA(cell_ptr);
201 *ptr = TrailVal(aux_tr);
202 }
203 /* skip the old value */
204 aux_tr--;
205 }
206#endif /* MULTI_ASSIGNMENT_VARIABLES */
207 }
208
209 /* update registers and return */
210 /* REMOTE_reply_signal(worker_p) = worker_ready; */
211 LOCAL_reply_signal = worker_ready;
212 PUT_IN_REQUESTABLE(worker_id);
213 TR = LOCAL_top_cp->cp_tr;
214 return TRUE;
215}
216
217
218
219/* ------------------------- **
220** Local functions **
221** ------------------------- */
222
223static
224void share_private_nodes(int worker_q) {
225 int depth;
226 choiceptr AuxB;
227 or_fr_ptr or_frame, previous_or_frame;
228
229 /* initialize auxiliary variables */
230 AuxB = B;
231 previous_or_frame = NULL;
232 depth = OrFr_depth(LOCAL_top_or_fr);
233 /* sharing loop */
234 while (AuxB != LOCAL_top_cp) {
235 depth++;
236 ALLOC_OR_FRAME(or_frame);
237 INIT_LOCK(OrFr_lock(or_frame));
238 OrFr_node(or_frame) = AuxB;
239 OrFr_alternative(or_frame) = AuxB->cp_ap;
240 OrFr_pend_prune_cp(or_frame) = NULL;
241 OrFr_nearest_leftnode(or_frame) = LOCAL_top_or_fr;
242 OrFr_qg_solutions(or_frame) = NULL;
243 BITMAP_clear(OrFr_members(or_frame));
244 BITMAP_insert(OrFr_members(or_frame), worker_id);
245 BITMAP_insert(OrFr_members(or_frame), worker_q);
246 if (AuxB->cp_ap && YAMOP_SEQ(AuxB->cp_ap)) {
247 AuxB->cp_ap = GETWORK_SEQ;
248 } else {
249 AuxB->cp_ap = GETWORK;
250 }
251 AuxB->cp_or_fr = or_frame;
252 AuxB = AuxB->cp_b;
253 if (previous_or_frame) {
254 OrFr_nearest_livenode(previous_or_frame) = OrFr_next(previous_or_frame) = or_frame;
255 }
256 previous_or_frame = or_frame;
257 }
258 /* initialize last or-frame pointer */
259 or_frame = AuxB->cp_or_fr;
260 if (previous_or_frame) {
261 OrFr_nearest_livenode(previous_or_frame) = OrFr_next(previous_or_frame) = or_frame;
262 }
263 /* update depth */
264 if (depth >= MAX_BRANCH_DEPTH)
265 Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, "maximum depth exceded (share_private_nodes)");
266 or_frame = B->cp_or_fr;
267
268 while (or_frame != LOCAL_top_or_fr) {
269 unsigned int branch;
270 if (OrFr_alternative(or_frame)) {
271 branch = YAMOP_OR_ARG(OrFr_alternative(or_frame)) + 1;
272 } else {
273 branch = 1;
274 }
275 branch |= YAMOP_CUT_FLAG; /* in doubt, assume cut */
276 BRANCH(worker_id, depth) = BRANCH(worker_q, depth) = branch;
277 OrFr_depth(or_frame) = depth--;
278 or_frame = OrFr_next_on_stack(or_frame);
279 }
280 /* update old shared nodes */
281 while (or_frame != REMOTE_top_or_fr(worker_q)) {
282 LOCK_OR_FRAME(or_frame);
283 BRANCH(worker_q, OrFr_depth(or_frame)) = BRANCH(worker_id, OrFr_depth(or_frame));
284 BITMAP_insert(OrFr_members(or_frame), worker_q);
285 UNLOCK_OR_FRAME(or_frame);
286 or_frame = OrFr_next_on_stack(or_frame);
287 }
288 /* move conditional bindings to BA */
289 {
290 tr_fr_ptr top, tr_ptr;
291 top = LOCAL_top_cp->cp_tr;
292 tr_ptr = TR;
293 while (tr_ptr != top) {
294 CELL aux_cell = TrailTerm(--tr_ptr);
295 if (IsVarTerm(aux_cell) &&
296 ((CELL *)aux_cell < B->cp_h || (choiceptr)aux_cell > B) &&
297 !((CELL *)aux_cell < H_FZ || (choiceptr)aux_cell > B_FZ)) {
298 CELL *ptr = STACK_TO_SBA(aux_cell);
299 *ptr = TrailVal(tr_ptr);
300 *(CELL *)aux_cell = (CELL)ptr;
301 } else if (IsPairTerm(aux_cell) && (ADDR) RepPair(aux_cell) > HeapTop) {
302 /* avoid frozen segments */
303 aux_cell = (CELL) RepPair(aux_cell);
304 tr_ptr = (tr_fr_ptr) aux_cell;
305#ifdef MULTI_ASSIGNMENT_VARIABLES
306 } else {
307 CELL *cell_ptr = RepAppl(aux_cell);
308 /* first do as a for a standard cell */
309 if ((cell_ptr < B->cp_h || cell_ptr > (CELL *)B) && !(cell_ptr < H_FZ || (choiceptr)cell_ptr > B_FZ)) {
310 CELL *ptr = STACK_TO_SBA(cell_ptr);
311 /* we may have several bindings in the trail */
312 if ((CELL)ptr != *cell_ptr) {
313 *ptr = TrailVal(tr_ptr);
314 *cell_ptr = (CELL)ptr;
315 }
316 }
317 /* but we also need to skip the old value */
318 tr_ptr--;
319#endif /* MULTI_ASSIGNMENT_VARIABLES */
320 }
321 }
322 }
323 /* update frozen registers */
324 B_FZ = B;
325 H_FZ = B->cp_h;
326 TR_FZ = B->cp_tr;
327 /* update top shared nodes */
328 REMOTE_top_cp(worker_q) = LOCAL_top_cp = B;
329 REMOTE_top_or_fr(worker_q) = LOCAL_top_or_fr = LOCAL_top_cp->cp_or_fr;
330 /* update prune request */
331 if (LOCAL_prune_request) {
332 CUT_send_prune_request(worker_q, LOCAL_prune_request);
333 }
334 /* update load and return */
335 REMOTE_load(worker_q) = LOCAL_load = 0;
336}
337#endif /* SBA */
Main definitions.