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