Miguel's support for multi-threaded tabling

This commit is contained in:
Ricardo Rocha 2011-12-22 16:50:20 +00:00
parent dc36b1cf65
commit c594d321ef
26 changed files with 1573 additions and 484 deletions

View File

@ -1924,6 +1924,9 @@ Yap_absmi(int inp)
case _table_retry:
case _table_trust:
case _table_completion:
#ifdef THREADS_CONSUMER_SHARING
case _table_answer_resolution_completion:
#endif /* THREADS_CONSUMER_SHARING */
#ifdef DETERMINISTIC_TABLING
if (IS_DET_GEN_CP(B))
low_level_trace(retry_table_generator, DET_GEN_CP(B)->cp_pred_entry, NULL);

View File

@ -588,6 +588,9 @@ PredForChoicePt(yamop *p_code) {
case _table_try_answer:
case _table_answer_resolution:
case _table_completion:
#ifdef THREADS_CONSUMER_SHARING
case _table_answer_resolution_completion:
#endif /* THREADS_CONSUMER_SHARING */
return NULL; /* ricroc: is this OK? */
/* compile error --> return ENV_ToP(gc_B->cp_cp); */
#endif /* TABLING */
@ -5486,6 +5489,9 @@ p_choicepoint_info( USES_REGS1 )
case _table_retry:
case _table_trust:
case _table_completion:
#ifdef THREADS_CONSUMER_SHARING
case _table_answer_resolution_completion:
#endif /* THREADS_CONSUMER_SHARING */
#ifdef LOW_LEVEL_TRACER
#ifdef DETERMINISTIC_TABLING
if (IS_DET_GEN_CP(cptr)) {

View File

@ -2112,6 +2112,9 @@ mark_choicepoints(register choiceptr gc_B, tr_fr_ptr saved_TR, int very_verbose
nargs = 0;
break;
case _table_completion:
#ifdef THREADS_CONSUMER_SHARING
case _table_answer_resolution_completion:
#endif /* THREADS_CONSUMER_SHARING */
{
CELL *vars_ptr, vars;
#ifdef DETERMINISTIC_TABLING
@ -3035,6 +3038,9 @@ sweep_choicepoints(choiceptr gc_B USES_REGS)
}
break;
case _table_completion:
#ifdef THREADS_CONSUMER_SHARING
case _table_answer_resolution_completion:
#endif /* THREADS_CONSUMER_SHARING */
{
int nargs;
CELL *vars_ptr, vars;

View File

@ -27,6 +27,9 @@ static char SccsId[] = "%W% %G%";
#if HAVE_STRING_H
#include <string.h>
#endif
#ifdef TABLING
#include "tab.macros.h"
#endif /* TABLING */
#if THREADS
@ -174,6 +177,20 @@ kill_thread_engine (int wid, int always_die)
static void
thread_die(int wid, int always_die)
{
#ifdef TABLING
CACHE_REGS
tab_ent_ptr tab_ent;
tab_ent = GLOBAL_root_tab_ent;
while (tab_ent) {
abolish_table(tab_ent);
tab_ent = TabEnt_next(tab_ent);
}
FREE_DEPENDENCY_FRAME(LOCAL_top_dep_fr);
#endif /* TABLING */
#ifdef OUTPUT_THREADS_TABLING
fclose(LOCAL_thread_output);
#endif /* OUTPUT_THREADS_TABLING */
if (!always_die) {
/* called by thread itself */
GLOBAL_ThreadsTotalTime += Yap_cputime();
@ -208,7 +225,7 @@ setup_engine(int myworker_id, int init_thread)
DEBUG_TLOCK_ACCESS(2, myworker_id);
pthread_mutex_unlock(&(REMOTE_ThreadHandle(myworker_id).tlock));
#ifdef TABLING
DepFr_cons_cp(LOCAL_top_dep_fr) = B; /* same as in Yap_init_root_frames() */
new_dependency_frame(LOCAL_top_dep_fr, FALSE, NULL, NULL, B, NULL, FALSE, NULL); /* same as in Yap_init_root_frames() */
#endif /* TABLING */
return TRUE;
}
@ -226,7 +243,14 @@ thread_run(void *widp)
Term tgoal, t;
Term tgs[2];
int myworker_id = *((int *)widp);
#ifdef OUTPUT_THREADS_TABLING
char thread_name[25];
char filename[YAP_FILENAME_MAX];
sprintf(thread_name, "/thread_output_%d", myworker_id);
strcpy(filename, YAP_BINDIR);
strncat(filename, thread_name, 25);
LOCAL_thread_output = fopen(filename, "w");
#endif /* OUTPUT_THREADS_TABLING */
start_thread(myworker_id);
regcache = ((REGSTORE *)pthread_getspecific(Yap_yaamregs_key));
do {
@ -772,8 +796,8 @@ p_thread_stacks( USES_REGS1 )
Int status= TRUE;
LOCK(GLOBAL_ThreadHandlesLock);
if (!REMOTE_ThreadHandle(tid).in_use &&
!REMOTE_ThreadHandle(tid).zombie) {
if (!Yap_local[tid] ||
(!REMOTE_ThreadHandle(tid).in_use && !REMOTE_ThreadHandle(tid).zombie)) {
UNLOCK(GLOBAL_ThreadHandlesLock);
return FALSE;
}

View File

@ -344,6 +344,9 @@
OPCODE(table_new_answer ,s),
OPCODE(table_answer_resolution ,Otapl),
OPCODE(table_completion ,Otapl),
#ifdef THREADS_CONSUMER_SHARING
OPCODE(table_answer_resolution_completion,Otapl),
#endif
OPCODE(trie_do_var ,e),
OPCODE(trie_trust_var ,e),
OPCODE(trie_try_var ,e),

View File

@ -179,6 +179,9 @@
#define TRY_ANSWER Yap_heap_regs->table_try_answer_code
#define ANSWER_RESOLUTION Yap_heap_regs->table_answer_resolution_code
#define COMPLETION Yap_heap_regs->table_completion_code
#ifdef THREADS_CONSUMER_SHARING
#define ANSWER_RESOLUTION_COMPLETION Yap_heap_regs->table_answer_resolution_completion_code
#endif /* THREADS_CONSUMER_SHARING */
#endif /* TABLING */

View File

@ -179,6 +179,9 @@
yamop table_try_answer_code[1];
yamop table_answer_resolution_code[1];
yamop table_completion_code[1];
#ifdef THREADS_CONSUMER_SHARING
yamop table_answer_resolution_completion_code[1];
#endif /* THREADS_CONSUMER_SHARING */
#endif /* TABLING */

View File

@ -179,6 +179,9 @@
InitOtaplInst(TRY_ANSWER,_table_try_answer,PredFail);
InitOtaplInst(ANSWER_RESOLUTION,_table_answer_resolution,PredFail);
InitOtaplInst(COMPLETION,_table_completion,PredFail);
#ifdef THREADS_CONSUMER_SHARING
InitOtaplInst(ANSWER_RESOLUTION_COMPLETION,_table_answer_resolution_completion,PredFail);
#endif /* THREADS_CONSUMER_SHARING */
#endif /* TABLING */

View File

@ -815,6 +815,9 @@ restore_opcodes(yamop *pc, yamop *max USES_REGS)
/* instructions type Otapl */
case _table_answer_resolution:
case _table_completion:
#ifdef THREADS_CONSUMER_SHARING
case _table_answer_resolution_completion:
#endif /* THREADS_CONSUMER_SHARING */
case _table_load_answer:
case _table_retry:
case _table_retry_me:

View File

@ -179,6 +179,9 @@
RestoreOtaplInst(TRY_ANSWER,_table_try_answer,PredFail);
RestoreOtaplInst(ANSWER_RESOLUTION,_table_answer_resolution,PredFail);
RestoreOtaplInst(COMPLETION,_table_completion,PredFail);
#ifdef THREADS_CONSUMER_SHARING
RestoreOtaplInst(ANSWER_RESOLUTION_COMPLETION,_table_answer_resolution_completion,PredFail);
#endif /* THREADS_CONSUMER_SHARING */
#endif /* TABLING */

View File

@ -835,6 +835,9 @@
/* instructions type Otapl */
case _table_answer_resolution:
case _table_completion:
#ifdef THREADS_CONSUMER_SHARING
case _table_answer_resolution_completion:
#endif /* THREADS_CONSUMER_SHARING */
case _table_load_answer:
case _table_retry:
case _table_retry_me:

View File

@ -614,6 +614,9 @@
/* instructions type Otapl */
case _table_answer_resolution:
case _table_completion:
#ifdef THREADS_CONSUMER_SHARING
case _table_answer_resolution_completion:
#endif /* THREADS_CONSUMER_SHARING */
case _table_load_answer:
case _table_retry:
case _table_retry_me:

View File

@ -22,8 +22,9 @@
****************************/
#define MAX_TABLE_VARS 1000
#define TRIE_LOCK_BUCKETS 512
#define THREADS_FIRST_LEVEL_BUCKETS 16
#define THREADS_SECOND_LEVEL_BUCKETS (MAX_THREADS / THREADS_FIRST_LEVEL_BUCKETS) /* 64 (1024/16) */
#define THREADS_DIRECT_BUCKETS 32
#define THREADS_INDIRECT_BUCKETS ((MAX_THREADS - THREADS_DIRECT_BUCKETS) / THREADS_DIRECT_BUCKETS) /* (1024 - 32) / 32 = 31 */
#define THREADS_NUM_BUCKETS (THREADS_DIRECT_BUCKETS + THREADS_INDIRECT_BUCKETS)
#define TG_ANSWER_SLOTS 20
#define MAX_LENGTH_ANSWER 1000
#define MAX_BRANCH_DEPTH 1000
@ -48,9 +49,9 @@
/************************************************************************
** multithreading design for tabling (mandatory, define one) **
************************************************************************/
#define THREADS_NO_SHARING 1
/* #define THREADS_SUBGOAL_SHARING 1 */
/* #define THREADS_FULL_SHARING 1 */
//#define THREADS_NO_SHARING 1
#define THREADS_SUBGOAL_SHARING 1
//#define THREADS_FULL_SHARING 1
/* #define THREADS_CONSUMER_SHARING 1 */
/*************************************************************************
@ -327,11 +328,7 @@
#undef TIMESTAMP_CHECK
#endif
#if defined(TABLING) && defined(THREADS)
#if THREADS_FIRST_LEVEL_BUCKETS > THREADS_SECOND_LEVEL_BUCKETS
#error THREADS_FIRST_LEVEL_BUCKETS cannot exceed THREADS_SECOND_LEVEL_BUCKETS
#endif
#else
#if !defined(TABLING) || !defined(THREADS)
#undef OUTPUT_THREADS_TABLING
#endif
@ -344,10 +341,9 @@
#endif
#if defined(YAPOR) || defined(THREADS)
#undef MODE_DIRECTED_TABLING
#undef TABLING_EARLY_COMPLETION
#undef INCOMPLETE_TABLING
#undef LIMIT_TABLING
#undef DETERMINISTIC_TABLING
#endif

View File

@ -148,7 +148,7 @@ void Yap_init_global_optyap_data(int max_table_size, int n_workers, int sch_loop
GLOBAL_check_sg_fr = NULL;
#endif /* LIMIT_TABLING */
#ifdef YAPOR
new_dependency_frame(GLOBAL_root_dep_fr, FALSE, NULL, NULL, NULL, NULL, NULL);
new_dependency_frame(GLOBAL_root_dep_fr, FALSE, NULL, NULL, NULL, NULL, FALSE, NULL);
#endif /* YAPOR */
for (i = 0; i < MAX_TABLE_VARS; i++) {
CELL *pt = GLOBAL_table_var_enumerator_addr(i);
@ -165,7 +165,9 @@ void Yap_init_global_optyap_data(int max_table_size, int n_workers, int sch_loop
void Yap_init_local_optyap_data(int wid) {
#ifdef THREADS_CONSUMER_SHARING
CACHE_REGS
#endif /* THREADS_CONSUMER_SHARING */
#if defined(TABLING) && (defined(YAPOR) || defined(THREADS))
/* local data related to memory management */
@ -216,9 +218,13 @@ void Yap_init_local_optyap_data(int wid) {
REMOTE_top_dep_fr(wid) = GLOBAL_root_dep_fr;
Set_REMOTE_top_cp_on_stack(wid, (choiceptr) LOCAL_LocalBase); /* ??? */
REMOTE_top_susp_or_fr(wid) = GLOBAL_root_or_fr;
#else
new_dependency_frame(REMOTE_top_dep_fr(wid), FALSE, NULL, NULL, NULL, NULL, NULL);
#endif /* YAPOR */
#ifdef THREADS_CONSUMER_SHARING
ThDepFr_terminator(GLOBAL_th_dep_fr(wid)) = 0;
ThDepFr_next(GLOBAL_th_dep_fr(wid)) = wid;
ThDepFr_state(GLOBAL_th_dep_fr(wid)) = working;
INIT_LOCK(ThDepFr_lock(GLOBAL_th_dep_fr(wid)));
#endif /* THREADS_CONSUMER_SHARING */
#endif /* TABLING */
return;
}
@ -256,7 +262,7 @@ void Yap_init_root_frames(void) {
#ifdef YAPOR
DepFr_cons_cp(GLOBAL_root_dep_fr) = B; /* with YAPOR, at that point, LOCAL_top_dep_fr shouldn't be the same as GLOBAL_root_dep_fr ? */
#else
DepFr_cons_cp(LOCAL_top_dep_fr) = B;
new_dependency_frame(LOCAL_top_dep_fr, FALSE, NULL, NULL, B, NULL, FALSE, NULL);
#endif /* YAPOR */
#endif /* TABLING */
}

View File

@ -76,14 +76,19 @@ extern int Yap_page_size;
free(block_ptr); \
}
#endif /******************************************************************************/
#define ALLOC_HASH_BUCKETS(BUCKET_PTR, NUM_BUCKETS) \
{ int i; void **bucket_ptr; \
ALLOC_BLOCK(bucket_ptr, NUM_BUCKETS * sizeof(void *), void *); \
BUCKET_PTR = (void *) bucket_ptr; \
#define INIT_BUCKETS(BUCKET_PTR, NUM_BUCKETS) \
{ int i; void **init_bucket_ptr; \
init_bucket_ptr = (void **) BUCKET_PTR; \
for (i = NUM_BUCKETS; i != 0; i--) \
*bucket_ptr++ = NULL; \
*init_bucket_ptr++ = NULL; \
}
#define FREE_HASH_BUCKETS(BUCKET_PTR) FREE_BLOCK(BUCKET_PTR)
#define ALLOC_BUCKETS(BUCKET_PTR, NUM_BUCKETS) \
{ void **alloc_bucket_ptr; \
ALLOC_BLOCK(alloc_bucket_ptr, NUM_BUCKETS * sizeof(void *), void *); \
INIT_BUCKETS(alloc_bucket_ptr, NUM_BUCKETS); \
BUCKET_PTR = (void *) alloc_bucket_ptr; \
}
#define FREE_BUCKETS(BUCKET_PTR) FREE_BLOCK(BUCKET_PTR)
@ -435,3 +440,13 @@ extern int Yap_page_size;
#else
#define OPTYAP_ERROR_CHECKING(PROCEDURE,TEST)
#endif /* DEBUG_OPTYAP */
#ifdef OUTPUT_THREADS_TABLING
#define INFO_THREADS(MESSAGE, ARGS...) \
fprintf(LOCAL_thread_output, "[ " MESSAGE " ]\n", ##ARGS)
#define INFO_THREADS_MAIN_THREAD(MESSAGE, ARGS...) \
Sfprintf(Serror, "[ " MESSAGE " ]\n", ##ARGS)
#else
#define INFO_THREADS(MESG, ARGS...)
#define INFO_THREADS_MAIN_THREAD(MESSAGE, ARGS...)
#endif /* OUTPUT_THREADS_TABLING */

View File

@ -42,11 +42,9 @@ static Int p_table( USES_REGS1 );
static Int p_tabling_mode( USES_REGS1 );
static Int p_abolish_table( USES_REGS1 );
static Int p_abolish_all_tables( USES_REGS1 );
static Int p_abolish_all_local_tables( USES_REGS1 );
static Int p_show_tabled_predicates( USES_REGS1 );
static Int p_show_table( USES_REGS1 );
static Int p_show_all_tables( USES_REGS1 );
static Int p_show_all_local_tables( USES_REGS1 );
static Int p_show_global_trie( USES_REGS1 );
static Int p_show_statistics_table( USES_REGS1 );
static Int p_show_statistics_tabling( USES_REGS1 );
@ -185,7 +183,7 @@ struct page_statistics {
INCREMENT_PAGE_STATS(STATS, STR_PAGES(wid)); \
} \
} \
} \
} \
UNLOCK(GLOBAL_ThreadHandlesLock); \
Pg_bytes_in_use(STATS) = Pg_str_in_use(STATS) * sizeof(STR_TYPE)
@ -218,11 +216,9 @@ void Yap_init_optyap_preds(void) {
Yap_InitCPred("$c_tabling_mode", 3, p_tabling_mode, SafePredFlag|SyncPredFlag|HiddenPredFlag);
Yap_InitCPred("$c_abolish_table", 2, p_abolish_table, SafePredFlag|SyncPredFlag|HiddenPredFlag);
Yap_InitCPred("abolish_all_tables", 0, p_abolish_all_tables, SafePredFlag|SyncPredFlag);
Yap_InitCPred("abolish_all_local_tables", 0, p_abolish_all_local_tables, SafePredFlag|SyncPredFlag);
Yap_InitCPred("show_tabled_predicates", 1, p_show_tabled_predicates, SafePredFlag|SyncPredFlag);
Yap_InitCPred("$c_show_table", 3, p_show_table, SafePredFlag|SyncPredFlag|HiddenPredFlag);
Yap_InitCPred("show_all_tables", 1, p_show_all_tables, SafePredFlag|SyncPredFlag);
Yap_InitCPred("show_all_local_tables", 1, p_show_all_local_tables, SafePredFlag|SyncPredFlag);
Yap_InitCPred("show_global_trie", 1, p_show_global_trie, SafePredFlag|SyncPredFlag);
Yap_InitCPred("$c_table_statistics", 3, p_show_statistics_table, SafePredFlag|SyncPredFlag|HiddenPredFlag);
Yap_InitCPred("tabling_statistics", 1, p_show_statistics_tabling, SafePredFlag|SyncPredFlag);
@ -467,8 +463,6 @@ static Int p_tabling_mode( USES_REGS1 ) {
static Int p_abolish_table( USES_REGS1 ) {
Term mod, t;
tab_ent_ptr tab_ent;
sg_hash_ptr hash;
sg_node_ptr sg_node;
mod = Deref(ARG1);
t = Deref(ARG2);
@ -478,67 +472,23 @@ static Int p_abolish_table( USES_REGS1 ) {
tab_ent = RepPredProp(PredPropByFunc(FunctorOfTerm(t), mod))->TableOfPred;
else
return (FALSE);
hash = TabEnt_hash_chain(tab_ent);
TabEnt_hash_chain(tab_ent) = NULL;
free_subgoal_hash_chain(hash);
sg_node = TrNode_child(TabEnt_subgoal_trie(tab_ent));
if (sg_node) {
if (TabEnt_arity(tab_ent)) {
free_subgoal_trie(sg_node, TRAVERSE_MODE_NORMAL, TRAVERSE_POSITION_FIRST);
} else {
sg_fr_ptr sg_fr = UNTAG_SUBGOAL_LEAF_NODE(sg_node);
FREE_ANSWER_TRIE_NODE(SgFr_answer_trie(sg_fr));
#ifdef LIMIT_TABLING
remove_from_global_sg_fr_list(sg_fr);
#endif /* LIMIT_TABLING */
FREE_SUBGOAL_FRAME(sg_fr);
}
TrNode_child(TabEnt_subgoal_trie(tab_ent)) = NULL;
}
abolish_table(tab_ent);
return (TRUE);
}
static Int p_abolish_all_tables( USES_REGS1 ) {
tab_ent_ptr tab_ent;
sg_hash_ptr hash;
sg_node_ptr sg_node;
tab_ent = GLOBAL_root_tab_ent;
while (tab_ent) {
hash = TabEnt_hash_chain(tab_ent);
TabEnt_hash_chain(tab_ent) = NULL;
free_subgoal_hash_chain(hash);
sg_node = TrNode_child(TabEnt_subgoal_trie(tab_ent));
if (sg_node) {
if (TabEnt_arity(tab_ent)) {
free_subgoal_trie(sg_node, TRAVERSE_MODE_NORMAL, TRAVERSE_POSITION_FIRST);
} else {
sg_fr_ptr sg_fr = UNTAG_SUBGOAL_LEAF_NODE(sg_node);
FREE_ANSWER_TRIE_NODE(SgFr_answer_trie(sg_fr));
#ifdef LIMIT_TABLING
remove_from_global_sg_fr_list(sg_fr);
#endif /* LIMIT_TABLING */
FREE_SUBGOAL_FRAME(sg_fr);
}
TrNode_child(TabEnt_subgoal_trie(tab_ent)) = NULL;
}
abolish_table(tab_ent);
tab_ent = TabEnt_next(tab_ent);
}
return (TRUE);
}
static Int p_abolish_all_local_tables( USES_REGS1 ) {
#ifdef THREADS
p_abolish_all_tables( PASS_REGS1 );
#else
p_abolish_all_tables();
#endif /* THREADS */
return (TRUE);
}
static Int p_show_tabled_predicates( USES_REGS1 ) {
IOSTREAM *out;
tab_ent_ptr tab_ent;
@ -597,26 +547,6 @@ static Int p_show_all_tables( USES_REGS1 ) {
}
static Int p_show_all_local_tables( USES_REGS1 ) {
#ifdef THREADS
IOSTREAM *out;
tab_ent_ptr tab_ent;
if (!PL_get_stream_handle(Yap_InitSlot(Deref(ARG1) PASS_REGS), &out))
return (FALSE);
tab_ent = GLOBAL_root_tab_ent;
while(tab_ent) {
show_table(tab_ent, SHOW_MODE_STRUCTURE, out);
tab_ent = TabEnt_next(tab_ent);
}
PL_release_stream(out);
#else
p_show_all_tables();
#endif /* THREADS */
return (TRUE);
}
static Int p_show_global_trie( USES_REGS1 ) {
IOSTREAM *out;
@ -1197,12 +1127,14 @@ static inline struct page_statistics show_statistics_table_entries(IOSTREAM *out
SHOW_GLOBAL_PAGE_STATS(out, struct table_entry, GLOBAL_pages_tab_ent, "Table entries: ");
}
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
static inline struct page_statistics show_statistics_subgoal_entries(IOSTREAM *out) {
SHOW_GLOBAL_PAGE_STATS(out, struct subgoal_entry, GLOBAL_pages_sg_ent, "Subgoal entries: ");
}
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
static inline struct page_statistics show_statistics_subgoal_frames(IOSTREAM *out) {
#if !defined(THREADS_NO_SHARING) && !defined(THREADS_SUBGOAL_SHARING) && !defined(THREADS_FULL_SHARING) && !defined(THREADS_CONSUMER_SHARING)
SHOW_GLOBAL_PAGE_STATS(out, struct subgoal_frame, GLOBAL_pages_sg_fr, "Subgoal frames: ");
@ -1211,6 +1143,7 @@ static inline struct page_statistics show_statistics_subgoal_frames(IOSTREAM *ou
#endif
}
static inline struct page_statistics show_statistics_dependency_frames(IOSTREAM *out) {
#if !defined(THREADS_NO_SHARING) && !defined(THREADS_SUBGOAL_SHARING) && !defined(THREADS_FULL_SHARING) && !defined(THREADS_CONSUMER_SHARING)
SHOW_GLOBAL_PAGE_STATS(out, struct dependency_frame, GLOBAL_pages_dep_fr, "Dependency frames: ");
@ -1219,6 +1152,7 @@ static inline struct page_statistics show_statistics_dependency_frames(IOSTREAM
#endif
}
static inline struct page_statistics show_statistics_subgoal_trie_nodes(IOSTREAM *out) {
#if !defined(THREADS_NO_SHARING)
SHOW_GLOBAL_PAGE_STATS(out, struct subgoal_trie_node, GLOBAL_pages_sg_node, "Subgoal trie nodes: ");
@ -1227,6 +1161,7 @@ static inline struct page_statistics show_statistics_subgoal_trie_nodes(IOSTREAM
#endif
}
static inline struct page_statistics show_statistics_subgoal_trie_hashes(IOSTREAM *out) {
#if !defined(THREADS_NO_SHARING)
SHOW_GLOBAL_PAGE_STATS(out, struct subgoal_trie_hash, GLOBAL_pages_sg_hash, "Subgoal trie hashes: ");
@ -1235,6 +1170,7 @@ static inline struct page_statistics show_statistics_subgoal_trie_hashes(IOSTREA
#endif
}
static inline struct page_statistics show_statistics_answer_trie_nodes(IOSTREAM *out) {
#if !defined(THREADS_NO_SHARING) && !defined(THREADS_SUBGOAL_SHARING)
SHOW_GLOBAL_PAGE_STATS(out, struct answer_trie_node, GLOBAL_pages_ans_node, "Answer trie nodes: ");
@ -1243,6 +1179,7 @@ static inline struct page_statistics show_statistics_answer_trie_nodes(IOSTREAM
#endif
}
static inline struct page_statistics show_statistics_answer_trie_hashes(IOSTREAM *out) {
#if !defined(THREADS_NO_SHARING) && !defined(THREADS_SUBGOAL_SHARING)
SHOW_GLOBAL_PAGE_STATS(out, struct answer_trie_hash, GLOBAL_pages_ans_hash, "Answer trie hashes: ");
@ -1251,16 +1188,19 @@ static inline struct page_statistics show_statistics_answer_trie_hashes(IOSTREAM
#endif
}
#if defined(THREADS_FULL_SHARING)
static inline struct page_statistics show_statistics_answer_ref_nodes(IOSTREAM *out) {
SHOW_GLOBAL_PAGE_STATS(out, struct answer_ref_node, REMOTE_pages_ans_ref_node, "Answer ref nodes: ");
SHOW_REMOTE_PAGE_STATS(out, struct answer_ref_node, REMOTE_pages_ans_ref_node, "Answer ref nodes: ");
}
#endif /* THREADS_FULL_SHARING */
static inline struct page_statistics show_statistics_global_trie_nodes(IOSTREAM *out) {
SHOW_GLOBAL_PAGE_STATS(out, struct global_trie_node, GLOBAL_pages_gt_node, "Global trie nodes: ");
}
static inline struct page_statistics show_statistics_global_trie_hashes(IOSTREAM *out) {
SHOW_GLOBAL_PAGE_STATS(out, struct global_trie_hash, GLOBAL_pages_gt_hash, "Global trie hashes: ");
}
@ -1272,10 +1212,12 @@ static inline struct page_statistics show_statistics_or_frames(IOSTREAM *out) {
SHOW_GLOBAL_PAGE_STATS(out, struct or_frame, GLOBAL_pages_or_fr, "Or-frames: ");
}
static inline struct page_statistics show_statistics_query_goal_solution_frames(IOSTREAM *out) {
SHOW_GLOBAL_PAGE_STATS(out, struct query_goal_solution_frame, GLOBAL_pages_qg_sol_fr, "Query goal solution frames: ");
}
static inline struct page_statistics show_statistics_query_goal_answer_frames(IOSTREAM *out) {
SHOW_GLOBAL_PAGE_STATS(out, struct query_goal_answer_frame, GLOBAL_pages_qg_ans_fr, "Query goal answer frames: ");
}
@ -1287,11 +1229,13 @@ static inline struct page_statistics show_statistics_suspension_frames(IOSTREAM
SHOW_GLOBAL_PAGE_STATS(out, struct suspension_frame, GLOBAL_pages_susp_fr, "Suspension frames: ");
}
#ifdef TABLING_INNER_CUTS
static inline struct page_statistics show_statistics_table_subgoal_solution_frames(IOSTREAM *out) {
SHOW_GLOBAL_PAGE_STATS(out, struct table_subgoal_solution_frame, GLOBAL_pages_tg_sol_fr, "Table subgoal solution frames:");
}
static inline struct page_statistics show_statistics_table_subgoal_answer_frames(IOSTREAM *out) {
SHOW_GLOBAL_PAGE_STATS(out, struct table_subgoal_answer_frame, GLOBAL_pages_tg_ans_fr, "Table subgoal answer frames: ");
}

View File

@ -53,8 +53,8 @@ CELL *exec_substitution(gt_node_ptr, CELL *);
void update_answer_trie(sg_fr_ptr);
void free_subgoal_trie(sg_node_ptr, int, int);
void free_answer_trie(ans_node_ptr, int, int);
void free_subgoal_hash_chain(sg_hash_ptr);
void free_answer_hash_chain(ans_hash_ptr);
void abolish_table(tab_ent_ptr);
void show_table(tab_ent_ptr, int, IOSTREAM *);
void show_global_trie(int, IOSTREAM *);
#endif /* TABLING */

View File

@ -466,6 +466,9 @@ struct local_optyap_data {
#endif /* YAPOR_THREADS */
struct or_frame *top_or_frame_with_suspensions;
#endif /* YAPOR */
#ifdef OUTPUT_THREADS_TABLING
FILE *thread_output;
#endif /* OUTPUT_THREADS_TABLING */
#endif /* TABLING */
#if (defined(TABLING) || !defined(YAPOR_COW)) && defined(MULTI_ASSIGNMENT_VARIABLES)
@ -529,6 +532,7 @@ struct local_optyap_data {
#define Set_LOCAL_top_cp_on_stack(cpt) (LOCAL_optyap_data.top_choice_point_on_stack = cpt)
#endif /* YAPOR_THREADS */
#define LOCAL_top_susp_or_fr (LOCAL_optyap_data.top_or_frame_with_suspensions)
#define LOCAL_thread_output (LOCAL_optyap_data.thread_output)
#define LOCAL_ma_timestamp (LOCAL_optyap_data.ma_timestamp)
#define LOCAL_ma_h_top (LOCAL_optyap_data.ma_h_top)
#define LOCAL_ma_hash_table (LOCAL_optyap_data.ma_hash_table)
@ -585,7 +589,10 @@ struct local_optyap_data {
#define Set_REMOTE_top_cp_on_stack(wid, bptr) (REMOTE(wid)->optyap_data_.top_choice_point_on_stack = (bptr))
#endif /* YAPOR_THREADS */
#define REMOTE_top_susp_or_fr(wid) (REMOTE(wid)->optyap_data_.top_or_frame_with_suspensions)
#define REMOTE_thread_output(wid) (REMOTE(wid)->optyap_data_.thread_output)
#define REMOTE_ma_timestamp(wid) (REMOTE(wid)->optyap_data_.ma_timestamp)
#define REMOTE_ma_h_top(wid) (REMOTE(wid)->optyap_data_.ma_h_top)
#define REMOTE_ma_hash_table(wid) (REMOTE(wid)->optyap_data_.ma_hash_table)
#ifdef YAPOR
#include "or.structs.h"

View File

@ -105,6 +105,7 @@ static void complete_suspension_branch(susp_fr_ptr susp_fr, choiceptr top_cp, or
void private_completion(sg_fr_ptr sg_fr) {
CACHE_REGS
/* complete subgoals */
#ifdef LIMIT_TABLING
sg_fr_ptr aux_sg_fr;
@ -137,6 +138,11 @@ void private_completion(sg_fr_ptr sg_fr) {
/* adjust freeze registers */
adjust_freeze_registers();
/* adjust thread dependency */
#ifdef THREADS_CONSUMER_SHARING
ThDepFr_state(GLOBAL_th_dep_fr(worker_id)) = working;
ThDepFr_next(GLOBAL_th_dep_fr(worker_id)) = worker_id;
#endif /* THREADS_CONSUMER_SHARING */
return;
}

View File

@ -22,58 +22,58 @@
#define store_low_level_trace_info(CP, TAB_ENT)
#endif /* LOW_LEVEL_TRACER */
#define TABLING_ERROR_CHECKING_STACK \
TABLING_ERROR_CHECKING(store_node, Unsigned(H) + 1024 > Unsigned(B)); \
#define TABLING_ERROR_CHECKING_STACK \
TABLING_ERROR_CHECKING(store_node, Unsigned(H) + 1024 > Unsigned(B)); \
TABLING_ERROR_CHECKING(store_node, Unsigned(H_FZ) + 1024 > Unsigned(B))
#define store_generator_node(TAB_ENT, SG_FR, ARITY, AP) \
{ register CELL *pt_args; \
register choiceptr gcp; \
/* store args */ \
pt_args = XREGS + (ARITY); \
while (pt_args > XREGS) { \
register CELL aux_arg = pt_args[0]; \
--YENV; \
--pt_args; \
*YENV = aux_arg; \
} \
/* initialize gcp and adjust subgoal frame field */ \
YENV = (CELL *) (GEN_CP(YENV) - 1); \
gcp = NORM_CP(YENV); \
SgFr_gen_cp(SG_FR) = gcp; \
/* store generator choice point */ \
HBREG = H; \
store_yaam_reg_cpdepth(gcp); \
gcp->cp_tr = TR; \
gcp->cp_ap = (yamop *)(AP); \
gcp->cp_h = H; \
gcp->cp_b = B; \
gcp->cp_env = ENV; \
gcp->cp_cp = CPREG; \
if (IsMode_Local(TabEnt_mode(TAB_ENT))) { \
/* go local */ \
register dep_fr_ptr new_dep_fr; \
/* adjust freeze registers */ \
H_FZ = H; \
B_FZ = gcp; \
TR_FZ = TR; \
/* store dependency frame */ \
new_dependency_frame(new_dep_fr, TRUE, LOCAL_top_or_fr, \
gcp, gcp, SG_FR, LOCAL_top_dep_fr); \
LOCAL_top_dep_fr = new_dep_fr; \
GEN_CP(gcp)->cp_dep_fr = LOCAL_top_dep_fr; \
} else { \
/* go batched */ \
GEN_CP(gcp)->cp_dep_fr = NULL; \
} \
GEN_CP(gcp)->cp_sg_fr = SG_FR; \
store_low_level_trace_info(GEN_CP(gcp), TAB_ENT); \
set_cut((CELL *)gcp, B); \
B = gcp; \
YAPOR_SET_LOAD(B); \
SET_BB(B); \
TABLING_ERROR_CHECKING_STACK; \
#define store_generator_node(TAB_ENT, SG_FR, ARITY, AP) \
{ register CELL *pt_args; \
register choiceptr gcp; \
/* store args */ \
pt_args = XREGS + (ARITY); \
while (pt_args > XREGS) { \
register CELL aux_arg = pt_args[0]; \
--YENV; \
--pt_args; \
*YENV = aux_arg; \
} \
/* initialize gcp and adjust subgoal frame field */ \
YENV = (CELL *) (GEN_CP(YENV) - 1); \
gcp = NORM_CP(YENV); \
SgFr_gen_cp(SG_FR) = gcp; \
/* store generator choice point */ \
HBREG = H; \
store_yaam_reg_cpdepth(gcp); \
gcp->cp_tr = TR; \
gcp->cp_ap = (yamop *)(AP); \
gcp->cp_h = H; \
gcp->cp_b = B; \
gcp->cp_env = ENV; \
gcp->cp_cp = CPREG; \
if (IsMode_Local(TabEnt_mode(TAB_ENT))) { \
/* go local */ \
register dep_fr_ptr new_dep_fr; \
/* adjust freeze registers */ \
H_FZ = H; \
B_FZ = gcp; \
TR_FZ = TR; \
/* store dependency frame */ \
new_dependency_frame(new_dep_fr, TRUE, LOCAL_top_or_fr, gcp, \
gcp, SG_FR, FALSE, LOCAL_top_dep_fr); \
LOCAL_top_dep_fr = new_dep_fr; \
GEN_CP(gcp)->cp_dep_fr = LOCAL_top_dep_fr; \
} else { \
/* go batched */ \
GEN_CP(gcp)->cp_dep_fr = NULL; \
} \
GEN_CP(gcp)->cp_sg_fr = SG_FR; \
store_low_level_trace_info(GEN_CP(gcp), TAB_ENT); \
set_cut((CELL *)gcp, B); \
B = gcp; \
YAPOR_SET_LOAD(B); \
SET_BB(B); \
TABLING_ERROR_CHECKING_STACK; \
}
@ -102,6 +102,52 @@
#endif /* DETERMINISTIC_TABLING */
#ifdef THREADS_CONSUMER_SHARING
#define store_generator_consumer_node(TAB_ENT, SG_FR, DEP_ON_STACK,ARITY) \
{ register CELL *pt_args; \
register choiceptr gccp; \
register dep_fr_ptr new_dep_fr; \
/* store args */ \
pt_args = XREGS + (ARITY); \
while (pt_args > XREGS) { \
register CELL aux_arg = pt_args[0]; \
--YENV; \
--pt_args; \
*YENV = aux_arg; \
} \
/* initialize gcp and adjust subgoal frame field */ \
YENV = (CELL *) (GEN_CP(YENV) - 1); \
gccp = NORM_CP(YENV); \
SgFr_gen_cp(SG_FR) = gccp; \
/* store generator choice point */ \
HBREG = H; \
store_yaam_reg_cpdepth(gccp); \
gccp->cp_tr = TR; \
gccp->cp_ap = ANSWER_RESOLUTION_COMPLETION; \
gccp->cp_h = H; \
gccp->cp_b = B; \
gccp->cp_env = ENV; \
gccp->cp_cp = CPREG; \
/* store dependency frame */ \
new_dependency_frame(new_dep_fr, DEP_ON_STACK, LOCAL_top_or_fr, \
gccp, gccp, SG_FR, TRUE, LOCAL_top_dep_fr); \
LOCAL_top_dep_fr = new_dep_fr; \
GEN_CP(gccp)->cp_dep_fr = LOCAL_top_dep_fr; \
GEN_CP(gccp)->cp_sg_fr = SG_FR; \
/* adjust freeze registers */ \
H_FZ = H; \
B_FZ = gccp; \
TR_FZ = TR; \
store_low_level_trace_info(GEN_CP(gccp), TAB_ENT); \
set_cut((CELL *)gccp, B); \
B = gccp; \
YAPOR_SET_LOAD(B); \
SET_BB(B); \
TABLING_ERROR_CHECKING_STACK; \
}
#endif /* THREADS_CONSUMER_SHARING */
#define restore_generator_node(ARITY, AP) \
{ register CELL *pt_args, *x_args; \
register choiceptr gcp = B; \
@ -149,39 +195,65 @@
}
#define store_consumer_node(TAB_ENT, SG_FR, LEADER_CP, DEP_ON_STACK) \
{ register choiceptr ccp; \
register dep_fr_ptr new_dep_fr; \
/* initialize ccp */ \
YENV = (CELL *) (CONS_CP(YENV) - 1); \
ccp = NORM_CP(YENV); \
/* adjust freeze registers */ \
H_FZ = H; \
B_FZ = ccp; \
TR_FZ = TR; \
/* store dependency frame */ \
new_dependency_frame(new_dep_fr, DEP_ON_STACK, LOCAL_top_or_fr, \
LEADER_CP, ccp, SG_FR, LOCAL_top_dep_fr); \
LOCAL_top_dep_fr = new_dep_fr; \
/* store consumer choice point */ \
HBREG = H; \
store_yaam_reg_cpdepth(ccp); \
ccp->cp_tr = TR; \
ccp->cp_ap = ANSWER_RESOLUTION; \
ccp->cp_h = H; \
ccp->cp_b = B; \
ccp->cp_env= ENV; \
ccp->cp_cp = CPREG; \
CONS_CP(ccp)->cp_dep_fr = LOCAL_top_dep_fr; \
store_low_level_trace_info(CONS_CP(ccp), TAB_ENT); \
/* set_cut((CELL *)ccp, B); --> no effect */ \
B = ccp; \
YAPOR_SET_LOAD(B); \
SET_BB(B); \
TABLING_ERROR_CHECKING_STACK; \
#define store_consumer_node(TAB_ENT, SG_FR, LEADER_CP, DEP_ON_STACK) \
{ register choiceptr ccp; \
register dep_fr_ptr new_dep_fr; \
/* initialize ccp */ \
YENV = (CELL *) (CONS_CP(YENV) - 1); \
ccp = NORM_CP(YENV); \
/* adjust freeze registers */ \
H_FZ = H; \
B_FZ = ccp; \
TR_FZ = TR; \
/* store dependency frame */ \
new_dependency_frame(new_dep_fr, DEP_ON_STACK, LOCAL_top_or_fr, \
LEADER_CP, ccp, SG_FR, FALSE, LOCAL_top_dep_fr); \
LOCAL_top_dep_fr = new_dep_fr; \
/* store consumer choice point */ \
HBREG = H; \
store_yaam_reg_cpdepth(ccp); \
ccp->cp_tr = TR; \
ccp->cp_ap = ANSWER_RESOLUTION; \
ccp->cp_h = H; \
ccp->cp_b = B; \
ccp->cp_env= ENV; \
ccp->cp_cp = CPREG; \
CONS_CP(ccp)->cp_dep_fr = LOCAL_top_dep_fr; \
store_low_level_trace_info(CONS_CP(ccp), TAB_ENT); \
/* set_cut((CELL *)ccp, B); --> no effect */ \
B = ccp; \
YAPOR_SET_LOAD(B); \
SET_BB(B); \
TABLING_ERROR_CHECKING_STACK; \
}
#ifdef THREADS_CONSUMER_SHARING
#define consume_answer_and_procceed(DEP_FR, ANSWER) \
{ CELL *subs_ptr; \
/* restore consumer choice point */ \
H = HBREG = PROTECT_FROZEN_H(B); \
restore_yaam_reg_cpdepth(B); \
CPREG = B->cp_cp; \
ENV = B->cp_env; \
/* set_cut(YENV, B->cp_b); --> no effect */ \
PREG = (yamop *) CPREG; \
PREFETCH_OP(PREG); \
/* load answer from table to global stack */ \
if (B == DepFr_leader_cp(DEP_FR) || DepFr_external(DEP_FR)) { \
/* B is a generator-consumer node */ \
TABLING_ERROR_CHECKING(generator_consumer, IS_BATCHED_GEN_CP(B)); \
subs_ptr = (CELL *) (GEN_CP(B) + 1); \
subs_ptr += SgFr_arity(GEN_CP(B)->cp_sg_fr); \
} else { \
subs_ptr = (CELL *) (CONS_CP(B) + 1); \
} \
load_answer(ANSWER, subs_ptr); \
/* procceed */ \
YENV = ENV; \
GONext(); \
}
#else
#define consume_answer_and_procceed(DEP_FR, ANSWER) \
{ CELL *subs_ptr; \
/* restore consumer choice point */ \
@ -207,6 +279,7 @@
YENV = ENV; \
GONext(); \
}
#endif /* THREADS_CONSUMER_SHARING */
#define store_loader_node(TAB_ENT, ANSWER) \
@ -401,7 +474,27 @@
YENV2MEM;
sg_fr = subgoal_search(PREG, YENV_ADDRESS);
MEM2YENV;
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
if (SgFr_state(sg_fr) <= ready) {
LOCK_SG_FR(sg_fr);
if (SgFr_sg_ent_state(sg_fr) >= complete)
SgFr_state(sg_fr) = SgFr_sg_ent_state(sg_fr);
else
SgFr_active_workers(sg_fr)++;
UNLOCK_SG_FR(sg_fr);
}
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
LOCK_SG_FR(sg_fr);
#ifdef THREADS_CONSUMER_SHARING
if (SgFr_state(sg_fr) == ready_external) {
init_subgoal_frame(sg_fr);
store_generator_consumer_node(tab_ent, sg_fr, TRUE, PREG->u.Otapl.s);
PREFETCH_OP(PREG);
allocate_environment();
check_for_deadlock(sg_fr);
goto answer_resolution_completion;
} else
#endif /* THREADS_CONSUMER_SHARING */
if (SgFr_state(sg_fr) == ready) {
/* subgoal new */
init_subgoal_frame(sg_fr);
@ -478,7 +571,11 @@
TRAIL_FRAME(sg_fr);
}
#endif /* LIMIT_TABLING */
if (IsMode_LoadAnswers(TabEnt_mode(tab_ent))) {
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
if (IsMode_LoadAnswers(TabEnt_mode(tab_ent)) || SgFr_active_workers(sg_fr) > 0) {
#else
if (IsMode_LoadAnswers(TabEnt_mode(tab_ent))) {
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
/* load answers from the trie */
UNLOCK_SG_FR(sg_fr);
if(TrNode_child(ans_node) != NULL) {
@ -491,7 +588,11 @@
GONext();
} else {
/* execute compiled code from the trie */
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
if (SgFr_sg_ent_state(sg_fr) < compiled)
#else
if (SgFr_state(sg_fr) < compiled)
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
update_answer_trie(sg_fr);
UNLOCK_SG_FR(sg_fr);
PREG = (yamop *) TrNode_child(SgFr_answer_trie(sg_fr));
@ -519,7 +620,28 @@
YENV2MEM;
sg_fr = subgoal_search(PREG, YENV_ADDRESS);
MEM2YENV;
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
if (SgFr_state(sg_fr) <= ready) {
LOCK_SG_FR(sg_fr);
if (SgFr_sg_ent_state(sg_fr) >= complete)
SgFr_state(sg_fr) = SgFr_sg_ent_state(sg_fr);
else
SgFr_active_workers(sg_fr)++;
UNLOCK_SG_FR(sg_fr);
}
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
LOCK_SG_FR(sg_fr);
#ifdef THREADS_CONSUMER_SHARING
if (SgFr_state(sg_fr) == ready_external) {
init_subgoal_frame(sg_fr);
UNLOCK_SG_FR(sg_fr);
store_generator_consumer_node(tab_ent, sg_fr, TRUE, PREG->u.Otapl.s);
PREFETCH_OP(PREG);
allocate_environment();
check_for_deadlock(sg_fr);
goto answer_resolution_completion;
} else
#endif /* THREADS_CONSUMER_SHARING */
if (SgFr_state(sg_fr) == ready) {
/* subgoal new */
init_subgoal_frame(sg_fr);
@ -589,7 +711,11 @@
TRAIL_FRAME(sg_fr);
}
#endif /* LIMIT_TABLING */
if (IsMode_LoadAnswers(TabEnt_mode(tab_ent))) {
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
if (IsMode_LoadAnswers(TabEnt_mode(tab_ent)) || SgFr_active_workers(sg_fr) > 0) {
#else
if (IsMode_LoadAnswers(TabEnt_mode(tab_ent))) {
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
/* load answers from the trie */
UNLOCK_SG_FR(sg_fr);
if(TrNode_child(ans_node) != NULL) {
@ -602,7 +728,11 @@
GONext();
} else {
/* execute compiled code from the trie */
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
if (SgFr_sg_ent_state(sg_fr) < compiled)
#else
if (SgFr_state(sg_fr) < compiled)
#endif /*THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING*/
update_answer_trie(sg_fr);
UNLOCK_SG_FR(sg_fr);
PREG = (yamop *) TrNode_child(SgFr_answer_trie(sg_fr));
@ -630,7 +760,28 @@
YENV2MEM;
sg_fr = subgoal_search(PREG, YENV_ADDRESS);
MEM2YENV;
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
if (SgFr_state(sg_fr) <= ready) {
LOCK_SG_FR(sg_fr);
if (SgFr_sg_ent_state(sg_fr) >= complete)
SgFr_state(sg_fr) = SgFr_sg_ent_state(sg_fr);
else
SgFr_active_workers(sg_fr)++;
UNLOCK_SG_FR(sg_fr);
}
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
LOCK_SG_FR(sg_fr);
#ifdef THREADS_CONSUMER_SHARING
if (SgFr_state(sg_fr) == ready_external) {
init_subgoal_frame(sg_fr);
UNLOCK_SG_FR(sg_fr);
store_generator_consumer_node(tab_ent, sg_fr, TRUE , PREG->u.Otapl.s);
PREFETCH_OP(PREG);
allocate_environment();
check_for_deadlock(sg_fr);
goto answer_resolution_completion;
} else
#endif /* THREADS_CONSUMER_SHARING */
if (SgFr_state(sg_fr) == ready) {
/* subgoal new */
init_subgoal_frame(sg_fr);
@ -700,7 +851,11 @@
TRAIL_FRAME(sg_fr);
}
#endif /* LIMIT_TABLING */
if (IsMode_LoadAnswers(TabEnt_mode(tab_ent))) {
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
if (IsMode_LoadAnswers(TabEnt_mode(tab_ent)) || SgFr_active_workers(sg_fr) > 0) {
#else
if (IsMode_LoadAnswers(TabEnt_mode(tab_ent))) {
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
/* load answers from the trie */
UNLOCK_SG_FR(sg_fr);
if(TrNode_child(ans_node) != NULL) {
@ -713,7 +868,11 @@
GONext();
} else {
/* execute compiled code from the trie */
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
if (SgFr_sg_ent_state(sg_fr) < compiled)
#else
if (SgFr_state(sg_fr) < compiled)
#endif /*THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
update_answer_trie(sg_fr);
UNLOCK_SG_FR(sg_fr);
PREG = (yamop *) TrNode_child(SgFr_answer_trie(sg_fr));
@ -997,6 +1156,14 @@
}
#endif /* TABLING_INNER_CUTS */
TAG_AS_ANSWER_LEAF_NODE(ans_node);
#ifdef THREADS_FULL_SHARING
INFO_THREADS("new answer (1) sgfr=%p ans_node=%p",SgFr_sg_ent(sg_fr),ans_node);
if (IsMode_Batched(TabEnt_mode(SgFr_tab_ent(sg_fr)))) {
ANSWER_LEAF_NODE_INSTR_RELATIVE(ans_node);
if (worker_id < ANSWER_LEAF_NODE_MAX_THREADS)
ANSWER_LEAF_NODE_SET_WID(ans_node,worker_id);
}
#endif /* THREADS_FULL_SHARING */
UNLOCK_ANSWER_NODE(ans_node);
#ifndef ANSWER_TRIE_LOCK_AT_ENTRY_LEVEL
LOCK_SG_FR(sg_fr);
@ -1017,6 +1184,10 @@
#endif /* DEBUG_TABLING */
UNLOCK_SG_FR(sg_fr);
if (IS_BATCHED_GEN_CP(gcp)) {
#ifdef THREADS_FULL_SHARING
if (worker_id >= ANSWER_LEAF_NODE_MAX_THREADS)
SgFr_batched_cached_answers_check_insert(sg_fr,ans_node); //add to buffer all answers except the ans_node
#endif /* THREADS_FULL_SHARING */
#ifdef TABLING_EARLY_COMPLETION
if (gcp == PROTECT_FROZEN_B(B) && (*subs_ptr == 0 || gcp->cp_ap == COMPLETION)) {
/* if the current generator choice point is the topmost choice point and the current */
@ -1059,8 +1230,55 @@
}
} else {
/* repeated answer */
#ifdef THREADS_FULL_SHARING
if (IsMode_Batched(TabEnt_mode(SgFr_tab_ent(sg_fr)))){
if (worker_id >= ANSWER_LEAF_NODE_MAX_THREADS) {
UNLOCK_ANSWER_NODE(ans_node);
UNLOCK_ANSWER_TRIE(sg_fr);
SgFr_batched_cached_answers_check_insert(sg_fr,NULL);
INFO_THREADS("new answer (2) sgfr=%p ans_node=%p",SgFr_sg_ent(sg_fr),ans_node);
if (SgFr_batched_cached_answers_check_remove(sg_fr , ans_node) == 1){
INFO_THREADS("ans_node=%p not found", ans_node);
goto fail;
}
/* deallocate and procceed */
PREG = (yamop *) YENV[E_CP];
PREFETCH_OP(PREG);
CPREG = PREG;
SREG = YENV;
ENV = YENV = (CELL *) YENV[E_E];
#ifdef DEPTH_LIMIT
DEPTH = YENV[E_DEPTH];
#endif /*DEPTH_LIMIT */
GONext();
} else {
if (!ANSWER_LEAF_NODE_CHECK_WID(ans_node,worker_id)){
ANSWER_LEAF_NODE_SET_WID(ans_node,worker_id);
UNLOCK_ANSWER_NODE(ans_node);
UNLOCK_ANSWER_TRIE(sg_fr);
/* deallocate and procceed */
INFO_THREADS("new answer (2) sgfr=%p ans_node=%p",SgFr_sg_ent(sg_fr),ans_node);
PREG = (yamop *) YENV[E_CP];
PREFETCH_OP(PREG);
CPREG = PREG;
SREG = YENV;
ENV = YENV = (CELL *) YENV[E_E];
#ifdef DEPTH_LIMIT
DEPTH = YENV[E_DEPTH];
#endif /*DEPTH_LIMIT */
GONext();
}
}
}
#else
UNLOCK_ANSWER_NODE(ans_node);
UNLOCK_ANSWER_TRIE(sg_fr);
#endif /* THREADS_FULL_SHARING */
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
INFO_THREADS("new answer(rep) sgfr=%p ans_node=%p",SgFr_sg_ent(sg_fr),ans_node);
#else
INFO_THREADS("new answer(rep) sgfr=%p ans_node=%p",sg_fr,ans_node);
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
goto fail;
}
ENDPBOp();
@ -1092,13 +1310,13 @@
if (TrNode_child(ans_node)) {
/* unconsumed answers */
#ifdef MODE_DIRECTED_TABLING
if (IS_INVALID_LEAF_NODE(TrNode_child(ans_node))) {
if (IS_ANSWER_INVALID_NODE(TrNode_child(ans_node))) {
ans_node_ptr old_ans_node;
old_ans_node = ans_node;
ans_node = TrNode_child(ans_node);
do {
ans_node = TrNode_child(ans_node);
} while (IS_INVALID_LEAF_NODE(ans_node));
} while (IS_ANSWER_INVALID_NODE(ans_node));
TrNode_child(old_ans_node) = ans_node;
} else
#endif /* MODE_DIRECTED_TABLING */
@ -1151,13 +1369,13 @@
if (TrNode_child(ans_node)) {
/* dependency frame with unconsumed answers */
#ifdef MODE_DIRECTED_TABLING
if (IS_INVALID_LEAF_NODE(TrNode_child(ans_node))) {
if (IS_ANSWER_INVALID_NODE(TrNode_child(ans_node))) {
ans_node_ptr old_ans_node;
old_ans_node = ans_node;
ans_node = TrNode_child(ans_node);
do {
ans_node = TrNode_child(ans_node);
} while (IS_INVALID_LEAF_NODE(ans_node));
} while (IS_ANSWER_INVALID_NODE(ans_node));
TrNode_child(old_ans_node) = ans_node;
} else
#endif /* MODE_DIRECTED_TABLING */
@ -1360,6 +1578,11 @@
} else
#endif /* YAPOR */
{
#ifdef THREADS_CONSUMER_SHARING
goto answer_resolution_completion;
#endif /* THREADS_CONSUMER_SHARING */
if (IS_BATCHED_GEN_CP(B)) {
B->cp_ap = NULL;
if (EQUAL_OR_YOUNGER_CP(B_FZ, B) && B != DepFr_leader_cp(LOCAL_top_dep_fr)) {
@ -1380,6 +1603,9 @@
completion:
#ifdef THREADS_CONSUMER_SHARING
goto answer_resolution_completion;
#endif /* THREADS_CONSUMER_SHARING */
INIT_PREFETCH()
dep_fr_ptr dep_fr;
ans_node_ptr ans_node;
@ -1405,13 +1631,13 @@
if (TrNode_child(ans_node)) {
/* dependency frame with unconsumed answers */
#ifdef MODE_DIRECTED_TABLING
if (IS_INVALID_LEAF_NODE(TrNode_child(ans_node))) {
if (IS_ANSWER_INVALID_NODE(TrNode_child(ans_node))) {
ans_node_ptr old_ans_node;
old_ans_node = ans_node;
ans_node = TrNode_child(ans_node);
do {
ans_node = TrNode_child(ans_node);
} while (IS_INVALID_LEAF_NODE(ans_node));
} while (IS_ANSWER_INVALID_NODE(ans_node));
TrNode_child(old_ans_node) = ans_node;
} else
#endif /* MODE_DIRECTED_TABLING */
@ -1575,13 +1801,13 @@
/* unconsumed answers */
UNLOCK_OR_FRAME(LOCAL_top_or_fr);
#ifdef MODE_DIRECTED_TABLING
if (IS_INVALID_LEAF_NODE(TrNode_child(ans_node))) {
if (IS_ANSWER_INVALID_NODE(TrNode_child(ans_node))) {
ans_node_ptr old_ans_node;
old_ans_node = ans_node;
ans_node = TrNode_child(ans_node);
do {
ans_node = TrNode_child(ans_node);
} while (IS_INVALID_LEAF_NODE(ans_node));
} while (IS_ANSWER_INVALID_NODE(ans_node));
TrNode_child(old_ans_node) = ans_node;
} else
#endif /* MODE_DIRECTED_TABLING */
@ -1594,7 +1820,7 @@
UNLOCK_DEP_FR(LOCAL_top_dep_fr);
if (OrFr_owners(LOCAL_top_or_fr) > 1) {
/* more owners -> move up one node */
Set_LOCAL_top_cp_on_stack( GetOrFr_node(OrFr_next_on_stack(LOCAL_top_or_fr)) );
Set_LOCAL_top_cp_on_stack(GetOrFr_node(OrFr_next_on_stack(LOCAL_top_or_fr)));
BITMAP_delete(OrFr_members(LOCAL_top_or_fr), worker_id);
OrFr_owners(LOCAL_top_or_fr)--;
LOCAL_top_dep_fr = DepFr_next(LOCAL_top_dep_fr);
@ -1625,6 +1851,10 @@
GONext();
} else
#endif /* YAPOR */
#ifdef THREADS_CONSUMER_SHARING
complete_all:
#endif /* THREADS_CONSUMER_SHARING */
{
/* complete all */
sg_fr_ptr sg_fr;
@ -1636,7 +1866,11 @@
#endif /* DETERMINISTIC_TABLING */
sg_fr = GEN_CP(B)->cp_sg_fr;
private_completion(sg_fr);
#ifdef THREADS_CONSUMER_SHARING
if (IS_BATCHED_GEN_CP(B) || SgFr_gen_worker(sg_fr) != worker_id) { /* if it is an gen_cons node then all the answers were already consumed */
#else
if (IS_BATCHED_GEN_CP(B)) {
#endif /*THREADS_CONSUMER_SHARING */
/* backtrack */
B = B->cp_b;
SET_BB(PROTECT_FROZEN_B(B));
@ -1678,9 +1912,28 @@
YENV = ENV;
GONext();
} else {
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
LOCK_SG_FR(sg_fr);
if (SgFr_active_workers(sg_fr) > 0) {
/* load answers from the trie */
UNLOCK_SG_FR(sg_fr);
if(TrNode_child(ans_node) != NULL) {
store_loader_node(tab_ent, ans_node);
}
PREG = (yamop *) CPREG;
PREFETCH_OP(PREG);
load_answer(ans_node, YENV);
YENV = ENV;
GONext();
}
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
/* execute compiled code from the trie */
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
if (SgFr_sg_ent_state(sg_fr) < compiled)
#else
LOCK_SG_FR(sg_fr);
if (SgFr_state(sg_fr) < compiled)
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
update_answer_trie(sg_fr);
UNLOCK_SG_FR(sg_fr);
PREG = (yamop *) TrNode_child(SgFr_answer_trie(sg_fr));
@ -1694,3 +1947,192 @@
}
END_PREFETCH()
ENDBOp();
/************************************************************************
** table_answer_resolution_completion **
************************************************************************/
#ifdef THREADS_CONSUMER_SHARING
BOp(table_answer_resolution_completion, Otapl)
answer_resolution_completion:
{
INIT_PREFETCH()
int do_not_complete_tables;
int wid = worker_id ;
do {
dep_fr_ptr dep_fr;
ans_node_ptr ans_node;
do_not_complete_tables = 0; /* 0 - complete all the tables 1 - do not complete all the tables */
if (B->cp_ap == ANSWER_RESOLUTION_COMPLETION ){
/* generator consumer node (external node) */
if ((IS_BATCHED_GEN_CP(B) && (EQUAL_OR_YOUNGER_CP(B_FZ, B) && B != DepFr_leader_cp(LOCAL_top_dep_fr))) ||
(B != DepFr_leader_cp(LOCAL_top_dep_fr))) {
/* not leader on that node */
INFO_THREADS("ans_reso_com (1) : not leader on that node dep_fr = %p leader_node =%p", LOCAL_top_dep_fr, GEN_CP(DepFr_leader_cp(LOCAL_top_dep_fr))->cp_dep_fr);
ThDepFr_state(GLOBAL_th_dep_fr(wid)) = working;
B->cp_ap = ANSWER_RESOLUTION;
goto answer_resolution;
}
/* leader on that node */
dep_fr = GEN_CP(B)->cp_dep_fr;
ans_node = DepFr_last_answer(dep_fr);
if (TrNode_child(ans_node)) {
/* unconsumed answer */
ThDepFr_state(GLOBAL_th_dep_fr(wid)) = working;
ans_node = DepFr_last_answer(dep_fr) = TrNode_child(ans_node);
INFO_THREADS("ans_reso_com (2) : consume_answer =%p dep_fr = %p leader_node =%p", ans_node, dep_fr, GEN_CP(DepFr_leader_cp(dep_fr))->cp_dep_fr);
consume_answer_and_procceed(dep_fr, ans_node);
}
sg_fr_ptr sg_fr = GEN_CP(B)->cp_sg_fr;
if (SgFr_sg_ent_state(sg_fr) < complete || (SgFr_sg_ent_state(sg_fr) >= complete && TrNode_child(ans_node)!= NULL))
do_not_complete_tables = 1;
} else { /* using the B->cp_ap == ANSWER_RESOLUTION_COMPLETION to distinguish gen_cons nodes from gen */
/* generator node */
if (IS_BATCHED_GEN_CP(B)) {
if (EQUAL_OR_YOUNGER_CP(B_FZ, B) && B != DepFr_leader_cp(LOCAL_top_dep_fr)) {
/* not leader on that node */
ThDepFr_state(GLOBAL_th_dep_fr(wid)) = working;
B->cp_ap = NULL;
B = B->cp_b;
goto fail;
}
} else {
if (B != DepFr_leader_cp(LOCAL_top_dep_fr)) {
/* not leader on that node */
ThDepFr_state(GLOBAL_th_dep_fr(wid)) = working;
B->cp_ap = ANSWER_RESOLUTION;
B = B->cp_b;
INFO_THREADS("ans_reso_com (3) : not leader on that node dep_fr = %p leader_node =%p", LOCAL_top_dep_fr, GEN_CP(DepFr_leader_cp(LOCAL_top_dep_fr))->cp_dep_fr);
goto fail;
}
}
}
/* leader on that node */
/* no unconsumed answers */
dep_fr = LOCAL_top_dep_fr;
/* check for dependency frames with unconsumed answers */
while (YOUNGER_CP(DepFr_cons_cp(dep_fr), B)) {
ans_node = DepFr_last_answer(dep_fr);
if (TrNode_child(ans_node)) {
ThDepFr_state(GLOBAL_th_dep_fr(wid)) = working;
/*dependency frame with unconsumed answers */
ans_node = DepFr_last_answer(dep_fr) = TrNode_child(ans_node);
if (IS_BATCHED_GEN_CP(B))
DepFr_backchain_cp(dep_fr) = B->cp_b;
else
DepFr_backchain_cp(dep_fr) = B;
/*rebind variables, update registers, consume answer and procceed */
TABLING_ERROR_CHECKING(answer_resolution_completion, EQUAL_OR_YOUNGER_CP(B, DepFr_cons_cp(dep_fr)));
TABLING_ERROR_CHECKING(answer_resolution_completion, B->cp_tr > DepFr_cons_cp(dep_fr)->cp_tr);
rebind_variables(DepFr_cons_cp(dep_fr)->cp_tr,B->cp_tr); //don't know if it is the same unbind_variables(DepFr_cons_cp(dep_fr)->cp_tr, B->cp_tr);
TABLING_ERROR_CHECKING(answer_resolution_completion, TR != B->cp_tr && !IsPairTerm((CELL)TrailTerm(TR - 1)));
TABLING_ERROR_CHECKING(answer_resolution_completion, TR != B->cp_tr && (tr_fr_ptr) RepPair((CELL)TrailTerm(TR - 1)) != B->cp_tr);
B = DepFr_cons_cp(dep_fr);
TR = TR_FZ;
if (TR != B->cp_tr)
TRAIL_LINK(B->cp_tr);
INFO_THREADS("ans_reso_com (4) : consume_answer =%p dep_fr = %p leader_node =%p", ans_node, dep_fr, GEN_CP(DepFr_leader_cp(dep_fr))->cp_dep_fr);
consume_answer_and_procceed(dep_fr, ans_node);
}
if (DepFr_external(dep_fr) == TRUE){
sg_fr_ptr sg_fr = GEN_CP(DepFr_cons_cp(dep_fr))->cp_sg_fr;
if (SgFr_sg_ent_state(sg_fr) < complete || (SgFr_sg_ent_state(sg_fr) >= complete && TrNode_child(ans_node)!= NULL))
do_not_complete_tables = 1;
}
dep_fr = DepFr_next(dep_fr);
}
/******************************** a terminaçao das threads *************************************/
if (do_not_complete_tables == 1){
/*all the dependency frames have consumed all answers and we have external tables */
if (ThDepFr_next(GLOBAL_th_dep_fr(wid)) == wid)
/* worker_id is not inside an SCC */
continue;
if (ThDepFr_state(GLOBAL_th_dep_fr(wid)) == working) {
int c_wid = ThDepFr_next(GLOBAL_th_dep_fr(wid));
do {
ThDepFr_terminator(GLOBAL_th_dep_fr(c_wid)) = 1;
c_wid = ThDepFr_next(GLOBAL_th_dep_fr(c_wid));
}while(c_wid != wid);
ThDepFr_terminator(GLOBAL_th_dep_fr(wid)) = 1;
ThDepFr_state(GLOBAL_th_dep_fr(wid)) = idle;
}else if (ThDepFr_state(GLOBAL_th_dep_fr(wid)) == idle){
int l_wid = wid; /* leader wid */
int c_wid = ThDepFr_next(GLOBAL_th_dep_fr(wid));
int jump_state = TRUE;
do{
if (ThDepFr_state(GLOBAL_th_dep_fr(c_wid)) != idle){
jump_state = FALSE;
break;
} else
if (l_wid > c_wid)
l_wid = c_wid;
c_wid = ThDepFr_next(GLOBAL_th_dep_fr(c_wid));
} while(c_wid != wid);
if (jump_state && l_wid == wid){
/* wid is the current leader thread */
ThDepFr_terminator(GLOBAL_th_dep_fr(wid)) = 0;
c_wid = ThDepFr_next(GLOBAL_th_dep_fr(wid));
do {
dep_fr_ptr remote_dep_fr = REMOTE_top_dep_fr(c_wid);
while(YOUNGER_CP(DepFr_cons_cp(remote_dep_fr),DepFr_leader_cp(REMOTE_top_dep_fr(c_wid)))){
if (TrNode_child(DepFr_last_answer(remote_dep_fr))){
/* dependency frame with unconsumed answers */
jump_state = FALSE;
break;
}
remote_dep_fr = DepFr_next(remote_dep_fr);
}
if (ThDepFr_state(GLOBAL_th_dep_fr(c_wid)) != idle){
jump_state = FALSE;
break;
}
c_wid = ThDepFr_next(GLOBAL_th_dep_fr(c_wid));
} while(c_wid != wid);
}
if (jump_state && ThDepFr_terminator(GLOBAL_th_dep_fr(wid)) == 0){
c_wid = ThDepFr_next(GLOBAL_th_dep_fr(wid));
do {
ThDepFr_state(GLOBAL_th_dep_fr(c_wid)) = completing;
c_wid = ThDepFr_next(GLOBAL_th_dep_fr(c_wid));
}while(c_wid != wid);
ThDepFr_state(GLOBAL_th_dep_fr(wid)) = completing;
}
}else if (ThDepFr_state(GLOBAL_th_dep_fr(wid)) == completing){
INFO_THREADS("ans_reso_com (5) : completing thread_state =%d",ThDepFr_state(GLOBAL_th_dep_fr(wid)));
break; /*do_not_complete_tables = 0; -- same as "break;" */
}
}
} while(do_not_complete_tables);
END_PREFETCH()
INFO_THREADS("ans_reso_com (6) : completing thread_state =%d",ThDepFr_state(GLOBAL_th_dep_fr(worker_id)));
goto complete_all;
}
ENDBOp();
#endif /* THREADS_CONSUMER_SHARING */

View File

@ -21,6 +21,26 @@
#endif /* HAVE_STRING_H */
#include "opt.mavar.h"
#ifdef THREADS
static inline void **get_insert_thread_bucket(void **, lockvar *);
static inline void **get_thread_bucket(void **);
static inline void abolish_thread_buckets(void **);
#endif /* THREADS */
static inline sg_node_ptr get_insert_subgoal_trie(tab_ent_ptr USES_REGS);
static inline sg_node_ptr get_subgoal_trie(tab_ent_ptr);
static inline sg_node_ptr get_subgoal_trie_for_abolish(tab_ent_ptr USES_REGS);
static inline sg_fr_ptr *get_insert_subgoal_frame_addr(sg_node_ptr USES_REGS);
static inline sg_fr_ptr get_subgoal_frame(sg_node_ptr);
static inline sg_fr_ptr get_subgoal_frame_for_abolish(sg_node_ptr USES_REGS);
#ifdef THREADS_FULL_SHARING
static inline void SgFr_batched_cached_answers_check_insert(sg_fr_ptr, ans_node_ptr);
static inline int SgFr_batched_cached_answers_check_remove(sg_fr_ptr, ans_node_ptr);
#endif /* THREADS_FULL_SHARING */
#ifdef THREADS_CONSUMER_SHARING
static inline void add_to_tdv(int, int);
static inline void check_for_deadlock(sg_fr_ptr);
static inline sg_fr_ptr deadlock_detection(sg_fr_ptr);
#endif /* THREADS_CONSUMER_SHARING */
static inline Int freeze_current_cp(void);
static inline void wake_frozen_cp(Int);
static inline void abolish_frozen_cps_until(Int);
@ -148,8 +168,8 @@ static inline tg_sol_fr_ptr CUT_prune_tg_solution_frames(tg_sol_fr_ptr, int);
#else
#define ANSWER_LEAF_NODE_MAX_THREADS OOOOPPS!!! Unknown Pointer Sizeof
#endif /* SIZEOF_INT_P */
#define ANSWER_LEAF_NODE_INSTR_RELATIVE(NODE) TrNode_instr(NODE) = TrNode_instr(NODE) - _trie_do_var + 1
#define ANSWER_LEAF_NODE_INSTR_ABSOLUTE(NODE) TrNode_instr(NODE) = (TrNode_instr(NODE) & ANSWER_LEAF_NODE_INSTR_MASK) + _trie_do_var - 1
#define ANSWER_LEAF_NODE_INSTR_RELATIVE(NODE) (TrNode_instr(NODE) = TrNode_instr(NODE) - _trie_do_var + 1)
#define ANSWER_LEAF_NODE_INSTR_ABSOLUTE(NODE) (TrNode_instr(NODE) = (TrNode_instr(NODE) & ANSWER_LEAF_NODE_INSTR_MASK) + _trie_do_var - 1)
#define ANSWER_LEAF_NODE_SET_WID(NODE,WID) BITMAP_insert(TrNode_instr(NODE), WID + ANSWER_LEAF_NODE_INSTR_BITS)
#define ANSWER_LEAF_NODE_DEL_WID(NODE,WID) BITMAP_delete(TrNode_instr(NODE), WID + ANSWER_LEAF_NODE_INSTR_BITS)
#define ANSWER_LEAF_NODE_CHECK_WID(NODE,WID) BITMAP_member(TrNode_instr(NODE), WID + ANSWER_LEAF_NODE_INSTR_BITS)
@ -165,18 +185,22 @@ static inline tg_sol_fr_ptr CUT_prune_tg_solution_frames(tg_sol_fr_ptr, int);
#define IS_BATCHED_NORM_GEN_CP(CP) (GEN_CP(CP)->cp_dep_fr == NULL)
#define IS_BATCHED_GEN_CP(CP) (IS_DET_GEN_CP(CP) || IS_BATCHED_NORM_GEN_CP(CP))
#else
#ifdef THREADS_CONSUMER_SHARING
#define IS_BATCHED_GEN_CP(CP) (IsMode_Batched(TabEnt_mode(SgFr_tab_ent(GEN_CP(CP)->cp_sg_fr))))
#else
#define IS_BATCHED_GEN_CP(CP) (GEN_CP(CP)->cp_dep_fr == NULL)
#endif /* THREADS_CONSUMER_SHARING */
#endif /* DETERMINISTIC_TABLING */
/* leaf nodes */
#define TAG_AS_SUBGOAL_LEAF_NODE(NODE) TrNode_child(NODE) = (sg_node_ptr)((unsigned long int) TrNode_child(NODE) | 0x1)
#define UNTAG_SUBGOAL_LEAF_NODE(NODE) ((sg_fr_ptr)((unsigned long int) (NODE) & ~(0x1)))
#define IS_SUBGOAL_LEAF_NODE(NODE) ((unsigned long int) TrNode_child(NODE) & 0x1)
#define TAG_AS_ANSWER_LEAF_NODE(NODE) TrNode_parent(NODE) = (ans_node_ptr)((unsigned long int) TrNode_parent(NODE) | 0x1)
#define UNTAG_ANSWER_LEAF_NODE(NODE) ((ans_node_ptr)((unsigned long int) (NODE) & ~(0x1)))
#define IS_ANSWER_LEAF_NODE(NODE) ((unsigned long int) TrNode_parent(NODE) & 0x1)
#define TAG_AS_INVALID_LEAF_NODE(NODE) TrNode_parent(NODE) = (ans_node_ptr)((unsigned long int) TrNode_parent(NODE) | 0x2)
#define IS_INVALID_LEAF_NODE(NODE) ((unsigned long int) TrNode_parent(NODE) & 0x2)
/* tagging nodes */
#define TAG_AS_SUBGOAL_LEAF_NODE(NODE) TrNode_child(NODE) = (sg_node_ptr)((unsigned long int) TrNode_child(NODE) | 0x1)
#define IS_SUBGOAL_LEAF_NODE(NODE) ((unsigned long int) TrNode_child(NODE) & 0x1)
#define TAG_AS_ANSWER_LEAF_NODE(NODE) TrNode_parent(NODE) = (ans_node_ptr)((unsigned long int) TrNode_parent(NODE) | 0x1)
#define IS_ANSWER_LEAF_NODE(NODE) ((unsigned long int) TrNode_parent(NODE) & 0x1)
#define TAG_AS_ANSWER_INVALID_NODE(NODE) TrNode_parent(NODE) = (ans_node_ptr)((unsigned long int) TrNode_parent(NODE) | 0x2)
#define IS_ANSWER_INVALID_NODE(NODE) ((unsigned long int) TrNode_parent(NODE) & 0x2)
#define UNTAG_SUBGOAL_NODE(NODE) ((sg_fr_ptr)((unsigned long int) (NODE) & ~(0x1)))
#define UNTAG_ANSWER_NODE(NODE) ((ans_node_ptr)((unsigned long int) (NODE) & ~(0x3)))
/* trie hashes */
#define MAX_NODES_PER_TRIE_LEVEL 8
@ -278,18 +302,21 @@ static inline tg_sol_fr_ptr CUT_prune_tg_solution_frames(tg_sol_fr_ptr, int);
#endif /* YAPOR */
#ifdef MODE_DIRECTED_TABLING
#define TabEnt_init_mode_directed(TAB_ENT, MODE_ARRAY) \
#define TabEnt_init_mode_directed_field(TAB_ENT, MODE_ARRAY) \
TabEnt_mode_directed(TAB_ENT) = MODE_ARRAY
#define SgFr_init_mode_directed(SG_FR, MODE_ARRAY) \
SgFr_invalid_chain(SG_FR) = NULL; \
#define SgEnt_init_mode_directed_fields(SG_ENT, MODE_ARRAY) \
SgEnt_invalid_chain(SG_ENT) = NULL; \
SgEnt_mode_directed(SG_ENT) = MODE_ARRAY
#define SgFr_init_mode_directed_fields(SG_FR, MODE_ARRAY) \
SgFr_invalid_chain(SG_FR) = NULL; \
SgFr_mode_directed(SG_FR) = MODE_ARRAY
#define AnsHash_init_previous_field(HASH, SG_FR) \
if (SgFr_hash_chain(SG_FR)) \
Hash_previous(SgFr_hash_chain(SG_FR)) = HASH; \
#define AnsHash_init_previous_field(HASH, SG_FR) \
if (SgFr_hash_chain(SG_FR)) \
Hash_previous(SgFr_hash_chain(SG_FR)) = HASH; \
Hash_previous(HASH) = NULL
#else
#define TabEnt_init_mode_directed(TAB_ENT, MODE_ARRAY)
#define SgFr_init_mode_directed(SG_FR, MODE_ARRAY)
#define TabEnt_init_mode_directed_field(TAB_ENT, MODE_ARRAY)
#define SgFr_init_mode_directed_fields(SG_FR, MODE_ARRAY)
#define AnsHash_init_previous_field(HASH, SG_FR)
#endif /* MODE_DIRECTED_TABLING */
@ -315,20 +342,18 @@ static inline tg_sol_fr_ptr CUT_prune_tg_solution_frames(tg_sol_fr_ptr, int);
#define IS_UNLOCKED_DEP_FR(DEP_FR)
#endif /* YAPOR */
#if defined(SUBGOAL_TRIE_LOCK_AT_ENTRY_LEVEL) || defined(THREADS_NO_SHARING)
#define INIT_LOCK_TAB_ENT(TAB_ENT) INIT_LOCK(TabEnt_lock(TAB_ENT))
#else
#define INIT_LOCK_TAB_ENT(TAB_ENT)
#endif /* SUBGOAL_TRIE_LOCK_AT_ENTRY_LEVEL || THREADS_NO_SHARING */
#ifdef SUBGOAL_TRIE_LOCK_AT_ENTRY_LEVEL
#define LOCK_SUBGOAL_TRIE(TAB_ENT) LOCK(TabEnt_lock(TAB_ENT))
#define UNLOCK_SUBGOAL_TRIE(TAB_ENT) UNLOCK(TabEnt_lock(TAB_ENT))
#define SgHash_init_next_field(HASH, TAB_ENT) \
Hash_next(HASH) = TabEnt_hash_chain(TAB_ENT); \
TabEnt_hash_chain(TAB_ENT) = HASH
#else
#define LOCK_SUBGOAL_TRIE(TAB_ENT)
#define UNLOCK_SUBGOAL_TRIE(TAB_ENT)
#define SgHash_init_next_field(HASH, TAB_ENT) \
LOCK(TabEnt_lock(TAB_ENT)); \
Hash_next(HASH) = TabEnt_hash_chain(TAB_ENT); \
TabEnt_hash_chain(TAB_ENT) = HASH; \
UNLOCK(TabEnt_lock(TAB_ENT))
#endif /* SUBGOAL_TRIE_LOCK_AT_ENTRY_LEVEL */
#ifdef ANSWER_TRIE_LOCK_AT_ENTRY_LEVEL
@ -391,63 +416,137 @@ static inline tg_sol_fr_ptr CUT_prune_tg_solution_frames(tg_sol_fr_ptr, int);
#define GtNode_init_lock_field(NODE)
#endif /* GLOBAL_TRIE_LOCK_LEVEL */
#ifdef THREADS_NO_SHARING
#define TabEnt_init_subgoal_trie_field(TAB_ENT) \
INIT_BUCKETS(&TabEnt_subgoal_trie(TAB_ENT), THREADS_NUM_BUCKETS)
#else
#define TabEnt_init_subgoal_trie_field(TAB_ENT) \
{ register sg_node_ptr sg_node; \
new_subgoal_trie_node(sg_node, 0, NULL, NULL, NULL); \
TabEnt_subgoal_trie(TAB_ENT) = sg_node; \
}
#endif /* THREADS_NO_SHARING */
#if defined(THREADS_FULL_SHARING)
#define SgFr_init_batched_fields(SG_FR) \
SgFr_batched_last_answer(SG_FR) = NULL; \
SgFr_batched_cached_answers(SG_FR) = NULL;
#else
#define SgFr_init_batched_fields(SG_FR)
#endif /* THREADS_FULL_SHARING */
#ifdef THREADS_CONSUMER_SHARING
#define DepFr_init_external_field(DEP_FR, IS_EXTERNAL) \
DepFr_external(DEP_FR) = IS_EXTERNAL
#else
#define DepFr_init_external_field(DEP_FR, IS_EXTERNAL)
#endif /* THREADS_CONSUMER_SHARING */
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
#define DepFr_init_last_answer_field(DEP_FR, SG_FR) \
/* start with TrNode_child(DepFr_last_answer(DEP_FR)) ... */ \
/* ... pointing to SgEnt_first_answer(SgFr_sg_ent(SG_FR)) */ \
if (SG_FR) \
DepFr_last_answer(DEP_FR) = (ans_node_ptr) ( \
(unsigned long int) (SgFr_sg_ent((sg_fr_ptr)SG_FR)) + \
(unsigned long int) (&SgEnt_first_answer((sg_ent_ptr)DEP_FR)) - \
(unsigned long int) (&TrNode_child((ans_node_ptr)DEP_FR))); \
else \
DepFr_last_answer(DEP_FR) = NULL
#else
#define DepFr_init_last_answer_field(DEP_FR, SG_FR) \
/* start with TrNode_child(DepFr_last_answer(DEP_FR)) ... */ \
/* ... pointing to SgFr_first_answer(SG_FR) */ \
if (SG_FR) \
DepFr_last_answer(DEP_FR) = (ans_node_ptr) ( \
(unsigned long int) (SG_FR) + \
(unsigned long int) (&SgFr_first_answer((sg_fr_ptr)DEP_FR)) - \
(unsigned long int) (&TrNode_child((ans_node_ptr)DEP_FR))); \
else \
DepFr_last_answer(DEP_FR) = NULL
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
#define new_table_entry(TAB_ENT, PRED_ENTRY, ATOM, ARITY, MODE_ARRAY) \
{ register sg_node_ptr sg_node; \
new_subgoal_trie_node(sg_node, 0, NULL, NULL, NULL); \
ALLOC_TABLE_ENTRY(TAB_ENT); \
INIT_LOCK(TabEnt_lock(TAB_ENT)); \
TabEnt_pe(TAB_ENT) = PRED_ENTRY; \
TabEnt_atom(TAB_ENT) = ATOM; \
TabEnt_arity(TAB_ENT) = ARITY; \
TabEnt_flags(TAB_ENT) = 0; \
SetMode_Batched(TabEnt_flags(TAB_ENT)); \
SetMode_ExecAnswers(TabEnt_flags(TAB_ENT)); \
SetMode_LocalTrie(TabEnt_flags(TAB_ENT)); \
TabEnt_mode(TAB_ENT) = TabEnt_flags(TAB_ENT); \
if (IsMode_Local(yap_flags[TABLING_MODE_FLAG])) \
SetMode_Local(TabEnt_mode(TAB_ENT)); \
if (IsMode_LoadAnswers(yap_flags[TABLING_MODE_FLAG])) \
SetMode_LoadAnswers(TabEnt_mode(TAB_ENT)); \
if (IsMode_GlobalTrie(yap_flags[TABLING_MODE_FLAG])) \
SetMode_GlobalTrie(TabEnt_mode(TAB_ENT)); \
TabEnt_init_mode_directed(TAB_ENT, MODE_ARRAY); \
TabEnt_subgoal_trie(TAB_ENT) = sg_node; \
TabEnt_hash_chain(TAB_ENT) = NULL; \
TabEnt_next(TAB_ENT) = GLOBAL_root_tab_ent; \
GLOBAL_root_tab_ent = TAB_ENT; \
ALLOC_TABLE_ENTRY(TAB_ENT); \
INIT_LOCK_TAB_ENT(TAB_ENT); \
TabEnt_pe(TAB_ENT) = PRED_ENTRY; \
TabEnt_atom(TAB_ENT) = ATOM; \
TabEnt_arity(TAB_ENT) = ARITY; \
TabEnt_flags(TAB_ENT) = 0; \
SetMode_Batched(TabEnt_flags(TAB_ENT)); \
SetMode_ExecAnswers(TabEnt_flags(TAB_ENT)); \
SetMode_LocalTrie(TabEnt_flags(TAB_ENT)); \
TabEnt_mode(TAB_ENT) = TabEnt_flags(TAB_ENT); \
if (IsMode_Local(yap_flags[TABLING_MODE_FLAG])) \
SetMode_Local(TabEnt_mode(TAB_ENT)); \
if (IsMode_LoadAnswers(yap_flags[TABLING_MODE_FLAG])) \
SetMode_LoadAnswers(TabEnt_mode(TAB_ENT)); \
if (IsMode_GlobalTrie(yap_flags[TABLING_MODE_FLAG])) \
SetMode_GlobalTrie(TabEnt_mode(TAB_ENT)); \
TabEnt_init_mode_directed_field(TAB_ENT, MODE_ARRAY); \
TabEnt_init_subgoal_trie_field(TAB_ENT); \
TabEnt_next(TAB_ENT) = GLOBAL_root_tab_ent; \
GLOBAL_root_tab_ent = TAB_ENT
#define new_subgoal_entry(SG_ENT) \
{ register ans_node_ptr ans_node; \
new_answer_trie_node(ans_node, 0, 0, NULL, NULL, NULL); \
ALLOC_SUBGOAL_ENTRY(SG_ENT); \
INIT_LOCK(SgEnt_lock(SG_ENT)); \
SgEnt_hash_chain(SG_ENT) = NULL; \
SgEnt_answer_trie(SG_ENT) = ans_node; \
SgEnt_first_answer(SG_ENT) = NULL; \
SgEnt_last_answer(SG_ENT) = NULL; \
SgEnt_sg_ent_state(SG_ENT) = ready; \
SgEnt_active_workers(SG_ENT) = 0; \
INIT_BUCKETS(&SgEnt_sg_fr(SG_ENT), THREADS_NUM_BUCKETS); \
}
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
#define new_subgoal_frame(SG_FR, SG_ENT) \
{ ALLOC_SUBGOAL_FRAME(SG_FR); \
SgFr_sg_ent(SG_FR) = SG_ENT ; \
SgFr_init_batched_fields(SG_FR); \
}
#define init_subgoal_frame(SG_FR) \
{ SgFr_state(SG_FR) = evaluating; \
SgFr_next(SG_FR) = LOCAL_top_sg_fr; \
LOCAL_top_sg_fr = SG_FR; \
}
#else
#define new_subgoal_frame(SG_FR, CODE, MODE_ARRAY) \
{ register ans_node_ptr ans_node; \
new_answer_trie_node(ans_node, 0, 0, NULL, NULL, NULL); \
ALLOC_SUBGOAL_FRAME(SG_FR); \
INIT_LOCK_SG_FR(SG_FR); \
SgFr_code(SG_FR) = CODE; \
SgFr_state(SG_FR) = ready; \
SgFr_hash_chain(SG_FR) = NULL; \
SgFr_answer_trie(SG_FR) = ans_node; \
SgFr_first_answer(SG_FR) = NULL; \
SgFr_last_answer(SG_FR) = NULL; \
SgFr_init_mode_directed(SG_FR, MODE_ARRAY); \
SgFr_init_mode_directed_fields(SG_FR, MODE_ARRAY); \
SgFr_state(SG_FR) = ready; \
}
#define init_subgoal_frame(SG_FR) \
{ SgFr_init_yapor_fields(SG_FR); \
SgFr_state(SG_FR) = evaluating; \
SgFr_next(SG_FR) = LOCAL_top_sg_fr; \
LOCAL_top_sg_fr = SG_FR; \
#define init_subgoal_frame(SG_FR) \
{ SgFr_init_yapor_fields(SG_FR); \
SgFr_state(SG_FR) = evaluating; \
SgFr_next(SG_FR) = LOCAL_top_sg_fr; \
LOCAL_top_sg_fr = SG_FR; \
}
#endif /* THREADS_FULL_SHARING) || THREADS_CONSUMER_SHARING */
#define new_dependency_frame(DEP_FR, DEP_ON_STACK, TOP_OR_FR, LEADER_CP, CONS_CP, SG_FR, NEXT) \
ALLOC_DEPENDENCY_FRAME(DEP_FR); \
DepFr_init_yapor_fields(DEP_FR, DEP_ON_STACK, TOP_OR_FR); \
DepFr_backchain_cp(DEP_FR) = NULL; \
DepFr_leader_cp(DEP_FR) = NORM_CP(LEADER_CP); \
DepFr_cons_cp(DEP_FR) = NORM_CP(CONS_CP); \
/* start with TrNode_child(DepFr_last_answer(DEP_FR)) pointing to SgFr_first_answer(SG_FR) */ \
DepFr_last_answer(DEP_FR) = (ans_node_ptr) ((unsigned long int) (SG_FR) + \
(unsigned long int) (&SgFr_first_answer((sg_fr_ptr)DEP_FR)) - \
(unsigned long int) (&TrNode_child((ans_node_ptr)DEP_FR))); \
#define new_dependency_frame(DEP_FR, DEP_ON_STACK, TOP_OR_FR, LEADER_CP, CONS_CP, SG_FR, IS_EXTERNAL, NEXT) \
ALLOC_DEPENDENCY_FRAME(DEP_FR); \
DepFr_init_yapor_fields(DEP_FR, DEP_ON_STACK, TOP_OR_FR); \
DepFr_init_external_field(DEP_FR, IS_EXTERNAL); \
DepFr_backchain_cp(DEP_FR) = NULL; \
DepFr_leader_cp(DEP_FR) = NORM_CP(LEADER_CP); \
DepFr_cons_cp(DEP_FR) = NORM_CP(CONS_CP); \
DepFr_init_last_answer_field(DEP_FR, SG_FR); \
DepFr_next(DEP_FR) = NEXT
#define new_suspension_frame(SUSP_FR, TOP_OR_FR_ON_STACK, TOP_DEP, TOP_SG, \
@ -478,7 +577,7 @@ static inline tg_sol_fr_ptr CUT_prune_tg_solution_frames(tg_sol_fr_ptr, int);
SgNode_init_lock_field(NODE)
#define new_answer_trie_node(NODE, INSTR, ENTRY, CHILD, PARENT, NEXT) \
ALLOC_ANSWER_TRIE_NODE(NODE); \
ALLOC_ANSWER_TRIE_NODE(NODE); \
TrNode_instr(NODE) = INSTR; \
TrNode_entry(NODE) = ENTRY; \
TrNode_child(NODE) = CHILD; \
@ -494,27 +593,32 @@ static inline tg_sol_fr_ptr CUT_prune_tg_solution_frames(tg_sol_fr_ptr, int);
TrNode_next(NODE) = NEXT; \
GtNode_init_lock_field(NODE)
#define new_subgoal_trie_hash(HASH, NUM_NODES, TAB_ENT) \
ALLOC_SUBGOAL_TRIE_HASH(HASH); \
Hash_mark(HASH) = SUBGOAL_TRIE_HASH_MARK; \
Hash_num_buckets(HASH) = BASE_HASH_BUCKETS; \
ALLOC_HASH_BUCKETS(Hash_buckets(HASH), BASE_HASH_BUCKETS); \
Hash_num_nodes(HASH) = NUM_NODES; \
SgHash_init_next_field(HASH, TAB_ENT)
#define new_answer_ref_node(NODE, ANSWER, NEXT, PREVIOUS) \
ALLOC_ANSWER_REF_NODE(NODE); \
RefNode_answer(NODE) = ANSWER; \
RefNode_next(NODE) = NEXT; \
RefNode_previous(NODE) = PREVIOUS
#define new_answer_trie_hash(HASH, NUM_NODES, SG_FR) \
ALLOC_ANSWER_TRIE_HASH(HASH); \
Hash_mark(HASH) = ANSWER_TRIE_HASH_MARK; \
Hash_num_buckets(HASH) = BASE_HASH_BUCKETS; \
ALLOC_HASH_BUCKETS(Hash_buckets(HASH), BASE_HASH_BUCKETS); \
Hash_num_nodes(HASH) = NUM_NODES; \
#define new_subgoal_trie_hash(HASH, NUM_NODES, TAB_ENT) \
ALLOC_SUBGOAL_TRIE_HASH(HASH); \
Hash_mark(HASH) = SUBGOAL_TRIE_HASH_MARK; \
Hash_num_buckets(HASH) = BASE_HASH_BUCKETS; \
ALLOC_BUCKETS(Hash_buckets(HASH), BASE_HASH_BUCKETS); \
Hash_num_nodes(HASH) = NUM_NODES
#define new_answer_trie_hash(HASH, NUM_NODES, SG_FR) \
ALLOC_ANSWER_TRIE_HASH(HASH); \
Hash_mark(HASH) = ANSWER_TRIE_HASH_MARK; \
Hash_num_buckets(HASH) = BASE_HASH_BUCKETS; \
ALLOC_BUCKETS(Hash_buckets(HASH), BASE_HASH_BUCKETS); \
Hash_num_nodes(HASH) = NUM_NODES; \
AnsHash_init_chain_fields(HASH, SG_FR)
#define new_global_trie_hash(HASH, NUM_NODES) \
ALLOC_GLOBAL_TRIE_HASH(HASH); \
Hash_mark(HASH) = GLOBAL_TRIE_HASH_MARK; \
Hash_num_buckets(HASH) = BASE_HASH_BUCKETS; \
ALLOC_HASH_BUCKETS(Hash_buckets(HASH), BASE_HASH_BUCKETS); \
#define new_global_trie_hash(HASH, NUM_NODES) \
ALLOC_GLOBAL_TRIE_HASH(HASH); \
Hash_mark(HASH) = GLOBAL_TRIE_HASH_MARK; \
Hash_num_buckets(HASH) = BASE_HASH_BUCKETS; \
ALLOC_BUCKETS(Hash_buckets(HASH), BASE_HASH_BUCKETS); \
Hash_num_nodes(HASH) = NUM_NODES
#ifdef LIMIT_TABLING
@ -551,6 +655,327 @@ static inline tg_sol_fr_ptr CUT_prune_tg_solution_frames(tg_sol_fr_ptr, int);
** Inline funcions **
******************************/
#ifdef THREADS
static inline void **get_insert_thread_bucket(void **buckets, lockvar *buckets_lock) {
CACHE_REGS
/* direct bucket */
if (worker_id < THREADS_DIRECT_BUCKETS)
return buckets + worker_id;
/* indirect bucket */
buckets = buckets + THREADS_DIRECT_BUCKETS + (worker_id - THREADS_DIRECT_BUCKETS) / THREADS_DIRECT_BUCKETS;
if (*buckets)
return *buckets + (worker_id - THREADS_DIRECT_BUCKETS) % THREADS_DIRECT_BUCKETS;
/* insert indirect bucket */
LOCK(*buckets_lock);
if (*buckets == NULL)
ALLOC_BUCKETS(*buckets, THREADS_DIRECT_BUCKETS);
UNLOCK(*buckets_lock);
return *buckets + (worker_id - THREADS_DIRECT_BUCKETS) % THREADS_DIRECT_BUCKETS;
}
static inline void **get_thread_bucket(void **buckets) {
CACHE_REGS
/* direct bucket */
if (worker_id < THREADS_DIRECT_BUCKETS)
return buckets + worker_id;
/* indirect bucket */
buckets = buckets + THREADS_DIRECT_BUCKETS + (worker_id - THREADS_DIRECT_BUCKETS) / THREADS_DIRECT_BUCKETS;
if (*buckets)
return *buckets + (worker_id - THREADS_DIRECT_BUCKETS) % THREADS_DIRECT_BUCKETS;
/* empty indirect bucket */
return buckets;
}
static inline void abolish_thread_buckets(void **buckets) {
int i;
/* abolish indirect buckets */
buckets += THREADS_NUM_BUCKETS;
for (i = 0; i < THREADS_INDIRECT_BUCKETS; i++) {
if (*--buckets) {
FREE_BUCKETS(*buckets);
*buckets = NULL;
}
}
#if defined(THREADS_SUBGOAL_SHARING)
/* abolish direct buckets */
buckets -= THREADS_DIRECT_BUCKETS;
FREE_BUCKETS(buckets);
#endif /* THREADS_SUBGOAL_SHARING */
}
#endif /* THREADS */
static inline sg_node_ptr get_insert_subgoal_trie(tab_ent_ptr tab_ent USES_REGS) {
#ifdef THREADS_NO_SHARING
sg_node_ptr *sg_node_addr = (sg_node_ptr *) get_insert_thread_bucket((void **) &TabEnt_subgoal_trie(tab_ent), &TabEnt_lock(tab_ent));
if (*sg_node_addr == NULL) {
new_subgoal_trie_node(*sg_node_addr, 0, NULL, NULL, NULL);
}
return *sg_node_addr;
#else
return TabEnt_subgoal_trie(tab_ent);
#endif /* THREADS_NO_SHARING */
}
static inline sg_node_ptr get_subgoal_trie(tab_ent_ptr tab_ent) {
#ifdef THREADS_NO_SHARING
sg_node_ptr *sg_node_addr = (sg_node_ptr *) get_thread_bucket((void **) &TabEnt_subgoal_trie(tab_ent));
return *sg_node_addr;
#else
return TabEnt_subgoal_trie(tab_ent);
#endif /* THREADS_NO_SHARING */
}
static inline sg_node_ptr get_subgoal_trie_for_abolish(tab_ent_ptr tab_ent USES_REGS) {
#ifdef THREADS_NO_SHARING
sg_node_ptr *sg_node_addr = (sg_node_ptr *) get_thread_bucket((void **) &TabEnt_subgoal_trie(tab_ent));
sg_node_ptr sg_node = *sg_node_addr;
*sg_node_addr = NULL;
if (worker_id == 0)
abolish_thread_buckets((void **) &TabEnt_subgoal_trie(tab_ent));
return sg_node;
#else
return TabEnt_subgoal_trie(tab_ent);
#endif /* THREADS_NO_SHARING */
}
static inline sg_fr_ptr *get_insert_subgoal_frame_addr(sg_node_ptr sg_node USES_REGS) {
sg_fr_ptr *sg_fr_addr = (sg_fr_ptr *) &TrNode_sg_fr(sg_node);
#if defined(THREADS_SUBGOAL_SHARING) || defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
if (*sg_fr_addr == NULL) {
LOCK_SUBGOAL_NODE(sg_node);
if (*sg_fr_addr == NULL) {
#if defined(THREADS_SUBGOAL_SHARING)
ALLOC_BUCKETS(TrNode_sg_fr(sg_node), THREADS_NUM_BUCKETS);
#elif defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
sg_ent_ptr sg_ent;
new_subgoal_entry(sg_ent);
TrNode_sg_ent(sg_node) = (sg_node_ptr) sg_ent;
#endif
TAG_AS_SUBGOAL_LEAF_NODE(sg_node);
}
UNLOCK_SUBGOAL_NODE(sg_node);
}
sg_fr_addr = (sg_fr_ptr *) get_insert_thread_bucket(
#if defined(THREADS_SUBGOAL_SHARING)
(void **) UNTAG_SUBGOAL_NODE(TrNode_sg_fr(sg_node)),
#elif defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
(void **) &SgEnt_sg_fr(UNTAG_SUBGOAL_NODE(TrNode_sg_fr(sg_node))),
#endif
#ifdef SUBGOAL_TRIE_LOCK_USING_NODE_FIELD
&TrNode_lock(sg_node)
#elif defined(SUBGOAL_TRIE_LOCK_USING_GLOBAL_ARRAY)
&HASH_TRIE_LOCK(sg_node)
#endif
);
#endif /* THREADS_SUBGOAL_SHARING || THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
return sg_fr_addr;
}
static inline sg_fr_ptr get_subgoal_frame(sg_node_ptr sg_node) {
#if defined(THREADS_SUBGOAL_SHARING)
sg_fr_ptr *sg_fr_addr = (sg_fr_ptr *) get_thread_bucket((void **) UNTAG_SUBGOAL_NODE(TrNode_sg_fr(sg_node)));
return *sg_fr_addr;
#elif defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
sg_fr_ptr *sg_fr_addr = (sg_fr_ptr *) get_thread_bucket((void **) &SgEnt_sg_fr(UNTAG_SUBGOAL_NODE(TrNode_sg_fr(sg_node))));
return *sg_fr_addr;
#else
return UNTAG_SUBGOAL_NODE(TrNode_sg_fr(sg_node));
#endif
}
static inline sg_fr_ptr get_subgoal_frame_for_abolish(sg_node_ptr sg_node USES_REGS) {
#if defined(THREADS_SUBGOAL_SHARING)
sg_fr_ptr *sg_fr_addr = (sg_fr_ptr *) get_thread_bucket((void **) UNTAG_SUBGOAL_NODE(TrNode_sg_fr(sg_node)));
sg_fr_ptr sg_fr = *sg_fr_addr;
if (worker_id == 0)
abolish_thread_buckets((void **) UNTAG_SUBGOAL_NODE(TrNode_sg_fr(sg_node)));
else
*sg_fr_addr = NULL;
return sg_fr;
#elif defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
sg_fr_ptr *sg_fr_addr = (sg_fr_ptr *) get_thread_bucket((void **) &SgEnt_sg_fr(UNTAG_SUBGOAL_NODE(TrNode_sg_fr(sg_node))));
sg_fr_ptr sg_fr = *sg_fr_addr;
if (worker_id == 0)
abolish_thread_buckets((void **) &SgEnt_sg_fr(UNTAG_SUBGOAL_NODE(TrNode_sg_fr(sg_node))));
else
*sg_fr_addr = NULL;
return sg_fr;
#else
return UNTAG_SUBGOAL_NODE(TrNode_sg_fr(sg_node));
#endif
}
#ifdef THREADS_FULL_SHARING
static inline void SgFr_batched_cached_answers_check_insert(sg_fr_ptr sg_fr, ans_node_ptr ans_node) {
CACHE_REGS
if (SgFr_batched_last_answer(sg_fr) == NULL)
SgFr_batched_last_answer(sg_fr) = SgFr_first_answer(sg_fr);
else
SgFr_batched_last_answer(sg_fr) = TrNode_child(SgFr_batched_last_answer(sg_fr)) ;
while (SgFr_batched_last_answer(sg_fr) != ans_node) {
struct answer_ref_node *ref_node = NULL;
if (SgFr_batched_cached_answers(sg_fr) == NULL) {
new_answer_ref_node(ref_node, SgFr_batched_last_answer(sg_fr), NULL, NULL);
} else {
new_answer_ref_node(ref_node, SgFr_batched_last_answer(sg_fr), SgFr_batched_cached_answers(sg_fr), NULL);
RefNode_previous(SgFr_batched_cached_answers(sg_fr)) = ref_node;
}
SgFr_batched_cached_answers(sg_fr) = ref_node;
SgFr_batched_last_answer(sg_fr) = TrNode_child(SgFr_batched_last_answer(sg_fr)) ;
}
if (ans_node != NULL)
/* new answer */
SgFr_batched_last_answer(sg_fr) = ans_node;
else
/* repeated answer */
SgFr_batched_last_answer(sg_fr) = SgFr_last_answer(sg_fr);
return;
}
static inline int SgFr_batched_cached_answers_check_remove(sg_fr_ptr sg_fr, ans_node_ptr ans_node) {
CACHE_REGS
struct answer_ref_node *local_uncons_ans;
local_uncons_ans = SgFr_batched_cached_answers(sg_fr) ;
while ( local_uncons_ans != NULL ) {
if ( RefNode_answer(local_uncons_ans) == ans_node )
break;
local_uncons_ans = RefNode_next(local_uncons_ans) ;
}
if ( local_uncons_ans == NULL )
return 1;
/*remove node from buffer */
if (RefNode_previous(local_uncons_ans) == NULL) {
SgFr_batched_cached_answers(sg_fr) = RefNode_next(local_uncons_ans) ;
if (SgFr_batched_cached_answers(sg_fr) != NULL)
RefNode_previous(SgFr_batched_cached_answers(sg_fr)) = NULL;
} else{
RefNode_next(RefNode_previous(local_uncons_ans)) = RefNode_next(local_uncons_ans);
if (RefNode_next(local_uncons_ans) != NULL)
RefNode_previous(RefNode_next(local_uncons_ans)) = RefNode_previous(local_uncons_ans);
}
FREE_ANSWER_REF_NODE(local_uncons_ans);
return 0;
}
#endif /* THREADS_FULL_SHARING */
#ifdef THREADS_CONSUMER_SHARING
static inline void add_to_tdv(int wid, int wid_dep) {
#ifdef OUTPUT_THREADS_TABLING
CACHE_REGS
#endif /* OUTPUT_THREADS_TABLING */
// thread wid next of thread wid_dep
/* check before insert */
int c_wid = ThDepFr_next(GLOBAL_th_dep_fr(wid));
do {
if (c_wid == wid_dep)
break;
c_wid = ThDepFr_next(GLOBAL_th_dep_fr(c_wid));
} while( c_wid != wid );
if (c_wid == wid_dep)
return;
if (wid < wid_dep) {
LOCK(ThDepFr_lock(GLOBAL_th_dep_fr(wid)));
LOCK(ThDepFr_lock(GLOBAL_th_dep_fr(wid_dep)));
} else {
LOCK(ThDepFr_lock(GLOBAL_th_dep_fr(wid_dep)));
LOCK(ThDepFr_lock(GLOBAL_th_dep_fr(wid)));
}
c_wid = ThDepFr_next(GLOBAL_th_dep_fr(wid));
do {
if (c_wid == wid_dep)
break;
c_wid = ThDepFr_next(GLOBAL_th_dep_fr(c_wid));
} while( c_wid != wid );
if ( c_wid == wid ){
// joining the two different SCCs
int t = ThDepFr_next(GLOBAL_th_dep_fr(wid));
ThDepFr_next(GLOBAL_th_dep_fr(wid)) = ThDepFr_next(GLOBAL_th_dep_fr(wid_dep));
ThDepFr_next(GLOBAL_th_dep_fr(wid_dep)) = t;
}
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)));
UNLOCK(ThDepFr_lock(GLOBAL_th_dep_fr(wid)));
UNLOCK(ThDepFr_lock(GLOBAL_th_dep_fr(wid_dep)));
return;
}
static inline void check_for_deadlock(sg_fr_ptr sg_fr) {
CACHE_REGS
sg_fr_ptr local_sg_fr = deadlock_detection(sg_fr);
if (local_sg_fr){
LOCK(ThDepFr_lock(GLOBAL_th_dep_fr(worker_id)));
if (YOUNGER_CP(DepFr_leader_cp(LOCAL_top_dep_fr),SgFr_gen_cp(local_sg_fr)))
DepFr_leader_cp(LOCAL_top_dep_fr) = SgFr_gen_cp(local_sg_fr);
UNLOCK(ThDepFr_lock(GLOBAL_th_dep_fr(worker_id)));
}
return;
}
static inline sg_fr_ptr deadlock_detection(sg_fr_ptr sg_fr) {
CACHE_REGS
sg_fr_ptr remote_sg_fr = REMOTE_top_sg_fr(SgFr_gen_worker(sg_fr));
while( SgFr_sg_ent(remote_sg_fr) != SgFr_sg_ent(sg_fr)){
sg_fr_ptr local_sg_fr = SgFr_next(LOCAL_top_sg_fr);
while(local_sg_fr){
if ( SgFr_sg_ent(local_sg_fr) == SgFr_sg_ent(remote_sg_fr) ||
( SgFr_gen_worker(remote_sg_fr) != SgFr_gen_worker(sg_fr) && /* jump to other chain */
SgFr_gen_worker(remote_sg_fr) != worker_id && /* not jumping to the chain of the thread that is detecting the deadlock */
deadlock_detection(remote_sg_fr))){
sg_fr_ptr leader_remote_sg_fr;
do
leader_remote_sg_fr = SgFr_next(remote_sg_fr);
while(SgFr_sg_ent(leader_remote_sg_fr) != SgFr_sg_ent(sg_fr));
LOCK(ThDepFr_lock(GLOBAL_th_dep_fr(SgFr_gen_worker(leader_remote_sg_fr))));
if (YOUNGER_CP(DepFr_leader_cp(REMOTE_top_dep_fr(SgFr_gen_worker(leader_remote_sg_fr))),SgFr_gen_cp(leader_remote_sg_fr)))
DepFr_leader_cp(REMOTE_top_dep_fr(SgFr_gen_worker(leader_remote_sg_fr))) = SgFr_gen_cp(leader_remote_sg_fr);
UNLOCK(ThDepFr_lock(GLOBAL_th_dep_fr(SgFr_gen_worker(leader_remote_sg_fr))));
add_to_tdv(SgFr_gen_worker(local_sg_fr),SgFr_gen_worker(leader_remote_sg_fr));
return local_sg_fr;
}
local_sg_fr = SgFr_next(local_sg_fr);
}
remote_sg_fr = SgFr_next(remote_sg_fr);
}
return NULL;
}
#endif /* THREADS_CONSUMER_SHARING */
static inline Int freeze_current_cp(void) {
CACHE_REGS
choiceptr freeze_cp = B;
@ -606,8 +1031,17 @@ static inline void adjust_freeze_registers(void) {
static inline void mark_as_completed(sg_fr_ptr sg_fr) {
#ifdef OUTPUT_THREADS_TABLING
CACHE_REGS
#endif /* OUTPUT_THREADS_TABLING */
LOCK_SG_FR(sg_fr);
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
INFO_THREADS(" mark_as_completed sgfr=%p ", SgFr_sg_ent(sg_fr));
TABLING_ERROR_CHECKING(mark_as_completed, SgFr_sg_ent_state(sg_fr) > complete);
SgFr_active_workers(sg_fr)--;
SgFr_sg_ent_state(sg_fr) = complete;
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
SgFr_state(sg_fr) = complete;
UNLOCK_SG_FR(sg_fr);
#ifdef MODE_DIRECTED_TABLING
@ -615,13 +1049,13 @@ static inline void mark_as_completed(sg_fr_ptr sg_fr) {
ans_node_ptr current_node, next_node;
/* find first valid answer */
current_node = SgFr_first_answer(sg_fr);
while (IS_INVALID_LEAF_NODE(current_node))
while (IS_ANSWER_INVALID_NODE(current_node))
current_node = TrNode_child(current_node);
SgFr_first_answer(sg_fr) = current_node;
/* chain next valid answers */
next_node = TrNode_child(current_node);
while (next_node) {
if (! IS_INVALID_LEAF_NODE(next_node)) {
if (! IS_ANSWER_INVALID_NODE(next_node)) {
TrNode_child(current_node) = next_node;
current_node = next_node;
}
@ -850,13 +1284,13 @@ static inline void abolish_incomplete_subgoals(choiceptr prune_cp) {
ans_node_ptr current_node, next_node;
/* find first valid answer */
current_node = SgFr_first_answer(sg_fr);
while (IS_INVALID_LEAF_NODE(current_node))
while (IS_ANSWER_INVALID_NODE(current_node))
current_node = TrNode_child(current_node);
SgFr_first_answer(sg_fr) = current_node;
/* chain next valid answers */
next_node = TrNode_child(current_node);
while (next_node) {
if (! IS_INVALID_LEAF_NODE(next_node)) {
if (! IS_ANSWER_INVALID_NODE(next_node)) {
TrNode_child(current_node) = next_node;
current_node = next_node;
}
@ -882,14 +1316,50 @@ static inline void abolish_incomplete_subgoals(choiceptr prune_cp) {
SgFr_invalid_chain(sg_fr) = NULL;
#endif /* MODE_DIRECTED_TABLING */
SgFr_state(sg_fr) = ready;
free_answer_hash_chain(SgFr_hash_chain(sg_fr));
SgFr_hash_chain(sg_fr) = NULL;
SgFr_first_answer(sg_fr) = NULL;
SgFr_last_answer(sg_fr) = NULL;
node = TrNode_child(SgFr_answer_trie(sg_fr));
TrNode_child(SgFr_answer_trie(sg_fr)) = NULL;
UNLOCK_SG_FR(sg_fr);
free_answer_trie(node, TRAVERSE_MODE_NORMAL, TRAVERSE_POSITION_FIRST);
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
if (SgFr_active_workers(sg_fr) == 0) {
SgFr_sg_ent_state(sg_fr) = ready;
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
free_answer_hash_chain(SgFr_hash_chain(sg_fr));
SgFr_hash_chain(sg_fr) = NULL;
SgFr_first_answer(sg_fr) = NULL;
SgFr_last_answer(sg_fr) = NULL;
node = TrNode_child(SgFr_answer_trie(sg_fr));
TrNode_child(SgFr_answer_trie(sg_fr)) = NULL;
UNLOCK_SG_FR(sg_fr);
free_answer_trie(node, TRAVERSE_MODE_NORMAL, TRAVERSE_POSITION_FIRST);
#ifdef THREADS_FULL_SHARING
if (IsMode_Batched(TabEnt_mode(SgFr_tab_ent(sg_fr)))) {
SgFr_batched_last_answer(sg_fr) = NULL;
struct answer_ref_node *local_uncons_ans = SgFr_batched_cached_answers(sg_fr) ;
while ( local_uncons_ans ) {
SgFr_batched_cached_answers(sg_fr) = RefNode_next(SgFr_batched_cached_answers(sg_fr));
FREE_ANSWER_REF_NODE(local_uncons_ans);
local_uncons_ans = SgFr_batched_cached_answers(sg_fr);
}
}
} else{ /* SgFr_active_workers(sg_fr) != 0 */
if (IsMode_Batched(TabEnt_mode(SgFr_tab_ent(sg_fr)))){
SgFr_batched_last_answer(sg_fr) = NULL;
if ( worker_id >= ANSWER_LEAF_NODE_MAX_THREADS ) {
struct answer_ref_node *local_uncons_ans = SgFr_batched_cached_answers(sg_fr) ;
while ( local_uncons_ans ) {
SgFr_batched_cached_answers(sg_fr) = RefNode_next(SgFr_batched_cached_answers(sg_fr));
FREE_ANSWER_REF_NODE(local_uncons_ans);
local_uncons_ans = SgFr_batched_cached_answers(sg_fr);
}
} else { /* worker_id < ANSWER_LEAF_NODE_MAX_THREADS */
ans_node_ptr leaf_ans_trie_node = SgFr_first_answer(sg_fr);
while( leaf_ans_trie_node ){
ANSWER_LEAF_NODE_DEL_WID(leaf_ans_trie_node,worker_id);
leaf_ans_trie_node = TrNode_child(leaf_ans_trie_node);
}
}
}
#endif /* THREADS_FULL_SHARING */
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
}
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
#if defined(MODE_DIRECTED_TABLING) && ! defined(YAPOR)
/* free invalid answer nodes */
while (invalid_node) {

View File

@ -20,9 +20,9 @@
**************************/
typedef struct table_entry {
#if defined(YAPOR) || defined(THREADS)
#if defined(SUBGOAL_TRIE_LOCK_AT_ENTRY_LEVEL) || defined(THREADS_NO_SHARING)
lockvar lock;
#endif /* YAPOR || THREADS */
#endif /* SUBGOAL_TRIE_LOCK_AT_ENTRY_LEVEL || THREADS_NO_SHARING */
struct pred_entry *pred_entry;
Atom pred_atom;
int pred_arity;
@ -32,7 +32,7 @@ typedef struct table_entry {
int* mode_directed_array;
#endif /* MODE_DIRECTED_TABLING */
#ifdef THREADS_NO_SHARING
struct subgoal_trie_node *subgoal_trie[THREADS_FIRST_LEVEL_BUCKETS];
struct subgoal_trie_node *subgoal_trie[THREADS_NUM_BUCKETS];
#else
struct subgoal_trie_node *subgoal_trie;
#endif /* THREADS_NO_SHARING */
@ -47,12 +47,7 @@ typedef struct table_entry {
#define TabEnt_flags(X) ((X)->pred_flags)
#define TabEnt_mode(X) ((X)->execution_mode)
#define TabEnt_mode_directed(X) ((X)->mode_directed_array)
#ifdef THREADS_NO_SHARING
#define TabEnt_subgoal_trie(X) ((X)->subgoal_trie[worker_id])
//#define TabEnt_subgoal_trie(X,I) ((X)->subgoal_trie[I])
#else
#define TabEnt_subgoal_trie(X) ((X)->subgoal_trie)
#endif /* THREADS_NO_SHARING */
#define TabEnt_hash_chain(X) ((X)->hash_chain)
#define TabEnt_next(X) ((X)->next)
@ -102,11 +97,30 @@ typedef struct global_trie_node {
#define TrNode_parent(X) ((X)->parent)
#define TrNode_child(X) ((X)->child)
#define TrNode_sg_fr(X) ((X)->child)
#define TrNode_sg_ent(X) ((X)->child)
#define TrNode_next(X) ((X)->next)
#define TrNode_lock(X) ((X)->lock)
/******************************
** answer_ref_node **
******************************/
#ifdef THREADS_FULL_SHARING
typedef struct answer_ref_node {
struct answer_trie_node *ans_node;
struct answer_ref_node *next;
struct answer_ref_node *previous;
} *ans_ref_ptr;
#endif /* THREADS_FULL_SHARING */
#define RefNode_answer(X) ((X)->ans_node)
#define RefNode_next(X) ((X)->next)
#define RefNode_previous(X) ((X)->previous)
/***********************************************************************
** subgoal_trie_hash, answer_trie_hash and global_trie_hash **
***********************************************************************/
@ -118,7 +132,9 @@ typedef struct subgoal_trie_hash {
int number_of_buckets;
struct subgoal_trie_node **buckets;
int number_of_nodes;
#ifdef USE_PAGES_MALLOC
struct subgoal_trie_hash *next;
#endif /* USE_PAGES_MALLOC */
} *sg_hash_ptr;
typedef struct answer_trie_hash {
@ -155,24 +171,6 @@ typedef struct global_trie_hash {
/******************************
** answer_ref_node **
******************************/
#ifdef THREADS_FULL_SHARING
typedef struct answer_ref_node {
struct answer_trie_node *ans_node;
struct answer_ref_node *next;
struct answer_ref_node *previous;
} *ans_ref_ptr;
#endif /* THREADS_FULL_SHARING */
#define RefNode_answer(X) ((X)->ans_node)
#define RefNode_next(X) ((X)->next)
#define RefNode_previous(X) ((X)->previous)
/************************************************************************
** Execution Data Structures **
************************************************************************/
@ -267,7 +265,7 @@ typedef struct subgoal_entry {
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
subgoal_state_flag state_flag;
int active_workers;
struct subgoal_frame *subgoal_frame[THREADS_FIRST_LEVEL_BUCKETS];
struct subgoal_frame *subgoal_frame[THREADS_NUM_BUCKETS];
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
}* sg_ent_ptr;
@ -287,7 +285,7 @@ typedef struct subgoal_entry {
#define SgEnt_gen_worker(X) ((X)->generator_worker)
#define SgEnt_sg_ent_state(X) ((X)->state_flag)
#define SgEnt_active_workers(X) ((X)->active_workers)
#define SgEnt_sg_fr(X,I) ((X)->subgoal_frame[I])
#define SgEnt_sg_fr(X) ((X)->subgoal_frame)
@ -312,10 +310,10 @@ typedef struct subgoal_frame {
/* subgoal_entry fields */
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
#define SUBGOAL_ENTRY(X) SgFr_subgoal_entry(X)->
#define SUBGOAL_ENTRY(X) SgFr_sg_ent(X)->
#else
#define SUBGOAL_ENTRY(X) (X)->subgoal_entry.
#endif /* THREADS */
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
#define SgFr_lock(X) (SUBGOAL_ENTRY(X) lock)
#define SgFr_code(X) (SUBGOAL_ENTRY(X) code_of_subgoal)
#define SgFr_tab_ent(X) ((SUBGOAL_ENTRY(X) code_of_subgoal)->u.Otapl.te)
@ -333,7 +331,7 @@ typedef struct subgoal_frame {
#define SgFr_sg_ent_state(X) (SUBGOAL_ENTRY(X) state_flag)
#define SgFr_active_workers(X) (SUBGOAL_ENTRY(X) active_workers)
/* subgoal_frame fields */
#define SgFr_subgoal_entry(X) ((X)->subgoal_entry)
#define SgFr_sg_ent(X) ((X)->subgoal_entry)
#define SgFr_batched_last_answer(X) ((X)->batched_last_answer)
#define SgFr_batched_cached_answers(X) ((X)->batched_cached_answers)
#define SgFr_state(X) ((X)->state_flag)
@ -363,7 +361,7 @@ typedef struct subgoal_frame {
SgFr_gen_worker: the id of the worker that had allocated the frame.
SgFr_sg_ent_state: a flag that indicates the subgoal entry state.
SgFr_active_workers: the number of workers evaluating the subgoal.
SgFr_subgoal_entry: a pointer to the corresponding subgoal entry.
SgFr_sg_ent: a pointer to the corresponding subgoal entry.
SgFr_batched_last_answer: a pointer to the leaf answer trie node of the last checked answer
when using batched scheduling.
SgFr_batched_cached_answers: a pointer to the chain of answers already inserted in the trie, but not
@ -389,13 +387,13 @@ typedef struct dependency_frame {
long timestamp;
#endif /* TIMESTAMP_CHECK */
#endif /* YAPOR */
#ifdef THREADS_CONSUMER_SHARING
int generator_is_external;
#endif /* THREADS_CONSUMER_SHARING */
choiceptr backchain_choice_point;
choiceptr leader_choice_point;
choiceptr consumer_choice_point;
struct answer_trie_node *last_consumed_answer;
#ifdef THREADS_CONSUMER_SHARING
int generator_is_external;
#endif /* THREADS_CONSUMER_SHARING */
struct dependency_frame *next;
} *dep_fr_ptr;
@ -403,11 +401,11 @@ typedef struct dependency_frame {
#define DepFr_leader_dep_is_on_stack(X) ((X)->leader_dependency_is_on_stack)
#define DepFr_top_or_fr(X) ((X)->top_or_frame)
#define DepFr_timestamp(X) ((X)->timestamp)
#define DepFr_external(X) ((X)->generator_is_external)
#define DepFr_backchain_cp(X) ((X)->backchain_choice_point)
#define DepFr_leader_cp(X) ((X)->leader_choice_point)
#define DepFr_cons_cp(X) ((X)->consumer_choice_point)
#define DepFr_last_answer(X) ((X)->last_consumed_answer)
#define DepFr_external(X) ((X)->generator_is_external)
#define DepFr_next(X) ((X)->next)
/*********************************************************************************************************
@ -421,13 +419,13 @@ typedef struct dependency_frame {
backtracks through answers.
DepFr_timestamp: a timestamp used to optimize the search for suspension frames to be
resumed.
DepFr_external: the generator choice point is external to the current thread (FALSE/TRUE).
DepFr_backchain_cp: a pointer to the nearest choice point with untried alternatives.
It is used to efficiently return (backtrack) to the leader node where
we perform the last backtracking through answers operation.
DepFr_leader_cp: a pointer to the leader choice point.
DepFr_cons_cp: a pointer to the correspondent consumer choice point.
DepFr_last_answer: a pointer to the last consumed answer.
DepFr_external: the generator choice point is external to the current thread (FALSE/TRUE).
DepFr_next: a pointer to the next dependency frame on the chain.
*********************************************************************************************************/

View File

@ -58,7 +58,6 @@ static void free_global_trie_branch(gt_node_ptr, int);
#else
static void free_global_trie_branch(gt_node_ptr);
#endif /* GLOBAL_TRIE_FOR_SUBTERMS */
static void traverse_subgoal_trie(sg_node_ptr, char *, int, int *, int, int);
static void traverse_answer_trie(ans_node_ptr, char *, int, int *, int, int, int);
static void traverse_global_trie(gt_node_ptr, char *, int, int *, int, int);
@ -88,7 +87,25 @@ static struct trie_statistics{
long global_trie_terms;
long global_trie_nodes;
long global_trie_references;
} trie_stats;
}
#ifdef THREADS
trie_stats[MAX_THREADS];
#define TrStat_out trie_stats[worker_id].out
#define TrStat_show trie_stats[worker_id].show
#define TrStat_subgoals trie_stats[worker_id].subgoals
#define TrStat_sg_incomplete trie_stats[worker_id].subgoals_incomplete
#define TrStat_sg_nodes trie_stats[worker_id].subgoal_trie_nodes
#define TrStat_answers trie_stats[worker_id].answers
#define TrStat_answers_true trie_stats[worker_id].answers_true
#define TrStat_answers_no trie_stats[worker_id].answers_no
#define TrStat_answers_pruned trie_stats[worker_id].answers_pruned
#define TrStat_ans_nodes trie_stats[worker_id].answer_trie_nodes
#define TrStat_gt_terms trie_stats[worker_id].global_trie_terms
#define TrStat_gt_nodes trie_stats[worker_id].global_trie_nodes
#define TrStat_gt_refs trie_stats[worker_id].global_trie_references
#else /*!THREADS */
trie_stats;
#define TrStat_out trie_stats.out
#define TrStat_show trie_stats.show
@ -103,6 +120,20 @@ static struct trie_statistics{
#define TrStat_gt_terms trie_stats.global_trie_terms
#define TrStat_gt_nodes trie_stats.global_trie_nodes
#define TrStat_gt_refs trie_stats.global_trie_references
#endif /*THREADS */
#if defined(THREADS_SUBGOAL_SHARING) || defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
#define IF_ABOLISH_SUBGOAL_TRIE_SHARED_DATA_STRUCTURES if (worker_id == 0)
#else
#define IF_ABOLISH_SUBGOAL_TRIE_SHARED_DATA_STRUCTURES
#endif /* THREADS_SUBGOAL_SHARING || THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
#define IF_ABOLISH_ANSWER_TRIE_SHARED_DATA_STRUCTURES if (worker_id == 0)
#else
#define IF_ABOLISH_ANSWER_TRIE_SHARED_DATA_STRUCTURES
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
#define SHOW_TABLE_STR_ARRAY_SIZE 100000
#define SHOW_TABLE_ARITY_ARRAY_SIZE 10000
#define SHOW_TABLE_STRUCTURE(MESG, ARGS...) \
@ -441,6 +472,7 @@ static void update_answer_trie_branch(ans_node_ptr current_node, int position) {
TrNode_instr(current_node) = Yap_opcode(TrNode_instr(current_node) - position);
return;
}
#endif /* YAPOR */
@ -470,7 +502,7 @@ static void free_global_trie_branch(gt_node_ptr current_node) {
CHECK_DECREMENT_GLOBAL_TRIE_FOR_SUBTERMS_REFERENCE(t, mode);
FREE_GLOBAL_TRIE_NODE(current_node);
if (num_nodes == 0) {
FREE_HASH_BUCKETS(Hash_buckets(hash));
FREE_BUCKETS(Hash_buckets(hash));
FREE_GLOBAL_TRIE_HASH(hash);
if (parent_node != GLOBAL_root_gt) {
#ifdef GLOBAL_TRIE_FOR_SUBTERMS
@ -547,6 +579,7 @@ static void free_global_trie_branch(gt_node_ptr current_node) {
static void traverse_subgoal_trie(sg_node_ptr current_node, char *str, int str_index, int *arity, int mode, int position) {
CACHE_REGS
int *current_arity = NULL, current_str_index = 0, current_mode = 0;
/* test if hashing */
@ -589,35 +622,35 @@ static void traverse_subgoal_trie(sg_node_ptr current_node, char *str, int str_i
/* show answers ... */
if (IS_SUBGOAL_LEAF_NODE(current_node)) {
sg_fr_ptr sg_fr = UNTAG_SUBGOAL_LEAF_NODE(TrNode_sg_fr(current_node));
TrStat_subgoals++;
str[str_index] = 0;
SHOW_TABLE_STRUCTURE("%s.\n", str);
TrStat_ans_nodes++;
if (SgFr_first_answer(sg_fr) == NULL) {
if (SgFr_state(sg_fr) < complete) {
TrStat_sg_incomplete++;
SHOW_TABLE_STRUCTURE(" ---> INCOMPLETE\n");
sg_fr_ptr sg_fr = get_subgoal_frame(current_node);
if (sg_fr) {
TrStat_subgoals++;
str[str_index] = 0;
SHOW_TABLE_STRUCTURE("%s.\n", str);
TrStat_ans_nodes++;
if (SgFr_first_answer(sg_fr) == NULL) {
if (SgFr_state(sg_fr) < complete) {
TrStat_sg_incomplete++;
SHOW_TABLE_STRUCTURE(" ---> INCOMPLETE\n");
} else {
TrStat_answers_no++;
SHOW_TABLE_STRUCTURE(" NO\n");
}
} else if (SgFr_first_answer(sg_fr) == SgFr_answer_trie(sg_fr)) {
TrStat_answers_true++;
SHOW_TABLE_STRUCTURE(" TRUE\n");
} else {
TrStat_answers_no++;
SHOW_TABLE_STRUCTURE(" NO\n");
}
} else if (SgFr_first_answer(sg_fr) == SgFr_answer_trie(sg_fr)) {
TrStat_answers_true++;
SHOW_TABLE_STRUCTURE(" TRUE\n");
} else {
arity[0] = 0;
traverse_answer_trie(TrNode_child(SgFr_answer_trie(sg_fr)), &str[str_index], 0, arity, 0, TRAVERSE_MODE_NORMAL, TRAVERSE_POSITION_FIRST);
if (SgFr_state(sg_fr) < complete) {
TrStat_sg_incomplete++;
SHOW_TABLE_STRUCTURE(" ---> INCOMPLETE\n");
arity[0] = 0;
traverse_answer_trie(TrNode_child(SgFr_answer_trie(sg_fr)), &str[str_index], 0, arity, 0, TRAVERSE_MODE_NORMAL, TRAVERSE_POSITION_FIRST);
if (SgFr_state(sg_fr) < complete) {
TrStat_sg_incomplete++;
SHOW_TABLE_STRUCTURE(" ---> INCOMPLETE\n");
}
}
}
}
} else
/* ... or continue with child node */
else
traverse_subgoal_trie(TrNode_child(current_node), str, str_index, arity, mode, TRAVERSE_POSITION_FIRST);
/* restore the initial state and continue with sibling nodes */
if (position == TRAVERSE_POSITION_FIRST) {
str_index = current_str_index;
@ -637,12 +670,12 @@ static void traverse_subgoal_trie(sg_node_ptr current_node, char *str, int str_i
}
free(current_arity);
}
return;
}
static void traverse_answer_trie(ans_node_ptr current_node, char *str, int str_index, int *arity, int var_index, int mode, int position) {
CACHE_REGS
int *current_arity = NULL, current_str_index = 0, current_var_index = 0, current_mode = 0;
/* test if hashing */
@ -733,6 +766,7 @@ static void traverse_answer_trie(ans_node_ptr current_node, char *str, int str_i
static void traverse_global_trie(gt_node_ptr current_node, char *str, int str_index, int *arity, int mode, int position) {
CACHE_REGS
int *current_arity = NULL, current_str_index = 0, current_mode = 0;
/* test if hashing */
@ -816,6 +850,7 @@ static void traverse_global_trie_for_term(gt_node_ptr current_node, char *str, i
static inline void traverse_trie_node(Term t, char *str, int *str_index_ptr, int *arity, int *mode_ptr, int type) {
CACHE_REGS
int mode = *mode_ptr;
int str_index = *str_index_ptr;
@ -993,7 +1028,7 @@ sg_fr_ptr subgoal_search(yamop *preg, CELL **Yaddr) {
subs_arity = 0;
pred_arity = preg->u.Otapl.s;
tab_ent = preg->u.Otapl.te;
current_sg_node = TabEnt_subgoal_trie(tab_ent);
current_sg_node = get_insert_subgoal_trie(tab_ent PASS_REGS);
LOCK_SUBGOAL_TRIE(tab_ent);
#ifdef MODE_DIRECTED_TABLING
@ -1033,8 +1068,11 @@ sg_fr_ptr subgoal_search(yamop *preg, CELL **Yaddr) {
RESET_VARIABLE(t);
}
sg_fr_ptr *sg_fr_end = get_insert_subgoal_frame_addr(current_sg_node PASS_REGS);
#ifndef THREADS
LOCK_SUBGOAL_NODE(current_sg_node);
if (TrNode_sg_fr(current_sg_node) == NULL) {
#endif /* !THREADS */
if (*sg_fr_end == NULL) {
/* new tabled subgoal */
#ifdef MODE_DIRECTED_TABLING
if (subs_pos) {
@ -1043,18 +1081,46 @@ sg_fr_ptr subgoal_search(yamop *preg, CELL **Yaddr) {
} else
mode_directed = NULL;
#endif /* MODE_DIRECTED_TABLING */
#ifndef THREADS
new_subgoal_frame(sg_fr, preg, mode_directed);
TrNode_sg_fr(current_sg_node) = (sg_node_ptr) sg_fr;
*sg_fr_end = sg_fr;
TAG_AS_SUBGOAL_LEAF_NODE(current_sg_node);
UNLOCK_SUBGOAL_NODE(current_sg_node);
#else /* THREADS */
sg_ent_ptr sg_ent = (sg_ent_ptr) TrNode_sg_ent(current_sg_node);
new_subgoal_frame(sg_fr, sg_ent);
#ifdef THREADS_CONSUMER_SHARING
SgFr_state(sg_fr) = ready_external;
#else
SgFr_state(sg_fr) = ready;
#endif /* THREADS_CONSUMER_SHARING */
if (SgEnt_state(sg_ent) == ready) {
LOCK(SgEnt_lock(sg_ent));
if (SgEnt_state(sg_ent) == ready) {
SgEnt_gen_worker(sg_ent) = worker_id;
SgEnt_code(sg_ent) = preg;
SgEnt_init_mode_directed_fields(sg_ent, mode_directed);
SgEnt_state(sg_ent) = evaluating;
#ifdef THREADS_CONSUMER_SHARING
SgFr_state(sg_fr) = ready;
#endif /* THREADS_CONSUMER_SHARING */
}
UNLOCK(SgEnt_lock(sg_ent));
}
*sg_fr_end = sg_fr;
#endif /* !THREADS */
} else {
sg_fr = UNTAG_SUBGOAL_LEAF_NODE(TrNode_sg_fr(current_sg_node));
/* repeated tabled subgoal */
#ifndef THREADS
UNLOCK_SUBGOAL_NODE(current_sg_node);
#endif /* !THREADS */
sg_fr = UNTAG_SUBGOAL_NODE(*sg_fr_end);
#ifdef LIMIT_TABLING
if (SgFr_state(sg_fr) <= ready) { /* incomplete or ready */
remove_from_global_sg_fr_list(sg_fr);
}
#endif /* LIMIT_TABLING */
}
UNLOCK_SUBGOAL_NODE(current_sg_node);
UNLOCK_SUBGOAL_TRIE(tab_ent);
return sg_fr;
}
@ -1069,6 +1135,7 @@ ans_node_ptr answer_search(sg_fr_ptr sg_fr, CELL *subs_ptr) {
vars_arity = 0;
current_ans_node = SgFr_answer_trie(sg_fr);
if (IsMode_GlobalTrie(TabEnt_mode(SgFr_tab_ent(sg_fr)))) {
for (i = subs_arity; i >= 1; i--) {
TABLING_ERROR_CHECKING(answer_search, IsNonVarTerm(subs_ptr[i]));
@ -1228,6 +1295,21 @@ void update_answer_trie(sg_fr_ptr sg_fr) {
free_answer_hash_chain(SgFr_hash_chain(sg_fr));
SgFr_hash_chain(sg_fr) = NULL;
SgFr_state(sg_fr) += 2; /* complete --> compiled : complete_in_use --> compiled_in_use */
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
SgFr_sg_ent_state(sg_fr) += 2; /* complete --> compiled */
#ifdef THREADS_FULL_SHARING
if (IsMode_Batched(TabEnt_mode(SgFr_tab_ent(sg_fr)))) {
/* cleaning bits used by batched mode and shifting the instruction back to the original place */
ans_node_ptr leaf_ans_trie_node = SgFr_first_answer(sg_fr);
while (TrNode_child(leaf_ans_trie_node) != NULL) {
ANSWER_LEAF_NODE_INSTR_ABSOLUTE(leaf_ans_trie_node);
leaf_ans_trie_node = TrNode_child(leaf_ans_trie_node);
}
ANSWER_LEAF_NODE_INSTR_ABSOLUTE(leaf_ans_trie_node);
}
#endif /* THREADS_FULL_SHARING */
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
current_node = TrNode_child(SgFr_answer_trie(sg_fr));
if (current_node) {
#ifdef YAPOR
@ -1248,6 +1330,28 @@ void update_answer_trie(sg_fr_ptr sg_fr) {
void free_subgoal_trie(sg_node_ptr current_node, int mode, int position) {
CACHE_REGS
if (IS_SUBGOAL_TRIE_HASH(current_node)) {
sg_node_ptr *bucket, *last_bucket;
sg_hash_ptr hash;
hash = (sg_hash_ptr) current_node;
bucket = Hash_buckets(hash);
last_bucket = bucket + Hash_num_buckets(hash);
do {
if (*bucket) {
sg_node_ptr next_node = *bucket;
do {
current_node = next_node;
next_node = TrNode_next(current_node);
free_subgoal_trie(current_node, mode, TRAVERSE_POSITION_NEXT);
} while (next_node);
}
} while (++bucket != last_bucket);
IF_ABOLISH_SUBGOAL_TRIE_SHARED_DATA_STRUCTURES {
FREE_BUCKETS(Hash_buckets(hash));
FREE_SUBGOAL_TRIE_HASH(hash);
}
return;
}
if (! IS_SUBGOAL_LEAF_NODE(current_node)) {
int child_mode;
if (mode == TRAVERSE_MODE_NORMAL) {
@ -1274,43 +1378,53 @@ void free_subgoal_trie(sg_node_ptr current_node, int mode, int position) {
child_mode = TRAVERSE_MODE_NORMAL;
free_subgoal_trie(TrNode_child(current_node), child_mode, TRAVERSE_POSITION_FIRST);
} else {
sg_fr_ptr sg_fr;
ans_node_ptr ans_node;
sg_fr = UNTAG_SUBGOAL_LEAF_NODE(TrNode_sg_fr(current_node));
free_answer_hash_chain(SgFr_hash_chain(sg_fr));
ans_node = SgFr_answer_trie(sg_fr);
if (TrNode_child(ans_node))
free_answer_trie(TrNode_child(ans_node), TRAVERSE_MODE_NORMAL, TRAVERSE_POSITION_FIRST);
FREE_ANSWER_TRIE_NODE(ans_node);
#if defined(MODE_DIRECTED_TABLING) && defined(YAPOR)
if (SgFr_invalid_chain(sg_fr)) {
ans_node_ptr next_node, invalid_node = SgFr_invalid_chain(sg_fr);
SgFr_invalid_chain(sg_fr) = NULL;
/* free invalid answer nodes */
while (invalid_node) {
next_node = TrNode_next(invalid_node);
FREE_ANSWER_TRIE_NODE(invalid_node);
invalid_node = next_node;
sg_fr_ptr sg_fr = get_subgoal_frame_for_abolish(current_node PASS_REGS);
if (sg_fr) {
ans_node_ptr ans_node;
free_answer_hash_chain(SgFr_hash_chain(sg_fr));
ans_node = SgFr_answer_trie(sg_fr);
if (TrNode_child(ans_node))
free_answer_trie(TrNode_child(ans_node), TRAVERSE_MODE_NORMAL, TRAVERSE_POSITION_FIRST);
IF_ABOLISH_ANSWER_TRIE_SHARED_DATA_STRUCTURES {
FREE_ANSWER_TRIE_NODE(ans_node);
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
FREE_SUBGOAL_ENTRY(SgFr_sg_ent(sg_fr));
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
}
#if defined(MODE_DIRECTED_TABLING) && defined(YAPOR)
if (SgFr_invalid_chain(sg_fr)) {
ans_node_ptr next_node, invalid_node = SgFr_invalid_chain(sg_fr);
SgFr_invalid_chain(sg_fr) = NULL;
/* free invalid answer nodes */
while (invalid_node) {
next_node = TrNode_next(invalid_node);
FREE_ANSWER_TRIE_NODE(invalid_node);
invalid_node = next_node;
}
}
}
#endif /* MODE_DIRECTED_TABLING && YAPOR */
#ifdef LIMIT_TABLING
remove_from_global_sg_fr_list(sg_fr);
remove_from_global_sg_fr_list(sg_fr);
#endif /* LIMIT_TABLING */
FREE_SUBGOAL_FRAME(sg_fr);
FREE_SUBGOAL_FRAME(sg_fr);
}
}
if (position == TRAVERSE_POSITION_FIRST) {
sg_node_ptr next_node = TrNode_next(current_node);
CHECK_DECREMENT_GLOBAL_TRIE_REFERENCE(TrNode_entry(current_node), mode);
FREE_SUBGOAL_TRIE_NODE(current_node);
IF_ABOLISH_SUBGOAL_TRIE_SHARED_DATA_STRUCTURES {
CHECK_DECREMENT_GLOBAL_TRIE_REFERENCE(TrNode_entry(current_node), mode);
FREE_SUBGOAL_TRIE_NODE(current_node);
}
while (next_node) {
current_node = next_node;
next_node = TrNode_next(current_node);
free_subgoal_trie(current_node, mode, TRAVERSE_POSITION_NEXT);
}
} else {
CHECK_DECREMENT_GLOBAL_TRIE_REFERENCE(TrNode_entry(current_node), mode);
FREE_SUBGOAL_TRIE_NODE(current_node);
IF_ABOLISH_SUBGOAL_TRIE_SHARED_DATA_STRUCTURES {
CHECK_DECREMENT_GLOBAL_TRIE_REFERENCE(TrNode_entry(current_node), mode);
FREE_SUBGOAL_TRIE_NODE(current_node);
}
}
return;
}
@ -1351,46 +1465,20 @@ void free_answer_trie(ans_node_ptr current_node, int mode, int position) {
}
if (position == TRAVERSE_POSITION_FIRST) {
ans_node_ptr next_node = TrNode_next(current_node);
CHECK_DECREMENT_GLOBAL_TRIE_REFERENCE(TrNode_entry(current_node), mode);
FREE_ANSWER_TRIE_NODE(current_node);
IF_ABOLISH_ANSWER_TRIE_SHARED_DATA_STRUCTURES {
CHECK_DECREMENT_GLOBAL_TRIE_REFERENCE(TrNode_entry(current_node), mode);
FREE_ANSWER_TRIE_NODE(current_node);
}
while (next_node) {
current_node = next_node;
next_node = TrNode_next(current_node);
free_answer_trie(current_node, mode, TRAVERSE_POSITION_NEXT);
}
} else {
CHECK_DECREMENT_GLOBAL_TRIE_REFERENCE(TrNode_entry(current_node), mode);
FREE_ANSWER_TRIE_NODE(current_node);
}
return;
}
void free_subgoal_hash_chain(sg_hash_ptr hash) {
CACHE_REGS
while (hash) {
sg_node_ptr chain_node, *bucket, *last_bucket;
sg_hash_ptr next_hash;
bucket = Hash_buckets(hash);
last_bucket = bucket + Hash_num_buckets(hash);
while (! *bucket)
bucket++;
chain_node = *bucket;
TrNode_child(TrNode_parent(chain_node)) = chain_node;
while (++bucket != last_bucket) {
if (*bucket) {
while (TrNode_next(chain_node))
chain_node = TrNode_next(chain_node);
TrNode_next(chain_node) = *bucket;
chain_node = *bucket;
}
IF_ABOLISH_ANSWER_TRIE_SHARED_DATA_STRUCTURES {
CHECK_DECREMENT_GLOBAL_TRIE_REFERENCE(TrNode_entry(current_node), mode);
FREE_ANSWER_TRIE_NODE(current_node);
}
next_hash = Hash_next(hash);
FREE_HASH_BUCKETS(Hash_buckets(hash));
FREE_SUBGOAL_TRIE_HASH(hash);
hash = next_hash;
}
return;
}
@ -1408,7 +1496,7 @@ void free_answer_hash_chain(ans_hash_ptr hash) {
while (! *bucket)
bucket++;
chain_node = *bucket;
TrNode_child(UNTAG_ANSWER_LEAF_NODE(TrNode_parent(chain_node))) = chain_node;
TrNode_child(UNTAG_ANSWER_NODE(TrNode_parent(chain_node))) = chain_node;
while (++bucket != last_bucket) {
if (*bucket) {
while (TrNode_next(chain_node))
@ -1418,7 +1506,7 @@ void free_answer_hash_chain(ans_hash_ptr hash) {
}
}
next_hash = Hash_next(hash);
FREE_HASH_BUCKETS(Hash_buckets(hash));
FREE_BUCKETS(Hash_buckets(hash));
FREE_ANSWER_TRIE_HASH(hash);
hash = next_hash;
}
@ -1426,28 +1514,68 @@ void free_answer_hash_chain(ans_hash_ptr hash) {
}
/***********************************************************************************************************************
** - main thread (worker_id 0) abolishes its local and all shared data structures. **
** - all other threads only abolish their local data structures. **
** - for the main thread, we assume that all other threads have the table clean (i.e., without local data structures) **
** and that they will be not using the table during the abolish operation. **
***********************************************************************************************************************/
void abolish_table(tab_ent_ptr tab_ent) {
CACHE_REGS
sg_node_ptr sg_node;
sg_node = get_subgoal_trie_for_abolish(tab_ent PASS_REGS);
if (sg_node) {
if (TrNode_child(sg_node)) {
if (TabEnt_arity(tab_ent)) {
free_subgoal_trie(TrNode_child(sg_node), TRAVERSE_MODE_NORMAL, TRAVERSE_POSITION_FIRST);
} else {
sg_fr_ptr sg_fr = get_subgoal_frame_for_abolish(sg_node PASS_REGS);
if (sg_fr) {
IF_ABOLISH_ANSWER_TRIE_SHARED_DATA_STRUCTURES {
FREE_ANSWER_TRIE_NODE(SgFr_answer_trie(sg_fr));
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
FREE_SUBGOAL_ENTRY(SgFr_sg_ent(sg_fr));
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
}
#ifdef LIMIT_TABLING
remove_from_global_sg_fr_list(sg_fr);
#endif /* LIMIT_TABLING */
FREE_SUBGOAL_FRAME(sg_fr);
}
}
IF_ABOLISH_SUBGOAL_TRIE_SHARED_DATA_STRUCTURES
TrNode_child(sg_node) = NULL;
}
#ifdef THREADS_NO_SHARING
FREE_SUBGOAL_TRIE_NODE(sg_node);
#endif /* THREADS_NO_SHARING */
}
return;
}
void show_table(tab_ent_ptr tab_ent, int show_mode, IOSTREAM *out) {
CACHE_REGS
sg_node_ptr sg_node;
TrStat_out = out;
TrStat_show = show_mode;
if (show_mode == SHOW_MODE_STATISTICS) {
TrStat_subgoals = 0;
TrStat_sg_incomplete = 0;
TrStat_sg_nodes = 1;
TrStat_answers = 0;
TrStat_answers_true = 0;
TrStat_answers_no = 0;
TrStat_subgoals = 0;
TrStat_sg_incomplete = 0;
TrStat_sg_nodes = 1;
TrStat_answers = 0;
TrStat_answers_true = 0;
TrStat_answers_no = 0;
#ifdef TABLING_INNER_CUTS
TrStat_answers_pruned = 0;
TrStat_answers_pruned = 0;
#endif /* TABLING_INNER_CUTS */
TrStat_ans_nodes = 0;
TrStat_gt_refs = 0;
TrStat_ans_nodes = 0;
TrStat_gt_refs = 0;
if (show_mode == SHOW_MODE_STATISTICS)
Sfprintf(TrStat_out, "Table statistics for predicate '%s", AtomName(TabEnt_atom(tab_ent)));
} else { /* SHOW_MODE_STRUCTURE */
else /* SHOW_MODE_STRUCTURE */
Sfprintf(TrStat_out, "Table structure for predicate '%s", AtomName(TabEnt_atom(tab_ent)));
}
#ifdef MODE_DIRECTED_TABLING
if (TabEnt_mode_directed(tab_ent)) {
int i, *mode_directed = TabEnt_mode_directed(tab_ent);
@ -1475,36 +1603,41 @@ void show_table(tab_ent_ptr tab_ent, int show_mode, IOSTREAM *out) {
} else
#endif /* MODE_DIRECTED_TABLING */
Sfprintf(TrStat_out, "/%d'\n", TabEnt_arity(tab_ent));
sg_node = TrNode_child(TabEnt_subgoal_trie(tab_ent));
sg_node = get_subgoal_trie(tab_ent);
if (sg_node) {
if (TabEnt_arity(tab_ent)) {
char *str = (char *) malloc(sizeof(char) * SHOW_TABLE_STR_ARRAY_SIZE);
int str_index = sprintf(str, " ?- %s(", AtomName(TabEnt_atom(tab_ent)));
int *arity = (int *) malloc(sizeof(int) * SHOW_TABLE_ARITY_ARRAY_SIZE);
arity[0] = 1;
arity[1] = TabEnt_arity(tab_ent);
traverse_subgoal_trie(sg_node, str, str_index, arity, TRAVERSE_MODE_NORMAL, TRAVERSE_POSITION_FIRST);
free(str);
free(arity);
} else {
sg_fr_ptr sg_fr = UNTAG_SUBGOAL_LEAF_NODE(sg_node);
TrStat_subgoals++;
SHOW_TABLE_STRUCTURE(" ?- %s.\n", AtomName(TabEnt_atom(tab_ent)));
TrStat_ans_nodes++;
if (SgFr_first_answer(sg_fr) == NULL) {
if (SgFr_state(sg_fr) < complete) {
TrStat_sg_incomplete++;
SHOW_TABLE_STRUCTURE(" ---> INCOMPLETE\n");
} else {
TrStat_answers_no++;
SHOW_TABLE_STRUCTURE(" NO\n");
if (TrNode_child(sg_node)) {
if (TabEnt_arity(tab_ent)) {
char *str = (char *) malloc(sizeof(char) * SHOW_TABLE_STR_ARRAY_SIZE);
int *arity = (int *) malloc(sizeof(int) * SHOW_TABLE_ARITY_ARRAY_SIZE);
arity[0] = 1;
arity[1] = TabEnt_arity(tab_ent);
int str_index = sprintf(str, " ?- %s(", AtomName(TabEnt_atom(tab_ent)));
traverse_subgoal_trie(TrNode_child(sg_node), str, str_index, arity, TRAVERSE_MODE_NORMAL, TRAVERSE_POSITION_FIRST);
free(str);
free(arity);
} else {
sg_fr_ptr sg_fr = get_subgoal_frame(sg_node);
if (sg_fr) {
TrStat_subgoals++;
SHOW_TABLE_STRUCTURE(" ?- %s.\n", AtomName(TabEnt_atom(tab_ent)));
TrStat_ans_nodes++;
if (SgFr_first_answer(sg_fr) == NULL) {
if (SgFr_state(sg_fr) < complete) {
TrStat_sg_incomplete++;
SHOW_TABLE_STRUCTURE(" ---> INCOMPLETE\n");
} else {
TrStat_answers_no++;
SHOW_TABLE_STRUCTURE(" NO\n");
}
} else { /* SgFr_first_answer(sg_fr) == SgFr_answer_trie(sg_fr) */
TrStat_answers_true++;
SHOW_TABLE_STRUCTURE(" TRUE\n");
}
}
} else { /* SgFr_first_answer(sg_fr) == SgFr_answer_trie(sg_fr) */
TrStat_answers_true++;
SHOW_TABLE_STRUCTURE(" TRUE\n");
}
}
} else
}
if (TrStat_subgoals == 0)
SHOW_TABLE_STRUCTURE(" EMPTY\n");
if (show_mode == SHOW_MODE_STATISTICS) {
Sfprintf(TrStat_out, " Subgoal trie structure\n");
@ -1526,16 +1659,17 @@ void show_table(tab_ent_ptr tab_ent, int show_mode, IOSTREAM *out) {
void show_global_trie(int show_mode, IOSTREAM *out) {
CACHE_REGS
TrStat_out = out;
TrStat_show = show_mode;
if (show_mode == SHOW_MODE_STATISTICS) {
TrStat_gt_terms = 0;
TrStat_gt_nodes = 1;
TrStat_gt_refs = 0;
TrStat_gt_terms = 0;
TrStat_gt_nodes = 1;
TrStat_gt_refs = 0;
if (show_mode == SHOW_MODE_STATISTICS)
Sfprintf(TrStat_out, "Global trie statistics\n");
} else { /* SHOW_MODE_STRUCTURE */
else /* SHOW_MODE_STRUCTURE */
Sfprintf(TrStat_out, "Global trie structure\n");
}
if (TrNode_child(GLOBAL_root_gt)) {
char *str = (char *) malloc(sizeof(char) * SHOW_TABLE_STR_ARRAY_SIZE);
int *arity = (int *) malloc(sizeof(int) * SHOW_TABLE_ARITY_ARRAY_SIZE);
@ -1552,6 +1686,4 @@ void show_global_trie(int show_mode, IOSTREAM *out) {
}
return;
}
#endif /* TABLING */

View File

@ -64,7 +64,9 @@ static inline sg_node_ptr subgoal_trie_check_insert_gt_entry(tab_ent_ptr tab_ent
#else
static inline sg_node_ptr subgoal_trie_check_insert_entry(tab_ent_ptr tab_ent, sg_node_ptr parent_node, Term t) {
#endif /* MODE_GLOBAL_TRIE_ENTRY */
#ifdef THREADS_NO_SHARING
CACHE_REGS
#endif /* THREADS_NO_SHARING */
sg_node_ptr child_node;
LOCK_SUBGOAL_NODE(parent_node);
@ -133,7 +135,7 @@ static inline sg_node_ptr subgoal_trie_check_insert_entry(tab_ent_ptr tab_ent, s
sg_node_ptr chain_node, next_node, *old_bucket, *old_hash_buckets, *new_hash_buckets;
int num_buckets;
num_buckets = Hash_num_buckets(hash) * 2;
ALLOC_HASH_BUCKETS(new_hash_buckets, num_buckets);
ALLOC_BUCKETS(new_hash_buckets, num_buckets);
old_hash_buckets = Hash_buckets(hash);
old_bucket = old_hash_buckets + Hash_num_buckets(hash);
do {
@ -150,7 +152,7 @@ static inline sg_node_ptr subgoal_trie_check_insert_entry(tab_ent_ptr tab_ent, s
} while (old_bucket != old_hash_buckets);
Hash_buckets(hash) = new_hash_buckets;
Hash_num_buckets(hash) = num_buckets;
FREE_HASH_BUCKETS(old_hash_buckets);
FREE_BUCKETS(old_hash_buckets);
}
UNLOCK_SUBGOAL_NODE(parent_node);
return child_node;
@ -162,6 +164,9 @@ static inline sg_node_ptr subgoal_trie_check_insert_gt_entry(tab_ent_ptr tab_ent
#else
static inline sg_node_ptr subgoal_trie_check_insert_entry(tab_ent_ptr tab_ent, sg_node_ptr parent_node, Term t) {
#endif /* MODE_GLOBAL_TRIE_ENTRY */
#ifdef THREADS_NO_SHARING
CACHE_REGS
#endif /* THREADS_NO_SHARING */
sg_node_ptr child_node;
sg_hash_ptr hash;
@ -325,7 +330,7 @@ subgoal_trie_hash:
/* expand current hash */
sg_node_ptr chain_node, next_node, *old_bucket, *old_hash_buckets, *new_hash_buckets;
num_buckets = Hash_num_buckets(hash) * 2;
ALLOC_HASH_BUCKETS(new_hash_buckets, num_buckets);
ALLOC_BUCKETS(new_hash_buckets, num_buckets);
old_hash_buckets = Hash_buckets(hash);
old_bucket = old_hash_buckets + Hash_num_buckets(hash);
do {
@ -342,7 +347,7 @@ subgoal_trie_hash:
} while (old_bucket != old_hash_buckets);
Hash_buckets(hash) = new_hash_buckets;
Hash_num_buckets(hash) = num_buckets;
FREE_HASH_BUCKETS(old_hash_buckets);
FREE_BUCKETS(old_hash_buckets);
}
UNLOCK_SUBGOAL_NODE(parent_node);
return child_node;
@ -434,7 +439,7 @@ static inline ans_node_ptr answer_trie_check_insert_entry(sg_fr_ptr sg_fr, ans_n
ans_node_ptr chain_node, next_node, *old_bucket, *old_hash_buckets, *new_hash_buckets;
int num_buckets;
num_buckets = Hash_num_buckets(hash) * 2;
ALLOC_HASH_BUCKETS(new_hash_buckets, num_buckets);
ALLOC_BUCKETS(new_hash_buckets, num_buckets);
old_hash_buckets = Hash_buckets(hash);
old_bucket = old_hash_buckets + Hash_num_buckets(hash);
do {
@ -451,7 +456,7 @@ static inline ans_node_ptr answer_trie_check_insert_entry(sg_fr_ptr sg_fr, ans_n
} while (old_bucket != old_hash_buckets);
Hash_buckets(hash) = new_hash_buckets;
Hash_num_buckets(hash) = num_buckets;
FREE_HASH_BUCKETS(old_hash_buckets);
FREE_BUCKETS(old_hash_buckets);
}
UNLOCK_ANSWER_NODE(parent_node);
return child_node;
@ -463,6 +468,7 @@ static inline ans_node_ptr answer_trie_check_insert_gt_entry(sg_fr_ptr sg_fr, an
#else
static inline ans_node_ptr answer_trie_check_insert_entry(sg_fr_ptr sg_fr, ans_node_ptr parent_node, Term t, int instr) {
#endif /* MODE_GLOBAL_TRIE_ENTRY */
CACHE_REGS
ans_node_ptr child_node;
ans_hash_ptr hash;
@ -627,7 +633,7 @@ answer_trie_hash:
/* expand current hash */
ans_node_ptr chain_node, next_node, *old_bucket, *old_hash_buckets, *new_hash_buckets;
num_buckets = Hash_num_buckets(hash) * 2;
ALLOC_HASH_BUCKETS(new_hash_buckets, num_buckets);
ALLOC_BUCKETS(new_hash_buckets, num_buckets);
old_hash_buckets = Hash_buckets(hash);
old_bucket = old_hash_buckets + Hash_num_buckets(hash);
do {
@ -644,7 +650,7 @@ answer_trie_hash:
} while (old_bucket != old_hash_buckets);
Hash_buckets(hash) = new_hash_buckets;
Hash_num_buckets(hash) = num_buckets;
FREE_HASH_BUCKETS(old_hash_buckets);
FREE_BUCKETS(old_hash_buckets);
}
UNLOCK_ANSWER_NODE(parent_node);
return child_node;
@ -734,7 +740,7 @@ static inline gt_node_ptr global_trie_check_insert_entry(gt_node_ptr parent_node
gt_node_ptr chain_node, next_node, *old_bucket, *old_hash_buckets, *new_hash_buckets;
int num_buckets;
num_buckets = Hash_num_buckets(hash) * 2;
ALLOC_HASH_BUCKETS(new_hash_buckets, num_buckets);
ALLOC_BUCKETS(new_hash_buckets, num_buckets);
old_hash_buckets = Hash_buckets(hash);
old_bucket = old_hash_buckets + Hash_num_buckets(hash);
do {
@ -751,7 +757,7 @@ static inline gt_node_ptr global_trie_check_insert_entry(gt_node_ptr parent_node
} while (old_bucket != old_hash_buckets);
Hash_buckets(hash) = new_hash_buckets;
Hash_num_buckets(hash) = num_buckets;
FREE_HASH_BUCKETS(old_hash_buckets);
FREE_BUCKETS(old_hash_buckets);
}
UNLOCK_GLOBAL_NODE(parent_node);
return child_node;
@ -927,7 +933,7 @@ global_trie_hash:
/* expand current hash */
gt_node_ptr chain_node, next_node, *old_bucket, *old_hash_buckets, *new_hash_buckets;
num_buckets = Hash_num_buckets(hash) * 2;
ALLOC_HASH_BUCKETS(new_hash_buckets, num_buckets);
ALLOC_BUCKETS(new_hash_buckets, num_buckets);
old_hash_buckets = Hash_buckets(hash);
old_bucket = old_hash_buckets + Hash_num_buckets(hash);
do {
@ -944,7 +950,7 @@ global_trie_hash:
} while (old_bucket != old_hash_buckets);
Hash_buckets(hash) = new_hash_buckets;
Hash_num_buckets(hash) = num_buckets;
FREE_HASH_BUCKETS(old_hash_buckets);
FREE_BUCKETS(old_hash_buckets);
}
UNLOCK_GLOBAL_NODE(parent_node);
return child_node;
@ -1498,7 +1504,7 @@ static inline ans_node_ptr answer_search_min_max(sg_fr_ptr sg_fr, ans_node_ptr c
FREE_ANSWER_TRIE_NODE(NODE)
#endif /* YAPOR */
#define INVALIDATE_ANSWER_TRIE_LEAF_NODE(NODE, SG_FR) \
TAG_AS_INVALID_LEAF_NODE(NODE); \
TAG_AS_ANSWER_INVALID_NODE(NODE); \
TrNode_next(NODE) = SgFr_invalid_chain(SG_FR); \
SgFr_invalid_chain(SG_FR) = NODE
@ -1534,7 +1540,7 @@ static void invalidate_answer_trie(ans_node_ptr current_node, sg_fr_ptr sg_fr, i
Hash_next(Hash_previous(hash)) = Hash_next(hash);
else
SgFr_hash_chain(sg_fr) = Hash_next(hash);
FREE_HASH_BUCKETS(Hash_buckets(hash));
FREE_BUCKETS(Hash_buckets(hash));
FREE_ANSWER_TRIE_HASH(hash);
} else {
if (position == TRAVERSE_POSITION_FIRST) {
@ -1619,7 +1625,7 @@ static inline CELL *load_answer_loop(ans_node_ptr current_node) {
#ifdef MODE_GLOBAL_TRIE_LOOP
current_node = TrNode_parent(current_node);
#else
current_node = UNTAG_ANSWER_LEAF_NODE(TrNode_parent(current_node));
current_node = UNTAG_ANSWER_NODE(TrNode_parent(current_node));
#endif /* MODE_GLOBAL_TRIE_LOOP */
do {

View File

@ -189,10 +189,13 @@ yamop getwork_seq_code[1] GETWORK_SEQ InitOtaplInst(GETWORK_SEQ,_getwork_seq,P
yamop getwork_first_time[1] GETWORK_FIRST_TIME MkInstE _getwork_first_time
#endif /* YAPOR */
#ifdef TABLING
yamop table_load_answer_code[1] LOAD_ANSWER InitOtaplInst(LOAD_ANSWER,_table_load_answer,PredFail) RestoreOtaplInst(LOAD_ANSWER,_table_load_answer,PredFail)
yamop table_try_answer_code[1] TRY_ANSWER InitOtaplInst(TRY_ANSWER,_table_try_answer,PredFail) RestoreOtaplInst(TRY_ANSWER,_table_try_answer,PredFail)
yamop table_answer_resolution_code[1] ANSWER_RESOLUTION InitOtaplInst(ANSWER_RESOLUTION,_table_answer_resolution,PredFail) RestoreOtaplInst(ANSWER_RESOLUTION,_table_answer_resolution,PredFail)
yamop table_load_answer_code[1] LOAD_ANSWER InitOtaplInst(LOAD_ANSWER,_table_load_answer,PredFail) RestoreOtaplInst(LOAD_ANSWER,_table_load_answer,PredFail)
yamop table_try_answer_code[1] TRY_ANSWER InitOtaplInst(TRY_ANSWER,_table_try_answer,PredFail) RestoreOtaplInst(TRY_ANSWER,_table_try_answer,PredFail)
yamop table_answer_resolution_code[1] ANSWER_RESOLUTION InitOtaplInst(ANSWER_RESOLUTION,_table_answer_resolution,PredFail) RestoreOtaplInst(ANSWER_RESOLUTION,_table_answer_resolution,PredFail)
yamop table_completion_code[1] COMPLETION InitOtaplInst(COMPLETION,_table_completion,PredFail) RestoreOtaplInst(COMPLETION,_table_completion,PredFail)
#ifdef THREADS_CONSUMER_SHARING
yamop table_answer_resolution_completion_code[1] ANSWER_RESOLUTION_COMPLETION InitOtaplInst(ANSWER_RESOLUTION_COMPLETION,_table_answer_resolution_completion,PredFail) RestoreOtaplInst(ANSWER_RESOLUTION_COMPLETION,_table_answer_resolution_completion,PredFail)
#endif /* THREADS_CONSUMER_SHARING */
#endif /* TABLING */
/* */

View File

@ -164,6 +164,7 @@ end_special(Name, W) :-
end_special(_, _).
special_op("clause_with_cut","TABLING_INNER_CUTS").
special_op("table_answer_resolution_completion","THREADS_CONSUMER_SHARING").
special_op("cut_c","CUT_C").
special_op("cut_userc","CUT_C").
special_op("run_eam","BEAM").