00001
00002
00003
00004
00005
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
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