YAP 7.1.0
or.cow_engine.c
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#ifdef YAPOR_COW
20#include <sys/types.h>
21#if HAVE_UNISTD_H
22#include <unistd.h>
23#endif
24#include <stdio.h>
25#include "Yatom.h"
26#include "YapHeap.h"
27#include "or.macros.h"
28
29
30
31
32/* ------------------------------------- **
33** Local functions declaration **
34** ------------------------------------- */
35
36static void share_private_nodes(int worker_q);
37
38
39
40/* ----------------------- **
41** Local inlines **
42** ----------------------- */
43
44static inline void PUT_BUSY(int);
45
46static inline
47void PUT_BUSY(int worker_num) {
48 LOCK(GLOBAL_locks_bm_idle_workers);
49 BITMAP_delete(GLOBAL_bm_idle_workers, worker_num);
50 UNLOCK(GLOBAL_locks_bm_idle_workers);
51 return;
52}
53
54
55
56/* -------------------------- **
57** Global functions **
58** -------------------------- */
59
60void make_root_choice_point(void) {
61 if (worker_id == 0) {
62 LOCAL_top_cp = GLOBAL_root_cp = OrFr_node(GLOBAL_root_or_fr) = B;
63 } else {
64 B = LOCAL_top_cp = GLOBAL_root_cp;
65 B->cp_tr = TR = ((choiceptr) (worker_offset(0) + (CELL)(B)))->cp_tr;
66 }
67 B->cp_h = H0;
68 B->cp_ap = GETWORK;
69 B->cp_or_fr = GLOBAL_root_or_fr;
70 LOCAL_top_or_fr = GLOBAL_root_or_fr;
71 LOCAL_load = 0;
72 LOCAL_prune_request = NULL;
73 BRANCH(worker_id, 0) = 0;
74 return;
75}
76
77
78void free_root_choice_point(void) {
79 B = LOCAL_top_cp->cp_b;
80 LOCAL_top_cp = (choiceptr) LOCAL_LocalBase;
81 return;
82}
83
84
85int p_share_work(void) {
86 int worker_q = LOCAL_share_request;
87 int son;
88
89 if (! BITMAP_member(OrFr_members(REMOTE_top_or_fr(worker_q)), worker_id) ||
90 B == REMOTE_top_cp(worker_q) ||
91 (LOCAL_load <= GLOBAL_delayed_release_load && OrFr_nearest_livenode(LOCAL_top_or_fr) == NULL)) {
92 /* refuse sharing request */
93 REMOTE_reply_signal(LOCAL_share_request) = no_sharing;
94 LOCAL_share_request = MAX_WORKERS;
95 PUT_OUT_REQUESTABLE(worker_id);
96 return TRUE;
97 }
98 /* sharing request accepted */
99 REMOTE_reply_signal(worker_q) = sharing;
100 share_private_nodes(worker_q);
101 if ((son = fork()) == 0) {
102 worker_id = worker_q; /* child becomes requesting worker */
103 LOCAL = REMOTE(worker_id);
104 LOCAL_reply_signal = worker_ready;
105 PUT_IN_REQUESTABLE(worker_id);
106 PUT_BUSY(worker_id);
107
108 return FALSE;
109 } else {
110 GLOBAL_worker_pid(worker_q) = son;
111 LOCAL_share_request = MAX_WORKERS;
112 PUT_IN_REQUESTABLE(worker_id);
113
114 return TRUE;
115 }
116}
117
118
119int q_share_work(int worker_p) {
120 LOCK_OR_FRAME(LOCAL_top_or_fr);
121 if (Get_REMOTE_prune_request(worker_p)) {
122 /* worker p with prune request */
123 UNLOCK_OR_FRAME(LOCAL_top_or_fr);
124 return FALSE;
125 }
126 YAPOR_ERROR_CHECKING(q_share_work, OrFr_pend_prune_cp(LOCAL_top_or_fr) && BRANCH_LTT(worker_p, OrFr_depth(LOCAL_top_or_fr)) < OrFr_pend_prune_ltt(LOCAL_top_or_fr));
127 /* there is no pending prune with worker p at right --> safe move to worker p branch */
128 BRANCH(worker_id, OrFr_depth(LOCAL_top_or_fr)) = BRANCH(worker_p, OrFr_depth(LOCAL_top_or_fr));
129 LOCAL_prune_request = NULL;
130 UNLOCK_OR_FRAME(LOCAL_top_or_fr);
131
132 /* make sharing request */
133 LOCK_WORKER(worker_p);
134 if (BITMAP_member(GLOBAL_bm_idle_workers, worker_p) ||
135 REMOTE_share_request(worker_p) != MAX_WORKERS) {
136 /* worker p is idle or has another request */
137 UNLOCK_WORKER(worker_p);
138 return FALSE;
139 }
140 REMOTE_share_request(worker_p) = worker_id;
141 UNLOCK_WORKER(worker_p);
142
143 /* wait for an answer */
144 while (LOCAL_reply_signal == worker_ready);
145 if (LOCAL_reply_signal == no_sharing) {
146 /* sharing request refused */
147 LOCAL_reply_signal = worker_ready;
148 return FALSE;
149 }
150 /* exit this process */
151 exit(0);
152}
153
154
155
156/* ------------------------- **
157** Local functions **
158** ------------------------- */
159
160static
161void share_private_nodes(int worker_q) {
162 int depth;
163 choiceptr AuxB;
164 or_fr_ptr or_frame, previous_or_frame;
165
166 /* initialize auxiliary variables */
167 AuxB = B;
168 previous_or_frame = NULL;
169 depth = OrFr_depth(LOCAL_top_or_fr);
170 /* sharing loop */
171 while (AuxB != LOCAL_top_cp) {
172 depth++;
173 ALLOC_OR_FRAME(or_frame);
174 INIT_LOCK(OrFr_lock(or_frame));
175 SetOrFr_node(or_frame, AuxB);
176 OrFr_alternative(or_frame) = AuxB->cp_ap;
177 OrFr_pend_prune_cp(or_frame) = NULL;
178 OrFr_nearest_leftnode(or_frame) = LOCAL_top_or_fr;
179 OrFr_qg_solutions(or_frame) = NULL;
180 BITMAP_clear(OrFr_members(or_frame));
181 BITMAP_insert(OrFr_members(or_frame), worker_id);
182 BITMAP_insert(OrFr_members(or_frame), worker_q);
183 if (AuxB->cp_ap && YAMOP_SEQ(AuxB->cp_ap)) {
184 AuxB->cp_ap = GETWORK_SEQ;
185 } else {
186 AuxB->cp_ap = GETWORK;
187 }
188 AuxB->cp_or_fr = or_frame;
189 AuxB = AuxB->cp_b;
190 if (previous_or_frame) {
191 OrFr_nearest_livenode(previous_or_frame) = OrFr_next(previous_or_frame) = or_frame;
192 }
193 previous_or_frame = or_frame;
194 }
195 /* initialize last or-frame pointer */
196 or_frame = AuxB->cp_or_fr;
197 if (previous_or_frame) {
198 OrFr_nearest_livenode(previous_or_frame) = OrFr_next(previous_or_frame) = or_frame;
199 }
200 /* update depth */
201 if (depth >= MAX_BRANCH_DEPTH)
202 Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, "maximum depth exceded (share_private_nodes)");
203 or_frame = B->cp_or_fr;
204 while (or_frame != LOCAL_top_or_fr) {
205 unsigned int branch;
206 if (OrFr_alternative(or_frame)) {
207 branch = YAMOP_OR_ARG(OrFr_alternative(or_frame)) + 1;
208 } else {
209 branch = 1;
210 }
211 branch |= YAMOP_CUT_FLAG; /* in doubt, assume cut */
212 BRANCH(worker_id, depth) = BRANCH(worker_q, depth) = branch;
213 OrFr_depth(or_frame) = depth--;
214 or_frame = OrFr_next_on_stack(or_frame);
215 }
216 /* update old shared nodes */
217 while (or_frame != REMOTE_top_or_fr(worker_q)) {
218 LOCK_OR_FRAME(or_frame);
219 BRANCH(worker_q, OrFr_depth(or_frame)) = BRANCH(worker_id, OrFr_depth(or_frame));
220 BITMAP_insert(OrFr_members(or_frame), worker_q);
221 UNLOCK_OR_FRAME(or_frame);
222 or_frame = OrFr_next_on_stack(or_frame);
223 }
224 /* update top shared nodes */
225 REMOTE_top_cp(worker_q) = LOCAL_top_cp = B;
226 REMOTE_top_or_fr(worker_q) = LOCAL_top_or_fr = LOCAL_top_cp->cp_or_fr;
227 /* update prune request */
228 if (LOCAL_prune_request) {
229 CUT_send_prune_request(worker_q, LOCAL_prune_request);
230 }
231 /* update load and return */
232 REMOTE_load(worker_q) = LOCAL_load = 0;
233 return;
234}
235#endif /* YAPOR_COW */
Main definitions.