1 /************************************************************************
2 ** **
3 ** The YapTab/YapOr/OPTYap systems **
4 ** **
5 ** YapTab extends the Yap Prolog engine to support sequential tabling **
6 ** YapOr extends the Yap Prolog engine to support or-parallelism **
7 ** OPTYap extends the Yap Prolog engine to support or-parallel tabling **
8 ** **
9 ** **
10 ** Yap Prolog was developed at University of Porto, Portugal **
11 ** **
12 ************************************************************************/
13
14 /***********************
15 ** Includes **
16 ***********************/
17
18 #include "Yap.h"
19 #if defined(YAPOR) || defined(TABLING)
20 #define OPT_MAVAR_STATIC
21 #include "Yatom.h"
22 #include "YapHeap.h"
23 #include <unistd.h>
24 #include <signal.h>
25 #ifdef YAPOR
26 #include "or.macros.h"
27 #endif /* YAPOR */
28 #ifdef TABLING
29 #include "tab.macros.h"
30 #endif /* TABLING */
31 #if defined(TABLING) || !defined(ACOW)
32 #ifndef TABLING
33 #include "opt.mavar.h"
34 #endif /* !TABLING */
35 #ifdef MULTI_ASSIGNMENT_VARIABLES
36 ma_hash_entry Yap_ma_hash_table[MAVARS_HASH_SIZE];
37 UInt Yap_timestamp; /* an unsigned int */
38 ma_h_inner_struct *Yap_ma_h_top;
39 #endif /* MULTI_ASSIGNMENT_VARIABLES */
40 #endif /* TABLING || !ACOW */
41 #ifdef ACOW
42 #include "sys/wait.h"
43 #endif /* ACOW */
44
45
46
47
48 /************************************************
49 ** Global variables are defined here **
50 ************************************************/
51
52 #if defined(YAPOR) && ! defined(THREADS)
53 struct worker WORKER;
54 #endif /* YAPOR && ! THREADS */
55
56
57
58 /*********************
59 ** Macros **
60 *********************/
61
62 #ifdef SHM_MEMORY_ALLOC_SCHEME
63 #define STRUCTS_PER_PAGE(STR_TYPE) ((Yap_page_size - STRUCT_SIZE(struct page_header)) / STRUCT_SIZE(STR_TYPE))
64
65 #define INIT_PAGES(PG, STR_TYPE) \
66 INIT_LOCK(Pg_lock(PG)); \
67 Pg_pg_alloc(PG) = 0; \
68 Pg_str_in_use(PG) = 0; \
69 Pg_str_per_pg(PG) = STRUCTS_PER_PAGE(STR_TYPE); \
70 Pg_free_pg(PG) = NULL
71 #else
72 #define INIT_PAGES(PG, STR_TYPE) Pg_str_in_use(PG) = 0
73 #endif /* SHM_MEMORY_ALLOC_SCHEME */
74
75
76
77 /*******************************
78 ** Global functions **
79 *******************************/
80
Yap_init_global(int max_table_size,int n_workers,int sch_loop,int delay_load)81 void Yap_init_global(int max_table_size, int n_workers, int sch_loop, int delay_load) {
82 int i;
83
84 /* global data related to memory management */
85 #ifdef LIMIT_TABLING
86 if (max_table_size)
87 GLOBAL_MAX_PAGES = ((max_table_size - 1) * 1024 * 1024 / SHMMAX + 1) * SHMMAX / Yap_page_size;
88 else
89 GLOBAL_MAX_PAGES = -1;
90 #endif /* LIMIT_TABLING */
91 INIT_PAGES(GLOBAL_PAGES_void, void *);
92 #ifdef YAPOR
93 INIT_PAGES(GLOBAL_PAGES_or_fr, struct or_frame);
94 INIT_PAGES(GLOBAL_PAGES_qg_sol_fr, struct query_goal_solution_frame);
95 INIT_PAGES(GLOBAL_PAGES_qg_ans_fr, struct query_goal_answer_frame);
96 #endif /* YAPOR */
97 #ifdef TABLING_INNER_CUTS
98 INIT_PAGES(GLOBAL_PAGES_tg_sol_fr, struct table_subgoal_solution_frame);
99 INIT_PAGES(GLOBAL_PAGES_tg_ans_fr, struct table_subgoal_answer_frame);
100 #endif /* TABLING_INNER_CUTS */
101 #ifdef TABLING
102 INIT_PAGES(GLOBAL_PAGES_tab_ent, struct table_entry);
103 INIT_PAGES(GLOBAL_PAGES_sg_fr, struct subgoal_frame);
104 INIT_PAGES(GLOBAL_PAGES_dep_fr, struct dependency_frame);
105 INIT_PAGES(GLOBAL_PAGES_sg_node, struct subgoal_trie_node);
106 INIT_PAGES(GLOBAL_PAGES_ans_node, struct answer_trie_node);
107 INIT_PAGES(GLOBAL_PAGES_gt_node, struct global_trie_node);
108 INIT_PAGES(GLOBAL_PAGES_sg_hash, struct subgoal_trie_hash);
109 INIT_PAGES(GLOBAL_PAGES_ans_hash, struct answer_trie_hash);
110 INIT_PAGES(GLOBAL_PAGES_gt_hash, struct global_trie_hash);
111 #endif /* TABLING */
112 #if defined(YAPOR) && defined(TABLING)
113 INIT_PAGES(GLOBAL_PAGES_susp_fr, struct suspension_frame);
114 #endif /* YAPOR && TABLING */
115
116 #ifdef YAPOR
117 /* global static data */
118 number_workers = n_workers;
119 worker_pid(0) = getpid();
120 for (i = 1; i < number_workers; i++) worker_pid(i) = 0;
121 SCHEDULER_LOOP = sch_loop;
122 DELAYED_RELEASE_LOAD = delay_load;
123
124 /* global data related to or-performance */
125 GLOBAL_number_goals = 0;
126 GLOBAL_best_times(0) = 0;
127 GLOBAL_performance_mode = PERFORMANCE_OFF;
128
129 /* global data related to or-parallelism */
130 BITMAP_clear(GLOBAL_bm_present_workers);
131 for (i = 0; i < number_workers; i++)
132 BITMAP_insert(GLOBAL_bm_present_workers, i);
133 BITMAP_copy(GLOBAL_bm_idle_workers, GLOBAL_bm_present_workers);
134 BITMAP_clear(GLOBAL_bm_root_cp_workers);
135 BITMAP_clear(GLOBAL_bm_invisible_workers);
136 BITMAP_clear(GLOBAL_bm_requestable_workers);
137 BITMAP_clear(GLOBAL_bm_executing_workers);
138 BITMAP_copy(GLOBAL_bm_finished_workers, GLOBAL_bm_present_workers);
139 INIT_LOCK(GLOBAL_LOCKS_bm_idle_workers);
140 INIT_LOCK(GLOBAL_LOCKS_bm_root_cp_workers);
141 INIT_LOCK(GLOBAL_LOCKS_bm_invisible_workers);
142 INIT_LOCK(GLOBAL_LOCKS_bm_requestable_workers);
143 INIT_LOCK(GLOBAL_LOCKS_bm_executing_workers);
144 INIT_LOCK(GLOBAL_LOCKS_bm_finished_workers);
145 #ifdef TABLING_INNER_CUTS
146 INIT_LOCK(GLOBAL_LOCKS_bm_pruning_workers);
147 #endif /* TABLING_INNER_CUTS */
148 GLOBAL_LOCKS_who_locked_heap = MAX_WORKERS;
149 INIT_LOCK(GLOBAL_LOCKS_heap_access);
150 INIT_LOCK(GLOBAL_LOCKS_alloc_block);
151 if (number_workers == 1)
152 PARALLEL_EXECUTION_MODE = FALSE;
153 else
154 PARALLEL_EXECUTION_MODE = TRUE;
155 #endif /* YAPOR */
156
157 #ifdef TABLING
158 /* global data related to tabling */
159 new_global_trie_node(GLOBAL_root_gt, 0, NULL, NULL, NULL);
160 GLOBAL_root_tab_ent = NULL;
161 #ifdef LIMIT_TABLING
162 GLOBAL_first_sg_fr = NULL;
163 GLOBAL_last_sg_fr = NULL;
164 GLOBAL_check_sg_fr = NULL;
165 #endif /* LIMIT_TABLING */
166 GLOBAL_root_dep_fr = NULL;
167 for (i = 0; i < MAX_TABLE_VARS; i++) {
168 CELL *pt = GLOBAL_table_var_enumerator_addr(i);
169 RESET_VARIABLE(pt);
170 }
171 #ifdef TABLE_LOCK_AT_WRITE_LEVEL
172 for (i = 0; i < TABLE_LOCK_BUCKETS; i++)
173 INIT_LOCK(GLOBAL_table_lock(i));
174 #endif /* TABLE_LOCK_AT_WRITE_LEVEL */
175 #endif /* TABLING */
176
177 return;
178 }
179
180
Yap_init_local(void)181 void Yap_init_local(void) {
182 #ifdef YAPOR
183 /* local data related to or-parallelism */
184 LOCAL = REMOTE + worker_id;
185 Set_LOCAL_top_cp((choiceptr) Yap_LocalBase);
186 LOCAL_top_or_fr = GLOBAL_root_or_fr;
187 LOCAL_load = 0;
188 LOCAL_share_request = MAX_WORKERS;
189 LOCAL_reply_signal = worker_ready;
190 #ifdef ENV_COPY
191 INIT_LOCK(LOCAL_lock_signals);
192 #endif /* ENV_COPY */
193 Set_LOCAL_prune_request(NULL);
194 #endif /* YAPOR */
195 INIT_LOCK(LOCAL_lock);
196 #ifdef TABLING
197 /* local data related to tabling */
198 LOCAL_next_free_ans_node = NULL;
199 LOCAL_top_sg_fr = NULL;
200 LOCAL_top_dep_fr = GLOBAL_root_dep_fr;
201 #ifdef YAPOR
202 Set_LOCAL_top_cp_on_stack((choiceptr) Yap_LocalBase); /* ??? */
203 LOCAL_top_susp_or_fr = GLOBAL_root_or_fr;
204 #endif /* YAPOR */
205 #endif /* TABLING */
206 return;
207 }
208
209
make_root_frames(void)210 void make_root_frames(void) {
211 #ifdef YAPOR
212 /* root or frame */
213 or_fr_ptr or_fr;
214
215 ALLOC_OR_FRAME(or_fr);
216 INIT_LOCK(OrFr_lock(or_fr));
217 OrFr_alternative(or_fr) = NULL;
218 BITMAP_copy(OrFr_members(or_fr), GLOBAL_bm_present_workers);
219 SetOrFr_node(or_fr, (choiceptr) Yap_LocalBase);
220 OrFr_nearest_livenode(or_fr) = NULL;
221 OrFr_depth(or_fr) = 0;
222 Set_OrFr_pend_prune_cp(or_fr, NULL);
223 OrFr_nearest_leftnode(or_fr) = or_fr;
224 OrFr_qg_solutions(or_fr) = NULL;
225 #ifdef TABLING_INNER_CUTS
226 OrFr_tg_solutions(or_fr) = NULL;
227 #endif /* TABLING_INNER_CUTS */
228 #ifdef TABLING
229 OrFr_owners(or_fr) = number_workers;
230 OrFr_next_on_stack(or_fr) = NULL;
231 OrFr_suspensions(or_fr) = NULL;
232 OrFr_nearest_suspnode(or_fr) = or_fr;
233 #endif /* TABLING */
234 OrFr_next(or_fr) = NULL;
235 GLOBAL_root_or_fr = or_fr;
236 #endif /* YAPOR */
237
238 #ifdef TABLING
239 /* root dependency frame */
240 if (!GLOBAL_root_dep_fr) {
241 new_dependency_frame(GLOBAL_root_dep_fr, FALSE, NULL, NULL, NULL, NULL, NULL);
242 #ifdef TABLING
243 DepFr_cons_cp(GLOBAL_root_dep_fr) = B;
244 #endif /* TABLING */
245 }
246 #endif /* TABLING */
247 }
248
249 #ifdef YAPOR
init_workers(void)250 void init_workers(void) {
251 int proc;
252 #ifdef THREADS
253 return;
254 #endif
255 #ifdef ACOW
256 if (number_workers > 1) {
257 int son;
258 son = fork();
259 if (son == -1)
260 Yap_Error(FATAL_ERROR, TermNil, "fork error (init_workers)");
261 if (son > 0) {
262 /* I am the father, I must stay here and wait for my children to all die */
263 struct sigaction sigact;
264
265 GLOBAL_master_worker = getpid();
266 sigact.sa_handler = SIG_DFL;
267 sigemptyset(&sigact.sa_mask);
268 sigact.sa_flags = SA_RESTART;
269 sigaction(SIGINT, &sigact, NULL);
270 pause();
271 exit(0);
272 } else worker_pid(0) = getpid();
273 }
274 #endif /* ACOW */
275 for (proc = 1; proc < number_workers; proc++) {
276 int son;
277 son = fork();
278 if (son == -1)
279 Yap_Error(FATAL_ERROR, TermNil, "fork error (init_workers)");
280 if (son == 0) {
281 /* new worker */
282 worker_id = proc;
283 remap_memory();
284 break;
285 }
286 else worker_pid(proc) = son;
287 }
288 }
289 #endif /* YAPOR */
290
291
itos(int i,char * s)292 void itos(int i, char *s) {
293 int n,r,j;
294 n = 10;
295 while (n <= i) n *= 10;
296 j = 0;
297 while (n > 1) {
298 n = n / 10;
299 r = i / n;
300 i = i - r * n;
301 s[j++] = r + '0';
302 }
303 s[j] = 0;
304 return;
305 }
306 #endif /* YAPOR || TABLING */
307