1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 /****************************************************************************/
4 /* */
5 /* File: pcmds.c */
6 /* */
7 /* Purpose: DDD-commands for Prio Environment */
8 /* */
9 /* Author: Klaus Birken */
10 /* Institut fuer Computeranwendungen III */
11 /* Universitaet Stuttgart */
12 /* Pfaffenwaldring 27 */
13 /* 70569 Stuttgart */
14 /* email: birken@ica3.uni-stuttgart.de */
15 /* phone: 0049-(0)711-685-7007 */
16 /* fax : 0049-(0)711-685-7000 */
17 /* */
18 /* History: 980720 kb begin */
19 /* */
20 /* Remarks: */
21 /* */
22 /****************************************************************************/
23
24 /****************************************************************************/
25 /* */
26 /* include files */
27 /* system include files */
28 /* application include files */
29 /* */
30 /****************************************************************************/
31
32 /* standard C library */
33 #include <config.h>
34 #include <cstdlib>
35 #include <cstdio>
36 #include <cstring>
37
38 #include <dune/common/exceptions.hh>
39 #include <dune/common/stdstreams.hh>
40
41 #include <dune/uggrid/parallel/ddd/dddi.h>
42
43 #define DebugPrio 10 /* 0 is all, 10 is off */
44
45
46 /****************************************************************************/
47 /* */
48 /* defines in the following order */
49 /* */
50 /* compile time constants defining static data size (i.e. arrays) */
51 /* other constants */
52 /* macros */
53 /* */
54 /****************************************************************************/
55
56
57 namespace DDD {
58 namespace Prio {
59
60 /* overall mode of prio-environment */
61 enum class PrioMode : unsigned char {
62 PMODE_IDLE = 0, /* waiting for next DDD_PrioBegin() */
63 PMODE_CMDS, /* after DDD_PrioBegin(), before DDD_PrioEnd() */
64 PMODE_BUSY /* during DDD_PrioEnd() */
65 };
66
67 } /* namespace Prio */
68 } /* namespace DDD */
69
70 START_UGDIM_NAMESPACE
71
72 using DDD::Prio::PrioMode;
73
74 /*
75 management functions for PrioMode.
76
77 these functions control the mode the prio-module is
78 currently in. this is used for error detection, but
79 also for correct detection of coupling inconsistencies
80 and recovery.
81 */
82
PrioModeName(PrioMode mode)83 static const char* PrioModeName (PrioMode mode)
84 {
85 switch(mode)
86 {
87 case PrioMode::PMODE_IDLE : return "idle-mode";
88 case PrioMode::PMODE_CMDS : return "commands-mode";
89 case PrioMode::PMODE_BUSY : return "busy-mode";
90 }
91 return "unknown-mode";
92 }
93
94
PrioSetMode(DDD::DDDContext & context,PrioMode mode)95 static void PrioSetMode (DDD::DDDContext& context, PrioMode mode)
96 {
97 auto& ctx = context.prioContext();
98 ctx.prioMode = mode;
99
100 # if DebugPrio<=8
101 Dune::dinfo << "PrioMode=" << PrioModeName(ctx.prioMode) << "\n";
102 # endif
103 }
104
105
PrioSuccMode(PrioMode mode)106 static PrioMode PrioSuccMode (PrioMode mode)
107 {
108 switch(mode)
109 {
110 case PrioMode::PMODE_IDLE: return PrioMode::PMODE_CMDS;
111 case PrioMode::PMODE_CMDS: return PrioMode::PMODE_BUSY;
112 case PrioMode::PMODE_BUSY: return PrioMode::PMODE_IDLE;
113 default: std::abort();
114 }
115 }
116
117
ddd_PrioActive(const DDD::DDDContext & context)118 bool ddd_PrioActive (const DDD::DDDContext& context)
119 {
120 return context.prioContext().prioMode != PrioMode::PMODE_IDLE;
121 }
122
123
PrioStepMode(DDD::DDDContext & context,PrioMode old)124 static bool PrioStepMode(DDD::DDDContext& context, PrioMode old)
125 {
126 auto& ctx = context.prioContext();
127 if (ctx.prioMode!=old)
128 {
129 Dune::dwarn
130 << "wrong prio-mode (currently in " << PrioModeName(ctx.prioMode)
131 << ", expected " << PrioModeName(old) << ")\n";
132 return false;
133 }
134
135 PrioSetMode(context, PrioSuccMode(ctx.prioMode));
136 return true;
137 }
138
139
140 /****************************************************************************/
141
142
ddd_PrioInit(DDD::DDDContext & context)143 void ddd_PrioInit(DDD::DDDContext& context)
144 {
145 PrioSetMode(context, PrioMode::PMODE_IDLE);
146 }
147
148
ddd_PrioExit(DDD::DDDContext &)149 void ddd_PrioExit(DDD::DDDContext&)
150 {}
151
152
153
154 /****************************************************************************/
155 /* */
156 /* Function: DDD_PrioChange */
157 /* */
158 /****************************************************************************/
159
160 /**
161 Consistent change of a local object's priority during DDD Prio Environment.
162 Local objects which are part of a distributed object must notify
163 other copies about local priority changes.
164 DDD will send appropriate messages to the owner processors of
165 the other copies.
166
167 This function is regarded as a {\bf Prio}-operation due
168 to its influence on DDD management information on neighbouring
169 processors. Therefore the function has to be issued between
170 a starting \funk{PrioBegin} and a final \funk{PrioEnd} call.
171
172 @param hdr DDD local object whose priority should be changed.
173 @param prio new priority for this local object.
174 */
175
DDD_PrioChange(const DDD::DDDContext & context,DDD_HDR hdr,DDD_PRIO prio)176 void DDD_PrioChange (const DDD::DDDContext& context, DDD_HDR hdr, DDD_PRIO prio)
177 {
178 #if DebugPrio<=2
179 DDD_PRIO old_prio = OBJ_PRIO(hdr);
180 #endif
181
182 if (!ddd_PrioActive(context))
183 DUNE_THROW(Dune::Exception, "Missing DDD_PrioBegin()");
184
185
186 /* change priority of object directly, for local objects this
187 is all what we need. */
188 {
189 /*
190 DDD_PRIO newprio;
191 PriorityMerge(&context.typeDefs()[OBJ_TYPE(hdr)],
192 OBJ_PRIO(hdr), prio, &newprio);
193 OBJ_PRIO(hdr) = newprio;
194 */
195 OBJ_PRIO(hdr) = prio;
196 }
197
198 /* handle distributed objects
199 if (ObjHasCpl(context, hdr))
200 {
201 nothing to do here:
202 for distributed objects, we will communicate the prio
203 via standard interface later.
204 }
205 */
206
207
208 # if DebugPrio<=2
209 Dune::dvverb
210 << "DDD_PrioChange " << OBJ_GID(hdr)
211 << ", old_prio=" << old_prio << ", new_prio=" << OBJ_PRIO(hdr) << "\n";
212 # endif
213 }
214
215
216
217 /****************************************************************************/
218 /* */
219 /* Function: DDD_PrioEnd */
220 /* */
221 /****************************************************************************/
222
GatherPrio(DDD::DDDContext &,DDD_HDR obj,void * data,DDD_PROC proc,DDD_PRIO prio)223 static int GatherPrio (DDD::DDDContext&, DDD_HDR obj, void *data, DDD_PROC proc, DDD_PRIO prio)
224 {
225 # if DebugPrio<=1
226 Dune::dvverb
227 << "DDD_PrioEnd/GatherPrio " << OBJ_GID(obj) << ", prio=" << OBJ_PRIO(obj)
228 << ". Send to copy on proc " << proc << "/p" << prio << "\n";
229 # endif
230
231 *((DDD_PRIO *)data) = OBJ_PRIO(obj);
232 return(0);
233 }
234
ScatterPrio(DDD::DDDContext & context,DDD_HDR obj,void * data,DDD_PROC proc,DDD_PRIO prio)235 static int ScatterPrio (DDD::DDDContext& context, DDD_HDR obj, void *data, DDD_PROC proc, DDD_PRIO prio)
236 {
237 DDD_PRIO real_prio = *((DDD_PRIO *)data);
238
239 /* if prio on other processor has been changed, we adapt it here. */
240 if (real_prio!=prio)
241 {
242 # if DebugPrio<=1
243 Dune::dvverb
244 << "DDD_PrioEnd/ScatterPrio " << OBJ_GID(obj) << "/" << OBJ_PRIO(obj)
245 << ", copy on proc " << proc << "/p" << prio
246 << " changed prio " << prio << " -> " << real_prio << "\n";
247 # endif
248
249 ModCoupling(context, obj, proc, real_prio);
250 }
251 # if DebugPrio<=1
252 else
253 {
254 Dune::dvverb
255 << "DDD_PrioEnd/ScatterPrio " << OBJ_GID(obj) << "/" << OBJ_PRIO(obj)
256 << ", copy on proc " << proc << "/p" << prio
257 << " keeps prio " << prio << "\n";
258 }
259 # endif
260
261 return(0);
262 }
263
264
265 /**
266 End of PrioEnvironment.
267 This function starts the actual process of changing priorities.
268 After a call to this function (on all processors) all
269 \funk{PrioChange}-commands since the last call to \funk{PrioBegin}
270 are executed. This involves a set of interface communications
271 between the processors.
272 */
273
DDD_PrioEnd(DDD::DDDContext & context)274 DDD_RET DDD_PrioEnd(DDD::DDDContext& context)
275 {
276 /* step mode and check whether call to PrioEnd is valid */
277 if (!PrioStepMode(context, PrioMode::PMODE_CMDS))
278 DUNE_THROW(Dune::Exception, "DDD_PrioEnd() aborted");
279
280
281 ddd_StdIFExchangeX(context, sizeof(DDD_PRIO), GatherPrio, ScatterPrio);
282
283 /*
284 free temporary storage
285 */
286 STAT_RESET;
287 IFAllFromScratch(context);
288 STAT_TIMER(T_PRIO_BUILD_IF);
289
290
291 PrioStepMode(context, PrioMode::PMODE_BUSY);
292
293 return(DDD_RET_OK);
294 }
295
296
297
298
299 /****************************************************************************/
300 /* */
301 /* Function: DDD_PrioBegin */
302 /* */
303 /****************************************************************************/
304
305 /**
306 Starts a PrioEnvironment.
307 A call to this function establishes a global operation of changing
308 priorities. It must be issued on all processors. After this call an
309 arbitrary series of \funk{PrioChange}-commands may be issued. The
310 global transfer operation is carried out via a \funk{PrioEnd} call on
311 each processor.
312 */
313
DDD_PrioBegin(DDD::DDDContext & context)314 void DDD_PrioBegin(DDD::DDDContext& context)
315 {
316 /* step mode and check whether call to JoinBegin is valid */
317 if (!PrioStepMode(context, PrioMode::PMODE_IDLE))
318 DUNE_THROW(Dune::Exception, "DDD_PrioBegin() aborted");
319 }
320
321
322
323 END_UGDIM_NAMESPACE
324