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_retry:
case _table_trust: case _table_trust:
case _table_completion: case _table_completion:
#ifdef THREADS_CONSUMER_SHARING
case _table_answer_resolution_completion:
#endif /* THREADS_CONSUMER_SHARING */
#ifdef DETERMINISTIC_TABLING #ifdef DETERMINISTIC_TABLING
if (IS_DET_GEN_CP(B)) if (IS_DET_GEN_CP(B))
low_level_trace(retry_table_generator, DET_GEN_CP(B)->cp_pred_entry, NULL); 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_try_answer:
case _table_answer_resolution: case _table_answer_resolution:
case _table_completion: case _table_completion:
#ifdef THREADS_CONSUMER_SHARING
case _table_answer_resolution_completion:
#endif /* THREADS_CONSUMER_SHARING */
return NULL; /* ricroc: is this OK? */ return NULL; /* ricroc: is this OK? */
/* compile error --> return ENV_ToP(gc_B->cp_cp); */ /* compile error --> return ENV_ToP(gc_B->cp_cp); */
#endif /* TABLING */ #endif /* TABLING */
@ -5486,6 +5489,9 @@ p_choicepoint_info( USES_REGS1 )
case _table_retry: case _table_retry:
case _table_trust: case _table_trust:
case _table_completion: case _table_completion:
#ifdef THREADS_CONSUMER_SHARING
case _table_answer_resolution_completion:
#endif /* THREADS_CONSUMER_SHARING */
#ifdef LOW_LEVEL_TRACER #ifdef LOW_LEVEL_TRACER
#ifdef DETERMINISTIC_TABLING #ifdef DETERMINISTIC_TABLING
if (IS_DET_GEN_CP(cptr)) { 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; nargs = 0;
break; break;
case _table_completion: case _table_completion:
#ifdef THREADS_CONSUMER_SHARING
case _table_answer_resolution_completion:
#endif /* THREADS_CONSUMER_SHARING */
{ {
CELL *vars_ptr, vars; CELL *vars_ptr, vars;
#ifdef DETERMINISTIC_TABLING #ifdef DETERMINISTIC_TABLING
@ -3035,6 +3038,9 @@ sweep_choicepoints(choiceptr gc_B USES_REGS)
} }
break; break;
case _table_completion: case _table_completion:
#ifdef THREADS_CONSUMER_SHARING
case _table_answer_resolution_completion:
#endif /* THREADS_CONSUMER_SHARING */
{ {
int nargs; int nargs;
CELL *vars_ptr, vars; CELL *vars_ptr, vars;

View File

@ -27,6 +27,9 @@ static char SccsId[] = "%W% %G%";
#if HAVE_STRING_H #if HAVE_STRING_H
#include <string.h> #include <string.h>
#endif #endif
#ifdef TABLING
#include "tab.macros.h"
#endif /* TABLING */
#if THREADS #if THREADS
@ -174,6 +177,20 @@ kill_thread_engine (int wid, int always_die)
static void static void
thread_die(int wid, int always_die) 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) { if (!always_die) {
/* called by thread itself */ /* called by thread itself */
GLOBAL_ThreadsTotalTime += Yap_cputime(); GLOBAL_ThreadsTotalTime += Yap_cputime();
@ -208,7 +225,7 @@ setup_engine(int myworker_id, int init_thread)
DEBUG_TLOCK_ACCESS(2, myworker_id); DEBUG_TLOCK_ACCESS(2, myworker_id);
pthread_mutex_unlock(&(REMOTE_ThreadHandle(myworker_id).tlock)); pthread_mutex_unlock(&(REMOTE_ThreadHandle(myworker_id).tlock));
#ifdef TABLING #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 */ #endif /* TABLING */
return TRUE; return TRUE;
} }
@ -226,7 +243,14 @@ thread_run(void *widp)
Term tgoal, t; Term tgoal, t;
Term tgs[2]; Term tgs[2];
int myworker_id = *((int *)widp); 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); start_thread(myworker_id);
regcache = ((REGSTORE *)pthread_getspecific(Yap_yaamregs_key)); regcache = ((REGSTORE *)pthread_getspecific(Yap_yaamregs_key));
do { do {
@ -772,8 +796,8 @@ p_thread_stacks( USES_REGS1 )
Int status= TRUE; Int status= TRUE;
LOCK(GLOBAL_ThreadHandlesLock); LOCK(GLOBAL_ThreadHandlesLock);
if (!REMOTE_ThreadHandle(tid).in_use && if (!Yap_local[tid] ||
!REMOTE_ThreadHandle(tid).zombie) { (!REMOTE_ThreadHandle(tid).in_use && !REMOTE_ThreadHandle(tid).zombie)) {
UNLOCK(GLOBAL_ThreadHandlesLock); UNLOCK(GLOBAL_ThreadHandlesLock);
return FALSE; return FALSE;
} }

View File

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

View File

@ -179,6 +179,9 @@
#define TRY_ANSWER Yap_heap_regs->table_try_answer_code #define TRY_ANSWER Yap_heap_regs->table_try_answer_code
#define ANSWER_RESOLUTION Yap_heap_regs->table_answer_resolution_code #define ANSWER_RESOLUTION Yap_heap_regs->table_answer_resolution_code
#define COMPLETION Yap_heap_regs->table_completion_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 */ #endif /* TABLING */

View File

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

View File

@ -179,6 +179,9 @@
InitOtaplInst(TRY_ANSWER,_table_try_answer,PredFail); InitOtaplInst(TRY_ANSWER,_table_try_answer,PredFail);
InitOtaplInst(ANSWER_RESOLUTION,_table_answer_resolution,PredFail); InitOtaplInst(ANSWER_RESOLUTION,_table_answer_resolution,PredFail);
InitOtaplInst(COMPLETION,_table_completion,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 */ #endif /* TABLING */

View File

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

View File

@ -179,6 +179,9 @@
RestoreOtaplInst(TRY_ANSWER,_table_try_answer,PredFail); RestoreOtaplInst(TRY_ANSWER,_table_try_answer,PredFail);
RestoreOtaplInst(ANSWER_RESOLUTION,_table_answer_resolution,PredFail); RestoreOtaplInst(ANSWER_RESOLUTION,_table_answer_resolution,PredFail);
RestoreOtaplInst(COMPLETION,_table_completion,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 */ #endif /* TABLING */

View File

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

View File

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

View File

@ -22,8 +22,9 @@
****************************/ ****************************/
#define MAX_TABLE_VARS 1000 #define MAX_TABLE_VARS 1000
#define TRIE_LOCK_BUCKETS 512 #define TRIE_LOCK_BUCKETS 512
#define THREADS_FIRST_LEVEL_BUCKETS 16 #define THREADS_DIRECT_BUCKETS 32
#define THREADS_SECOND_LEVEL_BUCKETS (MAX_THREADS / THREADS_FIRST_LEVEL_BUCKETS) /* 64 (1024/16) */ #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 TG_ANSWER_SLOTS 20
#define MAX_LENGTH_ANSWER 1000 #define MAX_LENGTH_ANSWER 1000
#define MAX_BRANCH_DEPTH 1000 #define MAX_BRANCH_DEPTH 1000
@ -48,9 +49,9 @@
/************************************************************************ /************************************************************************
** multithreading design for tabling (mandatory, define one) ** ** multithreading design for tabling (mandatory, define one) **
************************************************************************/ ************************************************************************/
#define THREADS_NO_SHARING 1 //#define THREADS_NO_SHARING 1
/* #define THREADS_SUBGOAL_SHARING 1 */ #define THREADS_SUBGOAL_SHARING 1
/* #define THREADS_FULL_SHARING 1 */ //#define THREADS_FULL_SHARING 1
/* #define THREADS_CONSUMER_SHARING 1 */ /* #define THREADS_CONSUMER_SHARING 1 */
/************************************************************************* /*************************************************************************
@ -327,11 +328,7 @@
#undef TIMESTAMP_CHECK #undef TIMESTAMP_CHECK
#endif #endif
#if defined(TABLING) && defined(THREADS) #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
#undef OUTPUT_THREADS_TABLING #undef OUTPUT_THREADS_TABLING
#endif #endif
@ -344,10 +341,9 @@
#endif #endif
#if defined(YAPOR) || defined(THREADS) #if defined(YAPOR) || defined(THREADS)
#undef MODE_DIRECTED_TABLING
#undef TABLING_EARLY_COMPLETION #undef TABLING_EARLY_COMPLETION
#undef INCOMPLETE_TABLING #undef INCOMPLETE_TABLING
#undef LIMIT_TABLING #undef LIMIT_TABLING
#undef DETERMINISTIC_TABLING #undef DETERMINISTIC_TABLING
#endif #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; GLOBAL_check_sg_fr = NULL;
#endif /* LIMIT_TABLING */ #endif /* LIMIT_TABLING */
#ifdef YAPOR #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 */ #endif /* YAPOR */
for (i = 0; i < MAX_TABLE_VARS; i++) { for (i = 0; i < MAX_TABLE_VARS; i++) {
CELL *pt = GLOBAL_table_var_enumerator_addr(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) { void Yap_init_local_optyap_data(int wid) {
#ifdef THREADS_CONSUMER_SHARING
CACHE_REGS CACHE_REGS
#endif /* THREADS_CONSUMER_SHARING */
#if defined(TABLING) && (defined(YAPOR) || defined(THREADS)) #if defined(TABLING) && (defined(YAPOR) || defined(THREADS))
/* local data related to memory management */ /* 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; REMOTE_top_dep_fr(wid) = GLOBAL_root_dep_fr;
Set_REMOTE_top_cp_on_stack(wid, (choiceptr) LOCAL_LocalBase); /* ??? */ Set_REMOTE_top_cp_on_stack(wid, (choiceptr) LOCAL_LocalBase); /* ??? */
REMOTE_top_susp_or_fr(wid) = GLOBAL_root_or_fr; 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 */ #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 */ #endif /* TABLING */
return; return;
} }
@ -256,7 +262,7 @@ void Yap_init_root_frames(void) {
#ifdef YAPOR #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 ? */ 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 #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 /* YAPOR */
#endif /* TABLING */ #endif /* TABLING */
} }

View File

@ -76,14 +76,19 @@ extern int Yap_page_size;
free(block_ptr); \ free(block_ptr); \
} }
#endif /******************************************************************************/ #endif /******************************************************************************/
#define ALLOC_HASH_BUCKETS(BUCKET_PTR, NUM_BUCKETS) \ #define INIT_BUCKETS(BUCKET_PTR, NUM_BUCKETS) \
{ int i; void **bucket_ptr; \ { int i; void **init_bucket_ptr; \
ALLOC_BLOCK(bucket_ptr, NUM_BUCKETS * sizeof(void *), void *); \ init_bucket_ptr = (void **) BUCKET_PTR; \
BUCKET_PTR = (void *) bucket_ptr; \
for (i = NUM_BUCKETS; i != 0; i--) \ 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 #else
#define OPTYAP_ERROR_CHECKING(PROCEDURE,TEST) #define OPTYAP_ERROR_CHECKING(PROCEDURE,TEST)
#endif /* DEBUG_OPTYAP */ #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_tabling_mode( USES_REGS1 );
static Int p_abolish_table( USES_REGS1 ); static Int p_abolish_table( USES_REGS1 );
static Int p_abolish_all_tables( 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_tabled_predicates( USES_REGS1 );
static Int p_show_table( USES_REGS1 ); static Int p_show_table( USES_REGS1 );
static Int p_show_all_tables( 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_global_trie( USES_REGS1 );
static Int p_show_statistics_table( USES_REGS1 ); static Int p_show_statistics_table( USES_REGS1 );
static Int p_show_statistics_tabling( USES_REGS1 ); static Int p_show_statistics_tabling( USES_REGS1 );
@ -185,7 +183,7 @@ struct page_statistics {
INCREMENT_PAGE_STATS(STATS, STR_PAGES(wid)); \ INCREMENT_PAGE_STATS(STATS, STR_PAGES(wid)); \
} \ } \
} \ } \
} \ } \
UNLOCK(GLOBAL_ThreadHandlesLock); \ UNLOCK(GLOBAL_ThreadHandlesLock); \
Pg_bytes_in_use(STATS) = Pg_str_in_use(STATS) * sizeof(STR_TYPE) 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_tabling_mode", 3, p_tabling_mode, SafePredFlag|SyncPredFlag|HiddenPredFlag);
Yap_InitCPred("$c_abolish_table", 2, p_abolish_table, 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_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("show_tabled_predicates", 1, p_show_tabled_predicates, SafePredFlag|SyncPredFlag);
Yap_InitCPred("$c_show_table", 3, p_show_table, SafePredFlag|SyncPredFlag|HiddenPredFlag); 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_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("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("$c_table_statistics", 3, p_show_statistics_table, SafePredFlag|SyncPredFlag|HiddenPredFlag);
Yap_InitCPred("tabling_statistics", 1, p_show_statistics_tabling, SafePredFlag|SyncPredFlag); 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 ) { static Int p_abolish_table( USES_REGS1 ) {
Term mod, t; Term mod, t;
tab_ent_ptr tab_ent; tab_ent_ptr tab_ent;
sg_hash_ptr hash;
sg_node_ptr sg_node;
mod = Deref(ARG1); mod = Deref(ARG1);
t = Deref(ARG2); t = Deref(ARG2);
@ -478,67 +472,23 @@ static Int p_abolish_table( USES_REGS1 ) {
tab_ent = RepPredProp(PredPropByFunc(FunctorOfTerm(t), mod))->TableOfPred; tab_ent = RepPredProp(PredPropByFunc(FunctorOfTerm(t), mod))->TableOfPred;
else else
return (FALSE); return (FALSE);
hash = TabEnt_hash_chain(tab_ent); abolish_table(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;
}
return (TRUE); return (TRUE);
} }
static Int p_abolish_all_tables( USES_REGS1 ) { static Int p_abolish_all_tables( USES_REGS1 ) {
tab_ent_ptr tab_ent; tab_ent_ptr tab_ent;
sg_hash_ptr hash;
sg_node_ptr sg_node;
tab_ent = GLOBAL_root_tab_ent; tab_ent = GLOBAL_root_tab_ent;
while (tab_ent) { while (tab_ent) {
hash = TabEnt_hash_chain(tab_ent); abolish_table(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;
}
tab_ent = TabEnt_next(tab_ent); tab_ent = TabEnt_next(tab_ent);
} }
return (TRUE); 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 ) { static Int p_show_tabled_predicates( USES_REGS1 ) {
IOSTREAM *out; IOSTREAM *out;
tab_ent_ptr tab_ent; 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 ) { static Int p_show_global_trie( USES_REGS1 ) {
IOSTREAM *out; 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: "); SHOW_GLOBAL_PAGE_STATS(out, struct table_entry, GLOBAL_pages_tab_ent, "Table entries: ");
} }
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING) #if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
static inline struct page_statistics show_statistics_subgoal_entries(IOSTREAM *out) { 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: "); SHOW_GLOBAL_PAGE_STATS(out, struct subgoal_entry, GLOBAL_pages_sg_ent, "Subgoal entries: ");
} }
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */ #endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
static inline struct page_statistics show_statistics_subgoal_frames(IOSTREAM *out) { 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) #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: "); 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 #endif
} }
static inline struct page_statistics show_statistics_dependency_frames(IOSTREAM *out) { 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) #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: "); 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 #endif
} }
static inline struct page_statistics show_statistics_subgoal_trie_nodes(IOSTREAM *out) { static inline struct page_statistics show_statistics_subgoal_trie_nodes(IOSTREAM *out) {
#if !defined(THREADS_NO_SHARING) #if !defined(THREADS_NO_SHARING)
SHOW_GLOBAL_PAGE_STATS(out, struct subgoal_trie_node, GLOBAL_pages_sg_node, "Subgoal trie nodes: "); 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 #endif
} }
static inline struct page_statistics show_statistics_subgoal_trie_hashes(IOSTREAM *out) { static inline struct page_statistics show_statistics_subgoal_trie_hashes(IOSTREAM *out) {
#if !defined(THREADS_NO_SHARING) #if !defined(THREADS_NO_SHARING)
SHOW_GLOBAL_PAGE_STATS(out, struct subgoal_trie_hash, GLOBAL_pages_sg_hash, "Subgoal trie hashes: "); 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 #endif
} }
static inline struct page_statistics show_statistics_answer_trie_nodes(IOSTREAM *out) { static inline struct page_statistics show_statistics_answer_trie_nodes(IOSTREAM *out) {
#if !defined(THREADS_NO_SHARING) && !defined(THREADS_SUBGOAL_SHARING) #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: "); 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 #endif
} }
static inline struct page_statistics show_statistics_answer_trie_hashes(IOSTREAM *out) { static inline struct page_statistics show_statistics_answer_trie_hashes(IOSTREAM *out) {
#if !defined(THREADS_NO_SHARING) && !defined(THREADS_SUBGOAL_SHARING) #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: "); 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 #endif
} }
#if defined(THREADS_FULL_SHARING) #if defined(THREADS_FULL_SHARING)
static inline struct page_statistics show_statistics_answer_ref_nodes(IOSTREAM *out) { 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 */ #endif /* THREADS_FULL_SHARING */
static inline struct page_statistics show_statistics_global_trie_nodes(IOSTREAM *out) { 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: "); 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) { 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: "); 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: "); 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) { 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: "); 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) { 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: "); 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: "); SHOW_GLOBAL_PAGE_STATS(out, struct suspension_frame, GLOBAL_pages_susp_fr, "Suspension frames: ");
} }
#ifdef TABLING_INNER_CUTS #ifdef TABLING_INNER_CUTS
static inline struct page_statistics show_statistics_table_subgoal_solution_frames(IOSTREAM *out) { 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:"); 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) { 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: "); 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 update_answer_trie(sg_fr_ptr);
void free_subgoal_trie(sg_node_ptr, int, int); void free_subgoal_trie(sg_node_ptr, int, int);
void free_answer_trie(ans_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 free_answer_hash_chain(ans_hash_ptr);
void abolish_table(tab_ent_ptr);
void show_table(tab_ent_ptr, int, IOSTREAM *); void show_table(tab_ent_ptr, int, IOSTREAM *);
void show_global_trie(int, IOSTREAM *); void show_global_trie(int, IOSTREAM *);
#endif /* TABLING */ #endif /* TABLING */

View File

@ -466,6 +466,9 @@ struct local_optyap_data {
#endif /* YAPOR_THREADS */ #endif /* YAPOR_THREADS */
struct or_frame *top_or_frame_with_suspensions; struct or_frame *top_or_frame_with_suspensions;
#endif /* YAPOR */ #endif /* YAPOR */
#ifdef OUTPUT_THREADS_TABLING
FILE *thread_output;
#endif /* OUTPUT_THREADS_TABLING */
#endif /* TABLING */ #endif /* TABLING */
#if (defined(TABLING) || !defined(YAPOR_COW)) && defined(MULTI_ASSIGNMENT_VARIABLES) #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) #define Set_LOCAL_top_cp_on_stack(cpt) (LOCAL_optyap_data.top_choice_point_on_stack = cpt)
#endif /* YAPOR_THREADS */ #endif /* YAPOR_THREADS */
#define LOCAL_top_susp_or_fr (LOCAL_optyap_data.top_or_frame_with_suspensions) #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_timestamp (LOCAL_optyap_data.ma_timestamp)
#define LOCAL_ma_h_top (LOCAL_optyap_data.ma_h_top) #define LOCAL_ma_h_top (LOCAL_optyap_data.ma_h_top)
#define LOCAL_ma_hash_table (LOCAL_optyap_data.ma_hash_table) #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)) #define Set_REMOTE_top_cp_on_stack(wid, bptr) (REMOTE(wid)->optyap_data_.top_choice_point_on_stack = (bptr))
#endif /* YAPOR_THREADS */ #endif /* YAPOR_THREADS */
#define REMOTE_top_susp_or_fr(wid) (REMOTE(wid)->optyap_data_.top_or_frame_with_suspensions) #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 #ifdef YAPOR
#include "or.structs.h" #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) { void private_completion(sg_fr_ptr sg_fr) {
CACHE_REGS CACHE_REGS
/* complete subgoals */ /* complete subgoals */
#ifdef LIMIT_TABLING #ifdef LIMIT_TABLING
sg_fr_ptr aux_sg_fr; 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_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; return;
} }

View File

@ -22,58 +22,58 @@
#define store_low_level_trace_info(CP, TAB_ENT) #define store_low_level_trace_info(CP, TAB_ENT)
#endif /* LOW_LEVEL_TRACER */ #endif /* LOW_LEVEL_TRACER */
#define TABLING_ERROR_CHECKING_STACK \ #define TABLING_ERROR_CHECKING_STACK \
TABLING_ERROR_CHECKING(store_node, Unsigned(H) + 1024 > Unsigned(B)); \ TABLING_ERROR_CHECKING(store_node, Unsigned(H) + 1024 > Unsigned(B)); \
TABLING_ERROR_CHECKING(store_node, Unsigned(H_FZ) + 1024 > Unsigned(B)) TABLING_ERROR_CHECKING(store_node, Unsigned(H_FZ) + 1024 > Unsigned(B))
#define store_generator_node(TAB_ENT, SG_FR, ARITY, AP) \ #define store_generator_node(TAB_ENT, SG_FR, ARITY, AP) \
{ register CELL *pt_args; \ { register CELL *pt_args; \
register choiceptr gcp; \ register choiceptr gcp; \
/* store args */ \ /* store args */ \
pt_args = XREGS + (ARITY); \ pt_args = XREGS + (ARITY); \
while (pt_args > XREGS) { \ while (pt_args > XREGS) { \
register CELL aux_arg = pt_args[0]; \ register CELL aux_arg = pt_args[0]; \
--YENV; \ --YENV; \
--pt_args; \ --pt_args; \
*YENV = aux_arg; \ *YENV = aux_arg; \
} \ } \
/* initialize gcp and adjust subgoal frame field */ \ /* initialize gcp and adjust subgoal frame field */ \
YENV = (CELL *) (GEN_CP(YENV) - 1); \ YENV = (CELL *) (GEN_CP(YENV) - 1); \
gcp = NORM_CP(YENV); \ gcp = NORM_CP(YENV); \
SgFr_gen_cp(SG_FR) = gcp; \ SgFr_gen_cp(SG_FR) = gcp; \
/* store generator choice point */ \ /* store generator choice point */ \
HBREG = H; \ HBREG = H; \
store_yaam_reg_cpdepth(gcp); \ store_yaam_reg_cpdepth(gcp); \
gcp->cp_tr = TR; \ gcp->cp_tr = TR; \
gcp->cp_ap = (yamop *)(AP); \ gcp->cp_ap = (yamop *)(AP); \
gcp->cp_h = H; \ gcp->cp_h = H; \
gcp->cp_b = B; \ gcp->cp_b = B; \
gcp->cp_env = ENV; \ gcp->cp_env = ENV; \
gcp->cp_cp = CPREG; \ gcp->cp_cp = CPREG; \
if (IsMode_Local(TabEnt_mode(TAB_ENT))) { \ if (IsMode_Local(TabEnt_mode(TAB_ENT))) { \
/* go local */ \ /* go local */ \
register dep_fr_ptr new_dep_fr; \ register dep_fr_ptr new_dep_fr; \
/* adjust freeze registers */ \ /* adjust freeze registers */ \
H_FZ = H; \ H_FZ = H; \
B_FZ = gcp; \ B_FZ = gcp; \
TR_FZ = TR; \ TR_FZ = TR; \
/* store dependency frame */ \ /* store dependency frame */ \
new_dependency_frame(new_dep_fr, TRUE, LOCAL_top_or_fr, \ new_dependency_frame(new_dep_fr, TRUE, LOCAL_top_or_fr, gcp, \
gcp, gcp, SG_FR, LOCAL_top_dep_fr); \ gcp, SG_FR, FALSE, LOCAL_top_dep_fr); \
LOCAL_top_dep_fr = new_dep_fr; \ LOCAL_top_dep_fr = new_dep_fr; \
GEN_CP(gcp)->cp_dep_fr = LOCAL_top_dep_fr; \ GEN_CP(gcp)->cp_dep_fr = LOCAL_top_dep_fr; \
} else { \ } else { \
/* go batched */ \ /* go batched */ \
GEN_CP(gcp)->cp_dep_fr = NULL; \ GEN_CP(gcp)->cp_dep_fr = NULL; \
} \ } \
GEN_CP(gcp)->cp_sg_fr = SG_FR; \ GEN_CP(gcp)->cp_sg_fr = SG_FR; \
store_low_level_trace_info(GEN_CP(gcp), TAB_ENT); \ store_low_level_trace_info(GEN_CP(gcp), TAB_ENT); \
set_cut((CELL *)gcp, B); \ set_cut((CELL *)gcp, B); \
B = gcp; \ B = gcp; \
YAPOR_SET_LOAD(B); \ YAPOR_SET_LOAD(B); \
SET_BB(B); \ SET_BB(B); \
TABLING_ERROR_CHECKING_STACK; \ TABLING_ERROR_CHECKING_STACK; \
} }
@ -102,6 +102,52 @@
#endif /* DETERMINISTIC_TABLING */ #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) \ #define restore_generator_node(ARITY, AP) \
{ register CELL *pt_args, *x_args; \ { register CELL *pt_args, *x_args; \
register choiceptr gcp = B; \ register choiceptr gcp = B; \
@ -149,39 +195,65 @@
} }
#define store_consumer_node(TAB_ENT, SG_FR, LEADER_CP, DEP_ON_STACK) \ #define store_consumer_node(TAB_ENT, SG_FR, LEADER_CP, DEP_ON_STACK) \
{ register choiceptr ccp; \ { register choiceptr ccp; \
register dep_fr_ptr new_dep_fr; \ register dep_fr_ptr new_dep_fr; \
/* initialize ccp */ \ /* initialize ccp */ \
YENV = (CELL *) (CONS_CP(YENV) - 1); \ YENV = (CELL *) (CONS_CP(YENV) - 1); \
ccp = NORM_CP(YENV); \ ccp = NORM_CP(YENV); \
/* adjust freeze registers */ \ /* adjust freeze registers */ \
H_FZ = H; \ H_FZ = H; \
B_FZ = ccp; \ B_FZ = ccp; \
TR_FZ = TR; \ TR_FZ = TR; \
/* store dependency frame */ \ /* store dependency frame */ \
new_dependency_frame(new_dep_fr, DEP_ON_STACK, LOCAL_top_or_fr, \ new_dependency_frame(new_dep_fr, DEP_ON_STACK, LOCAL_top_or_fr, \
LEADER_CP, ccp, SG_FR, LOCAL_top_dep_fr); \ LEADER_CP, ccp, SG_FR, FALSE, LOCAL_top_dep_fr); \
LOCAL_top_dep_fr = new_dep_fr; \ LOCAL_top_dep_fr = new_dep_fr; \
/* store consumer choice point */ \ /* store consumer choice point */ \
HBREG = H; \ HBREG = H; \
store_yaam_reg_cpdepth(ccp); \ store_yaam_reg_cpdepth(ccp); \
ccp->cp_tr = TR; \ ccp->cp_tr = TR; \
ccp->cp_ap = ANSWER_RESOLUTION; \ ccp->cp_ap = ANSWER_RESOLUTION; \
ccp->cp_h = H; \ ccp->cp_h = H; \
ccp->cp_b = B; \ ccp->cp_b = B; \
ccp->cp_env= ENV; \ ccp->cp_env= ENV; \
ccp->cp_cp = CPREG; \ ccp->cp_cp = CPREG; \
CONS_CP(ccp)->cp_dep_fr = LOCAL_top_dep_fr; \ CONS_CP(ccp)->cp_dep_fr = LOCAL_top_dep_fr; \
store_low_level_trace_info(CONS_CP(ccp), TAB_ENT); \ store_low_level_trace_info(CONS_CP(ccp), TAB_ENT); \
/* set_cut((CELL *)ccp, B); --> no effect */ \ /* set_cut((CELL *)ccp, B); --> no effect */ \
B = ccp; \ B = ccp; \
YAPOR_SET_LOAD(B); \ YAPOR_SET_LOAD(B); \
SET_BB(B); \ SET_BB(B); \
TABLING_ERROR_CHECKING_STACK; \ 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) \ #define consume_answer_and_procceed(DEP_FR, ANSWER) \
{ CELL *subs_ptr; \ { CELL *subs_ptr; \
/* restore consumer choice point */ \ /* restore consumer choice point */ \
@ -207,6 +279,7 @@
YENV = ENV; \ YENV = ENV; \
GONext(); \ GONext(); \
} }
#endif /* THREADS_CONSUMER_SHARING */
#define store_loader_node(TAB_ENT, ANSWER) \ #define store_loader_node(TAB_ENT, ANSWER) \
@ -401,7 +474,27 @@
YENV2MEM; YENV2MEM;
sg_fr = subgoal_search(PREG, YENV_ADDRESS); sg_fr = subgoal_search(PREG, YENV_ADDRESS);
MEM2YENV; 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); 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) { if (SgFr_state(sg_fr) == ready) {
/* subgoal new */ /* subgoal new */
init_subgoal_frame(sg_fr); init_subgoal_frame(sg_fr);
@ -478,7 +571,11 @@
TRAIL_FRAME(sg_fr); TRAIL_FRAME(sg_fr);
} }
#endif /* LIMIT_TABLING */ #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 */ /* load answers from the trie */
UNLOCK_SG_FR(sg_fr); UNLOCK_SG_FR(sg_fr);
if(TrNode_child(ans_node) != NULL) { if(TrNode_child(ans_node) != NULL) {
@ -491,7 +588,11 @@
GONext(); GONext();
} else { } else {
/* execute compiled code from the trie */ /* 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) if (SgFr_state(sg_fr) < compiled)
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
update_answer_trie(sg_fr); update_answer_trie(sg_fr);
UNLOCK_SG_FR(sg_fr); UNLOCK_SG_FR(sg_fr);
PREG = (yamop *) TrNode_child(SgFr_answer_trie(sg_fr)); PREG = (yamop *) TrNode_child(SgFr_answer_trie(sg_fr));
@ -519,7 +620,28 @@
YENV2MEM; YENV2MEM;
sg_fr = subgoal_search(PREG, YENV_ADDRESS); sg_fr = subgoal_search(PREG, YENV_ADDRESS);
MEM2YENV; 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); 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) { if (SgFr_state(sg_fr) == ready) {
/* subgoal new */ /* subgoal new */
init_subgoal_frame(sg_fr); init_subgoal_frame(sg_fr);
@ -589,7 +711,11 @@
TRAIL_FRAME(sg_fr); TRAIL_FRAME(sg_fr);
} }
#endif /* LIMIT_TABLING */ #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 */ /* load answers from the trie */
UNLOCK_SG_FR(sg_fr); UNLOCK_SG_FR(sg_fr);
if(TrNode_child(ans_node) != NULL) { if(TrNode_child(ans_node) != NULL) {
@ -602,7 +728,11 @@
GONext(); GONext();
} else { } else {
/* execute compiled code from the trie */ /* 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) if (SgFr_state(sg_fr) < compiled)
#endif /*THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING*/
update_answer_trie(sg_fr); update_answer_trie(sg_fr);
UNLOCK_SG_FR(sg_fr); UNLOCK_SG_FR(sg_fr);
PREG = (yamop *) TrNode_child(SgFr_answer_trie(sg_fr)); PREG = (yamop *) TrNode_child(SgFr_answer_trie(sg_fr));
@ -630,7 +760,28 @@
YENV2MEM; YENV2MEM;
sg_fr = subgoal_search(PREG, YENV_ADDRESS); sg_fr = subgoal_search(PREG, YENV_ADDRESS);
MEM2YENV; 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); 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) { if (SgFr_state(sg_fr) == ready) {
/* subgoal new */ /* subgoal new */
init_subgoal_frame(sg_fr); init_subgoal_frame(sg_fr);
@ -700,7 +851,11 @@
TRAIL_FRAME(sg_fr); TRAIL_FRAME(sg_fr);
} }
#endif /* LIMIT_TABLING */ #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 */ /* load answers from the trie */
UNLOCK_SG_FR(sg_fr); UNLOCK_SG_FR(sg_fr);
if(TrNode_child(ans_node) != NULL) { if(TrNode_child(ans_node) != NULL) {
@ -713,7 +868,11 @@
GONext(); GONext();
} else { } else {
/* execute compiled code from the trie */ /* 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) if (SgFr_state(sg_fr) < compiled)
#endif /*THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
update_answer_trie(sg_fr); update_answer_trie(sg_fr);
UNLOCK_SG_FR(sg_fr); UNLOCK_SG_FR(sg_fr);
PREG = (yamop *) TrNode_child(SgFr_answer_trie(sg_fr)); PREG = (yamop *) TrNode_child(SgFr_answer_trie(sg_fr));
@ -997,6 +1156,14 @@
} }
#endif /* TABLING_INNER_CUTS */ #endif /* TABLING_INNER_CUTS */
TAG_AS_ANSWER_LEAF_NODE(ans_node); 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); UNLOCK_ANSWER_NODE(ans_node);
#ifndef ANSWER_TRIE_LOCK_AT_ENTRY_LEVEL #ifndef ANSWER_TRIE_LOCK_AT_ENTRY_LEVEL
LOCK_SG_FR(sg_fr); LOCK_SG_FR(sg_fr);
@ -1017,6 +1184,10 @@
#endif /* DEBUG_TABLING */ #endif /* DEBUG_TABLING */
UNLOCK_SG_FR(sg_fr); UNLOCK_SG_FR(sg_fr);
if (IS_BATCHED_GEN_CP(gcp)) { 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 #ifdef TABLING_EARLY_COMPLETION
if (gcp == PROTECT_FROZEN_B(B) && (*subs_ptr == 0 || gcp->cp_ap == 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 */ /* if the current generator choice point is the topmost choice point and the current */
@ -1059,8 +1230,55 @@
} }
} else { } else {
/* repeated answer */ /* 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_NODE(ans_node);
UNLOCK_ANSWER_TRIE(sg_fr); 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; goto fail;
} }
ENDPBOp(); ENDPBOp();
@ -1092,13 +1310,13 @@
if (TrNode_child(ans_node)) { if (TrNode_child(ans_node)) {
/* unconsumed answers */ /* unconsumed answers */
#ifdef MODE_DIRECTED_TABLING #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; ans_node_ptr old_ans_node;
old_ans_node = ans_node; old_ans_node = ans_node;
ans_node = TrNode_child(ans_node); ans_node = TrNode_child(ans_node);
do { do {
ans_node = TrNode_child(ans_node); 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; TrNode_child(old_ans_node) = ans_node;
} else } else
#endif /* MODE_DIRECTED_TABLING */ #endif /* MODE_DIRECTED_TABLING */
@ -1151,13 +1369,13 @@
if (TrNode_child(ans_node)) { if (TrNode_child(ans_node)) {
/* dependency frame with unconsumed answers */ /* dependency frame with unconsumed answers */
#ifdef MODE_DIRECTED_TABLING #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; ans_node_ptr old_ans_node;
old_ans_node = ans_node; old_ans_node = ans_node;
ans_node = TrNode_child(ans_node); ans_node = TrNode_child(ans_node);
do { do {
ans_node = TrNode_child(ans_node); 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; TrNode_child(old_ans_node) = ans_node;
} else } else
#endif /* MODE_DIRECTED_TABLING */ #endif /* MODE_DIRECTED_TABLING */
@ -1360,6 +1578,11 @@
} else } else
#endif /* YAPOR */ #endif /* YAPOR */
{ {
#ifdef THREADS_CONSUMER_SHARING
goto answer_resolution_completion;
#endif /* THREADS_CONSUMER_SHARING */
if (IS_BATCHED_GEN_CP(B)) { if (IS_BATCHED_GEN_CP(B)) {
B->cp_ap = NULL; B->cp_ap = NULL;
if (EQUAL_OR_YOUNGER_CP(B_FZ, B) && B != DepFr_leader_cp(LOCAL_top_dep_fr)) { if (EQUAL_OR_YOUNGER_CP(B_FZ, B) && B != DepFr_leader_cp(LOCAL_top_dep_fr)) {
@ -1380,6 +1603,9 @@
completion: completion:
#ifdef THREADS_CONSUMER_SHARING
goto answer_resolution_completion;
#endif /* THREADS_CONSUMER_SHARING */
INIT_PREFETCH() INIT_PREFETCH()
dep_fr_ptr dep_fr; dep_fr_ptr dep_fr;
ans_node_ptr ans_node; ans_node_ptr ans_node;
@ -1405,13 +1631,13 @@
if (TrNode_child(ans_node)) { if (TrNode_child(ans_node)) {
/* dependency frame with unconsumed answers */ /* dependency frame with unconsumed answers */
#ifdef MODE_DIRECTED_TABLING #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; ans_node_ptr old_ans_node;
old_ans_node = ans_node; old_ans_node = ans_node;
ans_node = TrNode_child(ans_node); ans_node = TrNode_child(ans_node);
do { do {
ans_node = TrNode_child(ans_node); 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; TrNode_child(old_ans_node) = ans_node;
} else } else
#endif /* MODE_DIRECTED_TABLING */ #endif /* MODE_DIRECTED_TABLING */
@ -1575,13 +1801,13 @@
/* unconsumed answers */ /* unconsumed answers */
UNLOCK_OR_FRAME(LOCAL_top_or_fr); UNLOCK_OR_FRAME(LOCAL_top_or_fr);
#ifdef MODE_DIRECTED_TABLING #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; ans_node_ptr old_ans_node;
old_ans_node = ans_node; old_ans_node = ans_node;
ans_node = TrNode_child(ans_node); ans_node = TrNode_child(ans_node);
do { do {
ans_node = TrNode_child(ans_node); 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; TrNode_child(old_ans_node) = ans_node;
} else } else
#endif /* MODE_DIRECTED_TABLING */ #endif /* MODE_DIRECTED_TABLING */
@ -1594,7 +1820,7 @@
UNLOCK_DEP_FR(LOCAL_top_dep_fr); UNLOCK_DEP_FR(LOCAL_top_dep_fr);
if (OrFr_owners(LOCAL_top_or_fr) > 1) { if (OrFr_owners(LOCAL_top_or_fr) > 1) {
/* more owners -> move up one node */ /* 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); BITMAP_delete(OrFr_members(LOCAL_top_or_fr), worker_id);
OrFr_owners(LOCAL_top_or_fr)--; OrFr_owners(LOCAL_top_or_fr)--;
LOCAL_top_dep_fr = DepFr_next(LOCAL_top_dep_fr); LOCAL_top_dep_fr = DepFr_next(LOCAL_top_dep_fr);
@ -1625,6 +1851,10 @@
GONext(); GONext();
} else } else
#endif /* YAPOR */ #endif /* YAPOR */
#ifdef THREADS_CONSUMER_SHARING
complete_all:
#endif /* THREADS_CONSUMER_SHARING */
{ {
/* complete all */ /* complete all */
sg_fr_ptr sg_fr; sg_fr_ptr sg_fr;
@ -1636,7 +1866,11 @@
#endif /* DETERMINISTIC_TABLING */ #endif /* DETERMINISTIC_TABLING */
sg_fr = GEN_CP(B)->cp_sg_fr; sg_fr = GEN_CP(B)->cp_sg_fr;
private_completion(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)) { if (IS_BATCHED_GEN_CP(B)) {
#endif /*THREADS_CONSUMER_SHARING */
/* backtrack */ /* backtrack */
B = B->cp_b; B = B->cp_b;
SET_BB(PROTECT_FROZEN_B(B)); SET_BB(PROTECT_FROZEN_B(B));
@ -1678,9 +1912,28 @@
YENV = ENV; YENV = ENV;
GONext(); GONext();
} else { } 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 */ /* 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); LOCK_SG_FR(sg_fr);
if (SgFr_state(sg_fr) < compiled) if (SgFr_state(sg_fr) < compiled)
#endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
update_answer_trie(sg_fr); update_answer_trie(sg_fr);
UNLOCK_SG_FR(sg_fr); UNLOCK_SG_FR(sg_fr);
PREG = (yamop *) TrNode_child(SgFr_answer_trie(sg_fr)); PREG = (yamop *) TrNode_child(SgFr_answer_trie(sg_fr));
@ -1694,3 +1947,192 @@
} }
END_PREFETCH() END_PREFETCH()
ENDBOp(); 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 */ #endif /* HAVE_STRING_H */
#include "opt.mavar.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 Int freeze_current_cp(void);
static inline void wake_frozen_cp(Int); static inline void wake_frozen_cp(Int);
static inline void abolish_frozen_cps_until(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 #else
#define ANSWER_LEAF_NODE_MAX_THREADS OOOOPPS!!! Unknown Pointer Sizeof #define ANSWER_LEAF_NODE_MAX_THREADS OOOOPPS!!! Unknown Pointer Sizeof
#endif /* SIZEOF_INT_P */ #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_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_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_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_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) #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_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)) #define IS_BATCHED_GEN_CP(CP) (IS_DET_GEN_CP(CP) || IS_BATCHED_NORM_GEN_CP(CP))
#else #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) #define IS_BATCHED_GEN_CP(CP) (GEN_CP(CP)->cp_dep_fr == NULL)
#endif /* THREADS_CONSUMER_SHARING */
#endif /* DETERMINISTIC_TABLING */ #endif /* DETERMINISTIC_TABLING */
/* leaf nodes */ /* tagging nodes */
#define TAG_AS_SUBGOAL_LEAF_NODE(NODE) TrNode_child(NODE) = (sg_node_ptr)((unsigned long int) TrNode_child(NODE) | 0x1) #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 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 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 UNTAG_ANSWER_LEAF_NODE(NODE) ((ans_node_ptr)((unsigned long int) (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_LEAF_NODE(NODE) ((unsigned long int) TrNode_parent(NODE) & 0x1) #define IS_ANSWER_INVALID_NODE(NODE) ((unsigned long int) TrNode_parent(NODE) & 0x2)
#define TAG_AS_INVALID_LEAF_NODE(NODE) TrNode_parent(NODE) = (ans_node_ptr)((unsigned long int) TrNode_parent(NODE) | 0x2) #define UNTAG_SUBGOAL_NODE(NODE) ((sg_fr_ptr)((unsigned long int) (NODE) & ~(0x1)))
#define IS_INVALID_LEAF_NODE(NODE) ((unsigned long int) TrNode_parent(NODE) & 0x2) #define UNTAG_ANSWER_NODE(NODE) ((ans_node_ptr)((unsigned long int) (NODE) & ~(0x3)))
/* trie hashes */ /* trie hashes */
#define MAX_NODES_PER_TRIE_LEVEL 8 #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 */ #endif /* YAPOR */
#ifdef MODE_DIRECTED_TABLING #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 TabEnt_mode_directed(TAB_ENT) = MODE_ARRAY
#define SgFr_init_mode_directed(SG_FR, MODE_ARRAY) \ #define SgEnt_init_mode_directed_fields(SG_ENT, MODE_ARRAY) \
SgFr_invalid_chain(SG_FR) = NULL; \ 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 SgFr_mode_directed(SG_FR) = MODE_ARRAY
#define AnsHash_init_previous_field(HASH, SG_FR) \ #define AnsHash_init_previous_field(HASH, SG_FR) \
if (SgFr_hash_chain(SG_FR)) \ if (SgFr_hash_chain(SG_FR)) \
Hash_previous(SgFr_hash_chain(SG_FR)) = HASH; \ Hash_previous(SgFr_hash_chain(SG_FR)) = HASH; \
Hash_previous(HASH) = NULL Hash_previous(HASH) = NULL
#else #else
#define TabEnt_init_mode_directed(TAB_ENT, MODE_ARRAY) #define TabEnt_init_mode_directed_field(TAB_ENT, MODE_ARRAY)
#define SgFr_init_mode_directed(SG_FR, MODE_ARRAY) #define SgFr_init_mode_directed_fields(SG_FR, MODE_ARRAY)
#define AnsHash_init_previous_field(HASH, SG_FR) #define AnsHash_init_previous_field(HASH, SG_FR)
#endif /* MODE_DIRECTED_TABLING */ #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) #define IS_UNLOCKED_DEP_FR(DEP_FR)
#endif /* YAPOR */ #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 #ifdef SUBGOAL_TRIE_LOCK_AT_ENTRY_LEVEL
#define LOCK_SUBGOAL_TRIE(TAB_ENT) LOCK(TabEnt_lock(TAB_ENT)) #define LOCK_SUBGOAL_TRIE(TAB_ENT) LOCK(TabEnt_lock(TAB_ENT))
#define UNLOCK_SUBGOAL_TRIE(TAB_ENT) UNLOCK(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 #else
#define LOCK_SUBGOAL_TRIE(TAB_ENT) #define LOCK_SUBGOAL_TRIE(TAB_ENT)
#define UNLOCK_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 */ #endif /* SUBGOAL_TRIE_LOCK_AT_ENTRY_LEVEL */
#ifdef ANSWER_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) #define GtNode_init_lock_field(NODE)
#endif /* GLOBAL_TRIE_LOCK_LEVEL */ #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) \ #define new_table_entry(TAB_ENT, PRED_ENTRY, ATOM, ARITY, MODE_ARRAY) \
{ register sg_node_ptr sg_node; \ ALLOC_TABLE_ENTRY(TAB_ENT); \
new_subgoal_trie_node(sg_node, 0, NULL, NULL, NULL); \ INIT_LOCK_TAB_ENT(TAB_ENT); \
ALLOC_TABLE_ENTRY(TAB_ENT); \ TabEnt_pe(TAB_ENT) = PRED_ENTRY; \
INIT_LOCK(TabEnt_lock(TAB_ENT)); \ TabEnt_atom(TAB_ENT) = ATOM; \
TabEnt_pe(TAB_ENT) = PRED_ENTRY; \ TabEnt_arity(TAB_ENT) = ARITY; \
TabEnt_atom(TAB_ENT) = ATOM; \ TabEnt_flags(TAB_ENT) = 0; \
TabEnt_arity(TAB_ENT) = ARITY; \ SetMode_Batched(TabEnt_flags(TAB_ENT)); \
TabEnt_flags(TAB_ENT) = 0; \ SetMode_ExecAnswers(TabEnt_flags(TAB_ENT)); \
SetMode_Batched(TabEnt_flags(TAB_ENT)); \ SetMode_LocalTrie(TabEnt_flags(TAB_ENT)); \
SetMode_ExecAnswers(TabEnt_flags(TAB_ENT)); \ TabEnt_mode(TAB_ENT) = TabEnt_flags(TAB_ENT); \
SetMode_LocalTrie(TabEnt_flags(TAB_ENT)); \ if (IsMode_Local(yap_flags[TABLING_MODE_FLAG])) \
TabEnt_mode(TAB_ENT) = TabEnt_flags(TAB_ENT); \ SetMode_Local(TabEnt_mode(TAB_ENT)); \
if (IsMode_Local(yap_flags[TABLING_MODE_FLAG])) \ if (IsMode_LoadAnswers(yap_flags[TABLING_MODE_FLAG])) \
SetMode_Local(TabEnt_mode(TAB_ENT)); \ SetMode_LoadAnswers(TabEnt_mode(TAB_ENT)); \
if (IsMode_LoadAnswers(yap_flags[TABLING_MODE_FLAG])) \ if (IsMode_GlobalTrie(yap_flags[TABLING_MODE_FLAG])) \
SetMode_LoadAnswers(TabEnt_mode(TAB_ENT)); \ SetMode_GlobalTrie(TabEnt_mode(TAB_ENT)); \
if (IsMode_GlobalTrie(yap_flags[TABLING_MODE_FLAG])) \ TabEnt_init_mode_directed_field(TAB_ENT, MODE_ARRAY); \
SetMode_GlobalTrie(TabEnt_mode(TAB_ENT)); \ TabEnt_init_subgoal_trie_field(TAB_ENT); \
TabEnt_init_mode_directed(TAB_ENT, MODE_ARRAY); \ TabEnt_next(TAB_ENT) = GLOBAL_root_tab_ent; \
TabEnt_subgoal_trie(TAB_ENT) = sg_node; \ GLOBAL_root_tab_ent = TAB_ENT
TabEnt_hash_chain(TAB_ENT) = NULL; \
TabEnt_next(TAB_ENT) = GLOBAL_root_tab_ent; \ #define new_subgoal_entry(SG_ENT) \
GLOBAL_root_tab_ent = TAB_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) \ #define new_subgoal_frame(SG_FR, CODE, MODE_ARRAY) \
{ register ans_node_ptr ans_node; \ { register ans_node_ptr ans_node; \
new_answer_trie_node(ans_node, 0, 0, NULL, NULL, NULL); \ new_answer_trie_node(ans_node, 0, 0, NULL, NULL, NULL); \
ALLOC_SUBGOAL_FRAME(SG_FR); \ ALLOC_SUBGOAL_FRAME(SG_FR); \
INIT_LOCK_SG_FR(SG_FR); \ INIT_LOCK_SG_FR(SG_FR); \
SgFr_code(SG_FR) = CODE; \ SgFr_code(SG_FR) = CODE; \
SgFr_state(SG_FR) = ready; \
SgFr_hash_chain(SG_FR) = NULL; \ SgFr_hash_chain(SG_FR) = NULL; \
SgFr_answer_trie(SG_FR) = ans_node; \ SgFr_answer_trie(SG_FR) = ans_node; \
SgFr_first_answer(SG_FR) = NULL; \ SgFr_first_answer(SG_FR) = NULL; \
SgFr_last_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) \ #define init_subgoal_frame(SG_FR) \
{ SgFr_init_yapor_fields(SG_FR); \ { SgFr_init_yapor_fields(SG_FR); \
SgFr_state(SG_FR) = evaluating; \ SgFr_state(SG_FR) = evaluating; \
SgFr_next(SG_FR) = LOCAL_top_sg_fr; \ SgFr_next(SG_FR) = LOCAL_top_sg_fr; \
LOCAL_top_sg_fr = 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) \ #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); \ ALLOC_DEPENDENCY_FRAME(DEP_FR); \
DepFr_init_yapor_fields(DEP_FR, DEP_ON_STACK, TOP_OR_FR); \ DepFr_init_yapor_fields(DEP_FR, DEP_ON_STACK, TOP_OR_FR); \
DepFr_backchain_cp(DEP_FR) = NULL; \ DepFr_init_external_field(DEP_FR, IS_EXTERNAL); \
DepFr_leader_cp(DEP_FR) = NORM_CP(LEADER_CP); \ DepFr_backchain_cp(DEP_FR) = NULL; \
DepFr_cons_cp(DEP_FR) = NORM_CP(CONS_CP); \ DepFr_leader_cp(DEP_FR) = NORM_CP(LEADER_CP); \
/* start with TrNode_child(DepFr_last_answer(DEP_FR)) pointing to SgFr_first_answer(SG_FR) */ \ DepFr_cons_cp(DEP_FR) = NORM_CP(CONS_CP); \
DepFr_last_answer(DEP_FR) = (ans_node_ptr) ((unsigned long int) (SG_FR) + \ DepFr_init_last_answer_field(DEP_FR, SG_FR); \
(unsigned long int) (&SgFr_first_answer((sg_fr_ptr)DEP_FR)) - \
(unsigned long int) (&TrNode_child((ans_node_ptr)DEP_FR))); \
DepFr_next(DEP_FR) = NEXT DepFr_next(DEP_FR) = NEXT
#define new_suspension_frame(SUSP_FR, TOP_OR_FR_ON_STACK, TOP_DEP, TOP_SG, \ #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) SgNode_init_lock_field(NODE)
#define new_answer_trie_node(NODE, INSTR, ENTRY, CHILD, PARENT, NEXT) \ #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_instr(NODE) = INSTR; \
TrNode_entry(NODE) = ENTRY; \ TrNode_entry(NODE) = ENTRY; \
TrNode_child(NODE) = CHILD; \ 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; \ TrNode_next(NODE) = NEXT; \
GtNode_init_lock_field(NODE) GtNode_init_lock_field(NODE)
#define new_subgoal_trie_hash(HASH, NUM_NODES, TAB_ENT) \ #define new_answer_ref_node(NODE, ANSWER, NEXT, PREVIOUS) \
ALLOC_SUBGOAL_TRIE_HASH(HASH); \ ALLOC_ANSWER_REF_NODE(NODE); \
Hash_mark(HASH) = SUBGOAL_TRIE_HASH_MARK; \ RefNode_answer(NODE) = ANSWER; \
Hash_num_buckets(HASH) = BASE_HASH_BUCKETS; \ RefNode_next(NODE) = NEXT; \
ALLOC_HASH_BUCKETS(Hash_buckets(HASH), BASE_HASH_BUCKETS); \ RefNode_previous(NODE) = PREVIOUS
Hash_num_nodes(HASH) = NUM_NODES; \
SgHash_init_next_field(HASH, TAB_ENT)
#define new_answer_trie_hash(HASH, NUM_NODES, SG_FR) \ #define new_subgoal_trie_hash(HASH, NUM_NODES, TAB_ENT) \
ALLOC_ANSWER_TRIE_HASH(HASH); \ ALLOC_SUBGOAL_TRIE_HASH(HASH); \
Hash_mark(HASH) = ANSWER_TRIE_HASH_MARK; \ Hash_mark(HASH) = SUBGOAL_TRIE_HASH_MARK; \
Hash_num_buckets(HASH) = BASE_HASH_BUCKETS; \ Hash_num_buckets(HASH) = BASE_HASH_BUCKETS; \
ALLOC_HASH_BUCKETS(Hash_buckets(HASH), BASE_HASH_BUCKETS); \ ALLOC_BUCKETS(Hash_buckets(HASH), BASE_HASH_BUCKETS); \
Hash_num_nodes(HASH) = NUM_NODES; \ 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) AnsHash_init_chain_fields(HASH, SG_FR)
#define new_global_trie_hash(HASH, NUM_NODES) \ #define new_global_trie_hash(HASH, NUM_NODES) \
ALLOC_GLOBAL_TRIE_HASH(HASH); \ ALLOC_GLOBAL_TRIE_HASH(HASH); \
Hash_mark(HASH) = GLOBAL_TRIE_HASH_MARK; \ Hash_mark(HASH) = GLOBAL_TRIE_HASH_MARK; \
Hash_num_buckets(HASH) = BASE_HASH_BUCKETS; \ Hash_num_buckets(HASH) = BASE_HASH_BUCKETS; \
ALLOC_HASH_BUCKETS(Hash_buckets(HASH), BASE_HASH_BUCKETS); \ ALLOC_BUCKETS(Hash_buckets(HASH), BASE_HASH_BUCKETS); \
Hash_num_nodes(HASH) = NUM_NODES Hash_num_nodes(HASH) = NUM_NODES
#ifdef LIMIT_TABLING #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 ** ** 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) { static inline Int freeze_current_cp(void) {
CACHE_REGS CACHE_REGS
choiceptr freeze_cp = B; 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) { static inline void mark_as_completed(sg_fr_ptr sg_fr) {
#ifdef OUTPUT_THREADS_TABLING
CACHE_REGS CACHE_REGS
#endif /* OUTPUT_THREADS_TABLING */
LOCK_SG_FR(sg_fr); 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; SgFr_state(sg_fr) = complete;
UNLOCK_SG_FR(sg_fr); UNLOCK_SG_FR(sg_fr);
#ifdef MODE_DIRECTED_TABLING #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; ans_node_ptr current_node, next_node;
/* find first valid answer */ /* find first valid answer */
current_node = SgFr_first_answer(sg_fr); 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); current_node = TrNode_child(current_node);
SgFr_first_answer(sg_fr) = current_node; SgFr_first_answer(sg_fr) = current_node;
/* chain next valid answers */ /* chain next valid answers */
next_node = TrNode_child(current_node); next_node = TrNode_child(current_node);
while (next_node) { while (next_node) {
if (! IS_INVALID_LEAF_NODE(next_node)) { if (! IS_ANSWER_INVALID_NODE(next_node)) {
TrNode_child(current_node) = next_node; TrNode_child(current_node) = next_node;
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; ans_node_ptr current_node, next_node;
/* find first valid answer */ /* find first valid answer */
current_node = SgFr_first_answer(sg_fr); 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); current_node = TrNode_child(current_node);
SgFr_first_answer(sg_fr) = current_node; SgFr_first_answer(sg_fr) = current_node;
/* chain next valid answers */ /* chain next valid answers */
next_node = TrNode_child(current_node); next_node = TrNode_child(current_node);
while (next_node) { while (next_node) {
if (! IS_INVALID_LEAF_NODE(next_node)) { if (! IS_ANSWER_INVALID_NODE(next_node)) {
TrNode_child(current_node) = next_node; TrNode_child(current_node) = next_node;
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; SgFr_invalid_chain(sg_fr) = NULL;
#endif /* MODE_DIRECTED_TABLING */ #endif /* MODE_DIRECTED_TABLING */
SgFr_state(sg_fr) = ready; SgFr_state(sg_fr) = ready;
free_answer_hash_chain(SgFr_hash_chain(sg_fr)); #if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
SgFr_hash_chain(sg_fr) = NULL; if (SgFr_active_workers(sg_fr) == 0) {
SgFr_first_answer(sg_fr) = NULL; SgFr_sg_ent_state(sg_fr) = ready;
SgFr_last_answer(sg_fr) = NULL; #endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
node = TrNode_child(SgFr_answer_trie(sg_fr)); free_answer_hash_chain(SgFr_hash_chain(sg_fr));
TrNode_child(SgFr_answer_trie(sg_fr)) = NULL; SgFr_hash_chain(sg_fr) = NULL;
UNLOCK_SG_FR(sg_fr); SgFr_first_answer(sg_fr) = NULL;
free_answer_trie(node, TRAVERSE_MODE_NORMAL, TRAVERSE_POSITION_FIRST); 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) #if defined(MODE_DIRECTED_TABLING) && ! defined(YAPOR)
/* free invalid answer nodes */ /* free invalid answer nodes */
while (invalid_node) { while (invalid_node) {

View File

@ -20,9 +20,9 @@
**************************/ **************************/
typedef struct table_entry { typedef struct table_entry {
#if defined(YAPOR) || defined(THREADS) #if defined(SUBGOAL_TRIE_LOCK_AT_ENTRY_LEVEL) || defined(THREADS_NO_SHARING)
lockvar lock; lockvar lock;
#endif /* YAPOR || THREADS */ #endif /* SUBGOAL_TRIE_LOCK_AT_ENTRY_LEVEL || THREADS_NO_SHARING */
struct pred_entry *pred_entry; struct pred_entry *pred_entry;
Atom pred_atom; Atom pred_atom;
int pred_arity; int pred_arity;
@ -32,7 +32,7 @@ typedef struct table_entry {
int* mode_directed_array; int* mode_directed_array;
#endif /* MODE_DIRECTED_TABLING */ #endif /* MODE_DIRECTED_TABLING */
#ifdef THREADS_NO_SHARING #ifdef THREADS_NO_SHARING
struct subgoal_trie_node *subgoal_trie[THREADS_FIRST_LEVEL_BUCKETS]; struct subgoal_trie_node *subgoal_trie[THREADS_NUM_BUCKETS];
#else #else
struct subgoal_trie_node *subgoal_trie; struct subgoal_trie_node *subgoal_trie;
#endif /* THREADS_NO_SHARING */ #endif /* THREADS_NO_SHARING */
@ -47,12 +47,7 @@ typedef struct table_entry {
#define TabEnt_flags(X) ((X)->pred_flags) #define TabEnt_flags(X) ((X)->pred_flags)
#define TabEnt_mode(X) ((X)->execution_mode) #define TabEnt_mode(X) ((X)->execution_mode)
#define TabEnt_mode_directed(X) ((X)->mode_directed_array) #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) #define TabEnt_subgoal_trie(X) ((X)->subgoal_trie)
#endif /* THREADS_NO_SHARING */
#define TabEnt_hash_chain(X) ((X)->hash_chain) #define TabEnt_hash_chain(X) ((X)->hash_chain)
#define TabEnt_next(X) ((X)->next) #define TabEnt_next(X) ((X)->next)
@ -102,11 +97,30 @@ typedef struct global_trie_node {
#define TrNode_parent(X) ((X)->parent) #define TrNode_parent(X) ((X)->parent)
#define TrNode_child(X) ((X)->child) #define TrNode_child(X) ((X)->child)
#define TrNode_sg_fr(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_next(X) ((X)->next)
#define TrNode_lock(X) ((X)->lock) #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 ** ** subgoal_trie_hash, answer_trie_hash and global_trie_hash **
***********************************************************************/ ***********************************************************************/
@ -118,7 +132,9 @@ typedef struct subgoal_trie_hash {
int number_of_buckets; int number_of_buckets;
struct subgoal_trie_node **buckets; struct subgoal_trie_node **buckets;
int number_of_nodes; int number_of_nodes;
#ifdef USE_PAGES_MALLOC
struct subgoal_trie_hash *next; struct subgoal_trie_hash *next;
#endif /* USE_PAGES_MALLOC */
} *sg_hash_ptr; } *sg_hash_ptr;
typedef struct answer_trie_hash { 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 ** ** Execution Data Structures **
************************************************************************/ ************************************************************************/
@ -267,7 +265,7 @@ typedef struct subgoal_entry {
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING) #if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
subgoal_state_flag state_flag; subgoal_state_flag state_flag;
int active_workers; 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 */ #endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
}* sg_ent_ptr; }* sg_ent_ptr;
@ -287,7 +285,7 @@ typedef struct subgoal_entry {
#define SgEnt_gen_worker(X) ((X)->generator_worker) #define SgEnt_gen_worker(X) ((X)->generator_worker)
#define SgEnt_sg_ent_state(X) ((X)->state_flag) #define SgEnt_sg_ent_state(X) ((X)->state_flag)
#define SgEnt_active_workers(X) ((X)->active_workers) #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 */ /* subgoal_entry fields */
#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING) #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 #else
#define SUBGOAL_ENTRY(X) (X)->subgoal_entry. #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_lock(X) (SUBGOAL_ENTRY(X) lock)
#define SgFr_code(X) (SUBGOAL_ENTRY(X) code_of_subgoal) #define SgFr_code(X) (SUBGOAL_ENTRY(X) code_of_subgoal)
#define SgFr_tab_ent(X) ((SUBGOAL_ENTRY(X) code_of_subgoal)->u.Otapl.te) #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_sg_ent_state(X) (SUBGOAL_ENTRY(X) state_flag)
#define SgFr_active_workers(X) (SUBGOAL_ENTRY(X) active_workers) #define SgFr_active_workers(X) (SUBGOAL_ENTRY(X) active_workers)
/* subgoal_frame fields */ /* 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_last_answer(X) ((X)->batched_last_answer)
#define SgFr_batched_cached_answers(X) ((X)->batched_cached_answers) #define SgFr_batched_cached_answers(X) ((X)->batched_cached_answers)
#define SgFr_state(X) ((X)->state_flag) #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_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_sg_ent_state: a flag that indicates the subgoal entry state.
SgFr_active_workers: the number of workers evaluating the subgoal. 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 SgFr_batched_last_answer: a pointer to the leaf answer trie node of the last checked answer
when using batched scheduling. when using batched scheduling.
SgFr_batched_cached_answers: a pointer to the chain of answers already inserted in the trie, but not 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; long timestamp;
#endif /* TIMESTAMP_CHECK */ #endif /* TIMESTAMP_CHECK */
#endif /* YAPOR */ #endif /* YAPOR */
#ifdef THREADS_CONSUMER_SHARING
int generator_is_external;
#endif /* THREADS_CONSUMER_SHARING */
choiceptr backchain_choice_point; choiceptr backchain_choice_point;
choiceptr leader_choice_point; choiceptr leader_choice_point;
choiceptr consumer_choice_point; choiceptr consumer_choice_point;
struct answer_trie_node *last_consumed_answer; struct answer_trie_node *last_consumed_answer;
#ifdef THREADS_CONSUMER_SHARING
int generator_is_external;
#endif /* THREADS_CONSUMER_SHARING */
struct dependency_frame *next; struct dependency_frame *next;
} *dep_fr_ptr; } *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_leader_dep_is_on_stack(X) ((X)->leader_dependency_is_on_stack)
#define DepFr_top_or_fr(X) ((X)->top_or_frame) #define DepFr_top_or_fr(X) ((X)->top_or_frame)
#define DepFr_timestamp(X) ((X)->timestamp) #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_backchain_cp(X) ((X)->backchain_choice_point)
#define DepFr_leader_cp(X) ((X)->leader_choice_point) #define DepFr_leader_cp(X) ((X)->leader_choice_point)
#define DepFr_cons_cp(X) ((X)->consumer_choice_point) #define DepFr_cons_cp(X) ((X)->consumer_choice_point)
#define DepFr_last_answer(X) ((X)->last_consumed_answer) #define DepFr_last_answer(X) ((X)->last_consumed_answer)
#define DepFr_external(X) ((X)->generator_is_external)
#define DepFr_next(X) ((X)->next) #define DepFr_next(X) ((X)->next)
/********************************************************************************************************* /*********************************************************************************************************
@ -421,13 +419,13 @@ typedef struct dependency_frame {
backtracks through answers. backtracks through answers.
DepFr_timestamp: a timestamp used to optimize the search for suspension frames to be DepFr_timestamp: a timestamp used to optimize the search for suspension frames to be
resumed. 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. 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 It is used to efficiently return (backtrack) to the leader node where
we perform the last backtracking through answers operation. we perform the last backtracking through answers operation.
DepFr_leader_cp: a pointer to the leader choice point. DepFr_leader_cp: a pointer to the leader choice point.
DepFr_cons_cp: a pointer to the correspondent consumer choice point. DepFr_cons_cp: a pointer to the correspondent consumer choice point.
DepFr_last_answer: a pointer to the last consumed answer. 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. 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 #else
static void free_global_trie_branch(gt_node_ptr); static void free_global_trie_branch(gt_node_ptr);
#endif /* GLOBAL_TRIE_FOR_SUBTERMS */ #endif /* GLOBAL_TRIE_FOR_SUBTERMS */
static void traverse_subgoal_trie(sg_node_ptr, char *, int, int *, int, int); 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_answer_trie(ans_node_ptr, char *, int, int *, int, int, int);
static void traverse_global_trie(gt_node_ptr, char *, 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_terms;
long global_trie_nodes; long global_trie_nodes;
long global_trie_references; 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_out trie_stats.out
#define TrStat_show trie_stats.show #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_terms trie_stats.global_trie_terms
#define TrStat_gt_nodes trie_stats.global_trie_nodes #define TrStat_gt_nodes trie_stats.global_trie_nodes
#define TrStat_gt_refs trie_stats.global_trie_references #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_STR_ARRAY_SIZE 100000
#define SHOW_TABLE_ARITY_ARRAY_SIZE 10000 #define SHOW_TABLE_ARITY_ARRAY_SIZE 10000
#define SHOW_TABLE_STRUCTURE(MESG, ARGS...) \ #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); TrNode_instr(current_node) = Yap_opcode(TrNode_instr(current_node) - position);
return; return;
} }
#endif /* YAPOR */ #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); CHECK_DECREMENT_GLOBAL_TRIE_FOR_SUBTERMS_REFERENCE(t, mode);
FREE_GLOBAL_TRIE_NODE(current_node); FREE_GLOBAL_TRIE_NODE(current_node);
if (num_nodes == 0) { if (num_nodes == 0) {
FREE_HASH_BUCKETS(Hash_buckets(hash)); FREE_BUCKETS(Hash_buckets(hash));
FREE_GLOBAL_TRIE_HASH(hash); FREE_GLOBAL_TRIE_HASH(hash);
if (parent_node != GLOBAL_root_gt) { if (parent_node != GLOBAL_root_gt) {
#ifdef GLOBAL_TRIE_FOR_SUBTERMS #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) { 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; int *current_arity = NULL, current_str_index = 0, current_mode = 0;
/* test if hashing */ /* test if hashing */
@ -589,35 +622,35 @@ static void traverse_subgoal_trie(sg_node_ptr current_node, char *str, int str_i
/* show answers ... */ /* show answers ... */
if (IS_SUBGOAL_LEAF_NODE(current_node)) { if (IS_SUBGOAL_LEAF_NODE(current_node)) {
sg_fr_ptr sg_fr = UNTAG_SUBGOAL_LEAF_NODE(TrNode_sg_fr(current_node)); sg_fr_ptr sg_fr = get_subgoal_frame(current_node);
TrStat_subgoals++; if (sg_fr) {
str[str_index] = 0; TrStat_subgoals++;
SHOW_TABLE_STRUCTURE("%s.\n", str); str[str_index] = 0;
TrStat_ans_nodes++; SHOW_TABLE_STRUCTURE("%s.\n", str);
if (SgFr_first_answer(sg_fr) == NULL) { TrStat_ans_nodes++;
if (SgFr_state(sg_fr) < complete) { if (SgFr_first_answer(sg_fr) == NULL) {
TrStat_sg_incomplete++; if (SgFr_state(sg_fr) < complete) {
SHOW_TABLE_STRUCTURE(" ---> INCOMPLETE\n"); 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 { } else {
TrStat_answers_no++; arity[0] = 0;
SHOW_TABLE_STRUCTURE(" NO\n"); 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) {
} else if (SgFr_first_answer(sg_fr) == SgFr_answer_trie(sg_fr)) { TrStat_sg_incomplete++;
TrStat_answers_true++; SHOW_TABLE_STRUCTURE(" ---> INCOMPLETE\n");
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");
} }
} }
} } else
/* ... or continue with child node */ /* ... or continue with child node */
else
traverse_subgoal_trie(TrNode_child(current_node), str, str_index, arity, mode, TRAVERSE_POSITION_FIRST); traverse_subgoal_trie(TrNode_child(current_node), str, str_index, arity, mode, TRAVERSE_POSITION_FIRST);
/* restore the initial state and continue with sibling nodes */ /* restore the initial state and continue with sibling nodes */
if (position == TRAVERSE_POSITION_FIRST) { if (position == TRAVERSE_POSITION_FIRST) {
str_index = current_str_index; 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); free(current_arity);
} }
return; 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) { 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; int *current_arity = NULL, current_str_index = 0, current_var_index = 0, current_mode = 0;
/* test if hashing */ /* 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) { 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; int *current_arity = NULL, current_str_index = 0, current_mode = 0;
/* test if hashing */ /* 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) { 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 mode = *mode_ptr;
int str_index = *str_index_ptr; int str_index = *str_index_ptr;
@ -993,7 +1028,7 @@ sg_fr_ptr subgoal_search(yamop *preg, CELL **Yaddr) {
subs_arity = 0; subs_arity = 0;
pred_arity = preg->u.Otapl.s; pred_arity = preg->u.Otapl.s;
tab_ent = preg->u.Otapl.te; 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); LOCK_SUBGOAL_TRIE(tab_ent);
#ifdef MODE_DIRECTED_TABLING #ifdef MODE_DIRECTED_TABLING
@ -1033,8 +1068,11 @@ sg_fr_ptr subgoal_search(yamop *preg, CELL **Yaddr) {
RESET_VARIABLE(t); 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); LOCK_SUBGOAL_NODE(current_sg_node);
if (TrNode_sg_fr(current_sg_node) == NULL) { #endif /* !THREADS */
if (*sg_fr_end == NULL) {
/* new tabled subgoal */ /* new tabled subgoal */
#ifdef MODE_DIRECTED_TABLING #ifdef MODE_DIRECTED_TABLING
if (subs_pos) { if (subs_pos) {
@ -1043,18 +1081,46 @@ sg_fr_ptr subgoal_search(yamop *preg, CELL **Yaddr) {
} else } else
mode_directed = NULL; mode_directed = NULL;
#endif /* MODE_DIRECTED_TABLING */ #endif /* MODE_DIRECTED_TABLING */
#ifndef THREADS
new_subgoal_frame(sg_fr, preg, mode_directed); 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); 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 { } 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 #ifdef LIMIT_TABLING
if (SgFr_state(sg_fr) <= ready) { /* incomplete or ready */ if (SgFr_state(sg_fr) <= ready) { /* incomplete or ready */
remove_from_global_sg_fr_list(sg_fr); remove_from_global_sg_fr_list(sg_fr);
} }
#endif /* LIMIT_TABLING */ #endif /* LIMIT_TABLING */
} }
UNLOCK_SUBGOAL_NODE(current_sg_node);
UNLOCK_SUBGOAL_TRIE(tab_ent); UNLOCK_SUBGOAL_TRIE(tab_ent);
return sg_fr; return sg_fr;
} }
@ -1069,6 +1135,7 @@ ans_node_ptr answer_search(sg_fr_ptr sg_fr, CELL *subs_ptr) {
vars_arity = 0; vars_arity = 0;
current_ans_node = SgFr_answer_trie(sg_fr); current_ans_node = SgFr_answer_trie(sg_fr);
if (IsMode_GlobalTrie(TabEnt_mode(SgFr_tab_ent(sg_fr)))) { if (IsMode_GlobalTrie(TabEnt_mode(SgFr_tab_ent(sg_fr)))) {
for (i = subs_arity; i >= 1; i--) { for (i = subs_arity; i >= 1; i--) {
TABLING_ERROR_CHECKING(answer_search, IsNonVarTerm(subs_ptr[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)); free_answer_hash_chain(SgFr_hash_chain(sg_fr));
SgFr_hash_chain(sg_fr) = NULL; SgFr_hash_chain(sg_fr) = NULL;
SgFr_state(sg_fr) += 2; /* complete --> compiled : complete_in_use --> compiled_in_use */ 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)); current_node = TrNode_child(SgFr_answer_trie(sg_fr));
if (current_node) { if (current_node) {
#ifdef YAPOR #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) { void free_subgoal_trie(sg_node_ptr current_node, int mode, int position) {
CACHE_REGS 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)) { if (! IS_SUBGOAL_LEAF_NODE(current_node)) {
int child_mode; int child_mode;
if (mode == TRAVERSE_MODE_NORMAL) { 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; child_mode = TRAVERSE_MODE_NORMAL;
free_subgoal_trie(TrNode_child(current_node), child_mode, TRAVERSE_POSITION_FIRST); free_subgoal_trie(TrNode_child(current_node), child_mode, TRAVERSE_POSITION_FIRST);
} else { } else {
sg_fr_ptr sg_fr; sg_fr_ptr sg_fr = get_subgoal_frame_for_abolish(current_node PASS_REGS);
ans_node_ptr ans_node; if (sg_fr) {
sg_fr = UNTAG_SUBGOAL_LEAF_NODE(TrNode_sg_fr(current_node)); ans_node_ptr ans_node;
free_answer_hash_chain(SgFr_hash_chain(sg_fr)); free_answer_hash_chain(SgFr_hash_chain(sg_fr));
ans_node = SgFr_answer_trie(sg_fr); ans_node = SgFr_answer_trie(sg_fr);
if (TrNode_child(ans_node)) if (TrNode_child(ans_node))
free_answer_trie(TrNode_child(ans_node), TRAVERSE_MODE_NORMAL, TRAVERSE_POSITION_FIRST); free_answer_trie(TrNode_child(ans_node), TRAVERSE_MODE_NORMAL, TRAVERSE_POSITION_FIRST);
FREE_ANSWER_TRIE_NODE(ans_node); IF_ABOLISH_ANSWER_TRIE_SHARED_DATA_STRUCTURES {
#if defined(MODE_DIRECTED_TABLING) && defined(YAPOR) FREE_ANSWER_TRIE_NODE(ans_node);
if (SgFr_invalid_chain(sg_fr)) { #if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
ans_node_ptr next_node, invalid_node = SgFr_invalid_chain(sg_fr); FREE_SUBGOAL_ENTRY(SgFr_sg_ent(sg_fr));
SgFr_invalid_chain(sg_fr) = NULL; #endif /* THREADS_FULL_SHARING || THREADS_CONSUMER_SHARING */
/* free invalid answer nodes */ }
while (invalid_node) { #if defined(MODE_DIRECTED_TABLING) && defined(YAPOR)
next_node = TrNode_next(invalid_node); if (SgFr_invalid_chain(sg_fr)) {
FREE_ANSWER_TRIE_NODE(invalid_node); ans_node_ptr next_node, invalid_node = SgFr_invalid_chain(sg_fr);
invalid_node = next_node; 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 */ #endif /* MODE_DIRECTED_TABLING && YAPOR */
#ifdef LIMIT_TABLING #ifdef LIMIT_TABLING
remove_from_global_sg_fr_list(sg_fr); remove_from_global_sg_fr_list(sg_fr);
#endif /* LIMIT_TABLING */ #endif /* LIMIT_TABLING */
FREE_SUBGOAL_FRAME(sg_fr); FREE_SUBGOAL_FRAME(sg_fr);
}
} }
if (position == TRAVERSE_POSITION_FIRST) { if (position == TRAVERSE_POSITION_FIRST) {
sg_node_ptr next_node = TrNode_next(current_node); sg_node_ptr next_node = TrNode_next(current_node);
CHECK_DECREMENT_GLOBAL_TRIE_REFERENCE(TrNode_entry(current_node), mode); IF_ABOLISH_SUBGOAL_TRIE_SHARED_DATA_STRUCTURES {
FREE_SUBGOAL_TRIE_NODE(current_node); CHECK_DECREMENT_GLOBAL_TRIE_REFERENCE(TrNode_entry(current_node), mode);
FREE_SUBGOAL_TRIE_NODE(current_node);
}
while (next_node) { while (next_node) {
current_node = next_node; current_node = next_node;
next_node = TrNode_next(current_node); next_node = TrNode_next(current_node);
free_subgoal_trie(current_node, mode, TRAVERSE_POSITION_NEXT); free_subgoal_trie(current_node, mode, TRAVERSE_POSITION_NEXT);
} }
} else { } else {
CHECK_DECREMENT_GLOBAL_TRIE_REFERENCE(TrNode_entry(current_node), mode); IF_ABOLISH_SUBGOAL_TRIE_SHARED_DATA_STRUCTURES {
FREE_SUBGOAL_TRIE_NODE(current_node); CHECK_DECREMENT_GLOBAL_TRIE_REFERENCE(TrNode_entry(current_node), mode);
FREE_SUBGOAL_TRIE_NODE(current_node);
}
} }
return; return;
} }
@ -1351,46 +1465,20 @@ void free_answer_trie(ans_node_ptr current_node, int mode, int position) {
} }
if (position == TRAVERSE_POSITION_FIRST) { if (position == TRAVERSE_POSITION_FIRST) {
ans_node_ptr next_node = TrNode_next(current_node); ans_node_ptr next_node = TrNode_next(current_node);
CHECK_DECREMENT_GLOBAL_TRIE_REFERENCE(TrNode_entry(current_node), mode); IF_ABOLISH_ANSWER_TRIE_SHARED_DATA_STRUCTURES {
FREE_ANSWER_TRIE_NODE(current_node); CHECK_DECREMENT_GLOBAL_TRIE_REFERENCE(TrNode_entry(current_node), mode);
FREE_ANSWER_TRIE_NODE(current_node);
}
while (next_node) { while (next_node) {
current_node = next_node; current_node = next_node;
next_node = TrNode_next(current_node); next_node = TrNode_next(current_node);
free_answer_trie(current_node, mode, TRAVERSE_POSITION_NEXT); free_answer_trie(current_node, mode, TRAVERSE_POSITION_NEXT);
} }
} else { } else {
CHECK_DECREMENT_GLOBAL_TRIE_REFERENCE(TrNode_entry(current_node), mode); IF_ABOLISH_ANSWER_TRIE_SHARED_DATA_STRUCTURES {
FREE_ANSWER_TRIE_NODE(current_node); 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;
}
} }
next_hash = Hash_next(hash);
FREE_HASH_BUCKETS(Hash_buckets(hash));
FREE_SUBGOAL_TRIE_HASH(hash);
hash = next_hash;
} }
return; return;
} }
@ -1408,7 +1496,7 @@ void free_answer_hash_chain(ans_hash_ptr hash) {
while (! *bucket) while (! *bucket)
bucket++; bucket++;
chain_node = *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) { while (++bucket != last_bucket) {
if (*bucket) { if (*bucket) {
while (TrNode_next(chain_node)) while (TrNode_next(chain_node))
@ -1418,7 +1506,7 @@ void free_answer_hash_chain(ans_hash_ptr hash) {
} }
} }
next_hash = Hash_next(hash); next_hash = Hash_next(hash);
FREE_HASH_BUCKETS(Hash_buckets(hash)); FREE_BUCKETS(Hash_buckets(hash));
FREE_ANSWER_TRIE_HASH(hash); FREE_ANSWER_TRIE_HASH(hash);
hash = next_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) { void show_table(tab_ent_ptr tab_ent, int show_mode, IOSTREAM *out) {
CACHE_REGS CACHE_REGS
sg_node_ptr sg_node; sg_node_ptr sg_node;
TrStat_out = out; TrStat_out = out;
TrStat_show = show_mode; TrStat_show = show_mode;
if (show_mode == SHOW_MODE_STATISTICS) { TrStat_subgoals = 0;
TrStat_subgoals = 0; TrStat_sg_incomplete = 0;
TrStat_sg_incomplete = 0; TrStat_sg_nodes = 1;
TrStat_sg_nodes = 1; TrStat_answers = 0;
TrStat_answers = 0; TrStat_answers_true = 0;
TrStat_answers_true = 0; TrStat_answers_no = 0;
TrStat_answers_no = 0;
#ifdef TABLING_INNER_CUTS #ifdef TABLING_INNER_CUTS
TrStat_answers_pruned = 0; TrStat_answers_pruned = 0;
#endif /* TABLING_INNER_CUTS */ #endif /* TABLING_INNER_CUTS */
TrStat_ans_nodes = 0; TrStat_ans_nodes = 0;
TrStat_gt_refs = 0; TrStat_gt_refs = 0;
if (show_mode == SHOW_MODE_STATISTICS)
Sfprintf(TrStat_out, "Table statistics for predicate '%s", AtomName(TabEnt_atom(tab_ent))); 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))); Sfprintf(TrStat_out, "Table structure for predicate '%s", AtomName(TabEnt_atom(tab_ent)));
}
#ifdef MODE_DIRECTED_TABLING #ifdef MODE_DIRECTED_TABLING
if (TabEnt_mode_directed(tab_ent)) { if (TabEnt_mode_directed(tab_ent)) {
int i, *mode_directed = 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 } else
#endif /* MODE_DIRECTED_TABLING */ #endif /* MODE_DIRECTED_TABLING */
Sfprintf(TrStat_out, "/%d'\n", TabEnt_arity(tab_ent)); 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 (sg_node) {
if (TabEnt_arity(tab_ent)) { if (TrNode_child(sg_node)) {
char *str = (char *) malloc(sizeof(char) * SHOW_TABLE_STR_ARRAY_SIZE); if (TabEnt_arity(tab_ent)) {
int str_index = sprintf(str, " ?- %s(", AtomName(TabEnt_atom(tab_ent))); char *str = (char *) malloc(sizeof(char) * SHOW_TABLE_STR_ARRAY_SIZE);
int *arity = (int *) malloc(sizeof(int) * SHOW_TABLE_ARITY_ARRAY_SIZE); int *arity = (int *) malloc(sizeof(int) * SHOW_TABLE_ARITY_ARRAY_SIZE);
arity[0] = 1; arity[0] = 1;
arity[1] = TabEnt_arity(tab_ent); arity[1] = TabEnt_arity(tab_ent);
traverse_subgoal_trie(sg_node, str, str_index, arity, TRAVERSE_MODE_NORMAL, TRAVERSE_POSITION_FIRST); int str_index = sprintf(str, " ?- %s(", AtomName(TabEnt_atom(tab_ent)));
free(str); traverse_subgoal_trie(TrNode_child(sg_node), str, str_index, arity, TRAVERSE_MODE_NORMAL, TRAVERSE_POSITION_FIRST);
free(arity); free(str);
} else { free(arity);
sg_fr_ptr sg_fr = UNTAG_SUBGOAL_LEAF_NODE(sg_node); } else {
TrStat_subgoals++; sg_fr_ptr sg_fr = get_subgoal_frame(sg_node);
SHOW_TABLE_STRUCTURE(" ?- %s.\n", AtomName(TabEnt_atom(tab_ent))); if (sg_fr) {
TrStat_ans_nodes++; TrStat_subgoals++;
if (SgFr_first_answer(sg_fr) == NULL) { SHOW_TABLE_STRUCTURE(" ?- %s.\n", AtomName(TabEnt_atom(tab_ent)));
if (SgFr_state(sg_fr) < complete) { TrStat_ans_nodes++;
TrStat_sg_incomplete++; if (SgFr_first_answer(sg_fr) == NULL) {
SHOW_TABLE_STRUCTURE(" ---> INCOMPLETE\n"); if (SgFr_state(sg_fr) < complete) {
} else { TrStat_sg_incomplete++;
TrStat_answers_no++; SHOW_TABLE_STRUCTURE(" ---> INCOMPLETE\n");
SHOW_TABLE_STRUCTURE(" NO\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"); SHOW_TABLE_STRUCTURE(" EMPTY\n");
if (show_mode == SHOW_MODE_STATISTICS) { if (show_mode == SHOW_MODE_STATISTICS) {
Sfprintf(TrStat_out, " Subgoal trie structure\n"); 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) { void show_global_trie(int show_mode, IOSTREAM *out) {
CACHE_REGS
TrStat_out = out; TrStat_out = out;
TrStat_show = show_mode; TrStat_show = show_mode;
if (show_mode == SHOW_MODE_STATISTICS) { TrStat_gt_terms = 0;
TrStat_gt_terms = 0; TrStat_gt_nodes = 1;
TrStat_gt_nodes = 1; TrStat_gt_refs = 0;
TrStat_gt_refs = 0; if (show_mode == SHOW_MODE_STATISTICS)
Sfprintf(TrStat_out, "Global trie statistics\n"); Sfprintf(TrStat_out, "Global trie statistics\n");
} else { /* SHOW_MODE_STRUCTURE */ else /* SHOW_MODE_STRUCTURE */
Sfprintf(TrStat_out, "Global trie structure\n"); Sfprintf(TrStat_out, "Global trie structure\n");
}
if (TrNode_child(GLOBAL_root_gt)) { if (TrNode_child(GLOBAL_root_gt)) {
char *str = (char *) malloc(sizeof(char) * SHOW_TABLE_STR_ARRAY_SIZE); char *str = (char *) malloc(sizeof(char) * SHOW_TABLE_STR_ARRAY_SIZE);
int *arity = (int *) malloc(sizeof(int) * SHOW_TABLE_ARITY_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; return;
} }
#endif /* TABLING */ #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 #else
static inline sg_node_ptr subgoal_trie_check_insert_entry(tab_ent_ptr tab_ent, sg_node_ptr parent_node, Term t) { 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 */ #endif /* MODE_GLOBAL_TRIE_ENTRY */
#ifdef THREADS_NO_SHARING
CACHE_REGS CACHE_REGS
#endif /* THREADS_NO_SHARING */
sg_node_ptr child_node; sg_node_ptr child_node;
LOCK_SUBGOAL_NODE(parent_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; sg_node_ptr chain_node, next_node, *old_bucket, *old_hash_buckets, *new_hash_buckets;
int num_buckets; int num_buckets;
num_buckets = Hash_num_buckets(hash) * 2; 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_hash_buckets = Hash_buckets(hash);
old_bucket = old_hash_buckets + Hash_num_buckets(hash); old_bucket = old_hash_buckets + Hash_num_buckets(hash);
do { 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); } while (old_bucket != old_hash_buckets);
Hash_buckets(hash) = new_hash_buckets; Hash_buckets(hash) = new_hash_buckets;
Hash_num_buckets(hash) = num_buckets; Hash_num_buckets(hash) = num_buckets;
FREE_HASH_BUCKETS(old_hash_buckets); FREE_BUCKETS(old_hash_buckets);
} }
UNLOCK_SUBGOAL_NODE(parent_node); UNLOCK_SUBGOAL_NODE(parent_node);
return child_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 #else
static inline sg_node_ptr subgoal_trie_check_insert_entry(tab_ent_ptr tab_ent, sg_node_ptr parent_node, Term t) { 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 */ #endif /* MODE_GLOBAL_TRIE_ENTRY */
#ifdef THREADS_NO_SHARING
CACHE_REGS
#endif /* THREADS_NO_SHARING */
sg_node_ptr child_node; sg_node_ptr child_node;
sg_hash_ptr hash; sg_hash_ptr hash;
@ -325,7 +330,7 @@ subgoal_trie_hash:
/* expand current hash */ /* expand current hash */
sg_node_ptr chain_node, next_node, *old_bucket, *old_hash_buckets, *new_hash_buckets; sg_node_ptr chain_node, next_node, *old_bucket, *old_hash_buckets, *new_hash_buckets;
num_buckets = Hash_num_buckets(hash) * 2; 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_hash_buckets = Hash_buckets(hash);
old_bucket = old_hash_buckets + Hash_num_buckets(hash); old_bucket = old_hash_buckets + Hash_num_buckets(hash);
do { do {
@ -342,7 +347,7 @@ subgoal_trie_hash:
} while (old_bucket != old_hash_buckets); } while (old_bucket != old_hash_buckets);
Hash_buckets(hash) = new_hash_buckets; Hash_buckets(hash) = new_hash_buckets;
Hash_num_buckets(hash) = num_buckets; Hash_num_buckets(hash) = num_buckets;
FREE_HASH_BUCKETS(old_hash_buckets); FREE_BUCKETS(old_hash_buckets);
} }
UNLOCK_SUBGOAL_NODE(parent_node); UNLOCK_SUBGOAL_NODE(parent_node);
return child_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; ans_node_ptr chain_node, next_node, *old_bucket, *old_hash_buckets, *new_hash_buckets;
int num_buckets; int num_buckets;
num_buckets = Hash_num_buckets(hash) * 2; 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_hash_buckets = Hash_buckets(hash);
old_bucket = old_hash_buckets + Hash_num_buckets(hash); old_bucket = old_hash_buckets + Hash_num_buckets(hash);
do { 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); } while (old_bucket != old_hash_buckets);
Hash_buckets(hash) = new_hash_buckets; Hash_buckets(hash) = new_hash_buckets;
Hash_num_buckets(hash) = num_buckets; Hash_num_buckets(hash) = num_buckets;
FREE_HASH_BUCKETS(old_hash_buckets); FREE_BUCKETS(old_hash_buckets);
} }
UNLOCK_ANSWER_NODE(parent_node); UNLOCK_ANSWER_NODE(parent_node);
return child_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 #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) { 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 */ #endif /* MODE_GLOBAL_TRIE_ENTRY */
CACHE_REGS
ans_node_ptr child_node; ans_node_ptr child_node;
ans_hash_ptr hash; ans_hash_ptr hash;
@ -627,7 +633,7 @@ answer_trie_hash:
/* expand current hash */ /* expand current hash */
ans_node_ptr chain_node, next_node, *old_bucket, *old_hash_buckets, *new_hash_buckets; ans_node_ptr chain_node, next_node, *old_bucket, *old_hash_buckets, *new_hash_buckets;
num_buckets = Hash_num_buckets(hash) * 2; 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_hash_buckets = Hash_buckets(hash);
old_bucket = old_hash_buckets + Hash_num_buckets(hash); old_bucket = old_hash_buckets + Hash_num_buckets(hash);
do { do {
@ -644,7 +650,7 @@ answer_trie_hash:
} while (old_bucket != old_hash_buckets); } while (old_bucket != old_hash_buckets);
Hash_buckets(hash) = new_hash_buckets; Hash_buckets(hash) = new_hash_buckets;
Hash_num_buckets(hash) = num_buckets; Hash_num_buckets(hash) = num_buckets;
FREE_HASH_BUCKETS(old_hash_buckets); FREE_BUCKETS(old_hash_buckets);
} }
UNLOCK_ANSWER_NODE(parent_node); UNLOCK_ANSWER_NODE(parent_node);
return child_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; gt_node_ptr chain_node, next_node, *old_bucket, *old_hash_buckets, *new_hash_buckets;
int num_buckets; int num_buckets;
num_buckets = Hash_num_buckets(hash) * 2; 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_hash_buckets = Hash_buckets(hash);
old_bucket = old_hash_buckets + Hash_num_buckets(hash); old_bucket = old_hash_buckets + Hash_num_buckets(hash);
do { 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); } while (old_bucket != old_hash_buckets);
Hash_buckets(hash) = new_hash_buckets; Hash_buckets(hash) = new_hash_buckets;
Hash_num_buckets(hash) = num_buckets; Hash_num_buckets(hash) = num_buckets;
FREE_HASH_BUCKETS(old_hash_buckets); FREE_BUCKETS(old_hash_buckets);
} }
UNLOCK_GLOBAL_NODE(parent_node); UNLOCK_GLOBAL_NODE(parent_node);
return child_node; return child_node;
@ -927,7 +933,7 @@ global_trie_hash:
/* expand current hash */ /* expand current hash */
gt_node_ptr chain_node, next_node, *old_bucket, *old_hash_buckets, *new_hash_buckets; gt_node_ptr chain_node, next_node, *old_bucket, *old_hash_buckets, *new_hash_buckets;
num_buckets = Hash_num_buckets(hash) * 2; 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_hash_buckets = Hash_buckets(hash);
old_bucket = old_hash_buckets + Hash_num_buckets(hash); old_bucket = old_hash_buckets + Hash_num_buckets(hash);
do { do {
@ -944,7 +950,7 @@ global_trie_hash:
} while (old_bucket != old_hash_buckets); } while (old_bucket != old_hash_buckets);
Hash_buckets(hash) = new_hash_buckets; Hash_buckets(hash) = new_hash_buckets;
Hash_num_buckets(hash) = num_buckets; Hash_num_buckets(hash) = num_buckets;
FREE_HASH_BUCKETS(old_hash_buckets); FREE_BUCKETS(old_hash_buckets);
} }
UNLOCK_GLOBAL_NODE(parent_node); UNLOCK_GLOBAL_NODE(parent_node);
return child_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) FREE_ANSWER_TRIE_NODE(NODE)
#endif /* YAPOR */ #endif /* YAPOR */
#define INVALIDATE_ANSWER_TRIE_LEAF_NODE(NODE, SG_FR) \ #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); \ TrNode_next(NODE) = SgFr_invalid_chain(SG_FR); \
SgFr_invalid_chain(SG_FR) = NODE 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); Hash_next(Hash_previous(hash)) = Hash_next(hash);
else else
SgFr_hash_chain(sg_fr) = Hash_next(hash); SgFr_hash_chain(sg_fr) = Hash_next(hash);
FREE_HASH_BUCKETS(Hash_buckets(hash)); FREE_BUCKETS(Hash_buckets(hash));
FREE_ANSWER_TRIE_HASH(hash); FREE_ANSWER_TRIE_HASH(hash);
} else { } else {
if (position == TRAVERSE_POSITION_FIRST) { 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 #ifdef MODE_GLOBAL_TRIE_LOOP
current_node = TrNode_parent(current_node); current_node = TrNode_parent(current_node);
#else #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 */ #endif /* MODE_GLOBAL_TRIE_LOOP */
do { 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 yamop getwork_first_time[1] GETWORK_FIRST_TIME MkInstE _getwork_first_time
#endif /* YAPOR */ #endif /* YAPOR */
#ifdef TABLING #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_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_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_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) 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 */ #endif /* TABLING */
/* */ /* */

View File

@ -164,6 +164,7 @@ end_special(Name, W) :-
end_special(_, _). end_special(_, _).
special_op("clause_with_cut","TABLING_INNER_CUTS"). 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_c","CUT_C").
special_op("cut_userc","CUT_C"). special_op("cut_userc","CUT_C").
special_op("run_eam","BEAM"). special_op("run_eam","BEAM").