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