YAP 7.1.0
tab.macros.h
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 & Prototypes **
16************************************/
17
18#include <stdlib.h>
19#if HAVE_STRING_H
20#include <string.h>
21#endif /* HAVE_STRING_H */
22#include "opt.mavar.h"
23#ifdef YAPOR
24#include "or.macros.h"
25#endif
26
27#ifdef THREADS
28static inline void **__get_insert_thread_bucket(void **, lockvar * USES_REGS);
29static inline void **__get_thread_bucket(void ** USES_REGS);
30static inline void abolish_thread_buckets(void **);
31#endif /* THREADS */
32static inline sg_node_ptr get_insert_subgoal_trie(tab_ent_ptr USES_REGS);
33static inline sg_node_ptr __get_subgoal_trie(tab_ent_ptr USES_REGS);
34static inline sg_node_ptr get_subgoal_trie_for_abolish(tab_ent_ptr USES_REGS);
35static inline sg_fr_ptr *get_insert_subgoal_frame_addr(sg_node_ptr USES_REGS);
36static inline sg_fr_ptr get_subgoal_frame(sg_node_ptr);
37static inline sg_fr_ptr get_subgoal_frame_for_abolish(sg_node_ptr USES_REGS);
38#ifdef THREADS_FULL_SHARING
39static inline void __SgFr_batched_cached_answers_check_insert(sg_fr_ptr, ans_node_ptr USES_REGS);
40static inline int SgFr_batched_cached_answers_check_remove(sg_fr_ptr, ans_node_ptr);
41#endif /* THREADS_FULL_SHARING */
42#ifdef THREADS_CONSUMER_SHARING
43static inline void __add_to_tdv(int, int USES_REGS);
44static inline void __check_for_deadlock(sg_fr_ptr USES_REGS);
45static inline sg_fr_ptr __deadlock_detection(sg_fr_ptr USES_REGS);
46#endif /* THREADS_CONSUMER_SHARING */
47static inline Int __freeze_current_cp( USES_REGS1 );
48static inline void __wake_frozen_cp(Int USES_REGS);
49static inline void __abolish_frozen_cps_until(Int USES_REGS);
50static inline void __abolish_frozen_cps_all( USES_REGS1 );
51static inline void __adjust_freeze_registers( USES_REGS1 );
52static inline void __mark_as_completed(sg_fr_ptr USES_REGS);
53static inline void __unbind_variables(tr_fr_ptr, tr_fr_ptr USES_REGS);
54static inline void __rebind_variables(tr_fr_ptr, tr_fr_ptr USES_REGS);
55static inline void __restore_bindings(tr_fr_ptr, tr_fr_ptr USES_REGS);
56static inline CELL *__expand_auxiliary_stack(CELL * USES_REGS);
57static inline void __abolish_incomplete_subgoals(choiceptr USES_REGS);
58#ifdef YAPOR
59static inline void pruning_over_tabling_data_structures(void);
60static inline void __collect_suspension_frames(or_fr_ptr USES_REGS);
61#ifdef TIMESTAMP_CHECK
62static inline susp_fr_ptr suspension_frame_to_resume(or_fr_ptr, long);
63#else
64static inline susp_fr_ptr suspension_frame_to_resume(or_fr_ptr);
65#endif /* TIMESTAMP_CHECK */
66#endif /* YAPOR */
67#ifdef TABLING_INNER_CUTS
68static inline void CUT_store_tg_answer(or_fr_ptr, ans_node_ptr, choiceptr, int);
69static inline tg_sol_fr_ptr CUT_store_tg_answers(or_fr_ptr, tg_sol_fr_ptr, int);
70static inline void CUT_validate_tg_answers(tg_sol_fr_ptr);
71static inline void CUT_join_tg_solutions(tg_sol_fr_ptr *, tg_sol_fr_ptr);
72static inline void CUT_join_solution_frame_tg_answers(tg_sol_fr_ptr);
73static inline void CUT_join_solution_frames_tg_answers(tg_sol_fr_ptr);
74static inline void CUT_free_tg_solution_frame(tg_sol_fr_ptr);
75static inline void CUT_free_tg_solution_frames(tg_sol_fr_ptr);
76static inline tg_sol_fr_ptr CUT_prune_tg_solution_frames(tg_sol_fr_ptr, int);
77#endif /* TABLING_INNER_CUTS */
78
79
80
81/*********************************
82** Tabling mode flags **
83*********************************/
84
85#define Flag_Batched 0x001
86#define Flag_Local 0x002
87#define Flags_SchedulingMode (Flag_Batched | Flag_Local)
88#define Flag_ExecAnswers 0x010
89#define Flag_LoadAnswers 0x020
90#define Flags_AnswersMode (Flag_ExecAnswers | Flag_LoadAnswers)
91#define Flag_LocalTrie 0x100
92#define Flag_GlobalTrie 0x200
93#define Flags_TrieMode (Flag_LocalTrie | Flag_GlobalTrie)
94#define Flag_CoInductive 0x008
95
96#define SetMode_Batched(X) (X) = ((X) & ~Flags_SchedulingMode) | Flag_Batched
97#define SetMode_Local(X) (X) = ((X) & ~Flags_SchedulingMode) | Flag_Local
98#define SetMode_ExecAnswers(X) (X) = ((X) & ~Flags_AnswersMode) | Flag_ExecAnswers
99#define SetMode_LoadAnswers(X) (X) = ((X) & ~Flags_AnswersMode) | Flag_LoadAnswers
100#define SetMode_LocalTrie(X) (X) = ((X) & ~Flags_TrieMode) | Flag_LocalTrie
101#define SetMode_GlobalTrie(X) (X) = ((X) & ~Flags_TrieMode) | Flag_GlobalTrie
102#define SetMode_CoInductive(X) (X) = (X) | Flag_CoInductive
103#define IsMode_Batched(X) ((X) & Flag_Batched)
104#define IsMode_Local(X) ((X) & Flag_Local)
105#define IsMode_ExecAnswers(X) ((X) & Flag_ExecAnswers)
106#define IsMode_LoadAnswers(X) ((X) & Flag_LoadAnswers)
107#define IsMode_LocalTrie(X) ((X) & Flag_LocalTrie)
108#define IsMode_GlobalTrie(X) ((X) & Flag_GlobalTrie)
109#define IsMode_CoInductive(X) ((X) & Flag_CoInductive)
110
111
112
113/******************************
114** Tabling defines **
115******************************/
116
117/* traverse macros */
118#define SHOW_MODE_STRUCTURE 0
119#define SHOW_MODE_STATISTICS 1
120typedef enum {
121 TRAVERSE_MODE_NORMAL = 0,
122 TRAVERSE_MODE_DOUBLE = 1,
123 TRAVERSE_MODE_DOUBLE2 = 2,
124 TRAVERSE_MODE_DOUBLE_END = 3,
125 TRAVERSE_MODE_BIGINT_OR_STRING = 4,
126 TRAVERSE_MODE_BIGINT_OR_STRING_END = 5,
127 TRAVERSE_MODE_LONGINT = 6,
128 TRAVERSE_MODE_LONGINT_END = 7
129} traverse_mode_t;
130/* do not change order !!! */
131#define TRAVERSE_TYPE_SUBGOAL 0
132#define TRAVERSE_TYPE_ANSWER 1
133#define TRAVERSE_TYPE_GT_SUBGOAL 2
134#define TRAVERSE_TYPE_GT_ANSWER 3
135/* do not change order !!! */
136#define TRAVERSE_POSITION_NEXT 0
137#define TRAVERSE_POSITION_FIRST 1
138#define TRAVERSE_POSITION_LAST 2
139
140/* mode directed tabling */
141#define MODE_DIRECTED_TAGBITS 0xF
142#define MODE_DIRECTED_NUMBER_TAGBITS 4
143#define MODE_DIRECTED_INDEX 1
144#define MODE_DIRECTED_MIN 2
145#define MODE_DIRECTED_MAX 3
146#define MODE_DIRECTED_ALL 4
147#define MODE_DIRECTED_SUM 5
148#define MODE_DIRECTED_LAST 6
149#define MODE_DIRECTED_FIRST 7
150#define MODE_DIRECTED_SET(ARG,MODE) (((ARG) << MODE_DIRECTED_NUMBER_TAGBITS) + MODE)
151#define MODE_DIRECTED_GET_ARG(X) ((X) >> MODE_DIRECTED_NUMBER_TAGBITS)
152#define MODE_DIRECTED_GET_MODE(X) ((X) & MODE_DIRECTED_TAGBITS)
153
154/* LowTagBits is 3 for 32 bit-machines and 7 for 64 bit-machines */
155#define NumberOfLowTagBits (LowTagBits == 3 ? 2 : 3)
156#define MakeTableVarTerm(INDEX) ((INDEX) << NumberOfLowTagBits)
157#define VarIndexOfTableTerm(TERM) (((unsigned int) (TERM)) >> NumberOfLowTagBits)
158#define VarIndexOfTerm(TERM) \
159 ((((CELL) (TERM)) - GLOBAL_table_var_enumerator(0)) / sizeof(CELL))
160#define IsTableVarTerm(TERM) \
161 ((CELL) (TERM)) >= GLOBAL_table_var_enumerator(0) && \
162 ((CELL) (TERM)) <= GLOBAL_table_var_enumerator(MAX_TABLE_VARS - 1)
163#ifdef TRIE_COMPACT_PAIRS
164#define PairTermMark NULL
165#define CompactPairInit AbsPair((Term *) 0)
166#define CompactPairEndTerm AbsPair((Term *) (LowTagBits + 1))
167#define CompactPairEndList AbsPair((Term *) (2*(LowTagBits + 1)))
168#endif /* TRIE_COMPACT_PAIRS */
169
170/* threads */
171#if (_trie_retry_gterm - _trie_do_var + 1) + 1 <= 64 /* 60 (trie instructions) + 1 (ANSWER_TRIE_HASH_MARK) <= 64 */
172#define ANSWER_LEAF_NODE_INSTR_BITS 6 /* 2^6 = 64 */
173#define ANSWER_LEAF_NODE_INSTR_MASK 0x3F
174#endif
175#if SIZEOF_INT_P == 4
176#define ANSWER_LEAF_NODE_MAX_THREADS (32 - ANSWER_LEAF_NODE_INSTR_BITS)
177#elif SIZEOF_INT_P == 8
178#define ANSWER_LEAF_NODE_MAX_THREADS (64 - ANSWER_LEAF_NODE_INSTR_BITS)
179#else
180#define ANSWER_LEAF_NODE_MAX_THREADS OOOOPPS!!! Unknown Pointer Sizeof
181#endif /* SIZEOF_INT_P */
182#define ANSWER_LEAF_NODE_INSTR_RELATIVE(NODE) (TrNode_instr(NODE) = TrNode_instr(NODE) - _trie_do_var + 1)
183#define ANSWER_LEAF_NODE_INSTR_ABSOLUTE(NODE) (TrNode_instr(NODE) = (TrNode_instr(NODE) & ANSWER_LEAF_NODE_INSTR_MASK) + _trie_do_var - 1)
184#define ANSWER_LEAF_NODE_SET_WID(NODE,WID) BITMAP_insert(TrNode_instr(NODE), WID + ANSWER_LEAF_NODE_INSTR_BITS)
185#define ANSWER_LEAF_NODE_DEL_WID(NODE,WID) BITMAP_delete(TrNode_instr(NODE), WID + ANSWER_LEAF_NODE_INSTR_BITS)
186#define ANSWER_LEAF_NODE_CHECK_WID(NODE,WID) BITMAP_member(TrNode_instr(NODE), WID + ANSWER_LEAF_NODE_INSTR_BITS)
187
188/* choice points */
189#define NORM_CP(CP) ((choiceptr)(CP))
190#define GEN_CP(CP) ((struct generator_choicept *)(CP))
191#define CONS_CP(CP) ((struct consumer_choicept *)(CP))
192#define LOAD_CP(CP) ((struct loader_choicept *)(CP))
193#ifdef DETERMINISTIC_TABLING
194#define DET_GEN_CP(CP) ((struct deterministic_generator_choicept *)(CP))
195#define IS_DET_GEN_CP(CP) (*(CELL*)(DET_GEN_CP(CP) + 1) <= MAX_TABLE_VARS)
196#define IS_BATCHED_NORM_GEN_CP(CP) (GEN_CP(CP)->cp_dep_fr == NULL)
197#define IS_BATCHED_GEN_CP(CP) (IS_DET_GEN_CP(CP) || IS_BATCHED_NORM_GEN_CP(CP))
198#else
199#ifdef THREADS_CONSUMER_SHARING
200#define IS_BATCHED_GEN_CP(CP) (IsMode_Batched(TabEnt_mode(SgFr_tab_ent(GEN_CP(CP)->cp_sg_fr))))
201#else
202#define IS_BATCHED_GEN_CP(CP) (GEN_CP(CP)->cp_dep_fr == NULL)
203#endif /* THREADS_CONSUMER_SHARING */
204#endif /* DETERMINISTIC_TABLING */
205
206/* tagging nodes */
207#define TAG_AS_SUBGOAL_LEAF_NODE(NODE) TrNode_child(NODE) = (sg_node_ptr)((CELL) TrNode_child(NODE) | 0x1)
208#define IS_SUBGOAL_LEAF_NODE(NODE) ((CELL) TrNode_child(NODE) & 0x1)
209#define TAG_AS_ANSWER_LEAF_NODE(NODE) TrNode_parent(NODE) = (ans_node_ptr)((CELL) TrNode_parent(NODE) | 0x1)
210#define IS_ANSWER_LEAF_NODE(NODE) ((CELL) TrNode_parent(NODE) & 0x1)
211#define TAG_AS_ANSWER_INVALID_NODE(NODE) TrNode_parent(NODE) = (ans_node_ptr)((CELL) TrNode_parent(NODE) | 0x2)
212#define IS_ANSWER_INVALID_NODE(NODE) ((CELL) TrNode_parent(NODE) & 0x2)
213#define UNTAG_SUBGOAL_NODE(NODE) ((CELL) (NODE) & ~(0x1))
214#define UNTAG_ANSWER_NODE(NODE) ((CELL) (NODE) & ~(0x3))
215
216/* trie hashes */
217#define MAX_NODES_PER_TRIE_LEVEL 8
218#define MAX_NODES_PER_BUCKET (MAX_NODES_PER_TRIE_LEVEL / 2)
219#define BASE_HASH_BUCKETS 64
220#define HASH_ENTRY(ENTRY, NUM_BUCKETS) ((((CELL) ENTRY) >> NumberOfLowTagBits) & (NUM_BUCKETS - 1))
221#define SUBGOAL_TRIE_HASH_MARK ((Term) MakeTableVarTerm(MAX_TABLE_VARS))
222#define IS_SUBGOAL_TRIE_HASH(NODE) (TrNode_entry(NODE) == SUBGOAL_TRIE_HASH_MARK)
223#define ANSWER_TRIE_HASH_MARK 0
224#define IS_ANSWER_TRIE_HASH(NODE) (TrNode_instr(NODE) == ANSWER_TRIE_HASH_MARK)
225#define GLOBAL_TRIE_HASH_MARK ((Term) MakeTableVarTerm(MAX_TABLE_VARS))
226#define IS_GLOBAL_TRIE_HASH(NODE) (TrNode_entry(NODE) == GLOBAL_TRIE_HASH_MARK)
227#define HASH_TRIE_LOCK(NODE) GLOBAL_trie_locks((((CELL) (NODE)) >> 5) & (TRIE_LOCK_BUCKETS - 1))
228
229/* auxiliary stack */
230#define STACK_PUSH_UP(ITEM, STACK) *--(STACK) = (CELL)(ITEM)
231#define STACK_POP_UP(STACK) *--(STACK)
232#define STACK_PUSH_DOWN(ITEM, STACK) *(STACK)++ = (CELL)(ITEM)
233#define STACK_POP_DOWN(STACK) *(STACK)++
234#define STACK_NOT_EMPTY(STACK, STACK_BASE) (STACK) != (STACK_BASE)
235#if defined(YAPOR_COPY) || defined(YAPOR_COW) || defined(YAPOR_SBA)
236#define AUX_STACK_CHECK_EXPAND(STACK, STACK_LIMIT) \
237 if ((STACK_LIMIT) >= (STACK)) \
238 Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, "stack full (AUX_STACK_CHECK_EXPAND)")
239#else /* YAPOR_THREADS */
240#define AUX_STACK_CHECK_EXPAND(STACK, STACK_LIMIT) \
241 if ((STACK_LIMIT) >= (STACK)) \
242 STACK = expand_auxiliary_stack(STACK)
243#endif /* YAPOR */
244#define STACK_CHECK_EXPAND(STACK, STACK_LIMIT) \
245 if ((STACK_LIMIT) >= (STACK) + 4096) \
246 Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, "stack full (STACK_CHECK_EXPAND)")
247
248
249
250/*************************************
251** Data structures macros **
252*************************************/
253
254#ifdef YAPOR
255#define frame_with_suspensions_not_collected(OR_FR) \
256 (OrFr_nearest_suspnode(OR_FR) == NULL)
257#define find_dependency_node(SG_FR, LEADER_CP, DEP_ON_STACK) \
258 if (SgFr_gen_worker(SG_FR) == worker_id) { \
259 LEADER_CP = SgFr_gen_cp(SG_FR); \
260 DEP_ON_STACK = TRUE; \
261 } else { \
262 or_fr_ptr aux_or_fr = SgFr_gen_top_or_fr(SG_FR); \
263 while (! BITMAP_member(OrFr_members(aux_or_fr), worker_id)) \
264 aux_or_fr = OrFr_next(aux_or_fr); \
265 LEADER_CP = GetOrFr_node(aux_or_fr); \
266 DEP_ON_STACK = (LEADER_CP == SgFr_gen_cp(SG_FR)); \
267 }
268#define find_leader_node(LEADER_CP, DEP_ON_STACK) \
269 { dep_fr_ptr chain_dep_fr = LOCAL_top_dep_fr; \
270 while (YOUNGER_CP(DepFr_cons_cp(chain_dep_fr), LEADER_CP)) { \
271 if (LEADER_CP == DepFr_leader_cp(chain_dep_fr)) { \
272 DEP_ON_STACK |= DepFr_leader_dep_is_on_stack(chain_dep_fr); \
273 break; \
274 } else if (YOUNGER_CP(LEADER_CP, DepFr_leader_cp(chain_dep_fr))) { \
275 LEADER_CP = DepFr_leader_cp(chain_dep_fr); \
276 DEP_ON_STACK = DepFr_leader_dep_is_on_stack(chain_dep_fr); \
277 break; \
278 } \
279 chain_dep_fr = DepFr_next(chain_dep_fr); \
280 } \
281 }
282#ifdef TIMESTAMP
283#define DepFr_init_timestamp_field(DEP_FR) DepFr_timestamp(DEP_FR) = 0
284#else
285#define DepFr_init_timestamp_field(DEP_FR)
286#endif /* TIMESTAMP */
287#define YAPOR_SET_LOAD(CP_PTR) SCH_set_load(CP_PTR)
288#define SgFr_init_yapor_fields(SG_FR) \
289 SgFr_gen_worker(SG_FR) = worker_id; \
290 SgFr_gen_top_or_fr(SG_FR) = LOCAL_top_or_fr
291#define DepFr_init_yapor_fields(DEP_FR, DEP_ON_STACK, TOP_OR_FR) \
292 INIT_LOCK_DEP_FR(DEP_FR); \
293 DepFr_leader_dep_is_on_stack(DEP_FR) = DEP_ON_STACK; \
294 DepFr_top_or_fr(DEP_FR) = TOP_OR_FR; \
295 DepFr_init_timestamp_field(DEP_FR)
296#else
297#define find_dependency_node(SG_FR, LEADER_CP, DEP_ON_STACK) \
298 LEADER_CP = SgFr_gen_cp(SG_FR)
299#define find_leader_node(LEADER_CP, DEP_ON_STACK) \
300 { dep_fr_ptr chain_dep_fr = LOCAL_top_dep_fr; \
301 while (YOUNGER_CP(DepFr_cons_cp(chain_dep_fr), LEADER_CP)) { \
302 if (EQUAL_OR_YOUNGER_CP(LEADER_CP, DepFr_leader_cp(chain_dep_fr))) { \
303 LEADER_CP = DepFr_leader_cp(chain_dep_fr); \
304 break; \
305 } \
306 chain_dep_fr = DepFr_next(chain_dep_fr); \
307 } \
308 }
309#define YAPOR_SET_LOAD(CP_PTR)
310#define SgFr_init_yapor_fields(SG_FR)
311#define DepFr_init_yapor_fields(DEP_FR, DEP_ON_STACK, TOP_OR_FR)
312#endif /* YAPOR */
313
314#ifdef MODE_DIRECTED_TABLING
315#define TabEnt_init_mode_directed_field(TAB_ENT, MODE_ARRAY) \
316 TabEnt_mode_directed(TAB_ENT) = MODE_ARRAY
317#define SgEnt_init_mode_directed_fields(SG_ENT, MODE_ARRAY) \
318 SgEnt_invalid_chain(SG_ENT) = NULL; \
319 SgEnt_mode_directed(SG_ENT) = MODE_ARRAY
320#define SgFr_init_mode_directed_fields(SG_FR, MODE_ARRAY) \
321 SgFr_invalid_chain(SG_FR) = NULL; \
322 SgFr_mode_directed(SG_FR) = MODE_ARRAY
323#define AnsHash_init_previous_field(HASH, SG_FR) \
324 if (SgFr_hash_chain(SG_FR)) \
325 Hash_previous(SgFr_hash_chain(SG_FR)) = HASH; \
326 Hash_previous(HASH) = NULL
327#else
328#define TabEnt_init_mode_directed_field(TAB_ENT, MODE_ARRAY)
329#define SgEnt_init_mode_directed_fields(SG_ENT, MODE_ARRAY)
330#define SgFr_init_mode_directed_fields(SG_FR, MODE_ARRAY)
331#define AnsHash_init_previous_field(HASH, SG_FR)
332#endif /* MODE_DIRECTED_TABLING */
333
334#if defined(YAPOR) || defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
335#define INIT_LOCK_SG_FR(SG_FR) INIT_LOCK(SgFr_lock(SG_FR))
336#define LOCK_SG_FR(SG_FR) LOCK(SgFr_lock(SG_FR))
337#define UNLOCK_SG_FR(SG_FR) UNLOCK(SgFr_lock(SG_FR))
338#else
339#define INIT_LOCK_SG_FR(SG_FR)
340#define LOCK_SG_FR(SG_FR)
341#define UNLOCK_SG_FR(SG_FR)
342#endif /* YAPOR || THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
343
344#ifdef YAPOR
345#define INIT_LOCK_DEP_FR(DEP_FR) INIT_LOCK(DepFr_lock(DEP_FR))
346#define LOCK_DEP_FR(DEP_FR) LOCK(DepFr_lock(DEP_FR))
347#define UNLOCK_DEP_FR(DEP_FR) UNLOCK(DepFr_lock(DEP_FR))
348#define IS_UNLOCKED_DEP_FR(DEP_FR) IS_UNLOCKED(DepFr_lock(DEP_FR))
349#else
350#define INIT_LOCK_DEP_FR(DEF_FR)
351#define LOCK_DEP_FR(DEP_FR)
352#define UNLOCK_DEP_FR(DEP_FR)
353#define IS_UNLOCKED_DEP_FR(DEP_FR)
354#endif /* YAPOR */
355
356#if defined(SUBGOAL_TRIE_LOCK_AT_ENTRY_LEVEL) || defined(THREADS_NO_SHARING)
357#define INIT_LOCK_TAB_ENT(TAB_ENT) INIT_LOCK(TabEnt_lock(TAB_ENT))
358#else
359#define INIT_LOCK_TAB_ENT(TAB_ENT)
360#endif /* SUBGOAL_TRIE_LOCK_AT_ENTRY_LEVEL || THREADS_NO_SHARING */
361
362#ifdef SUBGOAL_TRIE_LOCK_AT_ENTRY_LEVEL
363#define LOCK_SUBGOAL_TRIE(TAB_ENT) LOCK(TabEnt_lock(TAB_ENT))
364#define UNLOCK_SUBGOAL_TRIE(TAB_ENT) UNLOCK(TabEnt_lock(TAB_ENT))
365#else
366#define LOCK_SUBGOAL_TRIE(TAB_ENT)
367#define UNLOCK_SUBGOAL_TRIE(TAB_ENT)
368#endif /* SUBGOAL_TRIE_LOCK_AT_ENTRY_LEVEL */
369
370#ifdef ANSWER_TRIE_LOCK_AT_ENTRY_LEVEL
371#define LOCK_ANSWER_TRIE(SG_FR) LOCK_SG_FR(SG_FR)
372#define UNLOCK_ANSWER_TRIE(SG_FR) UNLOCK_SG_FR(SG_FR)
373#define AnsHash_init_chain_fields(HASH, SG_FR) \
374 AnsHash_init_previous_field(HASH, SG_FR); \
375 Hash_next(HASH) = SgFr_hash_chain(SG_FR); \
376 SgFr_hash_chain(SG_FR) = HASH
377#else
378#define LOCK_ANSWER_TRIE(SG_FR)
379#define UNLOCK_ANSWER_TRIE(SG_FR)
380#define AnsHash_init_chain_fields(HASH, SG_FR) \
381 LOCK_SG_FR(SG_FR); \
382 AnsHash_init_previous_field(HASH, SG_FR); \
383 Hash_next(HASH) = SgFr_hash_chain(SG_FR); \
384 SgFr_hash_chain(SG_FR) = HASH; \
385 UNLOCK_SG_FR(SG_FR)
386#endif /* ANSWER_TRIE_LOCK_AT_ENTRY_LEVEL */
387
388#ifdef SUBGOAL_TRIE_LOCK_USING_NODE_FIELD
389#define LOCK_SUBGOAL_NODE(NODE) LOCK(TrNode_lock(NODE))
390#define UNLOCK_SUBGOAL_NODE(NODE) UNLOCK(TrNode_lock(NODE))
391#define SgNode_init_lock_field(NODE) INIT_LOCK(TrNode_lock(NODE))
392#elif defined(SUBGOAL_TRIE_LOCK_USING_GLOBAL_ARRAY)
393#define LOCK_SUBGOAL_NODE(NODE) LOCK(HASH_TRIE_LOCK(NODE))
394#define UNLOCK_SUBGOAL_NODE(NODE) UNLOCK(HASH_TRIE_LOCK(NODE))
395#define SgNode_init_lock_field(NODE)
396#else
397#define LOCK_SUBGOAL_NODE(NODE)
398#define UNLOCK_SUBGOAL_NODE(NODE)
399#define SgNode_init_lock_field(NODE)
400#endif /* SUBGOAL_TRIE_LOCK_LEVEL */
401
402#ifdef ANSWER_TRIE_LOCK_USING_NODE_FIELD
403#define LOCK_ANSWER_NODE(NODE) LOCK(TrNode_lock(NODE))
404#define UNLOCK_ANSWER_NODE(NODE) UNLOCK(TrNode_lock(NODE))
405#define AnsNode_init_lock_field(NODE) INIT_LOCK(TrNode_lock(NODE))
406#elif defined(ANSWER_TRIE_LOCK_USING_GLOBAL_ARRAY)
407#define LOCK_ANSWER_NODE(NODE) LOCK(HASH_TRIE_LOCK(NODE))
408#define UNLOCK_ANSWER_NODE(NODE) UNLOCK(HASH_TRIE_LOCK(NODE))
409#define AnsNode_init_lock_field(NODE)
410#else
411#define LOCK_ANSWER_NODE(NODE)
412#define UNLOCK_ANSWER_NODE(NODE)
413#define AnsNode_init_lock_field(NODE)
414#endif /* ANSWER_TRIE_LOCK_LEVEL */
415
416#ifdef GLOBAL_TRIE_LOCK_USING_NODE_FIELD
417#define LOCK_GLOBAL_NODE(NODE) LOCK(TrNode_lock(NODE))
418#define UNLOCK_GLOBAL_NODE(NODE) UNLOCK(TrNode_lock(NODE))
419#define GtNode_init_lock_field(NODE) INIT_LOCK(TrNode_lock(NODE))
420#elif defined(GLOBAL_TRIE_LOCK_USING_GLOBAL_ARRAY)
421#define LOCK_GLOBAL_NODE(NODE) LOCK(HASH_TRIE_LOCK(NODE))
422#define UNLOCK_GLOBAL_NODE(NODE) UNLOCK(HASH_TRIE_LOCK(NODE))
423#define GtNode_init_lock_field(NODE)
424#else
425#define LOCK_GLOBAL_NODE(NODE)
426#define UNLOCK_GLOBAL_NODE(NODE)
427#define GtNode_init_lock_field(NODE)
428#endif /* GLOBAL_TRIE_LOCK_LEVEL */
429
430#ifdef THREADS_NO_SHARING
431#define TabEnt_init_subgoal_trie_field(TAB_ENT) \
432 INIT_BUCKETS(&TabEnt_subgoal_trie(TAB_ENT), THREADS_NUM_BUCKETS)
433#else
434#define TabEnt_init_subgoal_trie_field(TAB_ENT) \
435 { register sg_node_ptr sg_node; \
436 new_subgoal_trie_node(sg_node, 0, NULL, NULL, NULL); \
437 TabEnt_subgoal_trie(TAB_ENT) = sg_node; \
438 }
439#endif /* THREADS_NO_SHARING */
440
441#if defined(THREADS_FULL_SHARING)
442#define SgFr_init_batched_fields(SG_FR) \
443 SgFr_batched_last_answer(SG_FR) = NULL; \
444 SgFr_batched_cached_answers(SG_FR) = NULL;
445#else
446#define SgFr_init_batched_fields(SG_FR)
447#endif /* THREADS_FULL_SHARING */
448
449#ifdef THREADS_CONSUMER_SHARING
450#define DepFr_init_external_field(DEP_FR, IS_EXTERNAL) \
451 DepFr_external(DEP_FR) = IS_EXTERNAL
452#else
453#define DepFr_init_external_field(DEP_FR, IS_EXTERNAL)
454#endif /* THREADS_CONSUMER_SHARING */
455
456#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
457#define DepFr_init_last_answer_field(DEP_FR, SG_FR) \
458 /* start with TrNode_child(DepFr_last_answer(DEP_FR)) ... */ \
459 /* ... pointing to SgEnt_first_answer(SgFr_sg_ent(SG_FR)) */ \
460 if (SG_FR) \
461 DepFr_last_answer(DEP_FR) = (ans_node_ptr) ( \
462 (CELL) (SgFr_sg_ent((sg_fr_ptr)SG_FR)) + \
463 (CELL) (&SgEnt_first_answer((sg_ent_ptr)DEP_FR)) - \
464 (CELL) (&TrNode_child((ans_node_ptr)DEP_FR))); \
465 else \
466 DepFr_last_answer(DEP_FR) = NULL
467#else
468#define DepFr_init_last_answer_field(DEP_FR, SG_FR) \
469 /* start with TrNode_child(DepFr_last_answer(DEP_FR)) ... */ \
470 /* ... pointing to SgFr_first_answer(SG_FR) */ \
471 if (SG_FR) \
472 DepFr_last_answer(DEP_FR) = (ans_node_ptr) ( \
473 (CELL) (SG_FR) + \
474 (CELL) (&SgFr_first_answer((sg_fr_ptr)DEP_FR)) - \
475 (CELL) (&TrNode_child((ans_node_ptr)DEP_FR))); \
476 else \
477 DepFr_last_answer(DEP_FR) = NULL
478#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
479
480
481#define new_table_entry(TAB_ENT, PRED_ENTRY, ATOM, ARITY, MODE_ARRAY) \
482 ALLOC_TABLE_ENTRY(TAB_ENT); \
483 INIT_LOCK_TAB_ENT(TAB_ENT); \
484 TabEnt_pe(TAB_ENT) = PRED_ENTRY; \
485 TabEnt_atom(TAB_ENT) = ATOM; \
486 TabEnt_arity(TAB_ENT) = ARITY; \
487 TabEnt_flags(TAB_ENT) = 0; \
488 SetMode_Batched(TabEnt_flags(TAB_ENT)); \
489 SetMode_ExecAnswers(TabEnt_flags(TAB_ENT)); \
490 SetMode_LocalTrie(TabEnt_flags(TAB_ENT)); \
491 TabEnt_mode(TAB_ENT) = TabEnt_flags(TAB_ENT); \
492 if (IsMode_Local(LOCAL_TabMode)) \
493 SetMode_Local(TabEnt_mode(TAB_ENT)); \
494 if (IsMode_LoadAnswers(LOCAL_TabMode)) \
495 SetMode_LoadAnswers(TabEnt_mode(TAB_ENT)); \
496 if (IsMode_GlobalTrie(LOCAL_TabMode)) \
497 SetMode_GlobalTrie(TabEnt_mode(TAB_ENT)); \
498 TabEnt_init_mode_directed_field(TAB_ENT, MODE_ARRAY); \
499 TabEnt_init_subgoal_trie_field(TAB_ENT); \
500 TabEnt_next(TAB_ENT) = GLOBAL_root_tab_ent; \
501 GLOBAL_root_tab_ent = TAB_ENT
502
503#define new_subgoal_entry(SG_ENT) \
504 { register ans_node_ptr ans_node; \
505 new_answer_trie_node(ans_node, 0, 0, NULL, NULL, NULL); \
506 ALLOC_SUBGOAL_ENTRY(SG_ENT); \
507 INIT_LOCK(SgEnt_lock(SG_ENT)); \
508 SgEnt_hash_chain(SG_ENT) = NULL; \
509 SgEnt_answer_trie(SG_ENT) = ans_node; \
510 SgEnt_first_answer(SG_ENT) = NULL; \
511 SgEnt_last_answer(SG_ENT) = NULL; \
512 SgEnt_sg_ent_state(SG_ENT) = ready; \
513 SgEnt_active_workers(SG_ENT) = 0; \
514 INIT_BUCKETS(&SgEnt_sg_fr(SG_ENT), THREADS_NUM_BUCKETS); \
515 }
516
517#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
518#define new_subgoal_frame(SG_FR, SG_ENT) \
519 { ALLOC_SUBGOAL_FRAME(SG_FR); \
520 SgFr_sg_ent(SG_FR) = SG_ENT ; \
521 SgFr_init_batched_fields(SG_FR); \
522 }
523
524#define init_subgoal_frame(SG_FR) \
525 { SgFr_state(SG_FR) = evaluating; \
526 SgFr_next(SG_FR) = LOCAL_top_sg_fr; \
527 LOCAL_top_sg_fr = SG_FR; \
528 }
529#else
530#define new_subgoal_frame(SG_FR, CODE, MODE_ARRAY) \
531 { register ans_node_ptr ans_node; \
532 new_answer_trie_node(ans_node, 0, 0, NULL, NULL, NULL); \
533 ALLOC_SUBGOAL_FRAME(SG_FR); \
534 INIT_LOCK_SG_FR(SG_FR); \
535 SgFr_code(SG_FR) = CODE; \
536 SgFr_hash_chain(SG_FR) = NULL; \
537 SgFr_answer_trie(SG_FR) = ans_node; \
538 SgFr_first_answer(SG_FR) = NULL; \
539 SgFr_last_answer(SG_FR) = NULL; \
540 SgFr_init_mode_directed_fields(SG_FR, MODE_ARRAY); \
541 SgFr_state(SG_FR) = ready; \
542 }
543
544#define init_subgoal_frame(SG_FR) \
545 { SgFr_init_yapor_fields(SG_FR); \
546 SgFr_state(SG_FR) = evaluating; \
547 SgFr_next(SG_FR) = LOCAL_top_sg_fr; \
548 LOCAL_top_sg_fr = SG_FR; \
549 }
550#endif /* THREADS_FULL_SHARING) || THREADS_CONSUMER_SHARING */
551
552#define new_dependency_frame(DEP_FR, DEP_ON_STACK, TOP_OR_FR, LEADER_CP, CONS_CP, SG_FR, IS_EXTERNAL, NEXT) \
553 ALLOC_DEPENDENCY_FRAME(DEP_FR); \
554 DepFr_init_yapor_fields(DEP_FR, DEP_ON_STACK, TOP_OR_FR); \
555 DepFr_init_external_field(DEP_FR, IS_EXTERNAL); \
556 DepFr_backchain_cp(DEP_FR) = NULL; \
557 DepFr_leader_cp(DEP_FR) = NORM_CP(LEADER_CP); \
558 DepFr_cons_cp(DEP_FR) = NORM_CP(CONS_CP); \
559 DepFr_init_last_answer_field(DEP_FR, SG_FR); \
560 DepFr_next(DEP_FR) = NEXT
561
562#define new_suspension_frame(SUSP_FR, TOP_OR_FR_ON_STACK, TOP_DEP, TOP_SG, \
563 H_REG, B_REG, TR_REG, H_SIZE, B_SIZE, TR_SIZE) \
564 ALLOC_SUSPENSION_FRAME(SUSP_FR); \
565 SuspFr_top_or_fr_on_stack(SUSP_FR) = TOP_OR_FR_ON_STACK; \
566 SuspFr_top_dep_fr(SUSP_FR) = TOP_DEP; \
567 SuspFr_top_sg_fr(SUSP_FR) = TOP_SG; \
568 SuspFr_global_reg(SUSP_FR) = (void *) (H_REG); \
569 SuspFr_local_reg(SUSP_FR) = (void *) (B_REG); \
570 SuspFr_trail_reg(SUSP_FR) = (void *) (TR_REG); \
571 ALLOC_BLOCK(SuspFr_global_start(SUSP_FR), H_SIZE + B_SIZE + TR_SIZE, void *); \
572 SuspFr_local_start(SUSP_FR) = SuspFr_global_start(SUSP_FR) + H_SIZE; \
573 SuspFr_trail_start(SUSP_FR) = SuspFr_local_start(SUSP_FR) + B_SIZE; \
574 SuspFr_global_size(SUSP_FR) = H_SIZE; \
575 SuspFr_local_size(SUSP_FR) = B_SIZE; \
576 SuspFr_trail_size(SUSP_FR) = TR_SIZE; \
577 memcpy(SuspFr_global_start(SUSP_FR), SuspFr_global_reg(SUSP_FR), H_SIZE); \
578 memcpy(SuspFr_local_start(SUSP_FR), SuspFr_local_reg(SUSP_FR), B_SIZE); \
579 memcpy(SuspFr_trail_start(SUSP_FR), SuspFr_trail_reg(SUSP_FR), TR_SIZE)
580
581#define new_subgoal_trie_node(NODE, ENTRY, CHILD, PARENT, NEXT) \
582 ALLOC_SUBGOAL_TRIE_NODE(NODE); \
583 TrNode_entry(NODE) = ENTRY; \
584 TrNode_child(NODE) = CHILD; \
585 TrNode_parent(NODE) = PARENT; \
586 TrNode_next(NODE) = NEXT; \
587 SgNode_init_lock_field(NODE)
588
589#define new_answer_trie_node(NODE, INSTR, ENTRY, CHILD, PARENT, NEXT) \
590 ALLOC_ANSWER_TRIE_NODE(NODE); \
591 TrNode_instr(NODE) = INSTR; \
592 TrNode_entry(NODE) = ENTRY; \
593 TrNode_child(NODE) = CHILD; \
594 TrNode_parent(NODE) = PARENT; \
595 TrNode_next(NODE) = NEXT; \
596 AnsNode_init_lock_field(NODE)
597
598#define new_global_trie_node(NODE, ENTRY, CHILD, PARENT, NEXT) \
599 ALLOC_GLOBAL_TRIE_NODE(NODE); \
600 TrNode_entry(NODE) = ENTRY; \
601 TrNode_child(NODE) = CHILD; \
602 TrNode_parent(NODE) = PARENT; \
603 TrNode_next(NODE) = NEXT; \
604 GtNode_init_lock_field(NODE)
605
606#define new_answer_ref_node(NODE, ANSWER, NEXT, PREVIOUS) \
607 ALLOC_ANSWER_REF_NODE(NODE); \
608 RefNode_answer(NODE) = ANSWER; \
609 RefNode_next(NODE) = NEXT; \
610 RefNode_previous(NODE) = PREVIOUS
611
612#define new_subgoal_trie_hash(HASH, NUM_NODES, TAB_ENT) \
613 ALLOC_SUBGOAL_TRIE_HASH(HASH); \
614 Hash_mark(HASH) = SUBGOAL_TRIE_HASH_MARK; \
615 Hash_num_buckets(HASH) = BASE_HASH_BUCKETS; \
616 ALLOC_BUCKETS(Hash_buckets(HASH), BASE_HASH_BUCKETS); \
617 Hash_num_nodes(HASH) = NUM_NODES
618
619#define new_answer_trie_hash(HASH, NUM_NODES, SG_FR) \
620 ALLOC_ANSWER_TRIE_HASH(HASH); \
621 Hash_mark(HASH) = ANSWER_TRIE_HASH_MARK; \
622 Hash_num_buckets(HASH) = BASE_HASH_BUCKETS; \
623 ALLOC_BUCKETS(Hash_buckets(HASH), BASE_HASH_BUCKETS); \
624 Hash_num_nodes(HASH) = NUM_NODES; \
625 AnsHash_init_chain_fields(HASH, SG_FR)
626
627#define new_global_trie_hash(HASH, NUM_NODES) \
628 ALLOC_GLOBAL_TRIE_HASH(HASH); \
629 Hash_mark(HASH) = GLOBAL_TRIE_HASH_MARK; \
630 Hash_num_buckets(HASH) = BASE_HASH_BUCKETS; \
631 ALLOC_BUCKETS(Hash_buckets(HASH), BASE_HASH_BUCKETS); \
632 Hash_num_nodes(HASH) = NUM_NODES
633
634#ifdef LIMIT_TABLING
635#define insert_into_global_sg_fr_list(SG_FR) \
636 SgFr_previous(SG_FR) = GLOBAL_last_sg_fr; \
637 SgFr_next(SG_FR) = NULL; \
638 if (GLOBAL_first_sg_fr == NULL) \
639 GLOBAL_first_sg_fr = SG_FR; \
640 else \
641 SgFr_next(GLOBAL_last_sg_fr) = SG_FR; \
642 GLOBAL_last_sg_fr = SG_FR
643#define remove_from_global_sg_fr_list(SG_FR) \
644 if (SgFr_previous(SG_FR)) { \
645 if ((SgFr_next(SgFr_previous(SG_FR)) = SgFr_next(SG_FR)) != NULL) \
646 SgFr_previous(SgFr_next(SG_FR)) = SgFr_previous(SG_FR); \
647 else \
648 GLOBAL_last_sg_fr = SgFr_previous(SG_FR); \
649 } else { \
650 if ((GLOBAL_first_sg_fr = SgFr_next(SG_FR)) != NULL) \
651 SgFr_previous(SgFr_next(SG_FR)) = NULL; \
652 else \
653 GLOBAL_last_sg_fr = NULL; \
654 } \
655 if (GLOBAL_check_sg_fr == SG_FR) \
656 GLOBAL_check_sg_fr = SgFr_previous(SG_FR)
657#else
658#define insert_into_global_sg_fr_list(SG_FR)
659#define remove_from_global_sg_fr_list(SG_FR)
660#endif /* LIMIT_TABLING */
661
662
663
664/******************************
665** Inline funcions **
666******************************/
667
668#ifdef THREADS
669#define get_insert_thread_bucket(b, bl) __get_insert_thread_bucket((b), (bl) PASS_REGS)
670
671static inline void **__get_insert_thread_bucket(void **buckets, lockvar *buckets_lock USES_REGS) {
672
673 /* direct bucket */
674 if (worker_id < THREADS_DIRECT_BUCKETS)
675 return buckets + worker_id;
676
677 /* indirect bucket */
678 buckets = buckets + THREADS_DIRECT_BUCKETS + (worker_id - THREADS_DIRECT_BUCKETS) / THREADS_DIRECT_BUCKETS;
679 if (*buckets)
680 return (void **)((char *)(*buckets) + (worker_id - THREADS_DIRECT_BUCKETS) % THREADS_DIRECT_BUCKETS);
681
682 /* insert indirect bucket */
683 LOCK(*buckets_lock);
684 if (*buckets == NULL)
685 ALLOC_BUCKETS(*buckets, THREADS_DIRECT_BUCKETS);
686 UNLOCK(*buckets_lock);
687 return (void **)((char *)(*buckets) + (worker_id - THREADS_DIRECT_BUCKETS) % THREADS_DIRECT_BUCKETS);
688}
689
690#define get_thread_bucket(b) __get_thread_bucket((b) PASS_REGS)
691
692static inline void **__get_thread_bucket(void **buckets USES_REGS) {
693
694 /* direct bucket */
695 if (worker_id < THREADS_DIRECT_BUCKETS)
696 return buckets + worker_id;
697
698 /* indirect bucket */
699 buckets = buckets + THREADS_DIRECT_BUCKETS + (worker_id - THREADS_DIRECT_BUCKETS) / THREADS_DIRECT_BUCKETS;
700 if (*buckets)
701 return (void **)((char *)(buckets) + (worker_id - THREADS_DIRECT_BUCKETS) % THREADS_DIRECT_BUCKETS);
702
703 /* empty indirect bucket */
704 return buckets;
705}
706
707
708static inline void abolish_thread_buckets(void **buckets) {
709 int i;
710
711 /* abolish indirect buckets */
712 buckets += THREADS_NUM_BUCKETS;
713 for (i = 0; i < THREADS_INDIRECT_BUCKETS; i++) {
714 if (*--buckets) {
715 FREE_BUCKETS(*buckets);
716 *buckets = NULL;
717 }
718 }
719
720#if defined(THREADS_SUBGOAL_SHARING)
721 /* abolish direct buckets */
722 buckets -= THREADS_DIRECT_BUCKETS;
723 FREE_BUCKETS(buckets);
724#endif /* THREADS_SUBGOAL_SHARING */
725}
726#endif /* THREADS */
727
728
729static inline sg_node_ptr get_insert_subgoal_trie(tab_ent_ptr tab_ent USES_REGS) {
730#ifdef THREADS_NO_SHARING
731 sg_node_ptr *sg_node_addr = (sg_node_ptr *) get_insert_thread_bucket((void **) &TabEnt_subgoal_trie(tab_ent), &TabEnt_lock(tab_ent));
732 if (*sg_node_addr == NULL) {
733 new_subgoal_trie_node(*sg_node_addr, 0, NULL, NULL, NULL);
734 }
735 return *sg_node_addr;
736#else
737 return TabEnt_subgoal_trie(tab_ent);
738#endif /* THREADS_NO_SHARING */
739}
740
741#define get_subgoal_trie(te) __get_subgoal_trie((te) PASS_REGS)
742
743static inline sg_node_ptr __get_subgoal_trie(tab_ent_ptr tab_ent USES_REGS) {
744#ifdef THREADS_NO_SHARING
745 sg_node_ptr *sg_node_addr = (sg_node_ptr *) get_thread_bucket((void **) &TabEnt_subgoal_trie(tab_ent));
746 return *sg_node_addr;
747#else
748 return TabEnt_subgoal_trie(tab_ent);
749#endif /* THREADS_NO_SHARING */
750}
751
752
753static inline sg_node_ptr get_subgoal_trie_for_abolish(tab_ent_ptr tab_ent USES_REGS) {
754#ifdef THREADS_NO_SHARING
755 sg_node_ptr *sg_node_addr = (sg_node_ptr *) get_thread_bucket((void **) &TabEnt_subgoal_trie(tab_ent));
756 sg_node_ptr sg_node = *sg_node_addr;
757 *sg_node_addr = NULL;
758 if (GLOBAL_NOfThreads == 1)
759 abolish_thread_buckets((void **) &TabEnt_subgoal_trie(tab_ent));
760 return sg_node;
761#else
762 return TabEnt_subgoal_trie(tab_ent);
763#endif /* THREADS_NO_SHARING */
764}
765
766
767static inline sg_fr_ptr *get_insert_subgoal_frame_addr(sg_node_ptr sg_node USES_REGS) {
768 sg_fr_ptr *sg_fr_addr = (sg_fr_ptr *) &TrNode_sg_fr(sg_node);
769#if defined(THREADS_SUBGOAL_SHARING) || defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
770 if (*sg_fr_addr == NULL) {
771 LOCK_SUBGOAL_NODE(sg_node);
772 if (*sg_fr_addr == NULL) {
773#if defined(THREADS_SUBGOAL_SHARING)
774 ALLOC_BUCKETS(TrNode_sg_fr(sg_node), THREADS_NUM_BUCKETS);
775#elif defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
776 sg_ent_ptr sg_ent;
777 new_subgoal_entry(sg_ent);
778 TrNode_sg_ent(sg_node) = (sg_node_ptr) sg_ent;
779#endif
780 TAG_AS_SUBGOAL_LEAF_NODE(sg_node);
781 }
782 UNLOCK_SUBGOAL_NODE(sg_node);
783 }
784 sg_fr_addr = (sg_fr_ptr *) get_insert_thread_bucket(
785#if defined(THREADS_SUBGOAL_SHARING)
786 (void **) UNTAG_SUBGOAL_NODE(TrNode_sg_fr(sg_node)),
787#elif defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
788 (void **) &SgEnt_sg_fr((sg_ent_ptr) UNTAG_SUBGOAL_NODE(TrNode_sg_fr(sg_node))),
789#endif
790#ifdef SUBGOAL_TRIE_LOCK_USING_NODE_FIELD
791 &TrNode_lock(sg_node)
792#elif defined(SUBGOAL_TRIE_LOCK_USING_GLOBAL_ARRAY)
793 &HASH_TRIE_LOCK(sg_node)
794#endif
795 );
796#endif /* THREADS_SUBGOAL_SHARING || THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
797 return sg_fr_addr;
798}
799
800
801static inline sg_fr_ptr get_subgoal_frame(sg_node_ptr sg_node) {
802#if defined(THREADS_SUBGOAL_SHARING)
803 sg_fr_ptr *sg_fr_addr = (sg_fr_ptr *) get_thread_bucket((void **) UNTAG_SUBGOAL_NODE(TrNode_sg_fr(sg_node)));
804 return *sg_fr_addr;
805#elif defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
806 sg_fr_ptr *sg_fr_addr = (sg_fr_ptr *) get_thread_bucket((void **) &SgEnt_sg_fr((sg_ent_ptr) UNTAG_SUBGOAL_NODE(TrNode_sg_fr(sg_node))));
807 return *sg_fr_addr;
808#else
809 return (sg_fr_ptr) UNTAG_SUBGOAL_NODE(TrNode_sg_fr(sg_node));
810#endif
811}
812
813
814static inline sg_fr_ptr get_subgoal_frame_for_abolish(sg_node_ptr sg_node USES_REGS) {
815#if defined(THREADS_SUBGOAL_SHARING)
816 sg_fr_ptr *sg_fr_addr = (sg_fr_ptr *) get_thread_bucket((void **) UNTAG_SUBGOAL_NODE(TrNode_sg_fr(sg_node)));
817 sg_fr_ptr sg_fr = *sg_fr_addr;
818 if (GLOBAL_NOfThreads == 1)
819 abolish_thread_buckets((void **) UNTAG_SUBGOAL_NODE(TrNode_sg_fr(sg_node)));
820 else
821 *sg_fr_addr = NULL;
822 return sg_fr;
823#elif defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
824 sg_fr_ptr *sg_fr_addr = (sg_fr_ptr *) get_thread_bucket((void **) &SgEnt_sg_fr((sg_ent_ptr) UNTAG_SUBGOAL_NODE(TrNode_sg_fr(sg_node))));
825 sg_fr_ptr sg_fr = *sg_fr_addr;
826 if (GLOBAL_NOfThreads == 1)
827 abolish_thread_buckets((void **) &SgEnt_sg_fr((sg_ent_ptr) UNTAG_SUBGOAL_NODE(TrNode_sg_fr(sg_node))));
828 else
829 *sg_fr_addr = NULL;
830 return sg_fr;
831#else
832 return (sg_fr_ptr) UNTAG_SUBGOAL_NODE(TrNode_sg_fr(sg_node));
833#endif
834}
835
836
837#ifdef THREADS_FULL_SHARING
838#define SgFr_batched_cached_answers_check_insert(s, a) __SgFr_batched_cached_answers_check_insert((s), (a) PASS_REGS)
839static inline void SgFr_batched_cached_answers_check_insert(sg_fr_ptr sg_fr, ans_node_ptr ans_node USES_REGS) {
840
841 if (SgFr_batched_last_answer(sg_fr) == NULL)
842 SgFr_batched_last_answer(sg_fr) = SgFr_first_answer(sg_fr);
843 else
844 SgFr_batched_last_answer(sg_fr) = TrNode_child(SgFr_batched_last_answer(sg_fr)) ;
845
846 while (SgFr_batched_last_answer(sg_fr) != ans_node) {
847 struct answer_ref_node *ref_node = NULL;
848 if (SgFr_batched_cached_answers(sg_fr) == NULL) {
849 new_answer_ref_node(ref_node, SgFr_batched_last_answer(sg_fr), NULL, NULL);
850 } else {
851 new_answer_ref_node(ref_node, SgFr_batched_last_answer(sg_fr), SgFr_batched_cached_answers(sg_fr), NULL);
852 RefNode_previous(SgFr_batched_cached_answers(sg_fr)) = ref_node;
853 }
854 SgFr_batched_cached_answers(sg_fr) = ref_node;
855 SgFr_batched_last_answer(sg_fr) = TrNode_child(SgFr_batched_last_answer(sg_fr)) ;
856 }
857 if (ans_node != NULL)
858 /* new answer */
859 SgFr_batched_last_answer(sg_fr) = ans_node;
860 else
861 /* repeated answer */
862 SgFr_batched_last_answer(sg_fr) = SgFr_last_answer(sg_fr);
863
864 return;
865}
866
867#define SgFr_batched_cached_answers_check_remove(s, a) __SgFr_batched_cached_answers_check_remove((s), (a) PASS_REGS)
868
869static inline int __SgFr_batched_cached_answers_check_remove(sg_fr_ptr sg_fr, ans_node_ptr ans_node USES_REgS) {
870 struct answer_ref_node *local_uncons_ans;
871
872 local_uncons_ans = SgFr_batched_cached_answers(sg_fr) ;
873 while ( local_uncons_ans != NULL ) {
874 if ( RefNode_answer(local_uncons_ans) == ans_node )
875 break;
876 local_uncons_ans = RefNode_next(local_uncons_ans) ;
877 }
878 if ( local_uncons_ans == NULL )
879 return 1;
880
881 /*remove node from buffer */
882 if (RefNode_previous(local_uncons_ans) == NULL) {
883 SgFr_batched_cached_answers(sg_fr) = RefNode_next(local_uncons_ans) ;
884 if (SgFr_batched_cached_answers(sg_fr) != NULL)
885 RefNode_previous(SgFr_batched_cached_answers(sg_fr)) = NULL;
886 } else{
887 RefNode_next(RefNode_previous(local_uncons_ans)) = RefNode_next(local_uncons_ans);
888 if (RefNode_next(local_uncons_ans) != NULL)
889 RefNode_previous(RefNode_next(local_uncons_ans)) = RefNode_previous(local_uncons_ans);
890 }
891 FREE_ANSWER_REF_NODE(local_uncons_ans);
892 return 0;
893}
894#endif /* THREADS_FULL_SHARING */
895
896
897#ifdef THREADS_CONSUMER_SHARING
898
899#define add_to_tdv(w, wd) __add_to_tdv((w), (wd) PASS_REGS)
900
901static inline void __add_to_tdv(int wid, int wid_dep USES_REGS) {
902 // thread wid next of thread wid_dep
903 /* check before insert */
904 int c_wid = ThDepFr_next(GLOBAL_th_dep_fr(wid));
905 do {
906 if (c_wid == wid_dep)
907 break;
908 c_wid = ThDepFr_next(GLOBAL_th_dep_fr(c_wid));
909 } while( c_wid != wid );
910 if (c_wid == wid_dep)
911 return;
912
913 if (wid < wid_dep) {
914 LOCK(ThDepFr_lock(GLOBAL_th_dep_fr(wid)));
915 LOCK(ThDepFr_lock(GLOBAL_th_dep_fr(wid_dep)));
916 } else {
917 LOCK(ThDepFr_lock(GLOBAL_th_dep_fr(wid_dep)));
918 LOCK(ThDepFr_lock(GLOBAL_th_dep_fr(wid)));
919 }
920
921 c_wid = ThDepFr_next(GLOBAL_th_dep_fr(wid));
922 do {
923 if (c_wid == wid_dep)
924 break;
925 c_wid = ThDepFr_next(GLOBAL_th_dep_fr(c_wid));
926 } while( c_wid != wid );
927 if ( c_wid == wid ){
928 // joining the two different SCCs
929 int t = ThDepFr_next(GLOBAL_th_dep_fr(wid));
930 ThDepFr_next(GLOBAL_th_dep_fr(wid)) = ThDepFr_next(GLOBAL_th_dep_fr(wid_dep));
931 ThDepFr_next(GLOBAL_th_dep_fr(wid_dep)) = t;
932 }
933
934 INFO_THREADS("add_to_tdv (2) :tdv_next[%d] = %d tdv_next[%d]= %d", wid, ThDepFr_next(GLOBAL_th_dep_fr(wid)), wid_dep, ThDepFr_next(GLOBAL_th_dep_fr(wid_dep)));
935
936 UNLOCK(ThDepFr_lock(GLOBAL_th_dep_fr(wid)));
937 UNLOCK(ThDepFr_lock(GLOBAL_th_dep_fr(wid_dep)));
938 return;
939}
940
941#define check_for_deadlock(s) __check_for_deadlock((s) PASS_REGS)
942
943static inline void __check_for_deadlock(sg_fr_ptr sg_fr USES_REGS) {
944 sg_fr_ptr local_sg_fr = deadlock_detection(sg_fr);
945
946 if (local_sg_fr){
947 LOCK(ThDepFr_lock(GLOBAL_th_dep_fr(worker_id)));
948 if (YOUNGER_CP(DepFr_leader_cp(LOCAL_top_dep_fr),SgFr_gen_cp(local_sg_fr)))
949 DepFr_leader_cp(LOCAL_top_dep_fr) = SgFr_gen_cp(local_sg_fr);
950
951 UNLOCK(ThDepFr_lock(GLOBAL_th_dep_fr(worker_id)));
952 }
953 return;
954}
955
956#define deadlock_detection(s) __deadlock_detection((s) PASS_REGS)
957
958static inline sg_fr_ptr __deadlock_detection(sg_fr_ptr sg_fr USES_REGS) {
959 sg_fr_ptr remote_sg_fr = REMOTE_top_sg_fr(SgFr_gen_worker(sg_fr));
960
961 while( SgFr_sg_ent(remote_sg_fr) != SgFr_sg_ent(sg_fr)){
962 sg_fr_ptr local_sg_fr = SgFr_next(LOCAL_top_sg_fr);
963 while(local_sg_fr){
964 if ( SgFr_sg_ent(local_sg_fr) == SgFr_sg_ent(remote_sg_fr) ||
965 ( SgFr_gen_worker(remote_sg_fr) != SgFr_gen_worker(sg_fr) && /* jump to other chain */
966 SgFr_gen_worker(remote_sg_fr) != worker_id && /* not jumping to the chain of the thread that is detecting the deadlock */
967 deadlock_detection(remote_sg_fr))){
968
969 sg_fr_ptr leader_remote_sg_fr;
970 do
971 leader_remote_sg_fr = SgFr_next(remote_sg_fr);
972 while(SgFr_sg_ent(leader_remote_sg_fr) != SgFr_sg_ent(sg_fr));
973 LOCK(ThDepFr_lock(GLOBAL_th_dep_fr(SgFr_gen_worker(leader_remote_sg_fr))));
974
975 if (YOUNGER_CP(DepFr_leader_cp(REMOTE_top_dep_fr(SgFr_gen_worker(leader_remote_sg_fr))),SgFr_gen_cp(leader_remote_sg_fr)))
976 DepFr_leader_cp(REMOTE_top_dep_fr(SgFr_gen_worker(leader_remote_sg_fr))) = SgFr_gen_cp(leader_remote_sg_fr);
977 UNLOCK(ThDepFr_lock(GLOBAL_th_dep_fr(SgFr_gen_worker(leader_remote_sg_fr))));
978
979 add_to_tdv(SgFr_gen_worker(local_sg_fr),SgFr_gen_worker(leader_remote_sg_fr));
980
981 return local_sg_fr;
982 }
983 local_sg_fr = SgFr_next(local_sg_fr);
984 }
985 remote_sg_fr = SgFr_next(remote_sg_fr);
986 }
987 return NULL;
988}
989#endif /* THREADS_CONSUMER_SHARING */
990
991#define freeze_current_cp() __freeze_current_cp( PASS_REGS1 )
992
993static inline Int __freeze_current_cp(USES_REGS1) {
994 choiceptr freeze_cp = B;
995
996 B_FZ = freeze_cp;
997 H_FZ = freeze_cp->cp_h;
998 TR_FZ = freeze_cp->cp_tr;
999 B = B->cp_b;
1000 HB = B->cp_h;
1001 return (LOCAL_LocalBase - (ADDR)freeze_cp);
1002}
1003
1004
1005#define wake_frozen_cp(f) __wake_frozen_cp((f) PASS_REGS)
1006
1007#define restore_bindings(u, r) __restore_bindings((u), (r) PASS_REGS)
1008
1009static inline void __wake_frozen_cp(Int frozen_offset USES_REGS) {
1010 choiceptr frozen_cp = (choiceptr)(LOCAL_LocalBase - frozen_offset);
1011
1012 restore_bindings(TR, frozen_cp->cp_tr);
1013 B = frozen_cp;
1014 TR = TR_FZ;
1015 TRAIL_LINK(B->cp_tr);
1016 return;
1017}
1018
1019
1020#define abolish_frozen_cps_until(f) __abolish_frozen_cps_until((f) PASS_REGS )
1021
1022static inline void __abolish_frozen_cps_until(Int frozen_offset USES_REGS) {
1023 choiceptr frozen_cp = (choiceptr)(LOCAL_LocalBase - frozen_offset);
1024
1025 B_FZ = frozen_cp;
1026 H_FZ = frozen_cp->cp_h;
1027 TR_FZ = frozen_cp->cp_tr;
1028 return;
1029}
1030
1031#define abolish_frozen_cps_all() __abolish_frozen_cps_all( PASS_REGS1 )
1032
1033static inline void __abolish_frozen_cps_all( USES_REGS1 ) {
1034 B_FZ = (choiceptr) LOCAL_LocalBase;
1035 H_FZ = (CELL *) LOCAL_GlobalBase;
1036 TR_FZ = (tr_fr_ptr) LOCAL_TrailBase;
1037 return;
1038}
1039
1040#define adjust_freeze_registers() __adjust_freeze_registers( PASS_REGS1 )
1041
1042static inline void __adjust_freeze_registers( USES_REGS1 ) {
1043 B_FZ = DepFr_cons_cp(LOCAL_top_dep_fr);
1044 H_FZ = B_FZ->cp_h;
1045 TR_FZ = B_FZ->cp_tr;
1046 return;
1047}
1048
1049#define mark_as_completed(sg) __mark_as_completed((sg) PASS_REGS )
1050
1051static inline void __mark_as_completed(sg_fr_ptr sg_fr USES_REGS) {
1052#if defined(MODE_DIRECTED_TABLING) && !defined(THREADS_FULL_SHARING) && !defined(THREADS_CONSUMER_SHARING)
1053#endif /* MODE_DIRECTED_TABLING && !THREADS_FULL_SHARING && !THREADS_CONSUMER_SHARING */
1054
1055 LOCK_SG_FR(sg_fr);
1056#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
1057 INFO_THREADS(" mark_as_completed sgfr=%p ", SgFr_sg_ent(sg_fr));
1058 TABLING_ERROR_CHECKING(mark_as_completed, SgFr_sg_ent_state(sg_fr) > complete);
1059 SgFr_active_workers(sg_fr)--;
1060 SgFr_sg_ent_state(sg_fr) = complete;
1061#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
1062 SgFr_state(sg_fr) = complete;
1063 UNLOCK_SG_FR(sg_fr);
1064#ifdef MODE_DIRECTED_TABLING
1065 if (SgFr_invalid_chain(sg_fr)) {
1066 ans_node_ptr current_node, next_node;
1067 /* find first valid answer */
1068 current_node = SgFr_first_answer(sg_fr);
1069 while (IS_ANSWER_INVALID_NODE(current_node))
1070 current_node = TrNode_child(current_node);
1071 SgFr_first_answer(sg_fr) = current_node;
1072 /* chain next valid answers */
1073 next_node = TrNode_child(current_node);
1074 while (next_node) {
1075 if (! IS_ANSWER_INVALID_NODE(next_node)) {
1076 TrNode_child(current_node) = next_node;
1077 current_node = next_node;
1078 }
1079 next_node = TrNode_child(next_node);
1080 }
1081 SgFr_last_answer(sg_fr) = current_node;
1082#if !defined(THREADS_FULL_SHARING) && !defined(THREADS_CONSUMER_SHARING)
1083 /* free invalid answer nodes */
1084 current_node = SgFr_invalid_chain(sg_fr);
1085 SgFr_invalid_chain(sg_fr) = NULL;
1086 while (current_node) {
1087 next_node = TrNode_next(current_node);
1088 FREE_ANSWER_TRIE_NODE(current_node);
1089 current_node = next_node;
1090 }
1091#endif /* !THREADS_FULL_SHARING && !THREADS_CONSUMER_SHARING */
1092 }
1093#endif /* MODE_DIRECTED_TABLING */
1094 return;
1095}
1096
1097#define unbind_variables(u, e) __unbind_variables((u), (e) PASS_REGS)
1098
1099static inline void __unbind_variables(tr_fr_ptr unbind_tr, tr_fr_ptr end_tr USES_REGS) {
1100 TABLING_ERROR_CHECKING(unbind_variables, unbind_tr < end_tr);
1101 /* unbind loop */
1102 while (unbind_tr != end_tr) {
1103 CELL ref = (CELL) TrailTerm(--unbind_tr);
1104 /* check for global or local variables */
1105 if (IsVarTerm(ref)) {
1106 /* unbind variable */
1107 RESET_VARIABLE(ref);
1108 } else if (IsPairTerm(ref)) {
1109 ref = (CELL) RepPair(ref);
1110 if (IN_BETWEEN(LOCAL_TrailBase, ref, LOCAL_TrailTop)) {
1111 /* avoid frozen segments */
1112 unbind_tr = (tr_fr_ptr) ref;
1113 TABLING_ERROR_CHECKING(unbind_variables, unbind_tr > (tr_fr_ptr) LOCAL_TrailTop);
1114 TABLING_ERROR_CHECKING(unbind_variables, unbind_tr < end_tr);
1115 }
1116#ifdef MULTI_ASSIGNMENT_VARIABLES
1117 } else {
1118 CELL *aux_ptr = RepAppl(ref);
1119 --unbind_tr;
1120 Term aux_val = TrailVal(unbind_tr);
1121 *aux_ptr = aux_val;
1122#endif /* MULTI_ASSIGNMENT_VARIABLES */
1123 }
1124 }
1125 return;
1126}
1127
1128
1129#define rebind_variables(u, e) __rebind_variables(u, e PASS_REGS)
1130
1131static inline void __rebind_variables(tr_fr_ptr rebind_tr, tr_fr_ptr end_tr USES_REGS) {
1132 TABLING_ERROR_CHECKING(rebind_variables, rebind_tr < end_tr);
1133 /* rebind loop */
1134 Yap_NEW_MAHASH((ma_h_inner_struct *)HR PASS_REGS);
1135 while (rebind_tr != end_tr) {
1136 CELL ref = (CELL) TrailTerm(--rebind_tr);
1137 /* check for global or local variables */
1138 if (IsVarTerm(ref)) {
1139 /* rebind variable */
1140 *((CELL *)ref) = TrailVal(rebind_tr);
1141 } else if (IsPairTerm(ref)) {
1142 ref = (CELL) RepPair(ref);
1143 if (IN_BETWEEN(LOCAL_TrailBase, ref, LOCAL_TrailTop)) {
1144 /* avoid frozen segments */
1145 rebind_tr = (tr_fr_ptr) ref;
1146 TABLING_ERROR_CHECKING(rebind_variables, rebind_tr > (tr_fr_ptr) LOCAL_TrailTop);
1147 TABLING_ERROR_CHECKING(rebind_variables, rebind_tr < end_tr);
1148 }
1149#ifdef MULTI_ASSIGNMENT_VARIABLES
1150 } else {
1151 CELL *cell_ptr = RepAppl(ref);
1152 if (!Yap_lookup_ma_var(cell_ptr PASS_REGS)) {
1153 /* first time we found the variable, let's put the new value */
1154 *cell_ptr = TrailVal(rebind_tr);
1155 }
1156 --rebind_tr;
1157#endif /* MULTI_ASSIGNMENT_VARIABLES */
1158 }
1159 }
1160 return;
1161}
1162
1163static inline void __restore_bindings(tr_fr_ptr unbind_tr, tr_fr_ptr rebind_tr USES_REGS) {
1164 CELL ref;
1165 tr_fr_ptr end_tr;
1166
1167 TABLING_ERROR_CHECKING(restore_variables, unbind_tr < rebind_tr);
1168 end_tr = rebind_tr;
1169 Yap_NEW_MAHASH((ma_h_inner_struct *)HR PASS_REGS);
1170 while (unbind_tr != end_tr) {
1171 /* unbind loop */
1172 while (unbind_tr > end_tr) {
1173 ref = (CELL) TrailTerm(--unbind_tr);
1174 if (IsVarTerm(ref)) {
1175 RESET_VARIABLE(ref);
1176 } else if (IsPairTerm(ref)) {
1177 ref = (CELL) RepPair(ref);
1178 if (IN_BETWEEN(LOCAL_TrailBase, ref, LOCAL_TrailTop)) {
1179 /* avoid frozen segments */
1180 unbind_tr = (tr_fr_ptr) ref;
1181 TABLING_ERROR_CHECKING(restore_variables, unbind_tr > (tr_fr_ptr) LOCAL_TrailTop);
1182 }
1183#ifdef MULTI_ASSIGNMENT_VARIABLES
1184 } else if (IsApplTerm(ref)) {
1185 CELL *pt = RepAppl(ref);
1186
1187 /* AbsAppl means */
1188 /* multi-assignment variable */
1189 /* so that the upper cell is the old value */
1190 --unbind_tr;
1191 if (!Yap_lookup_ma_var(pt PASS_REGS)) {
1192 pt[0] = TrailVal(unbind_tr);
1193 }
1194#endif /* MULTI_ASSIGNMENT_VARIABLES */
1195 }
1196 }
1197 /* look for end */
1198 while (unbind_tr < end_tr) {
1199 ref = (CELL) TrailTerm(--end_tr);
1200 if (IsPairTerm(ref)) {
1201 ref = (CELL) RepPair(ref);
1202 if (IN_BETWEEN(LOCAL_TrailBase, ref, LOCAL_TrailTop)) {
1203 /* avoid frozen segments */
1204 end_tr = (tr_fr_ptr) ref;
1205 TABLING_ERROR_CHECKING(restore_variables, end_tr > (tr_fr_ptr) LOCAL_TrailTop);
1206 }
1207 }
1208 }
1209 }
1210 /* rebind loop */
1211 while (rebind_tr != end_tr) {
1212 ref = (CELL) TrailTerm(--rebind_tr);
1213 if (IsVarTerm(ref)) {
1214 *((CELL *)ref) = TrailVal(rebind_tr);
1215 } else if (IsPairTerm(ref)) {
1216 ref = (CELL) RepPair(ref);
1217 if (IN_BETWEEN(LOCAL_TrailBase, ref, LOCAL_TrailTop)) {
1218 /* avoid frozen segments */
1219 rebind_tr = (tr_fr_ptr) ref;
1220 TABLING_ERROR_CHECKING(restore_variables, rebind_tr > (tr_fr_ptr) LOCAL_TrailTop);
1221 TABLING_ERROR_CHECKING(restore_variables, rebind_tr < end_tr);
1222 }
1223#ifdef MULTI_ASSIGNMENT_VARIABLES
1224 } else {
1225 CELL *cell_ptr = RepAppl(ref);
1226 /* first time we found the variable, let's put the new value */
1227 *cell_ptr = TrailVal(rebind_tr);
1228 --rebind_tr;
1229#endif /* MULTI_ASSIGNMENT_VARIABLES */
1230 }
1231 }
1232 return;
1233}
1234
1235#define expand_auxiliary_stack(s) __expand_auxiliary_stack((s) PASS_REGS)
1236
1237static inline CELL *__expand_auxiliary_stack(CELL *stack USES_REGS) {
1238 char *old_top = (char *)LOCAL_TrailTop;
1239 INFORMATION_MESSAGE("Expanding trail in " UInt_FORMAT " bytes", K64);
1240 if (! Yap_growtrail(K64, TRUE)) { /* TRUE means 'contiguous_only' */
1241 Yap_Error(RESOURCE_ERROR_TRAIL, TermNil, "stack full (STACK_CHECK_EXPAND)");
1242 return NULL;
1243 } else {
1244 UInt diff = (char *)LOCAL_TrailTop - old_top;
1245 CELL *new_stack = (CELL *)((char *)stack + diff);
1246 memmove((void *)new_stack, stack, old_top - (char *)stack);
1247 return new_stack;
1248 }
1249}
1250
1251#define abolish_incomplete_subgoals(p) __abolish_incomplete_subgoals((p) PASS_REGS)
1252
1253
1254static inline void __abolish_incomplete_subgoals(choiceptr prune_cp USES_REGS) {
1255
1256#ifdef YAPOR
1257 if (EQUAL_OR_YOUNGER_CP(GetOrFr_node(LOCAL_top_susp_or_fr), prune_cp))
1258 pruning_over_tabling_data_structures();
1259#endif /* YAPOR */
1260 if (LOCAL_CBorder )
1261 return;
1262
1263 if (EQUAL_OR_YOUNGER_CP(DepFr_cons_cp(LOCAL_top_dep_fr), prune_cp)) {
1264#ifdef YAPOR
1265 if (GLOBAL_parallel_mode == PARALLEL_MODE_RUNNING)
1266 pruning_over_tabling_data_structures();
1267#endif /* YAPOR */
1268 do {
1269 dep_fr_ptr dep_fr = LOCAL_top_dep_fr;
1270 LOCAL_top_dep_fr = DepFr_next(dep_fr);
1271 FREE_DEPENDENCY_FRAME(dep_fr);
1272 } while (EQUAL_OR_YOUNGER_CP(DepFr_cons_cp(LOCAL_top_dep_fr), prune_cp));
1273 adjust_freeze_registers();
1274 }
1275
1276 while (LOCAL_top_sg_fr && EQUAL_OR_YOUNGER_CP(SgFr_gen_cp(LOCAL_top_sg_fr), prune_cp)) {
1277 sg_fr_ptr sg_fr;
1278#ifdef YAPOR
1279 if (GLOBAL_parallel_mode == PARALLEL_MODE_RUNNING)
1280 pruning_over_tabling_data_structures();
1281#endif /* YAPOR */
1282 sg_fr = LOCAL_top_sg_fr;
1283 LOCAL_top_sg_fr = SgFr_next(sg_fr);
1284 LOCK_SG_FR(sg_fr);
1285 if (SgFr_first_answer(sg_fr) == NULL) {
1286 /* no answers --> ready */
1287 SgFr_state(sg_fr) = ready;
1288 UNLOCK_SG_FR(sg_fr);
1289 } else if (SgFr_first_answer(sg_fr) == SgFr_answer_trie(sg_fr)) {
1290 /* yes answer --> complete */
1291#ifndef TABLING_EARLY_COMPLETION
1292 /* with early completion, at this point the subgoal should be already completed */
1293 SgFr_state(sg_fr) = complete;
1294#endif /* TABLING_EARLY_COMPLETION */
1295 UNLOCK_SG_FR(sg_fr);
1296 } else {
1297 /* answers --> incomplete/ready */
1298#ifdef INCOMPLETE_TABLING
1299 SgFr_state(sg_fr) = incomplete;
1300 UNLOCK_SG_FR(sg_fr);
1301#ifdef MODE_DIRECTED_TABLING
1302 if (SgFr_invalid_chain(sg_fr)) {
1303 ans_node_ptr current_node, next_node;
1304 /* find first valid answer */
1305 current_node = SgFr_first_answer(sg_fr);
1306 while (IS_ANSWER_INVALID_NODE(current_node))
1307 current_node = TrNode_child(current_node);
1308 SgFr_first_answer(sg_fr) = current_node;
1309 /* chain next valid answers */
1310 next_node = TrNode_child(current_node);
1311 while (next_node) {
1312 if (! IS_ANSWER_INVALID_NODE(next_node)) {
1313 TrNode_child(current_node) = next_node;
1314 current_node = next_node;
1315 }
1316 next_node = TrNode_child(next_node);
1317 }
1318 SgFr_last_answer(sg_fr) = current_node;
1319#if !defined(THREADS_FULL_SHARING) && !defined(THREADS_CONSUMER_SHARING)
1320 /* free invalid answer nodes */
1321 current_node = SgFr_invalid_chain(sg_fr);
1322 SgFr_invalid_chain(sg_fr) = NULL;
1323 while (current_node) {
1324 next_node = TrNode_next(current_node);
1325 FREE_ANSWER_TRIE_NODE(current_node);
1326 current_node = next_node;
1327 }
1328#endif /* !THREADS_FULL_SHARING && !THREADS_CONSUMER_SHARING */
1329 }
1330#endif /* MODE_DIRECTED_TABLING */
1331#else
1332 ans_node_ptr node;
1333#if defined(MODE_DIRECTED_TABLING) && !defined(THREADS_FULL_SHARING) && !defined(THREADS_CONSUMER_SHARING)
1334 if (SgFr_invalid_chain(sg_fr)) {
1335 ans_node_ptr current_node, next_node;
1336 /* free invalid answer nodes */
1337 current_node = SgFr_invalid_chain(sg_fr);
1338 SgFr_invalid_chain(sg_fr) = NULL;
1339 while (current_node) {
1340 next_node = TrNode_next(current_node);
1341 FREE_ANSWER_TRIE_NODE(current_node);
1342 current_node = next_node;
1343 }
1344 }
1345#endif /* MODE_DIRECTED_TABLING && !THREADS_FULL_SHARING && !THREADS_CONSUMER_SHARING */
1346 SgFr_state(sg_fr) = ready;
1347#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
1348 if (SgFr_active_workers(sg_fr) == 0) {
1349 SgFr_sg_ent_state(sg_fr) = ready;
1350#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
1351 free_answer_hash_chain(SgFr_hash_chain(sg_fr));
1352 SgFr_hash_chain(sg_fr) = NULL;
1353 SgFr_first_answer(sg_fr) = NULL;
1354 SgFr_last_answer(sg_fr) = NULL;
1355 node = TrNode_child(SgFr_answer_trie(sg_fr));
1356 TrNode_child(SgFr_answer_trie(sg_fr)) = NULL;
1357 UNLOCK_SG_FR(sg_fr);
1358 free_answer_trie(node, TRAVERSE_MODE_NORMAL, TRAVERSE_POSITION_FIRST);
1359#ifdef THREADS_FULL_SHARING
1360 if (IsMode_Batched(TabEnt_mode(SgFr_tab_ent(sg_fr)))) {
1361 SgFr_batched_last_answer(sg_fr) = NULL;
1362 struct answer_ref_node *local_uncons_ans = SgFr_batched_cached_answers(sg_fr) ;
1363 while ( local_uncons_ans ) {
1364 SgFr_batched_cached_answers(sg_fr) = RefNode_next(SgFr_batched_cached_answers(sg_fr));
1365 FREE_ANSWER_REF_NODE(local_uncons_ans);
1366 local_uncons_ans = SgFr_batched_cached_answers(sg_fr);
1367 }
1368 }
1369 } else { /* SgFr_active_workers(sg_fr) != 0 */
1370 if (IsMode_Batched(TabEnt_mode(SgFr_tab_ent(sg_fr)))){
1371 SgFr_batched_last_answer(sg_fr) = NULL;
1372 if ( worker_id >= ANSWER_LEAF_NODE_MAX_THREADS ) {
1373 struct answer_ref_node *local_uncons_ans = SgFr_batched_cached_answers(sg_fr) ;
1374 while ( local_uncons_ans ) {
1375 SgFr_batched_cached_answers(sg_fr) = RefNode_next(SgFr_batched_cached_answers(sg_fr));
1376 FREE_ANSWER_REF_NODE(local_uncons_ans);
1377 local_uncons_ans = SgFr_batched_cached_answers(sg_fr);
1378 }
1379 } else { /* worker_id < ANSWER_LEAF_NODE_MAX_THREADS */
1380 ans_node_ptr leaf_ans_trie_node = SgFr_first_answer(sg_fr);
1381 while( leaf_ans_trie_node ){
1382 ANSWER_LEAF_NODE_DEL_WID(leaf_ans_trie_node,worker_id);
1383 leaf_ans_trie_node = TrNode_child(leaf_ans_trie_node);
1384 }
1385 }
1386 }
1387#endif /* THREADS_FULL_SHARING */
1388#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
1389 }
1390#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
1391#endif /* INCOMPLETE_TABLING */
1392 }
1393#ifdef LIMIT_TABLING
1394 insert_into_global_sg_fr_list(sg_fr);
1395#endif /* LIMIT_TABLING */
1396 }
1397
1398 return;
1399}
1400
1401
1402#ifdef YAPOR
1403static inline void pruning_over_tabling_data_structures(void) {
1404 Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, "pruning over tabling data structures");
1405 return;
1406}
1407
1408
1409#define collect_suspension_frames(o) __collect_suspension_frames((o) PASS_REGS)
1410
1411static inline void __collect_suspension_frames(or_fr_ptr or_fr USES_REGS) {
1412 int depth;
1413 or_fr_ptr *susp_ptr;
1414
1415 OPTYAP_ERROR_CHECKING(collect_suspension_frames, IS_UNLOCKED(or_fr));
1416 OPTYAP_ERROR_CHECKING(collect_suspension_frames, OrFr_suspensions(or_fr) == NULL);
1417
1418 /* order collected suspension frames by depth */
1419 depth = OrFr_depth(or_fr);
1420 susp_ptr = & LOCAL_top_susp_or_fr;
1421 while (OrFr_depth(*susp_ptr) > depth)
1422 susp_ptr = & OrFr_nearest_suspnode(*susp_ptr);
1423 OrFr_nearest_suspnode(or_fr) = *susp_ptr;
1424 *susp_ptr = or_fr;
1425 return;
1426}
1427
1428
1429static inline
1430#ifdef TIMESTAMP_CHECK
1431susp_fr_ptr suspension_frame_to_resume(or_fr_ptr susp_or_fr, long timestamp) {
1432#else
1433susp_fr_ptr suspension_frame_to_resume(or_fr_ptr susp_or_fr) {
1434#endif /* TIMESTAMP_CHECK */
1435 choiceptr top_cp;
1436 susp_fr_ptr *susp_ptr, susp_fr;
1437 dep_fr_ptr dep_fr;
1438
1439 top_cp = GetOrFr_node(susp_or_fr);
1440 susp_ptr = & OrFr_suspensions(susp_or_fr);
1441 susp_fr = *susp_ptr;
1442 while (susp_fr) {
1443 dep_fr = SuspFr_top_dep_fr(susp_fr);
1444 do {
1445 if (TrNode_child(DepFr_last_answer(dep_fr))) {
1446 /* unconsumed answers in susp_fr */
1447 *susp_ptr = SuspFr_next(susp_fr);
1448 return susp_fr;
1449 }
1450#ifdef TIMESTAMP_CHECK
1451 DepFr_timestamp(dep_fr) = timestamp;
1452#endif /* TIMESTAMP_CHECK */
1453 dep_fr = DepFr_next(dep_fr);
1454#ifdef TIMESTAMP_CHECK
1455 } while (timestamp > DepFr_timestamp(dep_fr) && YOUNGER_CP(DepFr_cons_cp(dep_fr), top_cp));
1456#else
1457 } while (YOUNGER_CP(DepFr_cons_cp(dep_fr), top_cp));
1458#endif /* TIMESTAMP_CHECK */
1459 susp_ptr = & SuspFr_next(susp_fr);
1460 susp_fr = *susp_ptr;
1461 }
1462 /* no suspension frame with unconsumed answers */
1463 return NULL;
1464}
1465#endif /* YAPOR */
1466
1467
1468#ifdef TABLING_INNER_CUTS
1469static inline void CUT_store_tg_answer(or_fr_ptr or_frame, ans_node_ptr ans_node, choiceptr gen_cp, int ltt) {
1470 tg_sol_fr_ptr tg_sol_fr, *solution_ptr, next, ltt_next;
1471 tg_ans_fr_ptr tg_ans_fr;
1472
1473 solution_ptr = & OrFr_tg_solutions(or_frame);
1474 while (*solution_ptr && YOUNGER_CP(gen_cp, TgSolFr_gen_cp(*solution_ptr))) {
1475 solution_ptr = & TgSolFr_next(*solution_ptr);
1476 }
1477 if (*solution_ptr && gen_cp == TgSolFr_gen_cp(*solution_ptr)) {
1478 if (ltt >= TgSolFr_ltt(*solution_ptr)) {
1479 while (*solution_ptr && ltt > TgSolFr_ltt(*solution_ptr)) {
1480 solution_ptr = & TgSolFr_ltt_next(*solution_ptr);
1481 }
1482 if (*solution_ptr && ltt == TgSolFr_ltt(*solution_ptr)) {
1483 tg_ans_fr = TgSolFr_first(*solution_ptr);
1484 if (TgAnsFr_free_slot(tg_ans_fr) == TG_ANSWER_SLOTS) {
1485 ALLOC_TG_ANSWER_FRAME(tg_ans_fr);
1486 TgAnsFr_free_slot(tg_ans_fr) = 1;
1487 TgAnsFr_answer(tg_ans_fr, 0) = ans_node;
1488 TgAnsFr_next(tg_ans_fr) = TgSolFr_first(*solution_ptr);
1489 TgSolFr_first(*solution_ptr) = tg_ans_fr;
1490 } else {
1491 TgAnsFr_answer(tg_ans_fr, TgAnsFr_free_slot(tg_ans_fr)) = ans_node;
1492 TgAnsFr_free_slot(tg_ans_fr)++;
1493 }
1494 return;
1495 }
1496 ltt_next = *solution_ptr;
1497 next = NULL;
1498 } else {
1499 ltt_next = *solution_ptr;
1500 next = TgSolFr_next(*solution_ptr);
1501 }
1502 } else {
1503 ltt_next = NULL;
1504 next = *solution_ptr;
1505 }
1506 ALLOC_TG_ANSWER_FRAME(tg_ans_fr);
1507 TgAnsFr_free_slot(tg_ans_fr) = 1;
1508 TgAnsFr_answer(tg_ans_fr, 0) = ans_node;
1509 TgAnsFr_next(tg_ans_fr) = NULL;
1510 ALLOC_TG_SOLUTION_FRAME(tg_sol_fr);
1511 TgSolFr_gen_cp(tg_sol_fr) = gen_cp;
1512 TgSolFr_ltt(tg_sol_fr) = ltt;
1513 TgSolFr_first(tg_sol_fr) = tg_ans_fr;
1514 TgSolFr_last(tg_sol_fr) = tg_ans_fr;
1515 TgSolFr_ltt_next(tg_sol_fr) = ltt_next;
1516 TgSolFr_next(tg_sol_fr) = next;
1517 *solution_ptr = tg_sol_fr;
1518 return;
1519}
1520
1521
1522static inline tg_sol_fr_ptr CUT_store_tg_answers(or_fr_ptr or_frame, tg_sol_fr_ptr new_solution, int ltt) {
1523 tg_sol_fr_ptr *old_solution_ptr, next_new_solution;
1524 choiceptr node, gen_cp;
1525
1526 old_solution_ptr = & OrFr_tg_solutions(or_frame);
1527 node = GetOrFr_node(or_frame);
1528 while (new_solution && YOUNGER_CP(node, TgSolFr_gen_cp(new_solution))) {
1529 next_new_solution = TgSolFr_next(new_solution);
1530 gen_cp = TgSolFr_gen_cp(new_solution);
1531 while (*old_solution_ptr && YOUNGER_CP(gen_cp, TgSolFr_gen_cp(*old_solution_ptr))) {
1532 old_solution_ptr = & TgSolFr_next(*old_solution_ptr);
1533 }
1534 if (*old_solution_ptr && gen_cp == TgSolFr_gen_cp(*old_solution_ptr)) {
1535 if (ltt >= TgSolFr_ltt(*old_solution_ptr)) {
1536 tg_sol_fr_ptr *ltt_next_old_solution_ptr;
1537 ltt_next_old_solution_ptr = old_solution_ptr;
1538 while (*ltt_next_old_solution_ptr && ltt > TgSolFr_ltt(*ltt_next_old_solution_ptr)) {
1539 ltt_next_old_solution_ptr = & TgSolFr_ltt_next(*ltt_next_old_solution_ptr);
1540 }
1541 if (*ltt_next_old_solution_ptr && ltt == TgSolFr_ltt(*ltt_next_old_solution_ptr)) {
1542 TgAnsFr_next(TgSolFr_last(*ltt_next_old_solution_ptr)) = TgSolFr_first(new_solution);
1543 TgSolFr_last(*ltt_next_old_solution_ptr) = TgSolFr_last(new_solution);
1544 FREE_TG_SOLUTION_FRAME(new_solution);
1545 } else {
1546 TgSolFr_ltt(new_solution) = ltt;
1547 TgSolFr_ltt_next(new_solution) = *ltt_next_old_solution_ptr;
1548 TgSolFr_next(new_solution) = NULL;
1549 *ltt_next_old_solution_ptr = new_solution;
1550 }
1551 } else {
1552 TgSolFr_ltt(new_solution) = ltt;
1553 TgSolFr_ltt_next(new_solution) = *old_solution_ptr;
1554 TgSolFr_next(new_solution) = TgSolFr_next(*old_solution_ptr);
1555 *old_solution_ptr = new_solution;
1556 }
1557 } else {
1558 TgSolFr_ltt(new_solution) = ltt;
1559 TgSolFr_ltt_next(new_solution) = NULL;
1560 TgSolFr_next(new_solution) = *old_solution_ptr;
1561 *old_solution_ptr = new_solution;
1562 }
1563 old_solution_ptr = & TgSolFr_next(*old_solution_ptr);
1564 new_solution = next_new_solution;
1565 }
1566 return new_solution;
1567}
1568
1569
1570static inline void CUT_validate_tg_answers(tg_sol_fr_ptr valid_solutions) {
1571 tg_ans_fr_ptr valid_answers, free_answer;
1572 tg_sol_fr_ptr ltt_valid_solutions, free_solution;
1573 ans_node_ptr first_answer, last_answer, ans_node;
1574 sg_fr_ptr sg_fr;
1575 int slots;
1576
1577 while (valid_solutions) {
1578 first_answer = last_answer = NULL;
1579#ifdef DETERMINISTIC_TABLING
1580 if (IS_DET_GEN_CP(TgSolFr_gen_cp(valid_solutions)))
1581 sg_fr = DET_GEN_CP(TgSolFr_gen_cp(valid_solutions))->cp_sg_fr;
1582 else
1583#endif /* DETERMINISTIC_TABLING */
1584 sg_fr = GEN_CP(TgSolFr_gen_cp(valid_solutions))->cp_sg_fr;
1585 ltt_valid_solutions = valid_solutions;
1586 valid_solutions = TgSolFr_next(valid_solutions);
1587 do {
1588 valid_answers = TgSolFr_first(ltt_valid_solutions);
1589 do {
1590 slots = TgAnsFr_free_slot(valid_answers);
1591 do {
1592 ans_node = TgAnsFr_answer(valid_answers, --slots);
1593 LOCK_ANSWER_TRIE(sg_fr);
1594 LOCK_ANSWER_NODE(ans_node);
1595 if (! IS_ANSWER_LEAF_NODE(ans_node)) {
1596 TAG_AS_ANSWER_LEAF_NODE(ans_node);
1597 if (first_answer == NULL)
1598 first_answer = ans_node;
1599 else
1600 TrNode_child(last_answer) = ans_node;
1601 last_answer = ans_node;
1602 }
1603 UNLOCK_ANSWER_NODE(ans_node);
1604 UNLOCK_ANSWER_TRIE(sg_fr);
1605 } while (slots);
1606 free_answer = valid_answers;
1607 valid_answers = TgAnsFr_next(valid_answers);
1608 FREE_TG_ANSWER_FRAME(free_answer);
1609 } while (valid_answers);
1610 free_solution = ltt_valid_solutions;
1611 ltt_valid_solutions = TgSolFr_ltt_next(ltt_valid_solutions);
1612 FREE_TG_SOLUTION_FRAME(free_solution);
1613 } while (ltt_valid_solutions);
1614 if (first_answer) {
1615 LOCK_SG_FR(sg_fr);
1616 if (SgFr_first_answer(sg_fr) == NULL) {
1617 SgFr_first_answer(sg_fr) = first_answer;
1618 } else {
1619 TrNode_child(SgFr_last_answer(sg_fr)) = first_answer;
1620 }
1621 SgFr_last_answer(sg_fr) = last_answer;
1622 UNLOCK_SG_FR(sg_fr);
1623 }
1624 }
1625 return;
1626}
1627
1628
1629static inline void CUT_join_tg_solutions(tg_sol_fr_ptr *old_solution_ptr, tg_sol_fr_ptr new_solution) {
1630 tg_sol_fr_ptr next_old_solution, next_new_solution;
1631 choiceptr gen_cp;
1632
1633 do {
1634 gen_cp = TgSolFr_gen_cp(new_solution);
1635 while (*old_solution_ptr && YOUNGER_CP(gen_cp, TgSolFr_gen_cp(*old_solution_ptr))) {
1636 old_solution_ptr = & TgSolFr_next(*old_solution_ptr);
1637 }
1638 if (*old_solution_ptr) {
1639 next_old_solution = *old_solution_ptr;
1640 *old_solution_ptr = new_solution;
1641 CUT_join_solution_frame_tg_answers(new_solution);
1642 if (gen_cp == TgSolFr_gen_cp(next_old_solution)) {
1643 tg_sol_fr_ptr free_solution;
1644 TgAnsFr_next(TgSolFr_last(new_solution)) = TgSolFr_first(next_old_solution);
1645 TgSolFr_last(new_solution) = TgSolFr_last(next_old_solution);
1646 free_solution = next_old_solution;
1647 next_old_solution = TgSolFr_next(next_old_solution);
1648 FREE_TG_SOLUTION_FRAME(free_solution);
1649 if (! next_old_solution) {
1650 if ((next_new_solution = TgSolFr_next(new_solution))) {
1651 CUT_join_solution_frames_tg_answers(next_new_solution);
1652 }
1653 return;
1654 }
1655 }
1656 gen_cp = TgSolFr_gen_cp(next_old_solution);
1657 next_new_solution = TgSolFr_next(new_solution);
1658 while (next_new_solution && YOUNGER_CP(gen_cp, TgSolFr_gen_cp(next_new_solution))) {
1659 new_solution = next_new_solution;
1660 next_new_solution = TgSolFr_next(new_solution);
1661 CUT_join_solution_frame_tg_answers(new_solution);
1662 }
1663 old_solution_ptr = & TgSolFr_next(new_solution);
1664 TgSolFr_next(new_solution) = next_old_solution;
1665 new_solution = next_new_solution;
1666 } else {
1667 *old_solution_ptr = new_solution;
1668 CUT_join_solution_frames_tg_answers(new_solution);
1669 return;
1670 }
1671 } while (new_solution);
1672 return;
1673}
1674
1675
1676static inline void CUT_join_solution_frame_tg_answers(tg_sol_fr_ptr join_solution) {
1677 tg_sol_fr_ptr next_solution;
1678
1679 while ((next_solution = TgSolFr_ltt_next(join_solution))) {
1680 TgAnsFr_next(TgSolFr_last(join_solution)) = TgSolFr_first(next_solution);
1681 TgSolFr_last(join_solution) = TgSolFr_last(next_solution);
1682 TgSolFr_ltt_next(join_solution) = TgSolFr_ltt_next(next_solution);
1683 FREE_TG_SOLUTION_FRAME(next_solution);
1684 }
1685 return;
1686}
1687
1688
1689static inline void CUT_join_solution_frames_tg_answers(tg_sol_fr_ptr join_solution) {
1690 do {
1691 CUT_join_solution_frame_tg_answers(join_solution);
1692 join_solution = TgSolFr_next(join_solution);
1693 } while (join_solution);
1694 return;
1695}
1696
1697
1698static inline void CUT_free_tg_solution_frame(tg_sol_fr_ptr solution) {
1699 tg_ans_fr_ptr current_answer, next_answer;
1700
1701 current_answer = TgSolFr_first(solution);
1702 do {
1703 next_answer = TgAnsFr_next(current_answer);
1704 FREE_TG_ANSWER_FRAME(current_answer);
1705 current_answer = next_answer;
1706 } while (current_answer);
1707 FREE_TG_SOLUTION_FRAME(solution);
1708 return;
1709}
1710
1711
1712static inline void CUT_free_tg_solution_frames(tg_sol_fr_ptr current_solution) {
1713 tg_sol_fr_ptr ltt_solution, next_solution;
1714
1715 while (current_solution) {
1716 ltt_solution = TgSolFr_ltt_next(current_solution);
1717 while (ltt_solution) {
1718 next_solution = TgSolFr_ltt_next(ltt_solution);
1719 CUT_free_tg_solution_frame(ltt_solution);
1720 ltt_solution = next_solution;
1721 }
1722 next_solution = TgSolFr_next(current_solution);
1723 CUT_free_tg_solution_frame(current_solution);
1724 current_solution = next_solution;
1725 }
1726 return;
1727}
1728
1729
1730static inline tg_sol_fr_ptr CUT_prune_tg_solution_frames(tg_sol_fr_ptr solutions, int ltt) {
1731 tg_sol_fr_ptr ltt_next_solution, return_solution;
1732
1733 if (! solutions) return NULL;
1734 return_solution = CUT_prune_tg_solution_frames(TgSolFr_next(solutions), ltt);
1735 while (solutions && ltt > TgSolFr_ltt(solutions)) {
1736 ltt_next_solution = TgSolFr_ltt_next(solutions);
1737 CUT_free_tg_solution_frame(solutions);
1738 solutions = ltt_next_solution;
1739 }
1740 if (solutions) {
1741 TgSolFr_next(solutions) = return_solution;
1742 return solutions;
1743 } else {
1744 return return_solution;
1745 }
1746}
1747#endif /* TABLING_INNER_CUTS */
Definition: tab.structs.h:240
Definition: tab.structs.h:22