conv-core/quiescence.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * $Source: /cvsroot/charm/src/conv-core/quiescence.c,v $
00003  * $Author: schak $
00004  * $Date: 2005-06-25 20:25:09 $
00005  * $Revision: 2.12 $
00006  *****************************************************************************/
00007 
00022 #include "converse.h"
00023 #include "quiescence.h"
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #ifndef  DEBUGF
00027 #define  DEBUGF(x) printf x 
00028 #endif
00029 
00030 CpvDeclare(CQdState, cQdState);
00031 unsigned int _CQdHandlerIdx;
00032 unsigned int _CQdAnnounceHandlerIdx;
00033 
00034 
00035 int  CQdMsgGetPhase(CQdMsg msg) 
00036 { return msg->phase; }
00037 
00038 void CQdMsgSetPhase(CQdMsg msg, int p) 
00039 { msg->phase = p; }
00040 
00041 int  CQdMsgGetCreated(CQdMsg msg) 
00042 { CmiAssert(msg->phase==1); return msg->u.p1.created; }
00043 
00044 void CQdMsgSetCreated(CQdMsg msg, int c) 
00045 { CmiAssert(msg->phase==1); msg->u.p1.created = c; }
00046 
00047 int  CQdMsgGetProcessed(CQdMsg msg) 
00048 { CmiAssert(msg->phase==1); return msg->u.p1.processed; }
00049 
00050 void CQdMsgSetProcessed(CQdMsg msg, int p) 
00051 { CmiAssert(msg->phase==1); msg->u.p1.processed = p; }
00052 
00053 int  CQdMsgGetDirty(CQdMsg msg) 
00054 { CmiAssert(msg->phase==2); return msg->u.p2.dirty; }
00055 
00056 void CQdMsgSetDirty(CQdMsg msg, int d) 
00057 { CmiAssert(msg->phase==2); msg->u.p2.dirty = d; }
00058 
00059 
00060 int CQdGetCreated(CQdState state)
00061 { return state->mCreated; }
00062 
00063 void CQdCreate(CQdState state, int n)
00064 { state->mCreated += n; }
00065 
00066 int CQdGetProcessed(CQdState state)
00067 { return state->mProcessed; }
00068 
00069 void CQdProcess(CQdState state, int n)
00070 { state->mProcessed += n; }
00071 
00072 void CQdPropagate(CQdState state, CQdMsg msg) 
00073 {   
00074   int i;
00075   CmiSetHandler(msg, _CQdHandlerIdx);
00076   for(i=0; i<state->nChildren; i++) {
00077     CQdCreate(state, -1);
00078     CmiSyncSend(state->children[i], sizeof(struct ConvQdMsg), (char *)msg);
00079   }
00080 }
00081 
00082 int  CQdGetParent(CQdState state) 
00083 { return state->parent; }
00084     
00085 int  CQdGetCCreated(CQdState state) 
00086 { return state->cCreated; }
00087 
00088 int  CQdGetCProcessed(CQdState state) 
00089 { return state->cProcessed; }
00090 
00091 void CQdSubtreeCreate(CQdState state, int c) 
00092 { state->cCreated += c; }
00093 
00094 void CQdSubtreeProcess(CQdState state, int p) 
00095 { state->cProcessed += p; }
00096 
00097 int  CQdGetStage(CQdState state) 
00098 { return state->stage; }
00099 
00100 void CQdSetStage(CQdState state, int p) 
00101 { state->stage = p; }
00102 
00103 void CQdReported(CQdState state) 
00104 { state->nReported++; }
00105 
00106 int  CQdAllReported(CQdState state) 
00107 { return state->nReported==(state->nChildren+1);}
00108 
00109 void CQdReset(CQdState state) 
00110 { 
00111   state->nReported=0; state->cCreated=0; 
00112   state->cProcessed=0; state->cDirty=0; 
00113 }
00114 
00115 void CQdMarkProcessed(CQdState state) 
00116 { state->oProcessed = state->mProcessed; }
00117 
00118 int  CQdIsDirty(CQdState state) 
00119 { return ((state->mProcessed > state->oProcessed) || state->cDirty); }
00120 
00121 void CQdSubtreeSetDirty(CQdState state, int d) 
00122 { state->cDirty = state->cDirty || d; }
00123 
00124 CQdState CQdStateCreate(void)
00125 {
00126   CQdState state = (CQdState) malloc(sizeof(struct ConvQdState));
00127   _MEMCHECK(state);
00128   state->mCreated = 0;
00129   state->mProcessed = 0;
00130   state->stage = 0;
00131   state->nReported = 0;
00132   state->oProcessed = 0;
00133   state->cCreated = 0;
00134   state->cProcessed = 0;
00135   state->cDirty = 0;
00136   state->nChildren = CmiNumSpanTreeChildren(CmiMyPe());
00137   state->parent = CmiSpanTreeParent(CmiMyPe());
00138   /* fixed bug on SP3, when nChildren is 0, NULL will be returned by malloc */
00139   if (state->nChildren) {
00140     state->children = (int *) malloc(state->nChildren*sizeof(int));
00141     _MEMCHECK(state->children);
00142   }
00143   else 
00144     state->children = NULL;
00145   CmiSpanTreeChildren(CmiMyPe(), state->children);
00146 
00147   return state;
00148 }
00149 
00150 
00151 static void CQdBcastQD1(CQdState state, CQdMsg msg)
00152 {  
00153   CQdMsgSetPhase(msg, 0); 
00154   CQdPropagate(state, msg); 
00155   CQdMsgSetPhase(msg, 1); 
00156   CQdMsgSetCreated(msg, CQdGetCreated(state)); 
00157   CQdMsgSetProcessed(msg, CQdGetProcessed(state)); 
00158   CQdCreate(state, -1);
00159   CmiSyncSendAndFree(CmiMyPe(), sizeof(struct ConvQdMsg), (char *) msg);
00160   CQdMarkProcessed(state); 
00161   CQdReset(state); 
00162   CQdSetStage(state, 1); 
00163 }
00164 
00165 
00166 static void CQdBcastQD2(CQdState state, CQdMsg msg)
00167 {
00168   CQdMsgSetPhase(msg, 1); 
00169   CQdPropagate(state, msg); 
00170   CQdMsgSetPhase(msg, 2); 
00171   CQdMsgSetDirty(msg, CQdIsDirty(state)); 
00172   CQdCreate(state, -1);
00173   CmiSyncSendAndFree(CmiMyPe(), sizeof(struct ConvQdMsg), (char *) msg);
00174   CQdReset(state); 
00175   CQdSetStage(state, 2); 
00176 }
00177 
00178 
00179 static void CQdHandlePhase0(CQdState state, CQdMsg msg)
00180 {
00181   CmiAssert(CmiMyPe()==0 || CQdGetStage(state)==0);
00182   if(CQdGetStage(state)==0)
00183     CQdBcastQD1(state, msg);
00184   else
00185     CmiFree(msg);
00186 }
00187 
00188 
00189 static void CQdHandlePhase1(CQdState state, CQdMsg msg)
00190 {
00191   switch(CQdGetStage(state)) {          
00192   case 0 :
00193     CmiAssert(CmiMyPe()!=0);
00194     CQdBcastQD2(state, msg);
00195     break;
00196   case 1 :
00197     CQdSubtreeCreate(state, CQdMsgGetCreated(msg)); 
00198     CQdSubtreeProcess(state, CQdMsgGetProcessed(msg)); 
00199     CQdReported(state); 
00200     
00201     if(CQdAllReported(state)) {
00202       if(CmiMyPe()==0) {
00203         if(CQdGetCCreated(state) == CQdGetCProcessed(state)) 
00204           CQdBcastQD2(state, msg); 
00205         else 
00206           CQdBcastQD1(state, msg);
00207       } 
00208       else {
00209         CQdMsgSetCreated(msg, CQdGetCCreated(state)); 
00210         CQdMsgSetProcessed(msg, CQdGetCProcessed(state)); 
00211         CQdCreate(state, -1);
00212         CmiSyncSendAndFree(CQdGetParent(state), 
00213                            sizeof(struct ConvQdMsg), (char *) msg);
00214         DEBUGF(("PE = %d, My parent = %d\n", CmiMyPe(), CQdGetParent(state)));
00215         CQdReset(state); 
00216         CQdSetStage(state, 0); 
00217       }
00218     } 
00219     else
00220       CmiFree(msg);
00221     break;
00222   default: 
00223     CmiAbort("Internal QD Error. Contact Developers.!\n");
00224   }
00225 }
00226 
00227 
00228 static void CQdHandlePhase2(CQdState state, CQdMsg msg)
00229 {
00230   CmiAssert(CQdGetStage(state)==2);
00231   CQdSubtreeSetDirty(state, CQdMsgGetDirty(msg));    
00232   CQdReported(state);
00233   if(CQdAllReported(state)) { 
00234     if(CmiMyPe()==0) {
00235       if(CQdIsDirty(state)) 
00236         CQdBcastQD1(state, msg);
00237       else {
00238         CmiSetHandler(msg, _CQdAnnounceHandlerIdx);
00239         CQdCreate(state, 0-CmiNumPes());
00240         CmiSyncBroadcastAllAndFree(sizeof(struct ConvQdMsg), (char *) msg);
00241         CQdReset(state); 
00242         CQdSetStage(state, 0); 
00243       }
00244     } 
00245     else {
00246       CQdMsgSetDirty(msg, CQdIsDirty(state)); 
00247       CQdCreate(state, -1);
00248       CmiSyncSendAndFree(CQdGetParent(state), 
00249                          sizeof(struct ConvQdMsg), (char *) msg);
00250       CQdReset(state); 
00251       CQdSetStage(state, 0); 
00252     }
00253   } 
00254   else
00255     CmiFree(msg);
00256 }
00257 
00258 
00259 static void CQdCallWhenIdle(CQdMsg msg)
00260 {
00261   CQdState state = CpvAccess(cQdState);
00262   
00263   switch(CQdMsgGetPhase(msg)) {
00264   case 0 : CQdHandlePhase0(state, msg); break;
00265   case 1 : CQdHandlePhase1(state, msg); break;
00266   case 2 : CQdHandlePhase2(state, msg); break;
00267   default: CmiAbort("Internal QD Error. Contact Developers.!\n");
00268   }
00269 }
00270 
00271 
00272 void CQdHandler(CQdMsg msg)
00273 {
00274   CQdProcess(CpvAccess(cQdState), -1);
00275   CcdCallOnCondition(CcdPROCESSOR_STILL_IDLE, 
00276                      (CcdVoidFn)CQdCallWhenIdle, (void*) msg);  
00277 }
00278 
00279 
00280 void CQdRegisterCallback(CQdVoidFn fn, void *arg)
00281 {
00282   CcdCallOnCondition(CcdQUIESCENCE, fn, arg);
00283 }
00284 
00285 void CQdAnnounceHandler(CQdMsg msg)
00286 {
00287   CQdProcess(CpvAccess(cQdState), -1);
00288   CcdRaiseCondition(CcdQUIESCENCE);
00289 }
00290 
00291 void CQdCpvInit(void) {
00292   CpvInitialize(CQdState, cQdState);
00293   CpvAccess(cQdState) = CQdStateCreate();
00294 }
00295 
00296 void CQdInit(void)
00297 {
00298   CQdCpvInit();
00299   _CQdHandlerIdx = CmiRegisterHandler((CmiHandler)CQdHandler);
00300   _CQdAnnounceHandlerIdx = 
00301     CmiRegisterHandler((CmiHandler)CQdAnnounceHandler);
00302 }
00303 
00304 void CmiStartQD(CQdVoidFn fn, void *arg)
00305 {
00306   register CQdMsg msg = (CQdMsg) CmiAlloc(sizeof(struct ConvQdMsg)); 
00307   CQdRegisterCallback(fn, arg);
00308   CQdMsgSetPhase(msg, 0);  
00309   CmiSetHandler(msg, _CQdHandlerIdx);
00310   CQdCreate(CpvAccess(cQdState), -1);
00311   CmiSyncSendAndFree(0, sizeof(struct ConvQdMsg), (char *)msg);
00312 }
00313 
00314 
00315 

Generated on Sun Jun 29 13:29:12 2008 for Charm++ by  doxygen 1.5.1